grist-widget-sdk 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/dist/actions.cjs +96 -0
- package/dist/actions.cjs.map +1 -0
- package/dist/actions.d.cts +36 -0
- package/dist/actions.d.ts +36 -0
- package/dist/actions.js +29 -0
- package/dist/actions.js.map +1 -0
- package/dist/app.cjs +49 -8
- package/dist/app.cjs.map +1 -1
- package/dist/app.d.cts +3 -2
- package/dist/app.d.ts +3 -2
- package/dist/app.js +4 -3
- package/dist/{chunk-4ZGVKGDF.js → chunk-A4KFKOEQ.js} +2 -58
- package/dist/chunk-A4KFKOEQ.js.map +1 -0
- package/dist/{chunk-OXA2VITC.js → chunk-CMN4M4S3.js} +6 -4
- package/dist/{chunk-OXA2VITC.js.map → chunk-CMN4M4S3.js.map} +1 -1
- package/dist/{chunk-MAPAWVQC.js → chunk-DKCRFNAW.js} +104 -17
- package/dist/chunk-DKCRFNAW.js.map +1 -0
- package/dist/{chunk-LSALXIGM.js → chunk-TUPCTWE5.js} +7 -3
- package/dist/chunk-TUPCTWE5.js.map +1 -0
- package/dist/chunk-YGQXH2P5.js +81 -0
- package/dist/chunk-YGQXH2P5.js.map +1 -0
- package/dist/{define-widget-B1FIvI-h.d.cts → define-widget-CYYdqRmB.d.cts} +39 -29
- package/dist/{define-widget-B9gEtJP0.d.ts → define-widget-D-NmSglS.d.ts} +39 -29
- package/dist/emulator/testing.cjs +49 -8
- package/dist/emulator/testing.cjs.map +1 -1
- package/dist/emulator/testing.d.cts +1 -0
- package/dist/emulator/testing.d.ts +1 -0
- package/dist/emulator/testing.js +8 -6
- package/dist/emulator/testing.js.map +1 -1
- package/dist/emulator.cjs.map +1 -1
- package/dist/emulator.js +3 -2
- package/dist/index.cjs +128 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -3
- package/dist/index.d.ts +30 -3
- package/dist/index.js +12 -11
- package/dist/{mount-grist-widget-Dtelqao_.d.cts → mount-grist-widget-D0mr__ga.d.cts} +1 -1
- package/dist/{mount-grist-widget-CkB-3iG_.d.ts → mount-grist-widget-DVcFl5Ys.d.ts} +1 -1
- package/package.json +11 -1
- package/dist/chunk-4ZGVKGDF.js.map +0 -1
- package/dist/chunk-LSALXIGM.js.map +0 -1
- package/dist/chunk-MAPAWVQC.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/emulator/testing/index.ts","../../src/emulator/testing/render-with-grist.tsx","../../src/app/mount-grist-widget.tsx","../../src/sdk/use-grist.ts","../../src/sdk/helpers/grist-value-codec.ts","../../src/sdk/helpers/grist-table-data.ts","../../src/sdk/helpers/grist-widget-options.ts","../../src/sdk/helpers/build-replica-document.ts","../../src/sdk/helpers/grist-columns-filters.ts","../../src/sdk/helpers/grist-attachment-download.ts","../../src/sdk/helpers/grist-fetch-with-auth.ts","../../src/sdk/helpers/grist-attachment-upload.ts","../../src/sdk/runtime/api.ts","../../src/sdk/helpers/grist-mappings.ts","../../src/sdk/runtime/cells.ts","../../src/sdk/runtime/derive.ts","../../src/sdk/helpers/grist-widget-interaction.ts","../../src/sdk/runtime/host.ts","../../src/sdk/runtime/ready.ts","../../src/sdk/helpers/grist-theme-payload.ts","../../src/sdk/runtime/runtime.ts","../../src/sdk/define-widget.ts","../../src/sdk/components/grist-widget-provider.tsx","../../src/sdk/components/grist-boundary.tsx","../../src/sdk/helpers/replica-normalize.ts","../../src/sdk/use-widget-metadata.ts","../../src/sdk/helpers/grist-user-actions.ts","../../src/app/chrome/local-dev-page.tsx","../../src/app/chrome/tokens.ts","../../src/app/chrome/widget-title.ts","../../src/app/chrome/release-page.tsx","../../src/app/deploy-path.ts","../../src/app/released-versions.ts","../../src/sdk/helpers/grist-sdk-alerts.ts","../../src/app/chrome/widget-alerts.tsx","../../src/app/widget-theme.tsx","../../src/emulator/testing/declared-document.ts","../../src/emulator/api/command-api.ts","../../src/emulator/core/mappings.ts","../../src/emulator/api/custom-section-api.ts","../../src/emulator/api/grist-api.ts","../../src/emulator/core/display-helpers.ts","../../src/emulator/core/document.ts","../../src/emulator/core/action-engine.ts","../../src/emulator/core/columnar.ts","../../src/emulator/api/grist-doc-api.ts","../../src/emulator/api/grist-view.ts","../../src/emulator/api/widget-api.ts","../../src/emulator/api/index.ts","../../src/emulator/core/event-bus.ts","../../src/emulator/theme-message.ts","../../src/emulator/transports/inline.ts","../../src/emulator/validators.ts","../../src/emulator/create-grist-emulator.ts","../../src/emulator/templates.ts","../../src/emulator/testing/smoke-test-widget.tsx","../../src/emulator/testing/jsdom-stubs.ts","../../src/emulator/testing/matchers.ts"],"sourcesContent":["/**\n * Test entry point — `grist-widget-sdk/emulator/testing`.\n *\n * Bundles `renderWithGrist`, matchers, document presets, and the most-used\n * @testing-library/react primitives so a typical test file only needs one\n * import line:\n *\n * import {\n * renderWithGrist, presets, screen, fireEvent, waitFor, actionsOf,\n * } from \"grist-widget-sdk/emulator/testing\"\n */\n\nexport { renderWithGrist } from \"./render-with-grist\"\nexport type {\n RenderWithGristOptions,\n RenderWithGristResult,\n} from \"./render-with-grist\"\n\nexport { smokeTestWidget, type SmokeTestWidgetOptions } from \"./smoke-test-widget\"\nexport { installJsdomStubs } from \"./jsdom-stubs\"\n\nexport {\n actionsOf,\n eventsOf,\n waitForEvent,\n type WaitForEventKind,\n type WaitForEventOptions,\n} from \"./matchers\"\n\n// Document fixtures (re-export from the emulator entry for convenience).\nexport { presets } from \"../templates\"\n\n// @testing-library/react convenience re-exports — see AGENTS.md\nexport {\n act,\n cleanup,\n fireEvent,\n render,\n screen,\n waitFor,\n within,\n} from \"@testing-library/react\"\nexport type { RenderOptions, RenderResult } from \"@testing-library/react\"\n","/**\n * `renderWithGrist(ui, options)` — drop-in replacement for\n * `@testing-library/react`'s `render(ui)` that boots a Grist emulator\n * (inline transport) and exposes it to the test.\n *\n * The emulator is mounted as `window.grist`. The SDK hooks (`useGrist`,\n * `useGristReady`, etc.) detect it via the same path they use in production.\n *\n * Cleanup is automatic when the test's container unmounts.\n */\n\nimport type { ReactElement } from \"react\"\n\nimport { render, type RenderOptions, type RenderResult } from \"@testing-library/react\"\n\nimport { GristWidgetApp } from \"../../app/mount-grist-widget\"\nimport type { GristWidget, UseGristOptions } from \"../../sdk\"\nimport { isGristWidget } from \"../../sdk/define-widget\"\nimport { resetGristForTests } from \"../../sdk/use-grist\"\nimport { declaredColumns, declaredDocument, mapEveryColumn } from \"./declared-document\"\nimport { createGristEmulator } from \"../create-grist-emulator\"\nimport type { CreateGristEmulatorOptions, GristEmulator } from \"../create-grist-emulator\"\nimport { presets } from \"../templates\"\n\nexport type RenderWithGristOptions = RenderOptions & {\n emulator?: CreateGristEmulatorOptions\n /** Skip mounting the emulator; you bring your own. Useful for shared fixtures. */\n existing?: GristEmulator\n /**\n * The widget's declaration (`defineGristWidget()`) or its `GRIST_OPTIONS`.\n * Given, the test runs the widget as `mountGristWidget()` does inside\n * Grist (provider, boundary, alerts), against a table with a column per\n * declared column, every one mapped, and the access it asks for granted.\n */\n widget?: GristWidget | UseGristOptions\n /**\n * With `widget`: the table's rows, under the declared names, as typed\n * reads give them (`{ Title: \"Ship\", Due: new Date(...) }`). The first is\n * selected. Defaults to one row of sample values.\n */\n rows?: ReadonlyArray<Record<string, unknown>>\n}\n\nexport type RenderWithGristResult = RenderResult & {\n emulator: GristEmulator\n}\n\nexport function renderWithGrist(\n ui: ReactElement,\n options: RenderWithGristOptions = {}\n): RenderWithGristResult {\n // Make `window.self !== window.top` evaluate to `true` so\n // `useGristAvailability` reports the widget as embedded. We only do this in\n // jsdom; real browsers already enforce this distinction for iframes.\n fakeIframeContext()\n\n resetGristForTests()\n\n const widgetOptions = options.widget ? (isGristWidget(options.widget) ? options.widget.options : options.widget) : undefined\n const columns = widgetOptions ? declaredColumns(widgetOptions) : []\n const emulatorOptions: CreateGristEmulatorOptions =\n widgetOptions && !options.emulator?.document\n ? {\n ...options.emulator,\n document: declaredDocument(columns, options.rows),\n widgetInteraction: options.emulator?.widgetInteraction ?? { access_level: widgetOptions.requiredAccess ?? \"read table\" },\n }\n : (options.emulator ?? { document: presets.blank() })\n const emulator = options.existing ?? createGristEmulator(emulatorOptions)\n if (widgetOptions && columns.length > 0) emulator.setColumnMappings(mapEveryColumn(columns))\n\n const Widget = () => ui\n const result = render(widgetOptions ? <GristWidgetApp App={Widget} options={widgetOptions} /> : ui, options)\n const originalUnmount = result.unmount\n result.unmount = () => {\n originalUnmount()\n if (!options.existing) emulator.dispose()\n resetGristForTests()\n }\n return Object.assign(result, { emulator })\n}\n\nfunction fakeIframeContext() {\n if (typeof window === \"undefined\") return\n if (window.self !== window.top) return // already iframe-like\n try {\n Object.defineProperty(window, \"top\", {\n configurable: true,\n get: () => ({}),\n })\n } catch {\n // Some jsdom versions block redefinition; fail silently — tests using\n // `useGristAvailability` will need to bypass it explicitly in that case.\n }\n}\n","import { StrictMode, Suspense, type ComponentType, type ReactNode } from \"react\"\nimport { createRoot } from \"react-dom/client\"\n\nimport { GristBoundary, GristWidgetProvider, useWidgetMetadata } from \"../sdk\"\nimport type { GristWidget, UseGristOptions } from \"../sdk\"\nimport { isGristWidget } from \"../sdk/define-widget\"\nimport { LocalDevPage as DefaultLocalDevPage } from \"./chrome/local-dev-page\"\nimport { ReleasePage as DefaultReleasePage } from \"./chrome/release-page\"\nimport { WidgetAlerts } from \"./chrome/widget-alerts\"\nimport { parseDeployPath, type DeployChannel } from \"./deploy-path\"\nimport { EmbeddedThemeProvider, StandaloneThemeProvider } from \"./widget-theme\"\n\nexport type GristWidgetAppProps = {\n /** The widget. A `React.lazy()` component works too: its code then loads only inside Grist. */\n App: ComponentType\n /** The widget's `GRIST_OPTIONS`: access level, columns, and so on. */\n options: UseGristOptions\n /** The page's title and description (the widget's `WIDGET_METADATA`, or its declaration's). */\n metadata?: { title?: string; description?: string }\n /**\n * Whether this is the local dev server. Pass `import.meta.env.DEV`.\n * Outside Grist it picks the local-dev page over the release page.\n */\n dev?: boolean\n /**\n * Wraps the widget inside Grist, under {@link GristBoundary}. The default\n * lists what needs the user's attention (column mapping, access level,\n * failed writes) above the widget; `null` renders the widget alone.\n */\n Alerts?: ComponentType<{ children: ReactNode }> | null\n /** Shown outside Grist on the local dev server. Defaults to a page pointing at `pnpm test` and the `dev` loop. */\n LocalDevPage?: ComponentType\n /**\n * Shown outside Grist on a deployed URL (`/latest/`, `/dev/`, `/v<version>/`).\n * Defaults to a page linking every channel and version, with the URL to\n * paste into Grist.\n */\n ReleasePage?: ComponentType<{ channel: DeployChannel }>\n}\n\nexport type MountGristWidgetConfig = GristWidgetAppProps & {\n /** The element to render into, or its CSS selector. Defaults to `#root`. */\n root?: Element | string\n}\n\n/**\n * A widget's entry module, `src/app/App.tsx`, as `import * as entry` gives\n * it: the widget as its default export, its declaration as `widget` (or, in\n * a widget made before `defineGristWidget`, `GRIST_OPTIONS` and\n * `WIDGET_METADATA`), and optionally its own `Alerts`, `LocalDevPage` and\n * `ReleasePage`. Everything a widget customises lives there, in its own\n * file: the template's `src/main.tsx` stays the same in every widget, and\n * `create-grist-widget upgrade` can rewrite it without losing anything.\n */\nexport type GristWidgetEntry = {\n default: ComponentType\n widget?: GristWidget\n GRIST_OPTIONS?: UseGristOptions\n WIDGET_METADATA?: { title?: string; description?: string }\n Alerts?: GristWidgetAppProps[\"Alerts\"]\n LocalDevPage?: GristWidgetAppProps[\"LocalDevPage\"]\n ReleasePage?: GristWidgetAppProps[\"ReleasePage\"]\n}\n\n/** The props {@link GristWidgetApp} takes, from a widget's entry module. */\nexport function entryProps(entry: GristWidgetEntry, dev = false): GristWidgetAppProps {\n const widget = isGristWidget(entry.widget) ? entry.widget : undefined\n const options = widget?.options ?? entry.GRIST_OPTIONS\n if (!options) {\n throw new Error(\n \"mountGristWidget: src/app/App.tsx exports neither `widget` (defineGristWidget) nor `GRIST_OPTIONS`.\"\n )\n }\n const props: GristWidgetAppProps = {\n App: entry.default,\n options,\n metadata: widget?.metadata ?? entry.WIDGET_METADATA,\n dev,\n }\n if (\"Alerts\" in entry) props.Alerts = entry.Alerts\n if (entry.LocalDevPage) props.LocalDevPage = entry.LocalDevPage\n if (entry.ReleasePage) props.ReleasePage = entry.ReleasePage\n return props\n}\n\nexport type MountedGristWidget = {\n unmount: () => void\n}\n\n/**\n * Render a widget into the page: everything `src/main.tsx` used to wire by\n * hand.\n *\n * ```tsx\n * import { mountGristWidget } from \"grist-widget-sdk/app\"\n * import \"./index.css\"\n * import * as entry from \"./app/App\"\n *\n * mountGristWidget(entry, { dev: import.meta.env.DEV })\n * ```\n *\n * It reads the entry module's exports ({@link GristWidgetEntry}): the widget,\n * its declaration and any page it replaces. The older form,\n * `mountGristWidget({ App, options: GRIST_OPTIONS, dev })`, still works.\n *\n * Inside Grist, the widget renders in {@link GristWidgetProvider} and\n * {@link GristBoundary}, which gates on its mapped columns when it declares\n * any, and follows Grist's light/dark theme. Outside Grist, where there is\n * nothing to connect to, the page shows `LocalDevPage` on the dev server and\n * `ReleasePage` on a deployed URL.\n */\nexport function mountGristWidget(entry: GristWidgetEntry, options?: { dev?: boolean; root?: Element | string }): MountedGristWidget\nexport function mountGristWidget(config: MountGristWidgetConfig): MountedGristWidget\nexport function mountGristWidget(\n config: MountGristWidgetConfig | GristWidgetEntry,\n entryOptions: { dev?: boolean; root?: Element | string } = {}\n): MountedGristWidget {\n const { root = \"#root\", ...props } =\n \"App\" in config ? config : { ...entryProps(config, entryOptions.dev), root: entryOptions.root }\n const container = typeof root === \"string\" ? document.querySelector(root) : root\n if (!container) {\n throw new Error(`mountGristWidget: no element matches \"${String(root)}\" to render the widget into.`)\n }\n\n const reactRoot = createRoot(container)\n reactRoot.render(\n <StrictMode>\n <GristWidgetApp {...props} />\n </StrictMode>\n )\n return { unmount: () => reactRoot.unmount() }\n}\n\n/**\n * The tree {@link mountGristWidget} renders, as a component: for a test, or\n * for a page that manages its own React root.\n */\nexport function GristWidgetApp({\n App,\n options,\n metadata,\n dev = false,\n Alerts = WidgetAlerts,\n LocalDevPage = DefaultLocalDevPage,\n ReleasePage = DefaultReleasePage,\n}: GristWidgetAppProps) {\n const Wrap = Alerts ?? PassThrough\n if (isEmbedded()) {\n return (\n <GristWidgetProvider options={options}>\n <PageMetadata metadata={metadata} />\n <EmbeddedThemeProvider>\n <GristBoundary>\n <div style={FILL}>\n <Wrap>\n <Suspense fallback={null}>\n <App />\n </Suspense>\n </Wrap>\n </div>\n </GristBoundary>\n </EmbeddedThemeProvider>\n </GristWidgetProvider>\n )\n }\n\n const channel = parseDeployPath(window.location.pathname).channel\n return (\n <StandaloneThemeProvider>\n <PageMetadata metadata={metadata} />\n <div style={FILL}>{dev ? <LocalDevPage /> : <ReleasePage channel={channel} />}</div>\n </StandaloneThemeProvider>\n )\n}\n\nconst FILL = { minHeight: \"100%\", width: \"100%\" } as const\n\n/** A Grist custom widget only ever runs in Grist's iframe. */\nfunction isEmbedded(): boolean {\n return typeof window !== \"undefined\" && window.self !== window.top\n}\n\n/** The page's title and description, from the widget's declaration. */\nfunction PageMetadata({ metadata }: { metadata: GristWidgetAppProps[\"metadata\"] }) {\n useWidgetMetadata(metadata?.title ? { title: metadata.title, description: metadata.description ?? \"\" } : null)\n return null\n}\n\nfunction PassThrough({ children }: { children: ReactNode }) {\n return <>{children}</>\n}\n","/**\n * `useGrist()`: the widget's one object for Grist — its connection, the\n * selected record and the section's records, column mapping, writes, widget\n * options, linking and the document's REST API.\n *\n * Inside `<GristWidgetProvider>` (what `mountGristWidget()` renders) it reads\n * the provider's connection; outside one, a page-wide connection made with\n * the first caller's options.\n */\n\nimport { createContext, useCallback, useContext, useEffect, useMemo, useSyncExternalStore } from \"react\"\n\nimport type { ValidateColumnMappingsResult } from \"./helpers/grist-mappings\"\nimport { createGristApi, type GristApi } from \"./runtime/api\"\nimport {\n deriveColumnMappingStatus,\n deriveError,\n deriveStatus,\n mapBackPatch,\n type GristWidgetStatus,\n} from \"./runtime/derive\"\nimport { mapAndCheck, type GristCellIssue } from \"./runtime/cells\"\nimport { ALL_STREAMS } from \"./runtime/host\"\nimport { resetGristReady } from \"./runtime/ready\"\nimport {\n createGristRuntime,\n initialRuntimeState,\n type GristRuntime,\n type GristRuntimeOptions,\n type GristRuntimeState,\n type GristTheme,\n type GristWidgetActionStatus,\n} from \"./runtime/runtime\"\nimport type { GristRowRecord, GristWidgetColumnMap } from \"./types\"\n\nexport type { GristTheme, GristWidgetActionStatus, GristWidgetStatus }\nexport type { GristColumnInfo, ListColumnsOptions, ListTablesOptions } from \"./runtime/api\"\n\n/** What the widget asks Grist for: access, columns to map, and the alerts it doesn't want. */\nexport type UseGristOptions = GristRuntimeOptions\n\n/** A write under declared names: any of the mapped record's fields but its `id`. */\nexport type GristRecordPatch<TMapped> = Partial<Omit<TMapped, \"id\">>\n\n/** Derived from the selection: no row, a row, or the add-row placeholder. */\nexport type GristWidgetMode = \"empty\" | \"row\" | \"new-row\"\n\n/**\n * The widget's Grist state and API. Every method is referentially stable for\n * the widget's lifetime: safe in effect dependencies. The object itself is\n * new whenever a value changes; depend on the members you use, not on it.\n */\nexport type UseGristResult<TRow = Record<string, unknown>, TMapped = Record<string, unknown>> = Omit<\n GristApi,\n \"fetchTableRows\"\n> & {\n /** `\"booting\"` until Grist answers, then `\"ready\"`; `\"unavailable\"` outside Grist; `\"error\"` otherwise. */\n status: GristWidgetStatus\n /** Inside Grist with its plugin API (null while connecting). */\n isAvailable: boolean | null\n isReady: boolean\n /** Why the widget can't run (status `\"error\"` or `\"unavailable\"`), else null. */\n error: string | null\n /** Grist's light or dark theme, null until Grist sends it. */\n theme: GristTheme | null\n\n /** The selected row, raw column ids. */\n record: GristRowRecord<TRow> | null\n /** The section's rows (what its filters show), raw column ids. */\n records: GristRowRecord<TRow>[] | null\n /**\n * The selected row under the declared column names, each cell the JS value\n * its declared type promises (a cell that doesn't match is null, and in\n * `cellIssues`); null until every required column is mapped.\n */\n mappedRecord: TMapped | null\n /** Every row of the section, like `mappedRecord`. */\n mappedRecords: TMapped[] | null\n /** The mapped cells that didn't match their declared type (or the widget's `schema`), by row. */\n cellIssues: readonly GristCellIssue[]\n /** Declared column name → the Grist column id(s) mapped to it. */\n mappings: GristWidgetColumnMap\n /** Whether every required declared column is mapped (`pending` until Grist reports mappings). */\n columnMappingStatus: ValidateColumnMappingsResult\n mode: GristWidgetMode\n /** The Grist column id mapped to a declared name, or the name itself. */\n resolveMappedColumnId: (name: string) => string\n /**\n * A patch under declared names, as real column ids for a write, each value\n * encoded for its declared type (multi-column mappings are skipped).\n */\n mapBack: (patch: Partial<TMapped>) => Record<string, unknown>\n /**\n * Writes a patch under declared names to the selected row (or to `rowId`),\n * encoded for each declared type: `mapBack` + `table.update` in one call.\n * Rejects when no row is selected.\n */\n updateRecord: {\n (patch: GristRecordPatch<TMapped>): Promise<void>\n (rowId: number, patch: GristRecordPatch<TMapped>): Promise<void>\n }\n /** Adds a row to the section's table from a patch under declared names; resolves to its row id. */\n addRecord: (patch: GristRecordPatch<TMapped>) => Promise<number>\n /** The section's table id. */\n currentTableId: string | null\n\n /** Any table as rows (full access). */\n fetchTableRows: <T extends Record<string, unknown> = Record<string, unknown>>(\n tableId: string,\n options?: Parameters<GristApi[\"fetchTableRows\"]>[1]\n ) => Promise<GristRowRecord<T>[]>\n\n /** The last write's state. */\n actionStatus: GristWidgetActionStatus\n actionError: string | null\n\n /** The options Grist stores for this widget, null until it sends them. */\n widgetOptions: Record<string, unknown> | null\n}\n\ntype GristContextValue = { runtime: GristRuntime; api: GristApi }\n\nconst GristContext = createContext<GristContextValue | null>(null)\nGristContext.displayName = \"GristContext\"\n\n/** @internal The provider's (or the page's) runtime, for the SDK's own components. */\nexport function useGristRuntime(): GristContextValue | null {\n return useContext(GristContext)\n}\n\nfunction newConnection(options: UseGristOptions | undefined): GristContextValue {\n const runtime = createGristRuntime(options)\n return { runtime, api: createGristApi(runtime) }\n}\n\nlet pageConnection: GristContextValue | null = null\n\n/** @internal Tests: forget the page's connection and every Grist binding. */\nexport function resetGristForTests(): void {\n pageConnection = null\n resetGristReady()\n for (const s of ALL_STREAMS) s.reset()\n}\n\nexport const GristContextProvider = GristContext.Provider\nexport { newConnection }\n\nconst serverState = () => initialRuntimeState()\n\n/** The connection's state, re-rendering on every change. */\nexport function useGristState(connection: GristContextValue): GristRuntimeState {\n const { runtime } = connection\n useEffect(() => runtime.start(), [runtime])\n return useSyncExternalStore(runtime.subscribe, runtime.getState, serverState)\n}\n\ntype Mapped<TMapped> = { record: TMapped | null; records: TMapped[] | null; issues: readonly GristCellIssue[] }\n\nconst NO_ISSUES: readonly GristCellIssue[] = Object.freeze([])\n\n/** The mapped, checked record and records; recomputed only when they, the mappings or the options change. */\nfunction useMapped<TMapped>(state: GristRuntimeState, options: GristRuntimeOptions): Mapped<TMapped> {\n const { record, records, mappings } = state\n const { columns, schema } = options\n return useMemo(() => {\n const issues: GristCellIssue[] = []\n const rows =\n records && (columns?.length ? mappings !== null : true)\n ? records.map((r) => {\n const out = mapAndCheck<TMapped>(r, columns, mappings, schema)\n issues.push(...out.issues)\n return out.value\n })\n : null\n const selected = mapAndCheck<TMapped>(record, columns, mappings, schema)\n if (record && !records?.some((r) => r.id === record.id)) issues.push(...selected.issues)\n const mappedRecords = rows && rows.every((r) => r !== null) ? (rows as TMapped[]) : null\n return { record: selected.value, records: mappedRecords, issues: issues.length ? issues : NO_ISSUES }\n }, [record, records, mappings, columns, schema])\n}\n\ntype RecordWrites = Pick<UseGristResult, \"updateRecord\" | \"addRecord\">\n\n/** `updateRecord` / `addRecord`: stable, reading the mappings and the selection when called. */\nfunction recordWrites(connection: GristContextValue): RecordWrites {\n const { runtime, api } = connection\n const fieldsOf = (patch: Record<string, unknown>) => {\n const { id: _id, ...rest } = patch\n return mapBackPatch(rest, runtime.getState().mappings ?? EMPTY_MAPPINGS, runtime.options.columns).fields\n }\n const updateRecord = ((a: number | Record<string, unknown>, b?: Record<string, unknown>) => {\n const rowId = typeof a === \"number\" ? a : runtime.getState().record?.id\n const patch = typeof a === \"number\" ? (b ?? {}) : a\n if (typeof rowId !== \"number\") {\n return Promise.reject(new Error(\"updateRecord(): no row is selected. Pass the row id: updateRecord(rowId, patch).\"))\n }\n return api.table.update({ id: rowId, fields: fieldsOf(patch) })\n }) as RecordWrites[\"updateRecord\"]\n const addRecord = async (patch: Record<string, unknown>) => {\n const created = await api.table.create({ fields: fieldsOf(patch) })\n return (Array.isArray(created) ? created[0]! : created).id\n }\n return { updateRecord, addRecord }\n}\n\nfunction buildResult<TRow, TMapped>(\n state: GristRuntimeState,\n mapped: Mapped<TMapped>,\n connection: GristContextValue,\n mapBack: (patch: Partial<TMapped>) => Record<string, unknown>,\n resolveMappedColumnId: (name: string) => string,\n writes: RecordWrites\n): UseGristResult<TRow, TMapped> {\n const { runtime, api } = connection\n const status = deriveStatus(state)\n const columns = runtime.options.columns\n return {\n ...api,\n status,\n isAvailable: state.connection === \"connecting\" ? null : state.connection !== \"not-embedded\" && state.connection !== \"unavailable\",\n isReady: status === \"ready\",\n error: deriveError(state),\n theme: state.theme,\n record: state.record as GristRowRecord<TRow> | null,\n records: state.records as GristRowRecord<TRow>[] | null,\n mappedRecord: mapped.record,\n mappedRecords: mapped.records,\n cellIssues: mapped.issues,\n mappings: state.mappings ?? EMPTY_MAPPINGS,\n columnMappingStatus: deriveColumnMappingStatus(columns, state.mappings),\n mode: state.isNewRecord ? \"new-row\" : state.record ? \"row\" : \"empty\",\n resolveMappedColumnId,\n mapBack,\n updateRecord: writes.updateRecord as UseGristResult<TRow, TMapped>[\"updateRecord\"],\n addRecord: writes.addRecord as UseGristResult<TRow, TMapped>[\"addRecord\"],\n currentTableId: state.currentTableId,\n actionStatus: state.actionStatus,\n actionError: state.actionError,\n widgetOptions: state.widgetOptions,\n }\n}\n\nconst EMPTY_MAPPINGS: GristWidgetColumnMap = Object.freeze({}) as GristWidgetColumnMap\n\nfunction useGristResult<TRow, TMapped>(connection: GristContextValue): UseGristResult<TRow, TMapped> {\n const state = useGristState(connection)\n const mappings = state.mappings ?? EMPTY_MAPPINGS\n const { runtime } = connection\n const resolveMappedColumnId = useCallback(\n (name: string) => {\n const real = mappings[name]\n if (typeof real === \"string\" && real) return real\n if (Array.isArray(real) && typeof real[0] === \"string\") return real[0]\n return name\n },\n [mappings]\n )\n const mapBack = useCallback(\n (patch: Partial<TMapped>) => {\n const { fields, skipped } = mapBackPatch(patch as Record<string, unknown>, mappings, runtime.options.columns)\n const previous = runtime.getState().mapBackSkipped\n if (previous.join(\"\\0\") !== skipped.join(\"\\0\")) runtime.update({ mapBackSkipped: skipped })\n return fields\n },\n [mappings, runtime]\n )\n const mapped = useMapped<TMapped>(state, runtime.options)\n const writes = useMemo(() => recordWrites(connection), [connection])\n return useMemo(\n () => buildResult<TRow, TMapped>(state, mapped, connection, mapBack, resolveMappedColumnId, writes),\n [state, mapped, connection, mapBack, resolveMappedColumnId, writes]\n )\n}\n\n/**\n * The widget's Grist state and API. Inside `<GristWidgetProvider>` it uses the\n * provider's connection and ignores `options`; outside one, the page's, made\n * with the first caller's `options`.\n */\nexport function useGrist<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>(\n options?: UseGristOptions\n): UseGristResult<TRow, TMapped> {\n const fromProvider = useContext(GristContext)\n const connection = fromProvider ?? (pageConnection ??= newConnection(options))\n return useGristResult<TRow, TMapped>(connection)\n}\n\n/** `useGrist()` inside a provider, or null outside one: for components that also work without Grist. */\nexport function useGristOptional<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>(): UseGristResult<\n TRow,\n TMapped\n> | null {\n const fromProvider = useContext(GristContext)\n // The hooks below run in both branches; the provider only decides which connection they read.\n const result = useGristResult<TRow, TMapped>(fromProvider ?? DETACHED)\n return fromProvider ? result : null\n}\n\n/** `useGrist()` inside `<GristWidgetProvider>`; throws outside one. */\nexport function useGristContext<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>(): UseGristResult<\n TRow,\n TMapped\n> {\n if (!useContext(GristContext)) {\n throw new Error(\"useGristContext() must be used inside <GristWidgetProvider> (mountGristWidget renders one).\")\n }\n return useGrist<TRow, TMapped>()\n}\n\n/** A connection that never starts: what useGristOptional reads outside a provider. */\nconst DETACHED: GristContextValue = (() => {\n const state = initialRuntimeState()\n const runtime: GristRuntime = {\n options: {},\n getState: () => state,\n subscribe: () => () => {},\n start: () => () => {},\n reload: async () => {},\n update: () => {},\n }\n return { runtime, api: createGristApi(runtime) }\n})()\n\n/** @internal The nearest provider's connection and its state (idle outside one). */\nexport function useNearestGristState(): {\n connection: GristContextValue | null\n state: GristRuntimeState\n cellIssues: readonly GristCellIssue[]\n} {\n const connection = useContext(GristContext)\n const state = useGristState(connection ?? DETACHED)\n const { issues } = useMapped(state, (connection ?? DETACHED).runtime.options)\n return { connection, state, cellIssues: issues }\n}\n","/**\n * Encoding helpers for Grist cell values.\n *\n * Grist sends some types as marshalled tuples or numeric epochs. This file\n * exposes pure decode/encode functions so widget code never has to spelunk\n * Grist's wire format.\n *\n * References: Grist `grist/RowRecord` and `grist/DocActions` typings.\n */\n\nimport type { GristReplicaColumn } from \"../types\"\n\n/** `[\"E\", \"ErrorClass\", \"message\", traceback?]` — Grist error sentinel. */\nexport type GristEncodedError = [\"E\", string, string?, string?]\n/** `[\"L\", ...items]` — list (used for ChoiceList, RefList, Attachments). */\nexport type GristEncodedList = [\"L\", ...unknown[]]\n/** `[\"D\", epochSeconds, \"tz/Name\"]` — DateTime with timezone. */\nexport type GristEncodedDateTime = [\"D\", number, string]\n/** `[\"d\", epochSeconds]` — Date (no time). */\nexport type GristEncodedDate = [\"d\", number]\n/** `[\"R\", tableId, rowId]` — explicit reference. */\nexport type GristEncodedRef = [\"R\", string, number]\n/** `[\"r\", rowId]` — bare reference (when table is contextual). */\nexport type GristEncodedBareRef = [\"r\", number]\n/** `[\"P\", encoded]` — pending marker. */\nexport type GristEncodedPending = [\"P\"]\n\nexport type GristDecodedValue =\n | null\n | string\n | number\n | boolean\n | Date\n | GristDecodedValue[]\n | { __error: true; type: string; message?: string; traceback?: string }\n | { __ref: true; tableId?: string; rowId: number }\n\nconst MARSHALLED_TAGS = new Set([\"E\", \"L\", \"D\", \"d\", \"R\", \"r\", \"P\"])\n\nfunction isMarshalledTuple(value: unknown): value is unknown[] {\n return (\n Array.isArray(value) &&\n typeof value[0] === \"string\" &&\n value[0].length <= 2 &&\n MARSHALLED_TAGS.has(value[0])\n )\n}\n\n/**\n * Normalises a Grist `fetchTable` cell that points at a row in another table.\n * Most payloads use a bare numeric row id, but `Ref:*` values may appear as\n * `[\"R\", tableId, rowId]` or `[\"r\", rowId]` (same shape as {@link decodeGristValue}).\n */\nexport function coerceGristDocApiRefRowId(value: unknown): number | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) return value\n if (!Array.isArray(value) || value.length < 2) return undefined\n const tag = value[0]\n if (tag === \"R\" && typeof value[2] === \"number\" && Number.isFinite(value[2])) return value[2]\n if (tag === \"r\" && typeof value[1] === \"number\" && Number.isFinite(value[1])) return value[1]\n return undefined\n}\n\nfunction looksLikeAttachmentColumn(column?: GristReplicaColumn): boolean {\n return column?.type === \"Attachments\"\n}\n\nfunction looksLikeChoiceListColumn(column?: GristReplicaColumn): boolean {\n return column?.type === \"ChoiceList\"\n}\n\nfunction looksLikeRefListColumn(column?: GristReplicaColumn): boolean {\n return typeof column?.type === \"string\" && column.type.startsWith(\"RefList:\")\n}\n\nfunction looksLikeRefColumn(column?: GristReplicaColumn): boolean {\n return typeof column?.type === \"string\" && column.type.startsWith(\"Ref:\")\n}\n\nfunction looksLikeDateColumn(column?: GristReplicaColumn): boolean {\n return column?.type === \"Date\"\n}\n\nfunction looksLikeDateTimeColumn(column?: GristReplicaColumn): boolean {\n return typeof column?.type === \"string\" && column.type.startsWith(\"DateTime\")\n}\n\n/**\n * Decodes a Grist cell value into an idiomatic JS value.\n *\n * Pass the column's metadata (from `useGristSchema` or `_grist_Tables_column`)\n * for type-aware decoding (e.g. `Date` columns return `Date` even when stored as a number).\n */\nexport function decodeGristValue(value: unknown, column?: GristReplicaColumn): GristDecodedValue {\n if (value === null || value === undefined) return null\n\n if (isMarshalledTuple(value)) {\n const tag = value[0] as string\n switch (tag) {\n case \"E\":\n return {\n __error: true,\n type: typeof value[1] === \"string\" ? value[1] : \"Error\",\n message: typeof value[2] === \"string\" ? value[2] : undefined,\n traceback: typeof value[3] === \"string\" ? value[3] : undefined,\n }\n case \"L\":\n return value.slice(1).map((v) => decodeGristValue(v, undefined)) as GristDecodedValue[]\n case \"D\":\n if (typeof value[1] === \"number\") return new Date(value[1] * 1000)\n return null\n case \"d\":\n if (typeof value[1] === \"number\") return new Date(value[1] * 1000)\n return null\n case \"R\":\n return {\n __ref: true,\n tableId: typeof value[1] === \"string\" ? value[1] : undefined,\n rowId: typeof value[2] === \"number\" ? value[2] : 0,\n }\n case \"r\":\n return { __ref: true, rowId: typeof value[1] === \"number\" ? value[1] : 0 }\n case \"P\":\n return null\n default:\n return null\n }\n }\n\n if (looksLikeDateColumn(column) || looksLikeDateTimeColumn(column)) {\n if (typeof value === \"number\" && Number.isFinite(value)) return new Date(value * 1000)\n }\n\n if (looksLikeRefColumn(column) && typeof value === \"number\") {\n return { __ref: true, rowId: value }\n }\n\n if ((looksLikeRefListColumn(column) || looksLikeChoiceListColumn(column) || looksLikeAttachmentColumn(column)) && Array.isArray(value)) {\n return value.map((v) => decodeGristValue(v, undefined)) as GristDecodedValue[]\n }\n\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") return value\n if (Array.isArray(value)) return value.map((v) => decodeGristValue(v, undefined)) as GristDecodedValue[]\n return null\n}\n\n/** Convenience: true when the cell is a Grist error sentinel. */\nexport function isGristCellError(value: unknown): value is GristEncodedError {\n return Array.isArray(value) && value[0] === \"E\"\n}\n\n/**\n * Encodes a JS value into Grist's expected wire form for a given column type.\n *\n * Use before passing values to `applyUserActions` or `TableOperations.update`\n * for `Date`, `DateTime`, `Ref`, `RefList`, and `ChoiceList` columns.\n */\nexport function encodeGristValue(value: unknown, column?: GristReplicaColumn): unknown {\n if (value === null || value === undefined) return null\n\n if (looksLikeDateColumn(column) || looksLikeDateTimeColumn(column)) {\n if (value instanceof Date) return Math.floor(value.getTime() / 1000)\n if (typeof value === \"string\") {\n const parsed = Date.parse(value)\n if (!Number.isNaN(parsed)) return Math.floor(parsed / 1000)\n }\n if (typeof value === \"number\") return Math.floor(value)\n }\n\n if (looksLikeRefColumn(column)) {\n if (typeof value === \"number\") return value\n if (value && typeof value === \"object\" && \"rowId\" in value) {\n return (value as { rowId: number }).rowId\n }\n }\n\n if (looksLikeRefListColumn(column) || looksLikeChoiceListColumn(column) || looksLikeAttachmentColumn(column)) {\n if (Array.isArray(value)) {\n const items = value.map((v) => {\n if (v && typeof v === \"object\" && \"rowId\" in v) return (v as { rowId: number }).rowId\n return v\n })\n return [\"L\", ...items]\n }\n }\n\n return value\n}\n","import type { GristDocApi, GristReplicaColumn, GristRowRecord } from \"../types\"\nimport { decodeGristValue } from \"./grist-value-codec\"\n\n/** Column-oriented table payload (`fetchTable`, `fetchSelectedTable`): `{ id: [...], Name: [...] }`. */\nexport type GristColumnarTable = Record<string, unknown[]>\nexport type GristTableRowsOrder = \"none\" | \"id\" | \"grist\"\nexport type FetchGristTableRowsOptions = {\n /** Column metadata, to decode each cell (except `id`) with `decodeGristValue`. */\n columns?: Record<string, GristReplicaColumn>\n /**\n * Row order:\n * - `grist` (default): `manualSort` ascending when present, then `id`.\n * - `id`: numeric `id` ascending.\n * - `none`: as `fetchTable` returned them.\n */\n order?: GristTableRowsOrder\n}\n\n/** Row count from columnar `fetchTable` data (prefers `id` column length). */\nexport function computeRowCount(data: Record<string, unknown[]>): number {\n const idCol = data.id\n if (Array.isArray(idCol)) return idCol.length\n for (const key of Object.keys(data)) {\n const col = data[key]\n if (Array.isArray(col)) return col.length\n }\n return 0\n}\n\n/**\n * Decode columnar `fetchTable` into replica row objects (`{ id, ...cells }`, one per row).\n */\nexport function decodeColumnarToReplicaRows(\n data: GristColumnarTable,\n columnIds: string[],\n columns: Record<string, GristReplicaColumn>,\n maxRows?: number\n): GristRowRecord[] {\n const nFull = computeRowCount(data)\n const n = maxRows !== undefined ? Math.min(nFull, maxRows) : nFull\n const out: GristRowRecord[] = []\n for (let i = 0; i < n; i++) {\n const row: Record<string, unknown> = {}\n for (const k of columnIds) {\n const arr = data[k]\n const raw = Array.isArray(arr) ? arr[i] : undefined\n if (k === \"id\") {\n row[k] = raw\n } else {\n row[k] = decodeGristValue(raw, columns[k]) as unknown\n }\n }\n out.push(row as GristRowRecord)\n }\n return out\n}\n\n/** Turn `fetchTable` output into row objects (order follows the `id` column). */\nexport function tableDataToRows<T = Record<string, unknown>>(\n data: GristColumnarTable\n): GristRowRecord<T>[] {\n const idCol = data.id\n if (!Array.isArray(idCol) || idCol.length === 0) return []\n const keys = Object.keys(data)\n const n = idCol.length\n const rows: GristRowRecord<T>[] = []\n for (let i = 0; i < n; i++) {\n const row: Record<string, unknown> = {}\n for (const k of keys) {\n const col = data[k]\n row[k] = Array.isArray(col) ? col[i] : undefined\n }\n rows.push(row as GristRowRecord<T>)\n }\n return rows\n}\n\nfunction manualSortKey(row: Record<string, unknown>): number | null {\n const v = row.manualSort\n if (typeof v === \"number\" && !Number.isNaN(v)) return v\n if (typeof v === \"string\" && v.trim() !== \"\") {\n const n = Number(v)\n if (!Number.isNaN(n)) return n\n }\n return null\n}\n\n/**\n * Sort rows by Grist's display order: `manualSort` ascending when present on\n * any row, otherwise numeric `id` ascending.\n */\nexport function sortRowsByGristOrder<T = Record<string, unknown>>(\n rows: readonly GristRowRecord<T>[]\n): GristRowRecord<T>[] {\n const hasManual = rows.some((r) => manualSortKey(r as Record<string, unknown>) !== null)\n if (!hasManual) {\n return [...rows].sort((a, b) => {\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n })\n }\n return [...rows].sort((a, b) => {\n const ma = manualSortKey(a as Record<string, unknown>)\n const mb = manualSortKey(b as Record<string, unknown>)\n if (ma !== null && mb !== null && ma !== mb) return ma - mb\n if (ma !== null && mb === null) return -1\n if (ma === null && mb !== null) return 1\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n })\n}\n\n/**\n * Same row materialization as {@link fetchGristTableRows} after `fetchTable`\n * returns columnar data. Hosts that already have columnar data (e.g. the\n * emulator building from in-memory rows) can use this and skip `docApi.fetchTable`.\n */\nexport function materializeGristRowsFromColumnar<T extends Record<string, unknown> = Record<string, unknown>>(\n data: GristColumnarTable,\n options?: FetchGristTableRowsOptions\n): GristRowRecord<T>[] {\n const order = options?.order ?? \"grist\"\n let rows: GristRowRecord<T>[]\n if (options?.columns) {\n const columnIds = Object.keys(data)\n rows = decodeColumnarToReplicaRows(data, columnIds, options.columns) as GristRowRecord<T>[]\n } else {\n rows = tableDataToRows<T>(data)\n }\n\n if (order === \"none\") return rows\n if (order === \"id\") {\n return [...rows].sort((a, b) => {\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n })\n }\n return sortRowsByGristOrder(rows)\n}\n\n/**\n * Fetch a table and return rows as objects, optionally decoded from schema and sorted.\n */\nexport async function fetchGristTableRows<T extends Record<string, unknown> = Record<string, unknown>>(\n docApi: GristDocApi,\n tableId: string,\n options?: FetchGristTableRowsOptions\n): Promise<GristRowRecord<T>[]> {\n const data = (await docApi.fetchTable(tableId)) as GristColumnarTable\n return materializeGristRowsFromColumnar<T>(data, options)\n}\n","/**\n * Grist stores column widget configuration in `_grist_Tables_column.widgetOptions`\n * as a JSON string. Choice fields use `choices: string[]` plus optional\n * `choiceOptions: Record<string, Style>` (e.g. `fillColor`, `textColor`).\n *\n * @see https://github.com/gristlabs/grist-core/blob/main/app/client/widgets/ChoiceEditor.js\n */\n\n/** One selectable choice for UI (value stored in the cell is `value`). */\nexport type GristChoiceListEntry = {\n value: string\n label: string\n fillColor?: string\n textColor?: string\n}\n\n/**\n * Parse a cell value from `_grist_Tables_column.widgetOptions` into a plain object.\n */\nexport function parseGristWidgetOptionsCell(raw: unknown): Record<string, unknown> | undefined {\n if (raw == null || raw === \"\") return undefined\n if (typeof raw === \"string\") {\n try {\n const parsed: unknown = JSON.parse(raw)\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>\n }\n } catch {\n return undefined\n }\n return undefined\n }\n if (typeof raw === \"object\" && !Array.isArray(raw)) {\n return raw as Record<string, unknown>\n }\n return undefined\n}\n\nfunction readStyleColor(style: Record<string, unknown>, key: string): string | undefined {\n const v = style[key]\n return typeof v === \"string\" ? v : undefined\n}\n\n/**\n * Normalizes Grist Choice / ChoiceList widgetOptions into a flat list for dropdowns.\n * `choices` entries are string labels (the stored cell value). Per-choice styling\n * lives in `choiceOptions[label]`.\n */\nexport function normalizeGristChoiceListEntries(\n widgetOptions: Record<string, unknown> | undefined\n): GristChoiceListEntry[] {\n if (!widgetOptions) return []\n const rawChoices = widgetOptions.choices\n if (!Array.isArray(rawChoices)) return []\n\n const choiceOptionsRaw = widgetOptions.choiceOptions\n const choiceOptions: Record<string, Record<string, unknown>> =\n choiceOptionsRaw &&\n typeof choiceOptionsRaw === \"object\" &&\n !Array.isArray(choiceOptionsRaw)\n ? (choiceOptionsRaw as Record<string, Record<string, unknown>>)\n : {}\n\n const out: GristChoiceListEntry[] = []\n for (const c of rawChoices) {\n const value = typeof c === \"string\" ? c : c != null ? String(c) : \"\"\n if (!value) continue\n const style = choiceOptions[value] ?? {}\n out.push({\n value,\n label: value,\n fillColor: readStyleColor(style, \"fillColor\"),\n textColor: readStyleColor(style, \"textColor\"),\n })\n }\n return out\n}\n","import type {\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","export type GristColumnLike = {\n formula?: string\n}\n\nexport type GristNoiseColumnsOptions = {\n excludeId?: boolean\n excludeGristHelpers?: boolean\n excludeLoggingColumns?: boolean\n /**\n * When `true`, treat Grist's `manualSort` column as noise (omit from filtered replicas).\n * Default `false` — `manualSort` is kept unless you opt in.\n */\n excludeManualSort?: boolean\n}\n\nconst NOISE_COLUMN_FORMULAS = new Set([\"now()\"])\n\nfunction normalizeFormulaForComparison(formula: string): string {\n return formula.trim().toLowerCase().replace(/\\s+/g, \"\")\n}\n\n/**\n * Grist-centric \"technical column\" detection used by document hooks and widgets.\n *\n * - `id` (when {@link GristNoiseColumnsOptions.excludeId} is true — default)\n * - `manualSort` (only when {@link GristNoiseColumnsOptions.excludeManualSort} is true)\n * - `gristHelper_*` (when `excludeGristHelpers` is true — default)\n * - trigger/logging formulas (`NOW()`, `user.*`) (when `excludeLoggingColumns` is true — default)\n */\nexport function isGristNoiseColumn(\n colId: string,\n col?: GristColumnLike,\n options?: GristNoiseColumnsOptions\n): boolean {\n const excludeId = options?.excludeId ?? true\n const excludeGristHelpers = options?.excludeGristHelpers ?? true\n const excludeLoggingColumns = options?.excludeLoggingColumns ?? true\n const excludeManualSort = options?.excludeManualSort ?? false\n\n if (excludeId && colId === \"id\") return true\n if (excludeManualSort && colId === \"manualSort\") return true\n if (excludeGristHelpers && colId.startsWith(\"gristHelper_\")) return true\n\n if (excludeLoggingColumns) {\n const formula = typeof col?.formula === \"string\" ? normalizeFormulaForComparison(col.formula) : \"\"\n if (formula && NOISE_COLUMN_FORMULAS.has(formula)) return true\n if (formula.startsWith(\"user.\")) return true\n }\n\n return false\n}\n","import type { GristDocApi } from \"../types\"\n\nexport type GristFetchedAttachment = {\n base64: string\n contentType: string\n}\n\nexport type GristFetchedAttachmentBlob = {\n blob: Blob\n contentType: string\n}\n\nfunction attachmentIdFromObjectRecord(record: Record<string, unknown>): string | undefined {\n for (const candidate of [record.id, record.attachmentId, record.fileId]) {\n if (candidate === undefined || candidate === null) continue\n return String(candidate)\n }\n return undefined\n}\n\n/**\n * All attachment ids found in a Grist attachment cell value (ordered, deduped).\n * Attachment columns are usually an **array** of file refs; a single id or one JSON object is also supported.\n */\nexport function extractGristAttachmentIdsFromCell(value: unknown): string[] {\n const out: string[] = []\n const seen = new Set<string>()\n const push = (id: string) => {\n if (seen.has(id)) return\n seen.add(id)\n out.push(id)\n }\n\n const walk = (v: unknown): void => {\n if (v === undefined || v === null) return\n if (typeof v === \"number\") {\n push(String(v))\n return\n }\n if (typeof v === \"string\") {\n const trimmed = v.trim()\n if (!trimmed) return\n if (/^\\d+$/.test(trimmed)) {\n push(trimmed)\n return\n }\n try {\n walk(JSON.parse(trimmed) as unknown)\n } catch {\n /* ignore */\n }\n return\n }\n if (Array.isArray(v)) {\n for (const item of v) walk(item)\n return\n }\n if (typeof v === \"object\") {\n const record = v as Record<string, unknown>\n const direct = attachmentIdFromObjectRecord(record)\n if (direct !== undefined) {\n push(direct)\n return\n }\n for (const nested of Object.values(record)) walk(nested)\n }\n }\n\n walk(value)\n return out\n}\n\n/** First attachment id in the cell, if any (see {@link extractGristAttachmentIdsFromCell}). */\nexport function extractGristAttachmentId(value: unknown): string | undefined {\n return extractGristAttachmentIdsFromCell(value)[0]\n}\n\n/**\n * Signed Grist download URL for a single attachment id (`getAccessToken` + query auth).\n */\nexport async function getAttachmentDownloadUrl(\n docApi: GristDocApi,\n attachmentId: string,\n options?: { readOnly?: boolean }\n): Promise<string> {\n const getAccessToken = docApi.getAccessToken\n if (!getAccessToken) {\n throw new Error(\"getAccessToken is not available on docApi\")\n }\n const { token, baseUrl } = await getAccessToken({ readOnly: options?.readOnly ?? false })\n return `${baseUrl}/attachments/${attachmentId}/download?auth=${token}`\n}\n\n/** URL for the `index`’th attachment in a cell value (0-based). */\nexport async function getAttachmentDownloadUrlForCell(\n docApi: GristDocApi,\n cellValue: unknown,\n index: number,\n options?: { readOnly?: boolean }\n): Promise<string | null> {\n const ids = extractGristAttachmentIdsFromCell(cellValue)\n const id = ids[index]\n if (!id) return null\n return getAttachmentDownloadUrl(docApi, id, options)\n}\n\nasync function fetchBytesFromSignedAttachmentUrl(url: string): Promise<{\n buffer: ArrayBuffer\n contentType: string\n}> {\n const response = await fetch(url)\n const contentType = response.headers.get(\"content-type\")?.trim() || \"application/octet-stream\"\n if (!response.ok) {\n throw new Error(`Attachment download failed (${response.status})`)\n }\n const buffer = await response.arrayBuffer()\n return { buffer, contentType }\n}\n\nfunction bufferToBase64(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer)\n let binary = \"\"\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i])\n return btoa(binary)\n}\n\n/** Token + URL + fetch for one attachment id. */\nexport async function fetchAttachmentBase64(\n docApi: GristDocApi,\n attachmentId: string,\n options?: { readOnly?: boolean }\n): Promise<GristFetchedAttachment> {\n const url = await getAttachmentDownloadUrl(docApi, attachmentId, options)\n const { buffer, contentType } = await fetchBytesFromSignedAttachmentUrl(url)\n return { base64: bufferToBase64(buffer), contentType }\n}\n\n/** Download attachment bytes as a `Blob` (preferred for large files). */\nexport async function fetchAttachmentBlob(\n docApi: GristDocApi,\n attachmentId: string,\n options?: { readOnly?: boolean }\n): Promise<GristFetchedAttachmentBlob> {\n const url = await getAttachmentDownloadUrl(docApi, attachmentId, options)\n const { buffer, contentType } = await fetchBytesFromSignedAttachmentUrl(url)\n return { blob: new Blob([buffer], { type: contentType }), contentType }\n}\n\n/** Download the `index`’th attachment in a cell (0-based). */\nexport async function fetchAttachmentBase64ForCell(\n docApi: GristDocApi,\n cellValue: unknown,\n index: number,\n options?: { readOnly?: boolean }\n): Promise<GristFetchedAttachment | null> {\n const url = await getAttachmentDownloadUrlForCell(docApi, cellValue, index, options)\n if (!url) return null\n const { buffer, contentType } = await fetchBytesFromSignedAttachmentUrl(url)\n return { base64: bufferToBase64(buffer), contentType }\n}\n","import type { GristDocApi } from \"../types\"\n\nexport type GristAccessToken = {\n token: string\n baseUrl: string\n}\n\ntype TokenCacheEntry = {\n token: GristAccessToken\n fetchedAt: number\n}\n\nconst TOKEN_TTL_MS = 45_000\nconst cache = new Map<string, TokenCacheEntry>()\nconst inFlight = new Map<string, Promise<GristAccessToken>>()\n\nfunction cacheKey(readOnly: boolean): string {\n return readOnly ? \"ro\" : \"rw\"\n}\n\n/**\n * Returns an access token suitable for calling Grist's REST API directly.\n * Tokens are short-lived; results are cached briefly and coalesced per readOnly flag.\n */\nexport async function getGristAccessToken(\n docApi: GristDocApi,\n options?: { readOnly?: boolean }\n): Promise<GristAccessToken> {\n if (!docApi.getAccessToken) {\n throw new Error(\"getAccessToken is not available on docApi (need higher access level)\")\n }\n\n const readOnly = options?.readOnly ?? false\n const key = cacheKey(readOnly)\n const now = Date.now()\n const hit = cache.get(key)\n if (hit && now - hit.fetchedAt < TOKEN_TTL_MS) {\n return hit.token\n }\n\n const pending = inFlight.get(key)\n if (pending) return pending\n\n const next = docApi.getAccessToken({ readOnly }).then((token) => {\n cache.set(key, { token, fetchedAt: Date.now() })\n inFlight.delete(key)\n return token\n })\n\n inFlight.set(key, next)\n return next\n}\n\n/** Clear cached tokens (tests or after auth errors). */\nexport function clearGristAccessTokenCache(): void {\n cache.clear()\n inFlight.clear()\n}\n\n/**\n * `fetch()` against Grist's REST API with the doc access token attached.\n */\nexport async function fetchWithGristAuth(\n docApi: GristDocApi,\n path: string,\n init?: RequestInit & { readOnly?: boolean }\n): Promise<Response> {\n const readOnly = init?.readOnly ?? false\n let token: GristAccessToken\n try {\n token = await getGristAccessToken(docApi, { readOnly })\n } catch (err) {\n clearGristAccessTokenCache()\n throw err\n }\n\n const isAbsolute = /^https?:\\/\\//i.test(path)\n const cleanPath = isAbsolute ? path : path.startsWith(\"/\") ? path : `/${path}`\n\n const url = isAbsolute\n ? new URL(path)\n : new URL(`${token.baseUrl.replace(/\\/$/, \"\")}${cleanPath}`)\n\n // The token goes into the URL, so it may only go to the Grist instance that\n // issued it. An absolute URL to any other origin (one read from a cell, say)\n // would hand the document's access token to that host.\n const gristOrigin = new URL(token.baseUrl).origin\n if (url.origin !== gristOrigin) {\n throw new Error(\n `fetchWithGristAuth: refusing to send the Grist access token to ${url.origin}; ` +\n `absolute URLs must point at this document's Grist instance (${gristOrigin}). ` +\n `Use plain fetch() for other hosts.`\n )\n }\n\n // Grist signs widget REST calls with a short-lived `auth` query parameter.\n // Do not send `Authorization: Bearer` from the browser: many Grist deployments\n // omit it from Access-Control-Allow-Headers, which breaks POST (e.g. attachment upload).\n if (!url.searchParams.has(\"auth\")) url.searchParams.set(\"auth\", token.token)\n\n const headers = new Headers(init?.headers ?? {})\n headers.delete(\"Authorization\")\n\n const response = await fetch(url.toString(), { ...init, headers })\n if (response.status === 401) {\n clearGristAccessTokenCache()\n const retryToken = await getGristAccessToken(docApi, { readOnly })\n url.searchParams.set(\"auth\", retryToken.token)\n return fetch(url.toString(), { ...init, headers })\n }\n return response\n}\n","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 { cause: err }\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","/**\n * `useGrist()`'s methods, created once per runtime: every one is\n * referentially stable for the widget's lifetime, and reads `grist` when\n * called (the emulator installs and removes it in tests).\n */\n\nimport { loadColumnMetadataByTable } from \"../helpers/build-replica-document\"\nimport { isGristNoiseColumn, type GristNoiseColumnsOptions } from \"../helpers/grist-columns-filters\"\nimport { fetchAttachmentBlob, getAttachmentDownloadUrl, type GristFetchedAttachmentBlob } from \"../helpers/grist-attachment-download\"\nimport { uploadGristAttachment, type GristAttachmentUploadResult } from \"../helpers/grist-attachment-upload\"\nimport { fetchWithGristAuth } from \"../helpers/grist-fetch-with-auth\"\nimport { fetchGristTableRows, type FetchGristTableRowsOptions, type GristColumnarTable } from \"../helpers/grist-table-data\"\nimport type { GristUserActionTuple } from \"../helpers/grist-user-actions\"\nimport type {\n GristApplyUserActionsOptions,\n GristCursorPos,\n GristDocApi,\n GristFetchSelectedOptions,\n GristRowRecord,\n GristTableOperations,\n} from \"../types\"\nimport type { GristRuntime } from \"./runtime\"\n\nexport type ListTablesOptions = {\n /** Include Grist's own tables (`_grist_*`, `GristHidden_*`). */\n includeSystem?: boolean\n}\n\nexport type ListColumnsOptions = GristNoiseColumnsOptions & {\n /** Include every column, Grist's helper and bookkeeping ones too. */\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 GristApi = {\n reload: () => Promise<void>\n fetchSelectedTable: (options?: GristFetchSelectedOptions) => Promise<GristColumnarTable>\n fetchTable: (tableId: string) => Promise<GristColumnarTable>\n fetchTableRows: <T extends Record<string, unknown> = Record<string, unknown>>(\n tableId: string,\n options?: FetchGristTableRowsOptions\n ) => Promise<GristRowRecord<T>[]>\n listTables: (options?: ListTablesOptions) => Promise<string[]>\n listColumns: (tableId: string, options?: ListColumnsOptions) => Promise<GristColumnInfo[]>\n table: GristTableOperations\n getTable: (tableId: string) => GristTableOperations\n applyActions: (actions: GristUserActionTuple[], options?: GristApplyUserActionsOptions) => Promise<unknown>\n setWidgetOptions: (options: Record<string, unknown>) => Promise<void>\n patchWidgetOptions: (patch: Record<string, unknown>) => Promise<void>\n setCursorPosition: (pos: GristCursorPos) => Promise<void>\n setLinkedRowSelection: (rowIds: number[] | null) => Promise<void>\n getAttachmentUrl: (attachmentId: string, options?: { readOnly?: boolean }) => Promise<string>\n fetchAttachmentBlob: (attachmentId: string, options?: { readOnly?: boolean }) => Promise<GristFetchedAttachmentBlob>\n uploadAttachment: (file: Blob | File, options?: { fileName?: string }) => Promise<GristAttachmentUploadResult>\n fetchWithAuth: (path: string, init?: RequestInit & { readOnly?: boolean }) => Promise<Response>\n}\n\nconst ACCESS_ERROR = [/access not granted/i, /need higher access level/i, /requires.*full.*access/i, /RPC_ONCALL_ERROR Access/i]\n\nexport function isAccessInsufficientError(message: string): boolean {\n return ACCESS_ERROR.some((re) => re.test(message))\n}\n\nconst message = (err: unknown) => (err instanceof Error ? err.message : String(err))\n\nexport function createGristApi(runtime: GristRuntime): GristApi {\n const docApi = (): GristDocApi => {\n if (runtime.getState().connection !== \"ready\" || typeof grist === \"undefined\" || !grist.docApi) {\n throw new Error(\"Grist is not ready: wait for useGrist().status === \\\"ready\\\".\")\n }\n return grist.docApi\n }\n\n /** A read: an access refusal is kept for the alerts, cleared by the next read that succeeds. */\n const read = async <T>(fn: () => Promise<T>): Promise<T> => {\n try {\n const out = await fn()\n if (runtime.getState().readError) runtime.update({ readError: null })\n return out\n } catch (err) {\n if (isAccessInsufficientError(message(err))) runtime.update({ readError: message(err) })\n throw err\n }\n }\n\n /**\n * A write: tracked in `actionStatus` / `actionError`. Overlapping writes\n * count as one run: `actionStatus` stays `\"running\"` until the last one\n * ends, then is `\"error\"` if any of them failed. A failure is shown in the\n * alerts and rejects the returned promise, which the SDK already handles:\n * a write nobody awaits (`onClick={() => w.table.update(...)}`) doesn't log\n * an unhandled rejection.\n */\n let running = 0\n let failure: string | null = null\n const write = <T>(fn: () => Promise<T>): Promise<T> => {\n if (running++ === 0) failure = null\n runtime.update({ actionStatus: \"running\", actionError: null })\n const done = (async () => {\n try {\n return await fn()\n } catch (err) {\n failure = message(err)\n throw err\n } finally {\n if (--running === 0) runtime.update(failure ? { actionStatus: \"error\", actionError: failure } : { actionStatus: \"idle\" })\n }\n })()\n done.catch(() => {})\n return done\n }\n\n const tableOps = (resolve: () => GristTableOperations): GristTableOperations => ({\n getTableId: () => resolve().getTableId(),\n create: ((records: never, opts?: never) => write(() => resolve().create(records, opts))) as GristTableOperations[\"create\"],\n update: (records, opts) => write(() => resolve().update(records, opts)),\n upsert: (records, opts) => write(() => resolve().upsert(records, opts)),\n destroy: (ids) => write(() => resolve().destroy(ids)),\n })\n const tables = new Map<string, GristTableOperations>()\n\n return {\n reload: () => runtime.reload(),\n\n fetchSelectedTable: (options) =>\n read(async () => {\n const impl = docApi().fetchSelectedTable ?? grist.fetchSelectedTable\n if (!impl) throw new Error(\"fetchSelectedTable is not available in this Grist version\")\n return (await impl({ keepEncoded: false, ...options })) as GristColumnarTable\n }),\n fetchTable: (tableId) => read(async () => (await docApi().fetchTable(tableId)) as GristColumnarTable),\n fetchTableRows: (tableId, options) => read(() => fetchGristTableRows(docApi(), tableId, options ?? {})) as never,\n listTables: (options) =>\n read(async () => {\n const all = [...(await docApi().listTables())]\n return options?.includeSystem ? all : all.filter((t) => !t.startsWith(\"_grist\") && !t.startsWith(\"GristHidden_\"))\n }),\n listColumns: (tableId, options) =>\n read(async () => {\n const meta = (await loadColumnMetadataByTable(docApi())).get(tableId)\n if (!meta) return []\n const noise: GristNoiseColumnsOptions = {\n excludeId: options?.excludeId ?? true,\n excludeGristHelpers: options?.excludeGristHelpers ?? true,\n excludeLoggingColumns: options?.excludeLoggingColumns ?? true,\n excludeManualSort: options?.excludeManualSort ?? true,\n }\n return [...meta]\n .filter(([colId, m]) => options?.includeSystem || !isGristNoiseColumn(colId, m, noise))\n .map(([colId, m]) => ({ colId, type: m.type, label: m.label, isFormula: m.isFormula, formula: m.formula, description: m.description }))\n }),\n\n table: tableOps(() => {\n if (!grist.selectedTable) throw new Error(\"grist.selectedTable is not available in this Grist version\")\n return grist.selectedTable\n }),\n getTable: (tableId) => {\n let ops = tables.get(tableId)\n if (!ops) {\n tables.set(\n tableId,\n (ops = tableOps(() => {\n if (typeof grist.getTable !== \"function\") throw new Error(\"grist.getTable is not available in this Grist version\")\n return grist.getTable(tableId)\n }))\n )\n }\n return ops\n },\n applyActions: (actions, options) => write(() => docApi().applyUserActions(actions, options)),\n\n setWidgetOptions: async (options) => {\n await grist.setOptions(options)\n },\n patchWidgetOptions: async (patch) => {\n const current = ((await grist.getOptions()) as Record<string, unknown> | null) ?? {}\n await grist.setOptions({ ...current, ...patch })\n },\n\n setCursorPosition: async (pos) => {\n if (!grist.setCursorPos) throw new Error(\"setCursorPos is not available in this Grist version\")\n await grist.setCursorPos(pos)\n },\n setLinkedRowSelection: async (rowIds) => {\n if (!grist.setSelectedRows) throw new Error(\"setSelectedRows is not available in this Grist version\")\n await grist.setSelectedRows(rowIds)\n },\n\n getAttachmentUrl: (id, options) => read(() => getAttachmentDownloadUrl(docApi(), id, options)),\n fetchAttachmentBlob: (id, options) => read(() => fetchAttachmentBlob(docApi(), id, options)),\n uploadAttachment: (file, options) => write(() => uploadGristAttachment(docApi(), file, options)),\n fetchWithAuth: (path, init) => read(() => fetchWithGristAuth(docApi(), path, init)),\n }\n}\n","import type { GristColumnsToMap, GristColumnToMap, GristWidgetColumnMap } from \"../types\"\n\nexport type ValidateColumnMappingsResult = {\n ok: boolean\n /**\n * `true` while the host has not yet reported column mappings (e.g. between\n * `grist.ready()` resolving and the first `onRecord` / `onRecords` callback,\n * or before `sectionApi.mappings()` returns). Callers should not gate UI or\n * emit mapping alerts while pending.\n */\n pending?: boolean\n /** Logical names of required columns the user has not yet mapped. */\n missing: string[]\n /** Logical names of `allowMultiple` columns mapped to an empty list. */\n emptyMultiples: string[]\n}\n\n/**\n * Merges mapping payloads from `onRecord`, `onRecords`, and `sectionApi.mappings()`.\n * Later sources win; `undefined` sources are skipped; `null` means \"host reported\n * no mappings\" but still counts as a known (empty) payload.\n */\nexport function mergeWidgetColumnMaps(\n ...sources: (GristWidgetColumnMap | null | undefined)[]\n): GristWidgetColumnMap | null | undefined {\n let merged: GristWidgetColumnMap = {}\n let sawDefined = false\n for (const src of sources) {\n if (src === undefined) continue\n sawDefined = true\n if (src === null) continue\n merged = { ...merged, ...src }\n }\n if (!sawDefined) return undefined\n return merged\n}\n\nfunction asColumnSpec(entry: string | GristColumnToMap): GristColumnToMap {\n return typeof entry === \"string\" ? { name: entry } : entry\n}\n\n/**\n * Verifies that the current Grist mappings cover every required column declared\n * in `grist.ready({ columns })`.\n *\n * Use this before reading `mappedRecord` so you can render a \"please configure\n * the widget\" prompt instead of a confusing `null`.\n */\nexport function validateColumnMappings(\n spec: GristColumnsToMap | undefined | null,\n mappings: GristWidgetColumnMap | null | undefined\n): ValidateColumnMappingsResult {\n const missing: string[] = []\n const emptyMultiples: string[] = []\n if (!spec) return { ok: true, pending: false, missing, emptyMultiples }\n\n const m = mappings ?? {}\n for (const raw of spec) {\n const col = asColumnSpec(raw)\n if (col.optional) continue\n const value = m[col.name]\n if (col.allowMultiple) {\n if (value === undefined) {\n missing.push(col.name)\n } else if (!Array.isArray(value) || value.length === 0) {\n emptyMultiples.push(col.name)\n }\n } else {\n if (value === undefined || value === null || value === \"\") missing.push(col.name)\n }\n }\n return {\n ok: missing.length === 0 && emptyMultiples.length === 0,\n pending: false,\n missing,\n emptyMultiples,\n }\n}\n\n/** Status while waiting for the host to report mappings (see `pending`). */\nexport const pendingColumnMappingStatus: ValidateColumnMappingsResult = {\n ok: true,\n pending: true,\n missing: [],\n emptyMultiples: [],\n}\n","/**\n * Typed reads, with read-only access: each mapped cell checked against the\n * type its column declares in `GRIST_OPTIONS.columns`.\n *\n * Grist's mapping panel only offers the columns of the declared type, so for\n * a mapped column the declaration is the contract; and the plugin API's\n * decoded values already say what they are (a `Date`, a `Reference` with a\n * `rowId`, a list of ids, a `RaisedException` for a formula error, the raw\n * text of an invalid cell). Checked in Grist 1.7.22, every type, both\n * `cellFormat`s. So a cell is turned into the JS value its type promises, or\n * into `null` with an issue: no schema to fetch, no full access, no\n * dependency.\n */\n\nimport type { GristColumnsToMap, GristWidgetColumnMap } from \"../types\"\n\n/** A mapped cell that didn't match its declared type, or a rule of the widget's schema. */\nexport type GristCellIssue = {\n rowId: number\n /** The declared column name, or \"\" for a schema rule on the whole record. */\n column: string\n message: string\n /** The value Grist sent. */\n value: unknown\n}\n\ntype Check = { ok: true; value: unknown } | { ok: false; message: string }\n\nconst ok = (value: unknown): Check => ({ ok: true, value })\nconst bad = (message: string): Check => ({ ok: false, message })\n\n/** A formula error, as the plugin API decodes it (`RaisedException`) or encodes it (`[\"E\", name, …]`). */\nfunction formulaError(value: unknown): string | null {\n if (Array.isArray(value) && value[0] === \"E\") return String(value[1] ?? \"error\")\n if (value && typeof value === \"object\" && (value as { constructor?: { name?: string } }).constructor?.name === \"RaisedException\") {\n return String((value as { name?: unknown }).name ?? \"error\")\n }\n return null\n}\n\nfunction rowIdOf(value: unknown): number | null | undefined {\n if (typeof value === \"number\" && Number.isInteger(value)) return value === 0 ? null : value\n if (value && typeof value === \"object\" && typeof (value as { rowId?: unknown }).rowId === \"number\") {\n const id = (value as { rowId: number }).rowId\n return id === 0 ? null : id\n }\n if (Array.isArray(value) && value[0] === \"R\" && typeof value[2] === \"number\") return value[2] === 0 ? null : value[2]\n return undefined\n}\n\nfunction idsOf(value: unknown): number[] | undefined {\n if (value === null || value === undefined) return []\n const list = Array.isArray(value)\n ? value[0] === \"L\"\n ? value.slice(1)\n : value\n : value && typeof value === \"object\" && Array.isArray((value as { rowIds?: unknown }).rowIds)\n ? (value as { rowIds: unknown[] }).rowIds\n : undefined\n return list?.every((v) => typeof v === \"number\") ? (list as number[]) : undefined\n}\n\nfunction checkOne(base: string, value: unknown): Check {\n switch (base) {\n case \"Any\":\n return ok(value)\n case \"Text\":\n return value === null || typeof value === \"string\" ? ok(value ?? \"\") : bad(\"not text\")\n case \"Numeric\":\n return value === null || (typeof value === \"number\" && Number.isFinite(value)) ? ok(value) : bad(\"not a number\")\n case \"Int\":\n return value === null || (typeof value === \"number\" && Number.isInteger(value)) ? ok(value) : bad(\"not an integer\")\n case \"Bool\":\n return value === null || typeof value === \"boolean\" ? ok(value ?? false) : bad(\"not true or false\")\n case \"Date\":\n case \"DateTime\":\n if (value === null) return ok(null)\n if (value instanceof Date && !Number.isNaN(value.getTime())) return ok(value)\n // Seconds since the epoch: Grist's \"normal\" format, and the emulator's raw rows.\n if (typeof value === \"number\" && Number.isFinite(value)) return ok(new Date(value * 1000))\n return bad(\"not a date\")\n case \"Choice\":\n return value === null || typeof value === \"string\" ? ok(value) : bad(\"not a choice\")\n case \"ChoiceList\": {\n if (value === null || value === undefined) return ok([])\n const list = Array.isArray(value) ? (value[0] === \"L\" ? value.slice(1) : value) : undefined\n return list?.every((v) => typeof v === \"string\") ? ok(list) : bad(\"not a list of choices\")\n }\n case \"Ref\": {\n if (value === null) return ok(null)\n const id = rowIdOf(value)\n return id === undefined ? bad(\"not a reference\") : ok(id)\n }\n case \"RefList\":\n case \"Attachments\": {\n const ids = idsOf(value)\n return ids === undefined ? bad(base === \"RefList\" ? \"not a list of references\" : \"not a list of attachments\") : ok(ids)\n }\n default:\n return ok(value)\n }\n}\n\n/**\n * `value` as its declared `type` promises (\"Numeric\", \"Ref:Tasks\",\n * \"Text,Ref\"…): a match of any listed type, or a failure that says why.\n * Without a type (or \"Any\"), the value as it is.\n */\n/** The base types a declared type accepts: `\"Text,Ref:People\"` → `[\"Text\", \"Ref\"]`. */\nfunction basesOf(type: string | undefined): string[] {\n return (type ?? \"Any\")\n .split(\",\")\n .map((t) => t.trim().split(\":\")[0]!)\n .filter(Boolean)\n}\n\nexport function checkGristCell(type: string | undefined, value: unknown): Check {\n const error = formulaError(value)\n if (error) return bad(`formula error (${error})`)\n const bases = basesOf(type)\n if (bases.length === 0 || bases.includes(\"Any\")) return ok(value === undefined ? null : value)\n let first: Check | null = null\n for (const base of bases) {\n const check = checkOne(base, value)\n if (check.ok) return check\n first ??= check\n }\n return first!\n}\n\nconst LIST_BASES = [\"ChoiceList\", \"RefList\", \"Attachments\"]\n\n/**\n * A value as Grist stores it in a column of the declared `type`: the\n * reverse of what typed reads give. Lists become `[\"L\", ...]` (a RefList's\n * `Reference` items become their row ids), a `Date` for a Date or DateTime\n * column becomes seconds since the epoch, a `Reference` for a Ref column its\n * row id. A list already encoded (`[\"L\", ...]`, as the attachment helpers\n * return it) and every other value pass through, so it is safe to call twice.\n *\n * Grist's plugin API writes values as given: a bare array written to a\n * ChoiceList or RefList column is stored as an error cell. Checked in\n * Grist 1.7.22.\n */\nexport function encodeGristCell(type: string | undefined, value: unknown): unknown {\n if (value === null || value === undefined) return value\n const bases = basesOf(type)\n const accepts = (...names: string[]) => names.some((n) => bases.includes(n))\n if (value instanceof Date) return accepts(\"Date\", \"DateTime\") ? Math.floor(value.getTime() / 1000) : value\n if (Array.isArray(value)) {\n if (!accepts(...LIST_BASES) || value[0] === \"L\") return value\n return [\"L\", ...value.map((item) => rowIdOf(item) ?? item)]\n }\n if (accepts(\"Ref\") && typeof value === \"object\") return rowIdOf(value) ?? value\n return value\n}\n\nexport const nameOf = (c: GristColumnsToMap[number]) => (typeof c === \"string\" ? c : c.name)\nexport const typeOf = (c: GristColumnsToMap[number]) => (typeof c === \"string\" ? undefined : c.type)\nconst isOptional = (c: GristColumnsToMap[number]) => typeof c === \"object\" && c.optional === true\n\n/** Minimal Standard Schema (https://standardschema.dev): zod 4, valibot, arktype implement it. */\nexport type StandardSchema<T = unknown> = {\n readonly \"~standard\": {\n readonly version: 1\n readonly vendor: string\n readonly validate: (\n value: unknown\n ) =>\n | { readonly value: T; readonly issues?: undefined }\n | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray<PropertyKey | { key: PropertyKey }> }> }\n | Promise<unknown>\n }\n}\n\n/**\n * A record under the widget's declared names, each cell checked against its\n * column's declared type, then the record against `schema` if given. Returns\n * null (no issues) while a required column isn't mapped, like Grist's\n * `mapColumnNames`; the record itself without declared columns.\n */\nexport function mapAndCheck<T>(\n record: Record<string, unknown> | null,\n columns: GristColumnsToMap | undefined,\n mappings: GristWidgetColumnMap | null,\n schema?: StandardSchema\n): { value: T | null; issues: GristCellIssue[] } {\n if (!record) return { value: null, issues: [] }\n if (!columns?.length) return { value: record as T, issues: [] }\n if (mappings === null) return { value: null, issues: [] }\n const rowId = typeof record.id === \"number\" ? record.id : 0\n const out: Record<string, unknown> = { id: record.id }\n const issues: GristCellIssue[] = []\n for (const col of columns) {\n const name = nameOf(col)\n const real = mappings[name]\n const take = (raw: unknown) => {\n const check = checkGristCell(typeOf(col), raw)\n if (check.ok) return check.value\n issues.push({ rowId, column: name, message: check.message, value: raw })\n return null\n }\n if (Array.isArray(real) && real.length > 0) out[name] = real.map((r) => take(record[r]))\n else if (typeof real === \"string\" && real) out[name] = take(record[real])\n else if (!isOptional(col)) return { value: null, issues: [] }\n }\n if (schema) {\n const result = schema[\"~standard\"].validate(out)\n if (result instanceof Promise) {\n issues.push({ rowId, column: \"\", message: \"the schema validates asynchronously; useGrist() needs a synchronous one\", value: out })\n } else if (\"issues\" in result && result.issues) {\n for (const issue of result.issues) {\n const key = issue.path?.[0]\n const column = key === undefined ? \"\" : String(typeof key === \"object\" ? key.key : key)\n issues.push({ rowId, column, message: issue.message, value: column ? out[column] : out })\n }\n } else if (\"value\" in result) {\n return { value: result.value as T, issues }\n }\n }\n return { value: out as T, issues }\n}\n\n// ---------------------------------------------------------------------------\n// Types from a declaration\n// ---------------------------------------------------------------------------\n\ntype BaseOf<T extends string> = T extends `${infer B}:${string}` ? B : T\n\ntype CellOf<T extends string> = T extends `${infer A},${infer Rest}`\n ? CellOf<A> | CellOf<Rest>\n : BaseOf<T> extends \"Text\"\n ? string\n : BaseOf<T> extends \"Numeric\" | \"Int\"\n ? number | null\n : BaseOf<T> extends \"Bool\"\n ? boolean\n : BaseOf<T> extends \"Date\" | \"DateTime\"\n ? Date | null\n : BaseOf<T> extends \"Choice\"\n ? string | null\n : BaseOf<T> extends \"ChoiceList\"\n ? string[]\n : BaseOf<T> extends \"Ref\"\n ? number | null\n : BaseOf<T> extends \"RefList\" | \"Attachments\"\n ? number[]\n : unknown\n\n// Every checked cell is `| null`: a cell that doesn't match its declared type\n// is null in mappedRecord (and listed in cellIssues), whatever the type.\ntype ColumnValue<C> = C extends { type: infer T extends string; allowMultiple: true }\n ? (CellOf<T> | null)[]\n : C extends { type: infer T extends string }\n ? CellOf<T> | null\n : C extends { allowMultiple: true }\n ? unknown[]\n : unknown\n\ntype RequiredName<C> = C extends { optional: true } ? never : C extends string ? C : C extends { name: infer N extends string } ? N : never\ntype OptionalName<C> = C extends { optional: true; name: infer N extends string } ? N : never\ntype ByName<Cs, N> = Extract<Cs, N | { name: N }>\n\n/**\n * The mapped record a `GRIST_OPTIONS` declaration gives, for `useGrist`'s\n * second type argument. Declare the options with `as const satisfies\n * UseGristOptions` so the column names and types stay literal:\n *\n * ```ts\n * export const GRIST_OPTIONS = {\n * requiredAccess: \"read table\",\n * columns: [{ name: \"Title\", type: \"Text\" }, { name: \"Due\", type: \"Date\", optional: true }],\n * } as const satisfies UseGristOptions\n *\n * const w = useGrist<GristRowRecord, GristMappedRow<typeof GRIST_OPTIONS>>()\n * w.mappedRecord?.Due // Date | null | undefined\n * ```\n */\nexport type GristMappedRow<O extends { columns?: readonly unknown[] }> = O[\"columns\"] extends readonly (infer C)[]\n ? { id: number } & { [N in RequiredName<C>]: ColumnValue<ByName<C, N>> } & { [N in OptionalName<C>]?: ColumnValue<ByName<C, N>> }\n : Record<string, unknown>\n","/**\n * What `useGrist()` shows, derived from the runtime state: status, error,\n * column-mapping status, the mapped record, and the access check. Pure\n * functions, so they are tested without React or Grist.\n */\n\nimport { validateColumnMappings, type ValidateColumnMappingsResult } from \"../helpers/grist-mappings\"\nimport type { GristColumnsToMap, GristRequiredAccess, GristWidgetColumnMap } from \"../types\"\nimport { encodeGristCell, nameOf, typeOf } from \"./cells\"\nimport type { GristRuntimeState } from \"./runtime\"\n\n/** The widget's connection to Grist, as `useGrist().status` reports it. */\nexport type GristWidgetStatus = \"booting\" | \"ready\" | \"unavailable\" | \"error\"\n\nexport const ACCESS_RANK: Record<GristRequiredAccess, number> = { none: 0, \"read table\": 1, full: 2 }\n\nexport function parseAccess(raw: unknown): GristRequiredAccess | null {\n return raw === \"none\" || raw === \"read table\" || raw === \"full\" ? raw : null\n}\n\nexport function accessLabel(level: GristRequiredAccess): string {\n return level === \"full\" ? \"Full document access\" : level === \"read table\" ? \"Read selected table\" : \"No document access\"\n}\n\n/** Grist granted less than the widget declared (Grist reports it with the widget options). */\nexport function accessDenied(state: GristRuntimeState): boolean {\n return state.grantedAccess !== null && ACCESS_RANK[state.grantedAccess] < ACCESS_RANK[state.declaredAccess]\n}\n\nexport function deriveStatus(state: GristRuntimeState): GristWidgetStatus {\n switch (state.connection) {\n case \"connecting\":\n return \"booting\"\n case \"not-embedded\":\n case \"unavailable\":\n return \"unavailable\"\n case \"error\":\n return \"error\"\n case \"ready\":\n return accessDenied(state) ? \"error\" : \"ready\"\n }\n}\n\nexport function deriveError(state: GristRuntimeState): string | null {\n if (state.connection === \"not-embedded\") return \"This page is not embedded in a Grist document.\"\n if (state.connection === \"unavailable\") return \"The Grist plugin API (grist-plugin-api.js) did not load.\"\n if (state.connection === \"error\") return state.connectionError\n if (state.connection === \"ready\" && accessDenied(state)) {\n return `Grist granted \"${accessLabel(state.grantedAccess!)}\"; this widget needs \"${accessLabel(state.declaredAccess)}\". Set the access level in the Custom widget settings.`\n }\n return null\n}\n\nconst MAPPINGS_OK: ValidateColumnMappingsResult = Object.freeze({ ok: true, pending: false, missing: [], emptyMultiples: [] }) as ValidateColumnMappingsResult\nconst MAPPINGS_PENDING: ValidateColumnMappingsResult = Object.freeze({ ok: true, pending: true, missing: [], emptyMultiples: [] }) as ValidateColumnMappingsResult\n\n/** Whether the declared columns are mapped: pending until Grist reports mappings. */\nexport function deriveColumnMappingStatus(\n columns: GristColumnsToMap | undefined,\n mappings: GristWidgetColumnMap | null\n): ValidateColumnMappingsResult {\n if (!columns?.length) return MAPPINGS_OK\n if (mappings === null) return MAPPINGS_PENDING\n return validateColumnMappings(columns, mappings)\n}\n\n/**\n * A logical-name patch as real column ids, for a write, each value encoded\n * for its declared type (`encodeGristCell`: lists, dates, references), so\n * what `mappedRecord` gave can be written back as is. A column mapped to\n * several Grist columns (`allowMultiple`) can't be written back and is\n * reported in `skipped`; a name with no mapping passes through unchanged.\n */\nexport function mapBackPatch(\n patch: Record<string, unknown>,\n mappings: GristWidgetColumnMap,\n columns?: GristColumnsToMap\n): { fields: Record<string, unknown>; skipped: string[] } {\n const fields: Record<string, unknown> = {}\n const skipped: string[] = []\n for (const [name, value] of Object.entries(patch)) {\n if (value === undefined) continue\n const real = mappings[name]\n if (Array.isArray(real)) {\n skipped.push(name)\n continue\n }\n const declared = columns?.find((c) => nameOf(c) === name)\n fields[typeof real === \"string\" && real ? real : name] = declared ? encodeGristCell(typeOf(declared), value) : value\n }\n return { fields, skipped }\n}\n","import type { GristWidgetInteraction, GristWidgetLinkingInfo } from \"../types\"\n\n/**\n * Parse `InteractionOptions.linking` from a Grist `onOptions` settings payload.\n */\nexport function parseGristWidgetLinkingInfo(raw: unknown): GristWidgetLinkingInfo | undefined {\n if (!raw || typeof raw !== \"object\" || !(\"asTarget\" in raw)) return undefined\n const linking = raw as { asTarget: unknown; asSource?: unknown }\n return {\n asTarget: linking.asTarget == null ? null : String(linking.asTarget),\n asSource: Boolean(linking.asSource),\n }\n}\n\n/**\n * Normalize the second argument to `grist.onOptions` (Grist `InteractionOptions`).\n * Hosts use `accessLevel` (camelCase); the emulator uses `access_level`.\n */\nexport function normalizeWidgetInteraction(\n interaction: GristWidgetInteraction | null\n): GristWidgetInteraction | null {\n if (!interaction || typeof interaction !== \"object\") return interaction\n const raw = interaction as Record<string, unknown>\n const access_level =\n typeof raw.access_level === \"string\"\n ? raw.access_level\n : typeof raw.accessLevel === \"string\"\n ? raw.accessLevel\n : undefined\n const linking = parseGristWidgetLinkingInfo(raw.linking)\n return {\n ...interaction,\n ...(access_level ? { access_level } : {}),\n ...(linking ? { linking } : {}),\n }\n}\n","/**\n * Grist's event streams, bound once per page.\n *\n * `grist.onRecord`, `onRecords`, `onOptions`, `onNewRecord` and `on(\"message\")`\n * are add-only: there is no `off`. Binding them in every provider (React's\n * StrictMode mounts twice; a widget may remount) would stack handlers for the\n * page's lifetime. Each stream here binds at its first subscriber and fans out\n * to the current ones; a late subscriber gets the last value at once.\n *\n * Records are bound with the plugin API's decoded rows (`keepEncoded: false`,\n * rows for `onRecords`), the shape widget code reads.\n */\n\nimport { normalizeWidgetInteraction } from \"../helpers/grist-widget-interaction\"\nimport type { GristWidgetColumnMap, GristWidgetInteraction } from \"../types\"\n\ntype Listener<T> = (value: T) => void\n\nexport class HostStream<T> {\n private listeners = new Set<Listener<T>>()\n private bound = false\n private has = false\n private last: T | undefined\n\n constructor(private readonly bind: (emit: (value: T) => void) => void) {}\n\n subscribe(listener: Listener<T>): () => void {\n this.listeners.add(listener)\n if (!this.bound) {\n this.bound = true\n try {\n this.bind((value) => this.emit(value))\n } catch (err) {\n console.error(\"[grist-widget-sdk] could not subscribe to a Grist event:\", err)\n }\n }\n if (this.has) listener(this.last as T)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n peek(): T | undefined {\n return this.last\n }\n\n /** Tests: deliver a value as if Grist had sent it. */\n emit(value: T): void {\n this.has = true\n this.last = value\n for (const l of [...this.listeners]) l(value)\n }\n\n /** Tests: forget the binding, so a new `window.grist` binds afresh. */\n reset(): void {\n this.listeners.clear()\n this.bound = false\n this.has = false\n this.last = undefined\n }\n}\n\nexport type RecordPayload = { record: Record<string, unknown> | null; mappings: GristWidgetColumnMap | null }\nexport type RecordsPayload = { records: Record<string, unknown>[]; mappings: GristWidgetColumnMap | null }\nexport type OptionsPayload = { options: Record<string, unknown> | null; interaction: GristWidgetInteraction | null }\nexport type NewRecordPayload = { mappings: GristWidgetColumnMap | null }\n\nconst asMappings = (m: unknown) => (m && typeof m === \"object\" ? (m as GristWidgetColumnMap) : null)\n\nexport const recordStream = new HostStream<RecordPayload>((emit) => {\n grist.onRecord((record, mappings) => emit({ record, mappings: asMappings(mappings) }), { keepEncoded: false })\n\n // Grist's RecordNotifier posts `{ tableId, rowId }` on a cursor move. The\n // plugin API's onRecord handles it, but refetching here when the row\n // changes keeps a widget from sticking on its first row if that path is\n // skipped (seen in production iframes).\n const fetchSelectedRecord = grist.fetchSelectedRecord ?? grist.docApi?.fetchSelectedRecord\n if (typeof grist.on !== \"function\" || typeof fetchSelectedRecord !== \"function\") return\n let lastRowId: number | undefined\n grist.on(\"message\", async (msg: unknown) => {\n const host = msg as { tableId?: string; rowId?: unknown } | null\n if (!host?.tableId || typeof host.rowId !== \"number\" || host.rowId === lastRowId) return\n lastRowId = host.rowId\n try {\n const record = await fetchSelectedRecord(host.rowId, { keepEncoded: false })\n emit({ record, mappings: recordStream.peek()?.mappings ?? null })\n } catch (err) {\n console.error(\"[grist-widget-sdk] fetchSelectedRecord on a cursor move failed:\", err)\n }\n })\n})\n\nexport const recordsStream = new HostStream<RecordsPayload>((emit) => {\n grist.onRecords((records, mappings) => emit({ records, mappings: asMappings(mappings) }), {\n keepEncoded: false,\n format: \"rows\",\n })\n})\n\nexport const optionsStream = new HostStream<OptionsPayload>((emit) => {\n grist.onOptions((options, interaction) =>\n emit({\n options: options ? { ...options } : null,\n interaction: normalizeWidgetInteraction((interaction as GristWidgetInteraction | null) ?? null),\n })\n )\n})\n\nexport const newRecordStream = new HostStream<NewRecordPayload>((emit) => {\n if (typeof grist.onNewRecord !== \"function\") return\n grist.onNewRecord((mappings) => emit({ mappings: asMappings(mappings) }))\n})\n\n/** Grist's host messages (`grist.on(\"message\")`): the theme travels here. */\nexport const messageStream = new HostStream<unknown>((emit) => {\n if (typeof grist.on !== \"function\") return\n grist.on(\"message\", (msg: unknown) => emit(msg))\n})\n\nexport const ALL_STREAMS = [recordStream, recordsStream, optionsStream, newRecordStream, messageStream] as const\n","/**\n * Single-call wrapper around `grist.ready()`.\n *\n * Grist's contract is \"call ready once\". Multiple `useGristReady` calls (or\n * `useGristWidget` from sibling components) would otherwise race. We:\n *\n * - Coalesce concurrent calls into one in-flight promise.\n * - Re-call `grist.ready` only when `requiredAccess` widens (so an action-capable\n * hook can upgrade a previously read-only handshake).\n */\n\nimport type { GristColumnsToMap, GristReadyOptions, GristRequiredAccess } from \"../types\"\n\nconst ACCESS_RANK: Record<GristRequiredAccess, number> = {\n none: 0,\n \"read table\": 1,\n full: 2,\n}\n\nlet inFlight: Promise<void> | null = null\nlet lastAccess: GristRequiredAccess | null = null\nlet lastColumnNames: ReadonlySet<string> | null = null\n\nfunction columnNamesOf(columns: GristColumnsToMap | undefined): Set<string> {\n return new Set((columns ?? []).map((c) => (typeof c === \"string\" ? c : c.name)))\n}\n\n/**\n * Re-init whenever the new payload asks for strictly more than what's\n * already cached: a higher access level, or a column name the cached\n * payload didn't declare. Prevents a bare fallback caller (e.g. a status\n * chip with no declared columns) from permanently sticking a widget's real,\n * richer requirements to the host once it happens to win the initial race.\n */\nfunction shouldReinit(next: GristRequiredAccess, nextColumns: ReadonlySet<string>): boolean {\n if (!lastAccess) return true\n if (ACCESS_RANK[next] > ACCESS_RANK[lastAccess]) return true\n for (const name of nextColumns) {\n if (!lastColumnNames?.has(name)) return true\n }\n return false\n}\n\n/**\n * Calls `grist.ready` at most once per page (re-called only if access widens\n * or previously-undeclared columns are requested).\n * Returns the same promise for all concurrent callers.\n */\nexport function ensureGristReady(payload: GristReadyOptions): Promise<void> {\n const access = payload.requiredAccess ?? \"read table\"\n const columns = columnNamesOf(payload.columns)\n if (inFlight && !shouldReinit(access, columns)) return inFlight\n\n lastAccess = access\n lastColumnNames = columns\n const next = Promise.resolve().then(() => {\n const result = grist.ready(payload)\n return result instanceof Promise ? result : Promise.resolve()\n })\n\n inFlight = next.catch((err) => {\n inFlight = null\n lastAccess = null\n lastColumnNames = null\n throw err\n })\n return inFlight\n}\n\n/**\n * Forget the cached ready state. Subsequent calls to {@link ensureGristReady}\n * will re-issue `grist.ready` even at the same access level.\n *\n * Production uses: the handshake manager's `reload()` clears the singleton so\n * a soft retry triggers a fresh `grist.ready` (otherwise the cached promise\n * would short-circuit and the user-visible reload would be a no-op).\n *\n * Tests use this between test cases when swapping `window.grist`.\n */\nexport function resetGristReady(): void {\n inFlight = null\n lastAccess = null\n lastColumnNames = null\n}\n\n/** @deprecated Use {@link resetGristReadySingleton}. Kept for test back-compat. */\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","/**\n * The widget's connection to Grist: one store, one `connect()`.\n *\n * The template loads `grist-plugin-api.js` with a classic blocking script, so\n * `window.grist` is there when the widget starts, or it never will be: the\n * check is synchronous (with one more look at `load`, for a page that loads\n * the script asynchronously). Then `grist.ready()` once, and every Grist\n * stream (records, options, mappings, theme) feeds one immutable state that\n * React reads through `useSyncExternalStore`. No polling, no heartbeat: the\n * iframe lives and dies with the Grist page, and a failed call fails where it\n * was made.\n */\n\nimport { parseGristThemePayload } from \"../helpers/grist-theme-payload\"\nimport type { GristSdkAlertKind } from \"../helpers/grist-sdk-alerts\"\nimport type { StandardSchema } from \"./cells\"\nimport type {\n GristReadyOptions,\n GristRequiredAccess,\n GristRowRecord,\n GristWidgetColumnMap,\n GristWidgetInteraction,\n} from \"../types\"\nimport { parseAccess } from \"./derive\"\nimport { messageStream, newRecordStream, optionsStream, recordsStream, recordStream } from \"./host\"\nimport { ensureGristReady, resetGristReady } from \"./ready\"\n\nexport type GristConnection = \"connecting\" | \"ready\" | \"not-embedded\" | \"unavailable\" | \"error\"\nexport type GristTheme = \"light\" | \"dark\"\nexport type GristWidgetActionStatus = \"idle\" | \"running\" | \"error\"\n\nexport type GristRuntimeState = {\n connection: GristConnection\n /** Why the connection failed (`connection === \"error\"`). */\n connectionError: string | null\n declaredAccess: GristRequiredAccess\n /** The access Grist reports with the widget options; null before it does. */\n grantedAccess: GristRequiredAccess | null\n record: GristRowRecord | null\n records: GristRowRecord[] | null\n isNewRecord: boolean\n /** Logical → real column ids; null until Grist reports them. */\n mappings: GristWidgetColumnMap | null\n widgetOptions: Record<string, unknown> | null\n interaction: GristWidgetInteraction | null\n currentTableId: string | null\n theme: GristTheme | null\n actionStatus: GristWidgetActionStatus\n actionError: string | null\n /** The last read that Grist refused for lack of access, for the alerts. */\n readError: string | null\n /** Logical columns the last `mapBack` couldn't write (allowMultiple), for the alerts. */\n mapBackSkipped: readonly string[]\n}\n\n/** What a widget asks Grist for (`UseGristOptions`). */\nexport type GristRuntimeOptions = GristReadyOptions & {\n /** Alert kinds mountGristWidget() never shows for this widget, e.g. [\"section-not-linked\"]. */\n suppressAlerts?: GristSdkAlertKind[]\n /**\n * Extra rules for the mapped records, as a Standard Schema (zod 4,\n * valibot, arktype…), checked after each cell's declared type. A record\n * that fails keeps its typed values; its issues go to `cellIssues`.\n */\n schema?: StandardSchema\n}\n\nexport type GristRuntime = {\n readonly options: GristRuntimeOptions\n getState(): GristRuntimeState\n subscribe(listener: () => void): () => void\n /** Connects (idempotent). Returns a function that stops listening. */\n start(): () => void\n /** Re-runs `grist.ready()` and re-reads mappings and the table. */\n reload(): Promise<void>\n update(patch: Partial<GristRuntimeState>): void\n}\n\nconst READY_TIMEOUT_MS = 30_000\n\nexport function initialRuntimeState(options: GristReadyOptions = {}): GristRuntimeState {\n return {\n connection: \"connecting\",\n connectionError: null,\n declaredAccess: options.requiredAccess ?? \"read table\",\n grantedAccess: null,\n record: null,\n records: null,\n isNewRecord: false,\n mappings: null,\n widgetOptions: null,\n interaction: null,\n currentTableId: null,\n theme: null,\n actionStatus: \"idle\",\n actionError: null,\n readError: null,\n mapBackSkipped: [],\n }\n}\n\nfunction isEmbedded(): boolean {\n try {\n return typeof window !== \"undefined\" && window.self !== window.top\n } catch {\n return true // a cross-origin parent throws: we are in an iframe\n }\n}\n\nconst hasGrist = () => typeof grist !== \"undefined\" && grist !== null\n\nexport function createGristRuntime(options: GristRuntimeOptions = {}): GristRuntime {\n let state = initialRuntimeState(options)\n const listeners = new Set<() => void>()\n let starts = 0\n let stopStreams: (() => void) | null = null\n let attempt = 0\n\n const update = (patch: Partial<GristRuntimeState>) => {\n let changed = false\n for (const key of Object.keys(patch) as (keyof GristRuntimeState)[]) {\n if (!Object.is(state[key], patch[key])) changed = true\n }\n if (!changed) return\n state = { ...state, ...patch }\n for (const l of [...listeners]) l()\n }\n\n const payload: GristReadyOptions = {\n requiredAccess: options.requiredAccess ?? \"read table\",\n columns: options.columns ?? [],\n ...(options.allowSelectBy !== undefined ? { allowSelectBy: options.allowSelectBy } : {}),\n ...(options.hasCustomOptions !== undefined ? { hasCustomOptions: options.hasCustomOptions } : {}),\n ...(options.onEditOptions ? { onEditOptions: options.onEditOptions } : {}),\n }\n\n const refreshTable = async () => {\n try {\n const tableId = await grist.selectedTable?.getTableId()\n if (tableId) update({ currentTableId: tableId })\n } catch {\n // Not every host answers; currentTableId stays as it was.\n }\n }\n\n const refreshMappings = async () => {\n if (typeof grist.sectionApi?.mappings !== \"function\") return\n try {\n const mappings = await grist.sectionApi.mappings()\n // A stream may have reported newer mappings while this was in flight.\n if (state.mappings === null) update({ mappings: (mappings as GristWidgetColumnMap | null) ?? {} })\n } catch {\n // The streams report mappings too.\n }\n }\n\n const connect = async () => {\n const mine = ++attempt\n update({ connection: \"connecting\", connectionError: null })\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n await Promise.race([\n ensureGristReady(payload),\n new Promise((_, reject) => {\n timer = setTimeout(() => reject(new Error(`Grist did not answer grist.ready() within ${READY_TIMEOUT_MS / 1000} s.`)), READY_TIMEOUT_MS)\n }),\n ])\n } catch (err) {\n if (mine === attempt) update({ connection: \"error\", connectionError: err instanceof Error ? err.message : String(err) })\n return\n } finally {\n clearTimeout(timer)\n }\n if (mine !== attempt) return\n update({ connection: \"ready\" })\n await Promise.all([refreshMappings(), refreshTable()])\n }\n\n const listen = () => {\n const offs = [\n // Copies: a host may reuse one record object and mutate it in place.\n recordStream.subscribe(({ record, mappings }) =>\n update({\n record: record ? ({ ...record } as GristRowRecord) : null,\n isNewRecord: false,\n ...(mappings ? { mappings } : {}),\n })\n ),\n recordsStream.subscribe(({ records, mappings }) => {\n update({ records: records.map((r) => ({ ...r }) as GristRowRecord), ...(mappings ? { mappings } : {}) })\n void refreshTable()\n }),\n optionsStream.subscribe(({ options: widgetOptions, interaction }) =>\n update({\n widgetOptions,\n interaction,\n grantedAccess: parseAccess(interaction?.access_level) ?? state.grantedAccess,\n })\n ),\n newRecordStream.subscribe(({ mappings }) => update({ isNewRecord: true, ...(mappings ? { mappings } : {}) })),\n messageStream.subscribe((msg) => {\n const theme = parseGristThemePayload(msg)\n if (theme) update({ theme })\n }),\n ]\n return () => offs.forEach((off) => off())\n }\n\n const begin = () => {\n if (!isEmbedded()) return update({ connection: \"not-embedded\" })\n if (!hasGrist()) {\n // A page that loads the plugin API asynchronously: one more look once\n // everything has loaded, then it is unavailable.\n if (typeof document !== \"undefined\" && document.readyState !== \"complete\" && typeof window !== \"undefined\") {\n window.addEventListener(\"load\", () => (hasGrist() ? begin() : update({ connection: \"unavailable\" })), { once: true })\n return\n }\n return update({ connection: \"unavailable\" })\n }\n // Bound before ready(): Grist may push the first record during it.\n stopStreams ??= listen()\n void connect()\n }\n\n return {\n options,\n getState: () => state,\n subscribe(listener) {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n start() {\n if (starts++ === 0) begin()\n return () => {\n if (--starts > 0) return\n stopStreams?.()\n stopStreams = null\n }\n },\n async reload() {\n if (!hasGrist() || !isEmbedded()) return begin()\n resetGristReady()\n update({ mappings: null })\n stopStreams ??= listen()\n await connect()\n },\n update,\n }\n}\n","/**\n * `defineGristWidget()`: a widget's whole declaration in one typed value.\n * Everything else reads it: `widget.useGrist()` types the mapped records and\n * the writes from it, `mountGristWidget()` takes the access level, the\n * columns and the title from it, and the tests map its columns.\n *\n * ```ts\n * export const widget = defineGristWidget({\n * title: \"Tasks\",\n * requiredAccess: \"full\",\n * columns: [{ name: \"Title\", type: \"Text\" }, { name: \"Done\", type: \"Bool\" }],\n * })\n *\n * const w = widget.useGrist() // w.mappedRecord: { id; Title: string | null; Done: boolean | null } | null\n * await w.updateRecord({ Done: true })\n * ```\n */\n\nimport type { GristMappedRow } from \"./runtime/cells\"\nimport type { GristRowRecord } from \"./types\"\nimport { useGrist, type UseGristOptions, type UseGristResult } from \"./use-grist\"\n\n/** What a widget declares: `UseGristOptions`, plus its title and description. */\nexport type GristWidgetDefinition = UseGristOptions & {\n /** The widget's name: the page's title, and its manifest's. */\n title?: string\n /** One sentence: the page's description, and its manifest's. */\n description?: string\n}\n\n/** The widget's mapped record type, from its declaration. */\nexport type GristWidgetRow<W> = W extends GristWidget<infer D> ? GristMappedRow<D> : never\n\n/** A declared widget. Pass it to `mountGristWidget()` (as `widget`, exported from `src/app/App.tsx`). */\nexport type GristWidget<D extends GristWidgetDefinition = GristWidgetDefinition> = {\n /** The declaration, as written. */\n readonly definition: D\n /** What the widget asks Grist for: the declaration without its title and description. */\n readonly options: UseGristOptions\n readonly metadata: { title?: string; description?: string }\n /**\n * `useGrist()`, typed from the declaration: `mappedRecord`, `mappedRecords`,\n * `mapBack`, `updateRecord` and `addRecord` use the declared names and the\n * value each declared type gives. A hook: call it in a component.\n */\n useGrist: () => UseGristResult<GristRowRecord, GristMappedRow<D>>\n}\n\n/**\n * Declares a widget. The `const` type parameter keeps the column names and\n * types literal, so the mapped record is typed with no annotation, no\n * `as const` and no generics.\n */\nexport function defineGristWidget<const D extends GristWidgetDefinition>(definition: D): GristWidget<D> {\n const { title, description, ...options } = definition\n return {\n definition,\n options,\n metadata: { title, description },\n useGrist: () => useGrist<GristRowRecord, GristMappedRow<D>>(options),\n }\n}\n\n/** True for a declared widget (as opposed to plain `GRIST_OPTIONS`). */\nexport function isGristWidget(value: unknown): value is GristWidget {\n return typeof value === \"object\" && value !== null && \"definition\" in value && \"useGrist\" in value\n}\n","import { useState, type ReactNode } from \"react\"\n\nimport { GristContextProvider, newConnection, type UseGristOptions } from \"../use-grist\"\n\nexport type GristWidgetProviderProps = {\n /** Read once, at mount: what the widget asks Grist for. */\n options?: UseGristOptions\n children: ReactNode\n}\n\n/**\n * Connects to Grist for the widgets below it: `useGrist()` under it reads this\n * connection. `mountGristWidget()` renders it; render it yourself only for a\n * page that manages its own React root.\n */\nexport function GristWidgetProvider({ options, children }: GristWidgetProviderProps) {\n const [connection] = useState(() => newConnection(options))\n return <GristContextProvider value={connection}>{children}</GristContextProvider>\n}\n","import { useCallback, useState, type CSSProperties, type ReactNode } from \"react\"\n\nimport { accessDenied, accessLabel, deriveColumnMappingStatus } from \"../runtime/derive\"\nimport type { GristRuntimeState } from \"../runtime/runtime\"\nimport { useGristRuntime, useGristState } from \"../use-grist\"\n\nexport type GristBoundaryProps = {\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\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\ntype Screen = { title: string; message: string; tone?: \"default\" | \"error\"; retry?: boolean }\n\n/** What the boundary shows instead of the widget, or null to render it. */\nexport function boundaryScreen(state: GristRuntimeState, columns: Parameters<typeof deriveColumnMappingStatus>[0]): Screen | null {\n switch (state.connection) {\n case \"connecting\":\n return { title: \"Connecting to Grist\", message: \"Asking Grist for the access this widget needs…\" }\n case \"not-embedded\":\n return {\n title: \"Open inside Grist\",\n message: \"Open this page as a custom widget inside a Grist document (it runs in an embedded panel, not on its own).\",\n retry: true,\n }\n case \"unavailable\":\n return {\n title: \"Open inside Grist\",\n message: \"The Grist plugin did not load. Reload the page, or open this URL as a custom widget inside a Grist document.\",\n retry: true,\n }\n case \"error\":\n return {\n title: \"Something went wrong\",\n message: state.connectionError ?? \"Something went wrong connecting to Grist. Try again, or reload the page.\",\n tone: \"error\",\n retry: true,\n }\n }\n if (accessDenied(state)) {\n return {\n title: \"More access needed\",\n message: `Set Access level to at least \"${accessLabel(state.declaredAccess)}\" in the Custom widget settings.`,\n tone: \"error\",\n retry: true,\n }\n }\n const mapping = deriveColumnMappingStatus(columns, state.mappings)\n if (mapping.pending) return { title: \"Connecting to Grist\", message: \"Waiting for Grist to report the column mapping…\" }\n if (!mapping.ok) {\n return {\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 }\n }\n return null\n}\n\n/**\n * Renders the widget once Grist is connected, has granted the access it\n * declares, and every required declared column is mapped; until then, a\n * screen that says what is missing (with a retry where one can help).\n * Requires `<GristWidgetProvider>`; `mountGristWidget()` renders both.\n */\nexport function GristBoundary({ children }: GristBoundaryProps) {\n const connection = useGristRuntime()\n if (!connection) throw new Error(\"<GristBoundary> must be used inside <GristWidgetProvider> (mountGristWidget renders both).\")\n const state = useGristState(connection)\n const [isReloading, setIsReloading] = useState(false)\n const reload = useCallback(async () => {\n setIsReloading(true)\n try {\n await connection.runtime.reload()\n } catch (err) {\n console.error(\"[grist-widget-sdk] reload failed:\", err)\n } finally {\n setIsReloading(false)\n }\n }, [connection])\n\n const screen = boundaryScreen(state, connection.runtime.options.columns)\n if (!screen) return <>{children}</>\n return (\n <GristBoundaryScreen\n title={screen.title}\n message={screen.message}\n tone={screen.tone}\n showRetry={screen.retry}\n actions={{ reload, isReloading }}\n retryLabel={screen.tone === \"error\" ? \"Try again\" : \"Try reconnecting\"}\n retryBusyLabel={screen.tone === \"error\" ? \"Retrying…\" : \"Reconnecting…\"}\n />\n )\n}\n","import type { GristReplicaDocument, GristReplicaRow, GristReplicaTable } from \"../replica-document\"\n\n/**\n * Ensure `rows` is a concrete array for emulator / merge logic.\n * Call at host boundaries (`createDocument`, tests); JSON may still omit `rows` for schema-only.\n */\nexport function normalizeReplicaTableInput<T extends GristReplicaTable>(table: T): T & { rows: GristReplicaRow[] } {\n return { ...table, rows: table.rows ?? [] }\n}\n\n/** Apply {@link normalizeReplicaTableInput} to every table; shallow-copies the document shell. */\nexport function normalizeReplicaDocumentInput<T extends GristReplicaDocument>(doc: T): T {\n return {\n ...doc,\n tables: Object.fromEntries(\n Object.entries(doc.tables).map(([tableId, t]) => [tableId, normalizeReplicaTableInput(t)])\n ),\n } as T\n}\n\n/** How row arrays appear in serialized replica JSON from {@link buildReplicaJsonPayload}. */\nexport type ReplicaJsonIncludeRows = \"none\" | \"samples\" | \"full\"\n\n/**\n * Clone a replica document for JSON output: strip rows, cap to first N, or pass through.\n * Does not mutate the source document.\n */\nexport function buildReplicaJsonPayload(\n doc: GristReplicaDocument,\n options: { includeRows: ReplicaJsonIncludeRows; sampleRowLimit?: number }\n): GristReplicaDocument {\n const limit = options.sampleRowLimit ?? 10\n const tables = Object.fromEntries(\n Object.entries(doc.tables).map(([tid, t]) => {\n if (options.includeRows === \"none\") {\n const { rows: _r, ...rest } = t\n return [tid, rest]\n }\n if (options.includeRows === \"samples\") {\n const r = t.rows ?? []\n return [tid, { ...t, rows: r.slice(0, limit) }]\n }\n return [tid, { ...t, rows: t.rows }]\n })\n ) as GristReplicaDocument[\"tables\"]\n return { ...doc, tables }\n}\n","import { useEffect } from \"react\"\n\nexport type UseWidgetMetadataInput = {\n title: string\n description: string\n}\n\nexport function useWidgetMetadata(input?: UseWidgetMetadataInput | null) {\n useEffect(() => {\n if (!input) return\n\n const { title, description } = 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 }, [input])\n}\n\nfunction setMetaTag(key: \"name\" | \"property\", value: string, content: string) {\n let meta = document.head.querySelector<HTMLMetaElement>(\n `meta[${key}=\"${value}\"]`\n )\n if (!meta) {\n meta = document.createElement(\"meta\")\n meta.setAttribute(key, value)\n document.head.appendChild(meta)\n }\n meta.setAttribute(\"content\", content)\n}\n","/**\n * Grist `docApi.applyUserActions` payloads are arrays of user-action tuples.\n * @see https://support.getgrist.com/code/interfaces/grist_plugin_api.GristDocAPI/#applyuseractions\n */\n\nexport type GristUserActionTuple = unknown[]\n\n/** `[\"UpdateRecord\", tableId, rowId, { col: value, ... }]` */\nexport function gristUpdateRecordAction(\n tableId: string,\n rowId: number,\n patch: Record<string, unknown>\n): GristUserActionTuple {\n return [\"UpdateRecord\", tableId, rowId, patch]\n}\n\n/** `[\"AddRecord\", tableId, null, { col: value, ... }]` */\nexport function gristAddRecordAction(tableId: string, values: Record<string, unknown>): GristUserActionTuple {\n return [\"AddRecord\", tableId, null, values]\n}\n\n/** `[\"RemoveRecord\", tableId, rowId]` */\nexport function gristRemoveRecordAction(tableId: string, rowId: number): GristUserActionTuple {\n return [\"RemoveRecord\", tableId, rowId]\n}\n\n/** `[\"AddColumn\", tableId, colId, colInfo]` — `colInfo` shape depends on Grist version / column type. */\nexport function gristBulkUpdateRecordAction(\n tableId: string,\n rowIds: number[],\n columnarPatch: Record<string, unknown[]>\n): GristUserActionTuple {\n return [\"BulkUpdateRecord\", tableId, rowIds, columnarPatch]\n}\n\n/**\n * `[\"BulkAddRecord\", tableId, rowIds | nullArray, { col: value[], ... }]`.\n * Pass `null` (or omit) for `rowIds` to let Grist allocate ids; in user-action\n * format Grist expects an array of nulls of the same length as the value arrays.\n */\nexport function gristBulkAddRecordAction(\n tableId: string,\n values: Record<string, unknown[]>,\n rowIds?: Array<number | null>\n): GristUserActionTuple {\n const length = inferBulkLength(values)\n const ids = rowIds ?? new Array<number | null>(length).fill(null)\n return [\"BulkAddRecord\", tableId, ids, values]\n}\n\n/** `[\"BulkRemoveRecord\", tableId, rowIds]` */\nexport function gristBulkRemoveRecordAction(tableId: string, rowIds: number[]): GristUserActionTuple {\n return [\"BulkRemoveRecord\", tableId, rowIds]\n}\n\n/** `[\"AddColumn\", tableId, colId, colInfo]` — `colInfo` shape depends on Grist version / column type. */\nexport function gristAddColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"AddVisibleColumn\", tableId, colId, colInfo]` — like `AddColumn` but also adds the column to the current view section. */\nexport function gristAddVisibleColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddVisibleColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"RenameColumn\", tableId, colId, newColId]` */\nexport function gristRenameColumnAction(tableId: string, colId: string, newColId: string): GristUserActionTuple {\n return [\"RenameColumn\", tableId, colId, newColId]\n}\n\n/** `[\"ModifyColumn\", tableId, colId, colInfo]` */\nexport function gristModifyColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"ModifyColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"RemoveColumn\", tableId, colId]` */\nexport function gristRemoveColumnAction(tableId: string, colId: string): GristUserActionTuple {\n return [\"RemoveColumn\", tableId, colId]\n}\n\n/** `[\"AddTable\", tableId, tableInfo]` */\nexport function gristAddTableAction(tableId: string, tableInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddTable\", tableId, tableInfo]\n}\n\nfunction inferBulkLength(values: Record<string, unknown[]>): number {\n for (const arr of Object.values(values)) if (Array.isArray(arr)) return arr.length\n return 0\n}\n","import { useEffect, useState } from \"react\"\n\nimport {\n cardStyle,\n cardTextStyle,\n cardTitleStyle,\n codeStyle,\n eyebrowStyle,\n headingStyle,\n leadStyle,\n pageStyle,\n} from \"./tokens\"\nimport { widgetTitle } from \"./widget-title\"\n\n/**\n * Whether the widget has a demo page (`public/demo/`). The dev server serves\n * it at `demo/index.html` (Vite answers a bare `demo/` with the app's own page).\n */\nfunction useHasDemo(): boolean | null {\n const [has, setHas] = useState<boolean | null>(null)\n useEffect(() => {\n if (typeof fetch !== \"function\") return\n let live = true\n fetch(\"demo/demo.grist\", { method: \"HEAD\" })\n .then((res) => live && setHas(res.ok))\n .catch(() => live && setHas(false))\n return () => {\n live = false\n }\n }, [])\n return has\n}\n\n/**\n * Shown outside Grist on the dev server. Deliberately not a preview of the\n * widget: an emulator can't match real Grist. It points at the loops worth\n * trusting: the widget in real Grist running in this browser (the demo page,\n * grist-static, on this dev server's build, so edits reload in place),\n * `pnpm test`, and the `dev` branch's preview inside a Grist document.\n */\nexport function LocalDevPage() {\n const hasDemo = useHasDemo()\n return (\n <main style={pageStyle}>\n <p style={eyebrowStyle}>{widgetTitle()} · local dev</p>\n <h1 style={headingStyle}>Not embedded in Grist</h1>\n <p style={leadStyle}>This is the local dev server: there's no Grist here to render the widget against.</p>\n\n <section style={cardStyle}>\n <h2 style={cardTitleStyle}>Open it in Grist, in this browser</h2>\n {hasDemo === false ? (\n <p style={cardTextStyle}>\n Run <code style={codeStyle}>pnpm demo --save</code> once (it needs Docker): it writes{\" \"}\n <code style={codeStyle}>public/demo/</code>, a document for this widget. Then{\" \"}\n <a href=\"demo/index.html\">demo/index.html</a> opens it in real Grist, running in the browser, on this dev server's\n widget: edits reload in place.\n </p>\n ) : (\n <p style={cardTextStyle}>\n <a href=\"demo/index.html\">Open demo/index.html</a>: real Grist running in the browser (no server, nothing saved), with\n this dev server's widget, so edits reload in place. Its document is{\" \"}\n <code style={codeStyle}>public/demo/demo.grist</code>: after changing the declared columns, run{\" \"}\n <code style={codeStyle}>pnpm demo --save</code> (Docker) to regenerate it.\n </p>\n )}\n </section>\n\n <section style={cardStyle}>\n <h2 style={cardTitleStyle}>Check it against real Grist</h2>\n <p style={cardTextStyle}>\n Push to <code style={codeStyle}>dev</code>, then open its <code style={codeStyle}>/dev/</code> URL in a\n custom widget of a real Grist document: later pushes reload it there within seconds. Locally,{\" \"}\n <code style={codeStyle}>pnpm test</code> runs the widget against an emulated Grist.\n </p>\n </section>\n\n <section style={cardStyle}>\n <h2 style={cardTitleStyle}>Starting from another example?</h2>\n <p style={cardTextStyle}>\n <code style={codeStyle}>npx create-grist-widget list</code> shows the examples, and{\" \"}\n <code style={codeStyle}>npx create-grist-widget use <example></code> swaps this widget for one.\n </p>\n </section>\n </main>\n )\n}\n","import type { CSSProperties } from \"react\"\n\n/**\n * The chrome's colours and radius: shadcn's CSS variables, so the pages\n * follow a widget's theme (light, dark, its own palette) without depending\n * on its Tailwind config, with neutral fallbacks for a widget without them.\n * Same approach as GristBoundaryScreen.\n */\nconst token = (name: string, fallback: string) => `var(--${name}, ${fallback})`\n\nexport const tokens = {\n background: token(\"background\", \"#ffffff\"),\n foreground: token(\"foreground\", \"#0a0a0a\"),\n card: token(\"card\", \"#ffffff\"),\n mutedForeground: token(\"muted-foreground\", \"#737373\"),\n border: token(\"border\", \"#e5e5e5\"),\n primary: token(\"primary\", \"#171717\"),\n primaryForeground: token(\"primary-foreground\", \"#fafafa\"),\n destructive: token(\"destructive\", \"#dc2626\"),\n radius: token(\"radius\", \"0.625rem\"),\n} as const\n\nexport const pageStyle: CSSProperties = {\n boxSizing: \"border-box\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n maxWidth: \"28rem\",\n minHeight: \"100%\",\n margin: \"0 auto\",\n padding: \"4rem 1.5rem\",\n color: tokens.foreground,\n font: \"inherit\",\n}\n\nexport const eyebrowStyle: CSSProperties = {\n margin: \"0 0 0.5rem\",\n textAlign: \"center\",\n fontSize: \"0.875rem\",\n fontWeight: 500,\n color: tokens.mutedForeground,\n}\n\nexport const headingStyle: CSSProperties = {\n margin: 0,\n textAlign: \"center\",\n fontSize: \"1.5rem\",\n fontWeight: 600,\n letterSpacing: \"-0.01em\",\n}\n\nexport const leadStyle: CSSProperties = {\n margin: \"0.75rem auto 2rem\",\n maxWidth: \"24rem\",\n textAlign: \"center\",\n fontSize: \"0.875rem\",\n lineHeight: 1.5,\n color: tokens.mutedForeground,\n}\n\nexport const cardStyle: CSSProperties = {\n boxSizing: \"border-box\",\n marginBottom: \"1rem\",\n padding: \"1.25rem\",\n border: `1px solid ${tokens.border}`,\n borderRadius: tokens.radius,\n background: tokens.card,\n}\n\nexport const cardTitleStyle: CSSProperties = {\n margin: \"0 0 0.375rem\",\n fontSize: \"1rem\",\n fontWeight: 600,\n}\n\nexport const cardTextStyle: CSSProperties = {\n margin: 0,\n fontSize: \"0.875rem\",\n lineHeight: 1.5,\n color: tokens.mutedForeground,\n}\n\nexport const codeStyle: CSSProperties = {\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, monospace\",\n fontSize: \"0.8125rem\",\n color: tokens.foreground,\n}\n","/**\n * The widget's name for the pages shown outside Grist: the page title,\n * which `create-grist-widget` sets to the widget's title in `index.html`.\n */\nexport function widgetTitle(): string {\n const title = typeof document === \"undefined\" ? \"\" : document.title.trim()\n return title || \"Grist widget\"\n}\n","import { useState, type CSSProperties } from \"react\"\n\nimport { deployChannelLabel, parseDeployPath, type DeployChannel } from \"../deploy-path\"\nimport { useReleasedVersions } from \"../released-versions\"\nimport {\n cardStyle,\n cardTextStyle,\n cardTitleStyle,\n codeStyle,\n eyebrowStyle,\n headingStyle,\n leadStyle,\n pageStyle,\n tokens,\n} from \"./tokens\"\nimport { widgetTitle } from \"./widget-title\"\n\n/**\n * Shown outside Grist on a deployed URL (`/latest/`, `/dev/`, `/v<version>/`\n * or the root): which build this is, links to the others, and the URL to\n * paste into a Grist custom widget.\n */\nexport function ReleasePage({ channel }: { channel: DeployChannel }) {\n const label = deployChannelLabel(channel)\n return (\n <main style={pageStyle}>\n <p style={eyebrowStyle}>\n {widgetTitle()} · {label}\n </p>\n <h1 style={headingStyle}>Grist isn't loaded here</h1>\n <p style={leadStyle}>\n This is the <code style={codeStyle}>{label}</code> build, opened outside Grist. Hover a version to see when it\n was released.\n </p>\n <ChannelLinks current={channel} />\n <InstallUrl />\n </main>\n )\n}\n\nfunction ChannelLinks({ current }: { current: DeployChannel }) {\n const { basePath } = parseDeployPath(window.location.pathname)\n const { versions } = useReleasedVersions()\n const isCurrent = (channel: DeployChannel) =>\n channel.kind === current.kind && (channel.kind !== \"version\" || (current.kind === \"version\" && channel.version === current.version))\n\n return (\n <nav aria-label=\"Versions\" style={{ display: \"flex\", flexWrap: \"wrap\", justifyContent: \"center\", gap: \"0.5rem\", marginBottom: \"2rem\" }}>\n <ChannelLink href={`${basePath}latest/`} active={isCurrent({ kind: \"latest\" })}>\n latest\n </ChannelLink>\n <ChannelLink href={`${basePath}dev/`} active={isCurrent({ kind: \"dev\" })}>\n dev\n </ChannelLink>\n {versions?.map((v) => (\n <ChannelLink\n key={v.version}\n href={`${basePath}v${v.version}/`}\n title={formatDate(v.publishedAt)}\n active={isCurrent({ kind: \"version\", version: v.version })}\n >\n {`v${v.version}`}\n </ChannelLink>\n ))}\n </nav>\n )\n}\n\nfunction ChannelLink({\n href,\n title,\n active,\n children,\n}: {\n href: string\n title?: string\n active: boolean\n children: string\n}) {\n const style: CSSProperties = {\n padding: \"0.25rem 0.75rem\",\n border: `1px solid ${active ? tokens.primary : tokens.border}`,\n borderRadius: \"9999px\",\n background: active ? tokens.primary : \"transparent\",\n color: active ? tokens.primaryForeground : tokens.mutedForeground,\n fontSize: \"0.75rem\",\n fontWeight: 500,\n textDecoration: \"none\",\n }\n return (\n <a href={href} title={title} aria-current={active ? \"page\" : undefined} style={style}>\n {children}\n </a>\n )\n}\n\nfunction InstallUrl() {\n const url = window.location.href\n const [copied, setCopied] = useState(false)\n\n function copy() {\n void navigator.clipboard?.writeText(url).then(() => {\n setCopied(true)\n setTimeout(() => setCopied(false), 1500)\n })\n }\n\n return (\n <section style={cardStyle}>\n <h2 style={cardTitleStyle}>Use it as a Grist custom widget</h2>\n <p style={{ ...cardTextStyle, marginBottom: \"1rem\" }}>Paste this URL into a custom widget's URL field in Grist.</p>\n <div style={{ display: \"flex\", gap: \"0.5rem\" }}>\n <input\n readOnly\n value={url}\n aria-label=\"Widget URL\"\n onFocus={(event) => event.target.select()}\n style={{\n flex: 1,\n minWidth: 0,\n padding: \"0.5rem 0.75rem\",\n border: `1px solid ${tokens.border}`,\n borderRadius: tokens.radius,\n background: \"transparent\",\n color: tokens.foreground,\n font: \"inherit\",\n fontSize: \"0.875rem\",\n }}\n />\n <button\n type=\"button\"\n onClick={copy}\n style={{\n padding: \"0.5rem 1rem\",\n border: \"none\",\n borderRadius: tokens.radius,\n background: tokens.primary,\n color: tokens.primaryForeground,\n font: \"inherit\",\n fontSize: \"0.875rem\",\n fontWeight: 500,\n cursor: \"pointer\",\n }}\n >\n {copied ? \"Copied\" : \"Copy\"}\n </button>\n </div>\n </section>\n )\n}\n\nfunction formatDate(iso: string): string {\n const date = new Date(iso)\n return Number.isNaN(date.getTime())\n ? iso\n : date.toLocaleDateString(undefined, { year: \"numeric\", month: \"short\", day: \"numeric\" })\n}\n","/**\n * Where a deployed build is being served from.\n *\n * A widget's deploy pipeline publishes the same build at its root and at\n * `/latest/`, a preview at `/dev/`, and each release at `/v<version>/`, all\n * under one base path (e.g. `/my-widget/` on GitHub Pages). Opened outside\n * Grist, the page tells them apart from `window.location.pathname` alone.\n */\nexport type DeployChannel =\n | { kind: \"latest\" }\n | { kind: \"dev\" }\n | { kind: \"version\"; version: string }\n\nexport type DeployPath = {\n channel: DeployChannel\n /**\n * The path the channels live under, always ending in `/`: the current\n * path without its channel segment. `\"/my-widget/v1.2.0/\"` gives\n * `\"/my-widget/\"`.\n */\n basePath: string\n}\n\nconst VERSION_SEGMENT = /^v(\\d+\\.\\d+\\.\\d+(?:-[\\w.]+)?)$/\n\n/**\n * Parse a pathname into its deploy channel and base path. A path without a\n * channel segment (the deployed root, or a local dev server) is `latest`:\n * the deploy places the latest release at the root too.\n */\nexport function parseDeployPath(pathname: string): DeployPath {\n const segments = pathname.replace(/\\/+$/, \"\").split(\"/\")\n const last = segments[segments.length - 1] ?? \"\"\n\n let channel: DeployChannel | null = null\n if (last === \"latest\") channel = { kind: \"latest\" }\n else if (last === \"dev\") channel = { kind: \"dev\" }\n else {\n const match = VERSION_SEGMENT.exec(last)\n if (match) channel = { kind: \"version\", version: match[1] }\n }\n\n if (!channel) return { channel: { kind: \"latest\" }, basePath: withTrailingSlash(pathname) }\n return { channel, basePath: withTrailingSlash(segments.slice(0, -1).join(\"/\")) }\n}\n\n/** `\"latest\"`, `\"dev\"` or `\"v1.2.0\"`. */\nexport function deployChannelLabel(channel: DeployChannel): string {\n return channel.kind === \"version\" ? `v${channel.version}` : channel.kind\n}\n\nfunction withTrailingSlash(path: string): string {\n return path.endsWith(\"/\") ? path : `${path}/`\n}\n","import { useEffect, useState } from \"react\"\n\nimport { parseDeployPath } from \"./deploy-path\"\n\n/** One entry of the `versions.json` a widget's deploy pipeline maintains. */\nexport type ReleasedVersion = {\n version: string\n publishedAt: string\n}\n\nexport type UseReleasedVersionsResult = {\n /** Newest first, as the deploy writes them; `null` until loaded. */\n versions: ReleasedVersion[] | null\n /** `true` when `versions.json` couldn't be fetched or read. */\n error: boolean\n}\n\n/**\n * The widget's released versions, read from the `versions.json` next to its\n * channels (see {@link parseDeployPath}). For a page shown outside Grist,\n * such as a release page linking to each version.\n */\nexport function useReleasedVersions(\n pathname: string = typeof window === \"undefined\" ? \"/\" : window.location.pathname\n): UseReleasedVersionsResult {\n const url = `${parseDeployPath(pathname).basePath}versions.json`\n const [result, setResult] = useState<UseReleasedVersionsResult>({ versions: null, error: false })\n\n useEffect(() => {\n let cancelled = false\n fetch(url, { cache: \"no-store\" })\n .then((res) => (res.ok ? res.json() : Promise.reject(new Error(`HTTP ${res.status}`))))\n .then((data: unknown) => {\n if (cancelled) return\n if (!Array.isArray(data)) throw new Error(\"versions.json is not an array\")\n setResult({ versions: data as ReleasedVersion[], error: false })\n })\n .catch(() => {\n if (!cancelled) setResult({ versions: null, error: true })\n })\n return () => {\n cancelled = true\n }\n }, [url])\n\n return result\n}\n","/**\n * The alerts `mountGristWidget()` shows above a running widget: what needs the\n * user's attention in Grist (column mapping, access, a failed write, an\n * unlinked section). The blocking states (not connected, access refused,\n * required columns unmapped) are `<GristBoundary>`'s, not alerts.\n */\n\nimport { useNearestGristState } from \"../use-grist\"\nimport { deriveColumnMappingStatus, deriveStatus } from \"../runtime/derive\"\nimport { isAccessInsufficientError } from \"../runtime/api\"\nimport type { GristCellIssue } from \"../runtime/cells\"\nimport type { GristRuntimeState } from \"../runtime/runtime\"\nimport type { GristColumnsToMap, GristWidgetInteraction } from \"../types\"\nimport { parseGristWidgetLinkingInfo } from \"./grist-widget-interaction\"\n\nexport type GristSdkAlertKind =\n | \"column-mapping\"\n | \"mapping-pending\"\n | \"section-not-linked\"\n | \"source-not-wired\"\n | \"action-error\"\n | \"access-insufficient\"\n | \"map-back-skip\"\n | \"cell-issues\"\n\nexport type GristSdkAlertSeverity = \"info\" | \"warning\" | \"error\"\n\nexport type GristSdkAlertDescriptor = {\n id: string\n kind: GristSdkAlertKind\n severity: GristSdkAlertSeverity\n title: string\n ariaRole: \"status\" | \"alert\"\n message: string\n}\n\nexport type GristSdkAlertsOptions = {\n /** Added to the \"section not linked\" message, e.g. how to link in Grist. */\n sectionNotLinkedHint?: string\n}\n\nconst TITLE: Record<GristSdkAlertKind, string> = {\n \"column-mapping\": \"Column mapping\",\n \"mapping-pending\": \"Column mapping\",\n \"section-not-linked\": \"Widget linking\",\n \"source-not-wired\": \"Widget linking\",\n \"action-error\": \"Action error\",\n \"access-insufficient\": \"Access level\",\n \"map-back-skip\": \"Write skipped\",\n \"cell-issues\": \"Unexpected values\",\n}\n\nconst SEVERITY: Record<GristSdkAlertKind, GristSdkAlertSeverity> = {\n \"column-mapping\": \"warning\",\n \"mapping-pending\": \"info\",\n \"section-not-linked\": \"warning\",\n \"source-not-wired\": \"warning\",\n \"action-error\": \"error\",\n \"access-insufficient\": \"error\",\n \"map-back-skip\": \"warning\",\n \"cell-issues\": \"warning\",\n}\n\nconst alert = (kind: GristSdkAlertKind, message: string, ariaRole: \"status\" | \"alert\" = \"status\"): GristSdkAlertDescriptor => ({\n id: kind,\n kind,\n severity: SEVERITY[kind],\n title: TITLE[kind],\n ariaRole,\n message,\n})\n\n/** A widget section Grist says is linked to nothing. */\nexport function isWidgetSectionNotLinked(interaction: GristWidgetInteraction | null | undefined): boolean {\n const linking = parseGristWidgetLinkingInfo(interaction?.linking)\n return Boolean(linking) && linking!.asTarget == null\n}\n\n/** The alerts for a widget in `state`, pure (tested without React). */\nexport function getGristSdkAlerts(\n state: GristRuntimeState,\n widget: {\n columns?: GristColumnsToMap\n allowSelectBy?: boolean\n suppressAlerts?: readonly GristSdkAlertKind[]\n cellIssues?: readonly GristCellIssue[]\n },\n options: GristSdkAlertsOptions = {}\n): GristSdkAlertDescriptor[] {\n if (deriveStatus(state) !== \"ready\") return []\n const out: GristSdkAlertDescriptor[] = []\n\n const mapping = deriveColumnMappingStatus(widget.columns, state.mappings)\n if (mapping.pending) out.push(alert(\"mapping-pending\", \"Waiting for Grist to report column mappings.\"))\n else if (!mapping.ok) {\n const parts = [\"Column mapping is incomplete.\"]\n if (mapping.missing.length) parts.push(`Required columns: ${mapping.missing.join(\", \")}.`)\n if (mapping.emptyMultiples.length) parts.push(`Assign at least one sheet column for: ${mapping.emptyMultiples.join(\", \")}.`)\n out.push(alert(\"column-mapping\", parts.join(\" \")))\n }\n\n const failure = state.actionError ?? state.readError\n if (failure && isAccessInsufficientError(failure)) {\n out.push(\n alert(\n \"access-insufficient\",\n 'This operation requires \"Full document access\". Set the Access level to \"Full document access\" in the Custom widget configuration panel.',\n \"alert\"\n )\n )\n } else if (state.actionError) {\n out.push(alert(\"action-error\", state.actionError, \"alert\"))\n }\n\n if (state.mapBackSkipped.length) {\n const list = state.mapBackSkipped.join(\", \")\n out.push(alert(\"map-back-skip\", `mapBack skipped multi-mapped column${state.mapBackSkipped.length === 1 ? \"\" : \"s\"}: ${list}.`))\n }\n\n const cellIssues = widget.cellIssues ?? []\n if (cellIssues.length) {\n const first = cellIssues[0]!\n const where = first.column ? `${first.column} in row ${first.rowId}` : `row ${first.rowId}`\n const more = cellIssues.length > 1 ? ` (and ${cellIssues.length - 1} more)` : \"\"\n out.push(alert(\"cell-issues\", `${where}: ${first.message}${more}. Check the column's type, or the cell, in Grist.`))\n }\n\n const linking = parseGristWidgetLinkingInfo(state.interaction?.linking)\n if (widget.allowSelectBy) {\n if (linking && !linking.asSource) {\n out.push(\n alert(\n \"source-not-wired\",\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 )\n )\n }\n } else if (isWidgetSectionNotLinked(state.interaction)) {\n const hint = options.sectionNotLinkedHint?.trim()\n out.push(\n alert(\n \"section-not-linked\",\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 (hint ? ` ${hint}` : \"\")\n )\n )\n }\n\n const suppressed = widget.suppressAlerts ?? []\n return out.filter((a) => !suppressed.includes(a.kind))\n}\n\n/** @internal The alerts for the widget under the nearest `<GristWidgetProvider>`; [] outside one. */\nexport function useGristSdkAlerts(options?: GristSdkAlertsOptions): GristSdkAlertDescriptor[] {\n const { connection, state, cellIssues } = useNearestGristState()\n if (!connection) return []\n const { columns, allowSelectBy, suppressAlerts } = connection.runtime.options\n return getGristSdkAlerts(state, { columns, allowSelectBy, suppressAlerts, cellIssues }, options)\n}\n","import type { CSSProperties, ReactNode } from \"react\"\n\nimport { useGristSdkAlerts, type GristSdkAlertDescriptor, type GristSdkAlertsOptions } from \"../../sdk/helpers/grist-sdk-alerts\"\nimport { tokens } from \"./tokens\"\n\nconst ALERT_OPTIONS: GristSdkAlertsOptions = {\n sectionNotLinkedHint:\n \"In Grist, select this widget section on the page, then use Link to connect a table, card, or chart view as the selector.\",\n}\n\n/**\n * The default `Alerts` of {@link mountGristWidget}: what needs the user's\n * attention (column mapping, access level, failed writes, an unlinked\n * section), above the widget. Renders nothing extra when all is well.\n */\nexport function WidgetAlerts({ children }: { children: ReactNode }) {\n const alerts = useGristSdkAlerts(ALERT_OPTIONS)\n if (alerts.length === 0) return <>{children}</>\n\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: \"0.75rem\" }}>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: \"0.75rem\", padding: \"0.75rem 0.75rem 0\" }}>\n {alerts.map((alert) => (\n <WidgetAlert key={alert.id} alert={alert} />\n ))}\n </div>\n {children}\n </div>\n )\n}\n\nfunction WidgetAlert({ alert }: { alert: GristSdkAlertDescriptor }) {\n const linkIcon = alert.kind === \"section-not-linked\" || alert.kind === \"source-not-wired\"\n return (\n <div role={alert.ariaRole} style={{ ...alertStyle, ...SEVERITY[alert.severity] }}>\n <span aria-hidden style={{ flexShrink: 0, marginTop: \"0.125rem\" }}>\n {linkIcon ? <LinkIcon /> : <WarningIcon />}\n </span>\n <div style={{ minWidth: 0 }}>\n <p style={{ margin: 0, fontWeight: 500 }}>{alert.title}</p>\n <p style={{ margin: \"0.25rem 0 0\", color: tokens.mutedForeground }}>{alert.message}</p>\n </div>\n </div>\n )\n}\n\nconst alertStyle: CSSProperties = {\n boxSizing: \"border-box\",\n display: \"flex\",\n gap: \"0.75rem\",\n padding: \"0.75rem 1rem\",\n border: `1px solid ${tokens.border}`,\n borderRadius: tokens.radius,\n color: tokens.foreground,\n fontSize: \"0.875rem\",\n lineHeight: 1.5,\n}\n\nconst SEVERITY: Record<GristSdkAlertDescriptor[\"severity\"], CSSProperties> = {\n error: { borderColor: tokens.destructive, color: tokens.destructive },\n warning: { borderColor: \"rgb(245 158 11 / 0.4)\", background: \"rgb(245 158 11 / 0.1)\" },\n info: { background: \"transparent\" },\n}\n\nconst ICON = {\n width: 16,\n height: 16,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n} as const\n\nfunction WarningIcon() {\n return (\n <svg {...ICON}>\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n </svg>\n )\n}\n\nfunction LinkIcon() {\n return (\n <svg {...ICON}>\n <path d=\"M9 17H7A5 5 0 0 1 7 7h2\" />\n <path d=\"M15 7h2a5 5 0 1 1 0 10h-2\" />\n <line x1=\"8\" x2=\"16\" y1=\"12\" y2=\"12\" />\n </svg>\n )\n}\n","import { createContext, useCallback, useContext, useEffect, useMemo, useState, type ReactNode } from \"react\"\n\nimport { useNearestGristState } from \"../sdk/use-grist\"\n\nexport type WidgetTheme = \"light\" | \"dark\" | \"system\"\nexport type ResolvedWidgetTheme = \"light\" | \"dark\"\n\nexport type UseThemeResult = {\n /**\n * Inside Grist: Grist's theme, or `\"system\"` until Grist has sent it.\n * Outside Grist: the saved choice, `\"system\"` by default.\n */\n theme: WidgetTheme\n /** The theme applied to `<html class>`: `\"system\"` resolved to light or dark. */\n resolvedTheme: ResolvedWidgetTheme\n /**\n * Choose a theme outside Grist; it is saved in `localStorage`. Inside Grist\n * this does nothing: the widget follows Grist's theme.\n */\n setTheme: (theme: WidgetTheme) => void\n}\n\nconst STORAGE_KEY = \"theme\"\nconst DARK_QUERY = \"(prefers-color-scheme: dark)\"\nconst THEMES: readonly WidgetTheme[] = [\"light\", \"dark\", \"system\"]\n\nconst ThemeContext = createContext<UseThemeResult | null>(null)\n\n/**\n * The widget's current theme, for components that need it in JavaScript\n * (a toaster, a chart). Same shape as shadcn's `useTheme()`. Styles should\n * rely on the `dark` class that {@link mountGristWidget} keeps on `<html>`.\n * Outside a mounted widget (a unit test, for instance) it reports the\n * system theme and `setTheme` does nothing.\n */\nexport function useTheme(): UseThemeResult {\n const value = useContext(ThemeContext)\n return value ?? { theme: \"system\", resolvedTheme: systemTheme(), setTheme: noop }\n}\n\n/** Inside Grist: follows Grist's theme, and the OS setting until Grist sends one. */\nexport function EmbeddedThemeProvider({ children }: { children: ReactNode }) {\n const gristTheme = useNearestGristState().state.theme\n const system = useSystemTheme(gristTheme === null)\n const resolvedTheme = gristTheme ?? system\n\n useApplyTheme(resolvedTheme)\n\n const value = useMemo<UseThemeResult>(\n () => ({ theme: gristTheme ?? \"system\", resolvedTheme, setTheme: noop }),\n [gristTheme, resolvedTheme]\n )\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>\n}\n\n/**\n * Outside Grist (`pnpm dev`, the deployed release page): the saved choice,\n * the OS setting by default, and the `d` key to switch between light and\n * dark, as shadcn's theme provider does.\n */\nexport function StandaloneThemeProvider({ children }: { children: ReactNode }) {\n const [theme, setThemeState] = useState<WidgetTheme>(() => readStoredTheme() ?? \"system\")\n const system = useSystemTheme(theme === \"system\")\n const resolvedTheme = theme === \"system\" ? system : theme\n\n useApplyTheme(resolvedTheme)\n\n const setTheme = useCallback((next: WidgetTheme) => {\n writeStoredTheme(next)\n setThemeState(next)\n }, [])\n\n // `d` switches between light and dark, unless typing or using a shortcut.\n useEffect(() => {\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.repeat || event.metaKey || event.ctrlKey || event.altKey) return\n if (event.key.toLowerCase() !== \"d\" || isEditableTarget(event.target)) return\n setThemeState((current) => {\n const currentResolved = current === \"system\" ? systemTheme() : current\n const next: WidgetTheme = currentResolved === \"dark\" ? \"light\" : \"dark\"\n writeStoredTheme(next)\n return next\n })\n }\n window.addEventListener(\"keydown\", onKeyDown)\n return () => window.removeEventListener(\"keydown\", onKeyDown)\n }, [])\n\n // Another tab saving a choice applies here too.\n useEffect(() => {\n const onStorage = (event: StorageEvent) => {\n if (event.key !== STORAGE_KEY) return\n setThemeState(isTheme(event.newValue) ? event.newValue : \"system\")\n }\n window.addEventListener(\"storage\", onStorage)\n return () => window.removeEventListener(\"storage\", onStorage)\n }, [])\n\n const value = useMemo<UseThemeResult>(\n () => ({ theme, resolvedTheme, setTheme }),\n [theme, resolvedTheme, setTheme]\n )\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>\n}\n\n/** The OS setting, kept current while `active`. */\nfunction useSystemTheme(active: boolean): ResolvedWidgetTheme {\n const [theme, setTheme] = useState<ResolvedWidgetTheme>(systemTheme)\n\n useEffect(() => {\n if (!active || typeof window.matchMedia !== \"function\") return\n const query = window.matchMedia(DARK_QUERY)\n const onChange = () => setTheme(query.matches ? \"dark\" : \"light\")\n onChange()\n query.addEventListener(\"change\", onChange)\n return () => query.removeEventListener(\"change\", onChange)\n }, [active])\n\n return theme\n}\n\n/** Keep `light` or `dark` on `<html class>`, which Tailwind's dark variant reads. */\nfunction useApplyTheme(theme: ResolvedWidgetTheme) {\n useEffect(() => {\n const root = document.documentElement\n if (root.classList.contains(theme) && !root.classList.contains(other(theme))) return\n const restoreTransitions = suspendTransitions()\n root.classList.remove(other(theme))\n root.classList.add(theme)\n restoreTransitions()\n }, [theme])\n}\n\nfunction systemTheme(): ResolvedWidgetTheme {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") return \"light\"\n return window.matchMedia(DARK_QUERY).matches ? \"dark\" : \"light\"\n}\n\nfunction other(theme: ResolvedWidgetTheme): ResolvedWidgetTheme {\n return theme === \"dark\" ? \"light\" : \"dark\"\n}\n\n/** Switch themes without every color transition animating at once. */\nfunction suspendTransitions(): () => void {\n const style = document.createElement(\"style\")\n style.appendChild(\n document.createTextNode(\"*,*::before,*::after{-webkit-transition:none!important;transition:none!important}\")\n )\n document.head.appendChild(style)\n return () => {\n window.getComputedStyle(document.body)\n requestAnimationFrame(() => requestAnimationFrame(() => style.remove()))\n }\n}\n\nfunction isEditableTarget(target: EventTarget | null): boolean {\n if (!(target instanceof HTMLElement)) return false\n return target.isContentEditable || target.closest(\"input, textarea, select, [contenteditable='true']\") !== null\n}\n\nfunction isTheme(value: string | null): value is WidgetTheme {\n return value !== null && (THEMES as readonly string[]).includes(value)\n}\n\nfunction readStoredTheme(): WidgetTheme | null {\n try {\n const value = localStorage.getItem(STORAGE_KEY)\n return isTheme(value) ? value : null\n } catch {\n return null\n }\n}\n\nfunction writeStoredTheme(theme: WidgetTheme) {\n try {\n localStorage.setItem(STORAGE_KEY, theme)\n } catch {\n // Storage blocked (private mode, sandboxed iframe): the choice lasts for this page only.\n }\n}\n\nfunction noop() {}\n","/**\n * A test document from a widget's declared columns: one table, `Table1`,\n * with a column per declared column (typed after the first type it accepts)\n * and the given rows, each value stored as Grist stores it; and the mappings\n * that map every declared column to its namesake. Shared by\n * `smokeTestWidget` and `renderWithGrist({ widget })`.\n */\n\nimport { encodeGristCell } from \"../../sdk/runtime/cells\"\nimport type { GristColumnToMap, GristReplicaDocument, GristWidgetColumnMap, UseGristOptions } from \"../../sdk\"\n\nexport type Column = { name: string; type: string; declared: string | undefined; allowMultiple: boolean }\n\nexport function declaredColumns(options: UseGristOptions): Column[] {\n return (options.columns ?? []).map((column: string | GristColumnToMap) =>\n typeof column === \"string\"\n ? { name: column, type: \"Any\", declared: undefined, allowMultiple: false }\n : { name: column.name, type: firstType(column.type), declared: column.type, allowMultiple: column.allowMultiple === true }\n )\n}\n\n/** The first Grist type a column accepts: `\"Text,Ref,Choice\"` gives `\"Text\"`. */\nfunction firstType(type: string | undefined): string {\n return (type ?? \"Any\").split(\",\")[0].trim() || \"Any\"\n}\n\nexport function mapEveryColumn(columns: Column[]): GristWidgetColumnMap {\n return Object.fromEntries(columns.map((c) => [c.name, c.allowMultiple ? [c.name] : c.name]))\n}\n\n/**\n * One table with a column per declared column, and `rows` (under the declared\n * names, as typed reads give them: a `Date`, a `string[]`…), or one row of\n * sample values.\n */\nexport function declaredDocument(columns: Column[], rows?: ReadonlyArray<Record<string, unknown>>): GristReplicaDocument {\n const given = rows ?? [Object.fromEntries(columns.map((c) => [c.name, sampleValue(c.type)]))]\n return {\n generatedAt: \"1970-01-01T00:00:00.000Z\",\n docName: \"Test document\",\n mode: \"schema+data\",\n tables: {\n Table1: {\n columns: Object.fromEntries(columns.map((c) => [c.name, { type: c.type }])),\n rows: given.map((row, i) => ({\n id: typeof row.id === \"number\" ? row.id : i + 1,\n ...Object.fromEntries(columns.map((c) => [c.name, encodeGristCell(c.declared, row[c.name] ?? null)])),\n })),\n },\n },\n }\n}\n\nfunction sampleValue(type: string): unknown {\n switch (type) {\n case \"Numeric\":\n case \"Int\":\n return 42\n case \"Bool\":\n return true\n case \"Date\":\n case \"DateTime\":\n return 1767225600 // 2026-01-01, as Grist stores it: epoch seconds\n default:\n return \"Sample\"\n }\n}\n","import type { EventBus } from \"../core/event-bus\"\nimport type { CommandApiImpl } from \"./types\"\n\n/**\n * `CommandAPI` host implementation. The widget's \"Edit Options\" gear and a\n * few keyboard shortcuts call into this. We forward the call name on the bus\n * so the inspector and tests can observe it; useful to assert\n * `onEditOptions` flows.\n */\nexport function createCommandApiImpl(bus: EventBus): CommandApiImpl {\n return {\n async run(name) {\n bus.emit({ type: \"user-action\", action: [\"RunCommand\", name] })\n },\n }\n}\n","/**\n * Resolves the `mappings` payload that `CustomSectionAPI.mappings()` returns.\n *\n * The emulator does **not** infer logical → real columns from names, as\n * real Grist doesn't: mappings come only from `state.selection.mappings`\n * (a test's `emulator.setColumnMappings(...)`). When unset, returns `null`.\n */\n\nimport type { GristWidgetColumnMap } from \"../../sdk/types\"\nimport type { EmulatorDocumentState } from \"./types\"\n\nexport function resolveMappings(state: EmulatorDocumentState): GristWidgetColumnMap | null {\n if (state.selection.mappings !== undefined && state.selection.mappings !== null) {\n return state.selection.mappings\n }\n return null\n}\n","import { resolveMappings } from \"../core/mappings\"\nimport type { EventBus } from \"../core/event-bus\"\nimport type { GristWidgetConfiguration } from \"../../sdk/types\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport type { CustomSectionApiImpl } from \"./types\"\n\n/**\n * `CustomSectionAPI` host implementation, called by `grist-plugin-api.js`\n * after `grist.ready()` to hand the host the widget's preferences:\n * required access, declared columns, allowSelectBy, hasCustomOptions, etc.\n *\n * Implementation:\n * - persists the configuration onto `state.configuration`,\n * - emits a `ready` event so the transport knows it is safe to push\n * initial cursor / data / options messages,\n * - re-emits a `mappings-change` so the inspector and tests can react.\n */\nexport function createCustomSectionApiImpl(\n state: EmulatorDocumentState,\n bus: EventBus\n): CustomSectionApiImpl {\n return {\n async configure(settings) {\n const config: GristWidgetConfiguration = {\n requiredAccess: settings.requiredAccess as GristWidgetConfiguration[\"requiredAccess\"],\n columns: settings.columns as GristWidgetConfiguration[\"columns\"],\n allowSelectBy: settings.allowSelectBy as boolean | undefined,\n hasCustomOptions: settings.hasCustomOptions as boolean | undefined,\n }\n state.configuration = config\n bus.emit({ type: \"ready\", configuration: config })\n bus.emit({ type: \"mappings-change\", mappings: resolveMappings(state) })\n },\n\n async mappings() {\n return resolveMappings(state)\n },\n }\n}\n","import type { GristApiImpl } from \"./types\"\n\n/** `_grist_api` host implementation. Minimal v1 — extend as needed. */\nexport function createGristApiImpl(): GristApiImpl {\n return {\n async ping() {\n return \"pong\"\n },\n }\n}\n","import type { GristReplicaColumn } from \"../../sdk/types\"\n\n/** Ref / RefList column → the gristHelper_ column holding its display values. */\nexport function inferDisplayHelpersByRef(\n columns: Record<string, GristReplicaColumn>\n): Record<string, string> {\n const out: Record<string, string> = {}\n const helperColumns = Object.entries(columns).filter(([colId]) =>\n colId.startsWith(\"gristHelper_\")\n )\n const usedHelpers = new Set<string>()\n const colRefToColId = new Map<number, string>()\n for (const [colId, col] of Object.entries(columns)) {\n if (typeof col?.colRef === \"number\" && Number.isFinite(col.colRef)) {\n colRefToColId.set(col.colRef, colId)\n }\n }\n for (const [colId, col] of Object.entries(columns)) {\n const type = col?.type\n if (typeof type !== \"string\" || (!type.startsWith(\"Ref:\") && !type.startsWith(\"RefList:\"))) {\n continue\n }\n if (typeof col.displayColRef === \"number\" && Number.isFinite(col.displayColRef)) {\n const helperColId = colRefToColId.get(col.displayColRef)\n if (helperColId) {\n out[colId] = helperColId\n usedHelpers.add(helperColId)\n continue\n }\n }\n const match = helperColumns.find(([, helper]) => {\n const formula = helper?.formula\n return typeof formula === \"string\" && (formula.includes(`$${colId}.`) || formula.includes(`$${colId}`))\n })\n if (match) {\n out[colId] = match[0]\n usedHelpers.add(match[0])\n }\n }\n\n // Secondary fallback for schemas where helper formulas are unavailable:\n // pair unresolved Ref/RefList columns with nearest following gristHelper_*.\n const unresolvedRefs = Object.entries(columns)\n .filter(([colId, col]) => {\n const type = col?.type\n return (\n !out[colId] &&\n typeof type === \"string\" &&\n (type.startsWith(\"Ref:\") || type.startsWith(\"RefList:\"))\n )\n })\n .sort((a, b) => (a[1]?.parentPos ?? Number.MAX_SAFE_INTEGER) - (b[1]?.parentPos ?? Number.MAX_SAFE_INTEGER))\n const helperByPos = helperColumns\n .filter(([helperId]) => !usedHelpers.has(helperId))\n .sort((a, b) => (a[1]?.parentPos ?? Number.MAX_SAFE_INTEGER) - (b[1]?.parentPos ?? Number.MAX_SAFE_INTEGER))\n for (const [refId, refCol] of unresolvedRefs) {\n const refPos = refCol?.parentPos ?? Number.MAX_SAFE_INTEGER\n const candidate = helperByPos.find(([, helperCol]) => {\n const helperPos = helperCol?.parentPos ?? Number.MAX_SAFE_INTEGER\n return helperPos > refPos\n })\n if (!candidate) continue\n out[refId] = candidate[0]\n usedHelpers.add(candidate[0])\n }\n // If multiple unresolved refs remain, greedily map by order.\n for (const [refId] of unresolvedRefs) {\n if (out[refId]) continue\n const candidate = helperByPos.find(([helperId]) => !usedHelpers.has(helperId))\n if (!candidate) continue\n out[refId] = candidate[0]\n usedHelpers.add(candidate[0])\n }\n return out\n}\n","import { inferDisplayHelpersByRef } from \"./display-helpers\"\nimport { normalizeReplicaDocumentInput } from \"../../sdk/helpers/replica-normalize\"\nimport { coerceGristDocApiRefRowId } from \"../../sdk/helpers/grist-value-codec\"\nimport type { GristReplicaDocument, GristReplicaTable } from \"../../sdk/replica-document\"\nimport type { GristRowRecord } from \"../../sdk/types\"\nimport type { EmulatorColumn, EmulatorDocumentState, EmulatorTable } from \"./types\"\n\nconst SYSTEM_COLUMN = \"id\"\n\nconst EMULATOR_JS_FORMULA_PLACEHOLDER = \"(emulator JavaScript formula)\"\n\n/** Replica table for {@link createDocument}; columns may include `formulaFn` / `inferredFormula` (emulator-only). */\nexport type CreateDocumentTableInput = Omit<GristReplicaTable, \"columns\"> & {\n columns?: Record<string, EmulatorColumn>\n}\n\n/** Replica document for {@link createDocument}; widens table columns to {@link EmulatorColumn}. */\nexport type CreateDocumentInput = Omit<GristReplicaDocument, \"tables\"> & {\n tables: Record<string, CreateDocumentTableInput>\n}\n\n/**\n * Ensure `formula` (original) and `inferredFormula` strings exist alongside optional `formulaFn`.\n */\nexport function enrichEmulatorColumnMetadata(col: EmulatorColumn): EmulatorColumn {\n const originalTrimmed = col.formula?.trim() ?? \"\"\n const explicitInferred = col.inferredFormula?.trim() ?? \"\"\n\n if (col.formulaFn) {\n const inferredFormula =\n explicitInferred || originalTrimmed || EMULATOR_JS_FORMULA_PLACEHOLDER\n return {\n ...col,\n ...(originalTrimmed ? { formula: col.formula } : {}),\n inferredFormula,\n }\n }\n\n if (explicitInferred || originalTrimmed) {\n return {\n ...col,\n inferredFormula: explicitInferred || originalTrimmed || undefined,\n }\n }\n\n return col\n}\n\n/** Order merged column metadata for stable `fetchTable` / RDG column order. */\nexport function sortEmulatorColumnsByParentPos(columns: Record<string, EmulatorColumn>): Record<string, EmulatorColumn> {\n const entries = Object.entries(columns)\n entries.sort(([ka, a], [kb, b]) => {\n const pa = a.parentPos\n const pb = 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 ka.localeCompare(kb)\n })\n return Object.fromEntries(entries)\n}\n\nfunction inferColumnsFromRows(rows: GristRowRecord[]): Record<string, EmulatorColumn> {\n const columns: Record<string, EmulatorColumn> = {}\n for (const row of rows) {\n for (const key of Object.keys(row)) {\n if (key === SYSTEM_COLUMN) continue\n if (!columns[key]) columns[key] = inferColumnType(row[key])\n }\n }\n return columns\n}\n\nfunction inferColumnType(sample: unknown): EmulatorColumn {\n switch (typeof sample) {\n case \"number\":\n return { type: \"Numeric\" }\n case \"boolean\":\n return { type: \"Bool\" }\n case \"string\":\n return { type: \"Text\" }\n default:\n return { type: \"Any\" }\n }\n}\n\nfunction buildTable(tableId: string, input: CreateDocumentTableInput): EmulatorTable {\n const rows = input.rows ?? []\n const inferred = inferColumnsFromRows(rows)\n const merged: Record<string, EmulatorColumn> = {}\n for (const [colId, col] of Object.entries({ ...inferred, ...(input.columns ?? {}) })) {\n merged[colId] = enrichEmulatorColumnMetadata(col)\n }\n const columns = sortEmulatorColumnsByParentPos(merged)\n return {\n tableId,\n label: input.label,\n columns,\n rows: rows.map((row) => ({ ...row })),\n }\n}\n\n/**\n * Build an immutable initial document state from a user-provided\n * {@link GristReplicaDocument}. The state is **not** frozen — the action\n * engine mutates it in place under deterministic event diffusion.\n */\nexport function createDocument(input: CreateDocumentInput): EmulatorDocumentState {\n if (!input.tables || Object.keys(input.tables).length === 0) {\n throw new Error(\"createDocument: at least one table is required\")\n }\n\n const normalized = normalizeReplicaDocumentInput(input)\n\n const tables = new Map<string, EmulatorTable>()\n for (const [tableId, tableInput] of Object.entries(normalized.tables)) {\n tables.set(tableId, buildTable(tableId, tableInput))\n }\n\n const firstTableId = tables.keys().next().value as string\n const requestedTableId = normalized.selection?.tableId\n const selectedTableId =\n requestedTableId && tables.has(requestedTableId) ? requestedTableId : firstTableId\n const selectedTable = tables.get(selectedTableId)!\n const fallbackRowId =\n typeof selectedTable.rows[0]?.id === \"number\" ? selectedTable.rows[0].id : null\n const selection = {\n tableId: selectedTableId,\n rowId: normalized.selection?.rowId ?? fallbackRowId,\n mappings: normalized.selection?.mappings,\n cursor: normalized.selection?.cursor,\n } as EmulatorDocumentState[\"selection\"]\n\n return {\n docName: normalized.docName ?? \"Untitled emulator document\",\n tables,\n selection,\n widgetOptions: { ...(normalized.widgetOptions ?? {}) },\n widgetInteraction: { ...(normalized.widgetInteraction ?? {}) },\n configuration: normalized.configuration ?? null,\n accessToken: normalized.accessToken ?? null,\n }\n}\n\nexport function getTable(state: EmulatorDocumentState, tableId: string): EmulatorTable {\n const table = state.tables.get(tableId)\n if (!table) throw new Error(`Unknown table: ${tableId}`)\n return table\n}\n\nexport function getSelectedTable(state: EmulatorDocumentState): EmulatorTable {\n return getTable(state, state.selection.tableId)\n}\n\nexport function nextRowId(table: EmulatorTable): number {\n let max = 0\n for (const row of table.rows) {\n if (typeof row.id === \"number\" && row.id > max) max = row.id\n }\n return max + 1\n}\n\nexport function findRow(table: EmulatorTable, rowId: number): GristRowRecord | undefined {\n return table.rows.find((r) => r.id === rowId)\n}\n\nexport function findRowIndex(table: EmulatorTable, rowId: number): number {\n return table.rows.findIndex((r) => r.id === rowId)\n}\n\n/**\n * Re-evaluate every formula column for a given row in-place. Called by the\n * action engine after Add/Update operations.\n */\nexport function evaluateRowFormulas(\n state: EmulatorDocumentState,\n table: EmulatorTable,\n row: GristRowRecord\n): void {\n for (const [colId, col] of Object.entries(table.columns)) {\n if (col.formulaFn) {\n try {\n row[colId] = col.formulaFn(row, { table, document: state })\n } catch (err) {\n row[colId] = formulaError(err)\n }\n }\n }\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\n}\n\n/** Pull stored row ids from a `RefList` cell (`[\"L\", ...]` or legacy shapes). */\nfunction extractRefListIdsFromWire(raw: unknown): number[] {\n if (raw == null) return []\n if (!Array.isArray(raw)) return []\n const items = raw[0] === \"L\" ? raw.slice(1) : raw\n const out: number[] = []\n for (const item of items) {\n if (typeof item === \"number\" && Number.isFinite(item) && item > 0) {\n out.push(Math.trunc(item))\n continue\n }\n if (item && typeof item === \"object\" && \"rowId\" in item) {\n const r = (item as { rowId: unknown }).rowId\n if (typeof r === \"number\" && Number.isFinite(r) && r > 0) {\n out.push(Math.trunc(r))\n continue\n }\n }\n const t = coerceGristDocApiRefRowId(item)\n if (t !== undefined && t > 0) out.push(Math.trunc(t))\n }\n return Array.from(new Set(out))\n}\n\nfunction fieldFromRefListHelperFormula(formula: string | undefined, refColId: string): string | null {\n if (!formula) return null\n const re = new RegExp(`\\\\$${escapeRegExp(refColId)}\\\\.([A-Za-z_]\\\\w*)`)\n const m = formula.match(re)\n return m?.[1] ?? null\n}\n\nfunction firstTextLikeColumnId(columns: Record<string, EmulatorColumn>): string | null {\n let best: { id: string; pos: number } | null = null\n for (const [colId, col] of Object.entries(columns)) {\n if (colId === \"id\" || colId.startsWith(\"gristHelper_\")) continue\n const t = col.type\n if (t !== \"Text\" && t !== \"Choice\") continue\n const pos = col.parentPos ?? 99999\n if (!best || pos < best.pos) best = { id: colId, pos }\n }\n return best?.id ?? null\n}\n\nfunction formatLabelFromCell(value: unknown): string {\n if (value == null) return \"\"\n if (typeof value === \"string\") return value.trim()\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value)\n if (value instanceof Date) return value.toISOString()\n if (Array.isArray(value) && value[0] === \"E\") return \"\"\n if (typeof value === \"object\" && value && \"__ref\" in value) {\n const r = (value as { rowId?: unknown }).rowId\n return typeof r === \"number\" && Number.isFinite(r) ? String(r) : \"\"\n }\n return \"\"\n}\n\n/**\n * Keep `gristHelper_*` display columns aligned with `RefList:*` ids after writes.\n *\n * Real Grist evaluates helper formulas (`$multiref.Nom`); replica JSON only\n * carries the formula string (no `formulaFn`), so helpers would stay stale and\n * a widget reading them would see empty labels.\n *\n * Skips helpers that define `formulaFn` so custom JS formulas keep ownership.\n */\nexport function syncRefListDisplayHelpers(\n state: EmulatorDocumentState,\n table: EmulatorTable,\n row: GristRowRecord\n): void {\n const displayHelpersByRef = inferDisplayHelpersByRef(table.columns)\n for (const [colId, col] of Object.entries(table.columns)) {\n const type = col.type\n if (typeof type !== \"string\" || !type.startsWith(\"RefList:\")) continue\n const helperColId = displayHelpersByRef[colId]\n if (!helperColId) continue\n const helperMeta = table.columns[helperColId]\n if (!helperMeta || helperMeta.formulaFn) continue\n\n const targetTableId = type.slice(\"RefList:\".length)\n const targetTable = state.tables.get(targetTableId)\n if (!targetTable) continue\n\n const ids = extractRefListIdsFromWire(row[colId])\n if (ids.length === 0) {\n row[helperColId] = []\n continue\n }\n\n const fieldId =\n fieldFromRefListHelperFormula(helperMeta.formula, colId) ??\n firstTextLikeColumnId(targetTable.columns)\n\n const labels = ids.map((rid) => {\n if (!fieldId) return String(rid)\n const trow = findRow(targetTable, rid)\n if (!trow) return String(rid)\n const lbl = formatLabelFromCell(trow[fieldId])\n return lbl !== \"\" ? lbl : String(rid)\n })\n row[helperColId] = labels\n }\n}\n\nfunction formulaError(err: unknown): unknown {\n // Match Grist's encoded error format: [\"E\", code, message]\n const message = err instanceof Error ? err.message : String(err)\n return [\"E\", \"Error\", message]\n}\n\n/**\n * Synthesise `_grist_Tables` metadata from the emulator's in-memory tables.\n * Returns Grist's columnar wire shape.\n */\nexport function synthesizeTablesMeta(state: EmulatorDocumentState): Record<string, unknown[]> {\n const ids: number[] = []\n const tableIds: string[] = []\n const labels: (string | null)[] = []\n\n let nextId = 1\n for (const [tableId, table] of state.tables.entries()) {\n ids.push(nextId)\n tableIds.push(tableId)\n labels.push(table.label ?? null)\n nextId += 1\n }\n\n return {\n id: ids,\n tableId: tableIds,\n // Optional human-readable label; real Grist keeps more fields, but these\n // are sufficient for `buildReplicaDocumentFromDocApi` to resolve table ids.\n label: labels,\n }\n}\n\n/**\n * Synthesise `_grist_Tables_column` metadata from emulator tables/columns.\n * Mirrors the subset of fields consumed by `buildReplicaDocumentFromDocApi`.\n */\nexport function synthesizeTablesColumnMeta(state: EmulatorDocumentState): Record<string, unknown[]> {\n const parentIds: number[] = []\n const colIds: string[] = []\n const columnIds: number[] = []\n const types: (string | null)[] = []\n const labels: (string | null)[] = []\n const parentPos: (number | null)[] = []\n const isFormula: boolean[] = []\n const formulas: (string | null)[] = []\n const descriptions: (string | null)[] = []\n const widgetOptions: unknown[] = []\n const displayCol: (number | null)[] = []\n const visibleCol: (number | null)[] = []\n\n // Mirror the synthetic table ids from `synthesizeTablesMeta`.\n const tableIdToInternalId = new Map<string, number>()\n {\n let nextId = 1\n for (const [tableId] of state.tables.entries()) {\n tableIdToInternalId.set(tableId, nextId)\n nextId += 1\n }\n }\n\n for (const [tableId, table] of state.tables.entries()) {\n const parentInternalId = tableIdToInternalId.get(tableId)\n if (parentInternalId === undefined) continue\n\n for (const [colId, col] of Object.entries(table.columns)) {\n parentIds.push(parentInternalId)\n colIds.push(colId)\n // Prefer explicit `colRef` when present; fall back to 1-based index of insertion.\n const ref = typeof col.colRef === \"number\" ? col.colRef : columnIds.length + 1\n columnIds.push(ref)\n types.push(col.type ?? null)\n labels.push(col.label ?? null)\n parentPos.push(col.parentPos ?? null)\n isFormula.push(Boolean(col.isFormula))\n const formula = typeof col.formula === \"string\" ? col.formula : null\n formulas.push(formula)\n descriptions.push(col.description ?? null)\n widgetOptions.push(col.widgetOptions ?? null)\n displayCol.push(typeof col.displayColRef === \"number\" ? col.displayColRef : null)\n visibleCol.push(typeof col.visibleColRef === \"number\" ? col.visibleColRef : null)\n }\n }\n\n return {\n parentId: parentIds,\n colId: colIds,\n id: columnIds,\n type: types,\n label: labels,\n parentPos,\n isFormula,\n formula: formulas,\n description: descriptions,\n // Also expose legacy `descr` for robustness.\n descr: descriptions,\n widgetOptions,\n displayCol,\n visibleCol,\n }\n}\n","/**\n * Pure action engine: applies Grist user actions to an\n * {@link EmulatorDocumentState} and emits the resulting events on the bus.\n *\n * This is the single place where state mutates. Every API impl ultimately\n * routes through `applyUserActions` so behaviour is consistent regardless of\n * the surface (`grist.docApi.applyUserActions`, `selectedTable.create`,\n * `setCursorPos`, etc.).\n *\n * Supported user actions:\n * - AddRecord, BulkAddRecord\n * - UpdateRecord, BulkUpdateRecord\n * - RemoveRecord, BulkRemoveRecord\n * - AddColumn, RemoveColumn, RenameColumn, ModifyColumn\n * - AddTable, RemoveTable, RenameTable\n *\n * Unknown actions throw a structured error instead of silently succeeding,\n * which surfaces protocol gaps loudly during widget development.\n */\n\nimport { coerceGristDocApiRefRowId } from \"../../sdk/helpers/grist-value-codec\"\nimport {\n evaluateRowFormulas,\n findRow,\n findRowIndex,\n getTable,\n nextRowId,\n syncRefListDisplayHelpers,\n} from \"./document\"\nimport type { EventBus } from \"./event-bus\"\nimport type { EmulatorColumn, EmulatorDocumentState, EmulatorTable } from \"./types\"\n\nexport class EmulatorActionError extends Error {\n constructor(\n public readonly action: unknown,\n message: string\n ) {\n super(message)\n this.name = \"EmulatorActionError\"\n }\n}\n\nexport type ApplyUserActionResult = {\n /** Result mirroring Grist's `applyUserActions`: per-action retValues. */\n retValues: unknown[]\n /** Tables that received row-level changes (de-duped). */\n changedTableIds: string[]\n}\n\nexport function applyUserActions(\n state: EmulatorDocumentState,\n bus: EventBus,\n actions: unknown[][]\n): ApplyUserActionResult {\n const retValues: unknown[] = []\n const changed = new Set<string>()\n\n for (const action of actions) {\n bus.emit({ type: \"user-action\", action })\n const ret = applySingle(state, action, changed)\n retValues.push(ret)\n }\n\n for (const tableId of changed) {\n bus.emit({ type: \"data-change\", tableId })\n }\n\n return { retValues, changedTableIds: [...changed] }\n}\n\nfunction applySingle(\n state: EmulatorDocumentState,\n action: unknown[],\n changed: Set<string>\n): unknown {\n const [name, ...args] = action\n switch (name) {\n case \"AddRecord\":\n return addRecord(state, args, changed)\n case \"BulkAddRecord\":\n return bulkAddRecord(state, args, changed)\n case \"UpdateRecord\":\n return updateRecord(state, args, changed)\n case \"BulkUpdateRecord\":\n return bulkUpdateRecord(state, args, changed)\n case \"RemoveRecord\":\n return removeRecord(state, args, changed)\n case \"BulkRemoveRecord\":\n return bulkRemoveRecord(state, args, changed)\n case \"AddColumn\":\n return addColumn(state, args)\n case \"AddVisibleColumn\":\n // The emulator has no concept of section view fields, so the \"visible\"\n // part of `AddVisibleColumn` is a no-op here. We still create the\n // column so widgets that issue this user action (the higher-level form\n // recommended by Grist for \"add a column to the active view\") work\n // identically against the emulator.\n return addColumn(state, args)\n case \"RemoveColumn\":\n return removeColumn(state, args, changed)\n case \"RenameColumn\":\n return renameColumn(state, args, changed)\n case \"ModifyColumn\":\n return modifyColumn(state, args, changed)\n case \"AddTable\":\n return addTable(state, args)\n case \"RemoveTable\":\n return removeTable(state, args)\n case \"RenameTable\":\n return renameTable(state, args)\n default:\n throw new EmulatorActionError(action, `Unsupported user action: ${String(name)}`)\n }\n}\n\n// ---------- row ops ----------\n\nfunction addRecord(\n state: EmulatorDocumentState,\n [tableId, rowId, values]: unknown[],\n changed: Set<string>\n): number {\n const table = getTable(state, requireString(tableId, \"AddRecord.tableId\"))\n const id = typeof rowId === \"number\" ? rowId : nextRowId(table)\n const normalizedValues = normalizeValuesForTable(\n table,\n (values as Record<string, unknown>) ?? {}\n )\n const row = { id, ...normalizedValues }\n ensureColumns(table, normalizedValues)\n evaluateRowFormulas(state, table, row)\n syncRefListDisplayHelpers(state, table, row)\n table.rows.push(row)\n changed.add(table.tableId)\n return id\n}\n\nfunction bulkAddRecord(\n state: EmulatorDocumentState,\n [tableId, rowIds, columnar]: unknown[],\n changed: Set<string>\n): number[] {\n const table = getTable(state, requireString(tableId, \"BulkAddRecord.tableId\"))\n const cols = normalizeColumnarForTable(\n table,\n (columnar as Record<string, unknown[]>) ?? {}\n )\n const ids = Array.isArray(rowIds) ? rowIds : []\n const length = ids.length || lengthOf(cols)\n const out: number[] = []\n ensureColumns(table, cols, true)\n for (let i = 0; i < length; i++) {\n const id = typeof ids[i] === \"number\" ? (ids[i] as number) : nextRowId(table)\n const row: Record<string, unknown> & { id: number } = { id }\n for (const colId of Object.keys(cols)) row[colId] = cols[colId][i]\n evaluateRowFormulas(state, table, row)\n syncRefListDisplayHelpers(state, table, row)\n table.rows.push(row)\n out.push(id)\n }\n changed.add(table.tableId)\n return out\n}\n\nfunction updateRecord(\n state: EmulatorDocumentState,\n [tableId, rowId, values]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"UpdateRecord.tableId\"))\n const id = requireNumber(rowId, \"UpdateRecord.rowId\")\n const row = findRow(table, id)\n if (!row) throw new EmulatorActionError([\"UpdateRecord\", tableId, rowId, values], `Row ${id} not found in ${table.tableId}`)\n const normalizedValues = normalizeValuesForTable(\n table,\n (values as Record<string, unknown>) ?? {}\n )\n ensureColumns(table, normalizedValues)\n Object.assign(row, normalizedValues)\n evaluateRowFormulas(state, table, row)\n syncRefListDisplayHelpers(state, table, row)\n changed.add(table.tableId)\n return null\n}\n\nfunction bulkUpdateRecord(\n state: EmulatorDocumentState,\n [tableId, rowIds, columnar]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"BulkUpdateRecord.tableId\"))\n const ids = rowIds as number[]\n const cols = normalizeColumnarForTable(\n table,\n (columnar as Record<string, unknown[]>) ?? {}\n )\n ensureColumns(table, cols, true)\n ids.forEach((id, idx) => {\n const row = findRow(table, id)\n if (!row) throw new EmulatorActionError([\"BulkUpdateRecord\", tableId, ids, cols], `Row ${id} not found in ${table.tableId}`)\n for (const colId of Object.keys(cols)) row[colId] = cols[colId][idx]\n evaluateRowFormulas(state, table, row)\n syncRefListDisplayHelpers(state, table, row)\n })\n changed.add(table.tableId)\n return null\n}\n\nfunction removeRecord(\n state: EmulatorDocumentState,\n [tableId, rowId]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"RemoveRecord.tableId\"))\n const id = requireNumber(rowId, \"RemoveRecord.rowId\")\n const idx = findRowIndex(table, id)\n if (idx >= 0) table.rows.splice(idx, 1)\n if (state.selection.tableId === table.tableId && state.selection.rowId === id) {\n state.selection.rowId = table.rows[0]?.id ?? null\n }\n changed.add(table.tableId)\n return null\n}\n\nfunction bulkRemoveRecord(\n state: EmulatorDocumentState,\n [tableId, rowIds]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"BulkRemoveRecord.tableId\"))\n const ids = new Set(rowIds as number[])\n table.rows = table.rows.filter((r) => !ids.has(r.id))\n if (state.selection.tableId === table.tableId && typeof state.selection.rowId === \"number\" && ids.has(state.selection.rowId)) {\n state.selection.rowId = table.rows[0]?.id ?? null\n }\n changed.add(table.tableId)\n return null\n}\n\n// ---------- column ops ----------\n\nfunction addColumn(\n state: EmulatorDocumentState,\n [tableId, colId, info]: unknown[]\n): null {\n const table = getTable(state, requireString(tableId, \"AddColumn.tableId\"))\n const col = requireString(colId, \"AddColumn.colId\")\n if (table.columns[col]) throw new EmulatorActionError([\"AddColumn\", tableId, colId], `Column ${col} already exists`)\n table.columns[col] = (info as EmulatorColumn) ?? {}\n for (const row of table.rows) {\n if (!(col in row)) row[col] = null\n }\n return null\n}\n\nfunction removeColumn(\n state: EmulatorDocumentState,\n [tableId, colId]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"RemoveColumn.tableId\"))\n const col = requireString(colId, \"RemoveColumn.colId\")\n delete table.columns[col]\n for (const row of table.rows) delete row[col]\n changed.add(table.tableId)\n return null\n}\n\nfunction renameColumn(\n state: EmulatorDocumentState,\n [tableId, colId, newColId]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"RenameColumn.tableId\"))\n const from = requireString(colId, \"RenameColumn.colId\")\n const to = requireString(newColId, \"RenameColumn.newColId\")\n if (!table.columns[from]) throw new EmulatorActionError([\"RenameColumn\", tableId, from, to], `Column ${from} not found`)\n if (from === to) return null\n table.columns[to] = table.columns[from]\n delete table.columns[from]\n for (const row of table.rows) {\n if (from in row) {\n row[to] = row[from]\n delete row[from]\n }\n }\n changed.add(table.tableId)\n return null\n}\n\nfunction modifyColumn(\n state: EmulatorDocumentState,\n [tableId, colId, info]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"ModifyColumn.tableId\"))\n const col = requireString(colId, \"ModifyColumn.colId\")\n if (!table.columns[col]) throw new EmulatorActionError([\"ModifyColumn\", tableId, colId], `Column ${col} not found`)\n table.columns[col] = { ...table.columns[col], ...(info as EmulatorColumn) }\n changed.add(table.tableId)\n return null\n}\n\n// ---------- table ops ----------\n\nfunction addTable(state: EmulatorDocumentState, [tableId, columns]: unknown[]): string {\n const id = requireString(tableId, \"AddTable.tableId\")\n if (state.tables.has(id)) throw new EmulatorActionError([\"AddTable\", tableId], `Table ${id} already exists`)\n const cols: Record<string, EmulatorColumn> = {}\n for (const c of (columns as Array<{ id: string } & EmulatorColumn>) ?? []) {\n cols[c.id] = { ...c }\n }\n state.tables.set(id, { tableId: id, columns: cols, rows: [] })\n return id\n}\n\nfunction removeTable(state: EmulatorDocumentState, [tableId]: unknown[]): null {\n const id = requireString(tableId, \"RemoveTable.tableId\")\n state.tables.delete(id)\n if (state.selection.tableId === id) {\n const fallback = state.tables.keys().next().value as string | undefined\n if (fallback) {\n state.selection.tableId = fallback\n state.selection.rowId = null\n }\n }\n return null\n}\n\nfunction renameTable(state: EmulatorDocumentState, [from, to]: unknown[]): null {\n const fromId = requireString(from, \"RenameTable.from\")\n const toId = requireString(to, \"RenameTable.to\")\n const table = state.tables.get(fromId)\n if (!table) throw new EmulatorActionError([\"RenameTable\", fromId], `Table ${fromId} not found`)\n state.tables.delete(fromId)\n table.tableId = toId\n state.tables.set(toId, table)\n if (state.selection.tableId === fromId) state.selection.tableId = toId\n return null\n}\n\n// ---------- helpers ----------\n\nfunction ensureColumns(\n table: EmulatorTable,\n values: Record<string, unknown> | Record<string, unknown[]>,\n bulk = false\n): void {\n for (const col of Object.keys(values)) {\n if (!table.columns[col]) {\n const sample = bulk ? (values as Record<string, unknown[]>)[col]?.[0] : (values as Record<string, unknown>)[col]\n table.columns[col] = inferType(sample)\n }\n }\n}\n\nfunction inferType(sample: unknown): EmulatorColumn {\n switch (typeof sample) {\n case \"number\":\n return { type: \"Numeric\" }\n case \"boolean\":\n return { type: \"Bool\" }\n case \"string\":\n return { type: \"Text\" }\n default:\n return { type: \"Any\" }\n }\n}\n\nfunction lengthOf(cols: Record<string, unknown[]>): number {\n for (const arr of Object.values(cols)) if (Array.isArray(arr)) return arr.length\n return 0\n}\n\nfunction requireString(value: unknown, name: string): string {\n if (typeof value !== \"string\" || !value) throw new Error(`Expected non-empty string for ${name}`)\n return value\n}\n\nfunction requireNumber(value: unknown, name: string): number {\n if (typeof value !== \"number\" || Number.isNaN(value)) throw new Error(`Expected number for ${name}`)\n return value\n}\n\nfunction normalizeValuesForTable(\n table: EmulatorTable,\n values: Record<string, unknown>\n): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const [colId, value] of Object.entries(values)) {\n out[colId] = normalizeCellValueForType(value, table.columns[colId]?.type)\n }\n return out\n}\n\nfunction normalizeColumnarForTable(\n table: EmulatorTable,\n columns: Record<string, unknown[]>\n): Record<string, unknown[]> {\n const out: Record<string, unknown[]> = {}\n for (const [colId, values] of Object.entries(columns)) {\n const type = table.columns[colId]?.type\n out[colId] = Array.isArray(values)\n ? values.map((value) => normalizeCellValueForType(value, type))\n : []\n }\n return out\n}\n\nfunction normalizeCellValueForType(value: unknown, type: string | undefined): unknown {\n if (value === null || value === undefined || typeof type !== \"string\") return value\n\n // As Grist does (checked in 1.7.22): a list column takes `[\"L\", ...]`; a\n // bare array written to it is stored as an error cell, not as the list.\n if (isListColumnType(type) && Array.isArray(value) && value[0] !== \"L\") return [\"E\", \"KeyError\"]\n if (type.startsWith(\"Ref:\")) return normalizeRefValue(value)\n if (type.startsWith(\"RefList:\")) return normalizeRefListValue(value)\n return value\n}\n\n/**\n * Canonical ref row id for emulator storage (`Ref:*` columns).\n * Accepts bare ids, `\"12\"`, Grist tuples `[\"r\", id]` / `[\"R\", tableId, id]`,\n * and detailed-ref shapes `{ rowId }` (decoded `Reference` values, grid edits).\n */\nfunction extractRefRowId(value: unknown): number | null {\n if (value === null || value === undefined) return null\n if (value && typeof value === \"object\" && \"__ref\" in value) {\n const inner = (value as { rowId?: unknown }).rowId\n return extractRefRowId(inner)\n }\n if (value && typeof value === \"object\" && \"rowId\" in value) {\n return extractRefRowId((value as { rowId: unknown }).rowId)\n }\n const fromTuple = coerceGristDocApiRefRowId(value)\n if (fromTuple !== undefined && fromTuple > 0) return Math.trunc(fromTuple)\n return toPositiveInt(value)\n}\n\nfunction isListColumnType(type: string): boolean {\n return type === \"ChoiceList\" || type === \"Attachments\" || type.startsWith(\"RefList:\")\n}\n\nfunction normalizeRefValue(value: unknown): number | null {\n return extractRefRowId(value)\n}\n\nfunction normalizeRefListValue(value: unknown): unknown[] {\n const toIdList = (items: unknown[]): number[] =>\n Array.from(\n new Set(items.map((item) => extractRefRowId(item)).filter((item): item is number => item !== null))\n )\n\n // Grist tuple form: [\"L\", ...ids]\n if (Array.isArray(value) && value[0] === \"L\") {\n return [\"L\", ...toIdList(value.slice(1))]\n }\n if (Array.isArray(value)) {\n return [\"L\", ...toIdList(value)]\n }\n if (typeof value === \"string\") {\n const tokens = value.split(\",\").map((t) => t.trim()).filter(Boolean)\n return [\"L\", ...toIdList(tokens)]\n }\n if (value && typeof value === \"object\" && Array.isArray((value as { rowIds?: unknown }).rowIds)) {\n return [\"L\", ...toIdList((value as { rowIds: unknown[] }).rowIds)]\n }\n return [\"L\"]\n}\n\nfunction toPositiveInt(value: unknown): number | null {\n if (typeof value === \"number\" && Number.isFinite(value) && value > 0) return Math.trunc(value)\n if (typeof value === \"string\") {\n const n = Number.parseInt(value.trim(), 10)\n if (Number.isFinite(n) && n > 0) return n\n }\n return null\n}\n","/**\n * Helpers to project an {@link EmulatorTable}'s row-array storage into Grist's\n * columnar wire format expected by `fetchTable` / `fetchSelectedTable`:\n *\n * { id: number[], colA: unknown[], colB: unknown[], ... }\n *\n * When `keepEncoded` is `false` (Grist's default for these APIs), values are\n * passed through as-is — JS-native primitives (string / number / boolean /\n * Date / arrays) are valid Grist plugin values. When `keepEncoded` is `true`,\n * Date columns are emitted in tuple form (`[\"d\", epoch]`) so callers can\n * round-trip them.\n */\n\nimport type { GristRowRecord } from \"../../sdk/types\"\nimport type { EmulatorTable } from \"./types\"\n\nexport type ColumnarTable = Record<string, unknown[]>\n\nexport type ToColumnarOptions = {\n keepEncoded?: boolean\n}\n\nexport function rowsToColumnar(\n table: EmulatorTable,\n rows: readonly GristRowRecord[],\n options: ToColumnarOptions = {}\n): ColumnarTable {\n const cols = Object.keys(table.columns)\n const out: ColumnarTable = { id: rows.map((r) => r.id) }\n for (const col of cols) {\n out[col] = rows.map((r) => encodeForWire(r[col], table.columns[col]?.type, options.keepEncoded))\n }\n return out\n}\n\nexport function rowToRecord(\n table: EmulatorTable,\n row: GristRowRecord,\n options: ToColumnarOptions = {}\n): Record<string, unknown> {\n const out: Record<string, unknown> = { id: row.id }\n for (const col of Object.keys(table.columns)) {\n out[col] = encodeForWire(row[col], table.columns[col]?.type, options.keepEncoded)\n }\n return out\n}\n\nfunction encodeForWire(value: unknown, type: string | undefined, keepEncoded: boolean | undefined): unknown {\n if (value instanceof Date) {\n const epoch = Math.floor(value.getTime() / 1000)\n if (keepEncoded) {\n return type && type.startsWith(\"DateTime\") ? [\"D\", epoch, \"UTC\"] : [\"d\", epoch]\n }\n return epoch\n }\n return value\n}\n","import { applyUserActions } from \"../core/action-engine\"\nimport { rowsToColumnar } from \"../core/columnar\"\nimport { getTable, synthesizeTablesColumnMeta, synthesizeTablesMeta } from \"../core/document\"\nimport type { EventBus } from \"../core/event-bus\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport type { GristDocApiImpl } from \"./types\"\n\n/**\n * `GristDocAPI` host implementation. Backs `grist.docApi.*` methods such as\n * `getDocName`, `listTables`, `fetchTable`, `applyUserActions` and\n * `getAccessToken`.\n *\n * `applyUserActions` is the only mutation entry point — every widget write\n * lands here, so tests can listen on the bus for `user-action` events to\n * assert exactly which actions a UI flow generated.\n */\nexport function createGristDocApiImpl(state: EmulatorDocumentState, bus: EventBus): GristDocApiImpl {\n return {\n async getDocName() {\n return state.docName\n },\n\n async listTables() {\n return [...state.tables.keys()]\n },\n\n async fetchTable(tableId) {\n if (tableId === \"_grist_Tables\") {\n return synthesizeTablesMeta(state)\n }\n if (tableId === \"_grist_Tables_column\") {\n return synthesizeTablesColumnMeta(state)\n }\n const table = getTable(state, tableId)\n return rowsToColumnar(table, table.rows)\n },\n\n async applyUserActions(actions) {\n const result = applyUserActions(state, bus, actions)\n return { retValues: result.retValues }\n },\n\n async getAccessToken() {\n if (!state.accessToken) {\n const err = new Error(\"getAccessToken not available (no token configured on emulator)\")\n // Mirror Grist's protocol: rejected stub call.\n throw err\n }\n return { ...state.accessToken }\n },\n }\n}\n","import { rowToRecord, rowsToColumnar } from \"../core/columnar\"\nimport { findRow, getSelectedTable } from \"../core/document\"\nimport type { EventBus } from \"../core/event-bus\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport type { GristViewImpl } from \"./types\"\n\n/**\n * `GristView` host implementation.\n *\n * Exposes the section-scoped data API the widget uses through\n * `grist.docApi.fetchSelectedTable()`, `fetchSelectedRecord()` and\n * `setCursorPos()`. Reads from the emulator state, writes to the same state\n * via the action engine where applicable, and emits events on the bus so\n * subscribers (transports, inspector, tests) stay in sync.\n *\n * IMPORTANT: `fetchSelectedTable` always returns Grist's **columnar** wire\n * shape. The production `grist-plugin-api.js` wrapper (which the iframe\n * transport talks to) expects the raw RPC stub to return columnar and does\n * the `format: \"rows\"` transposition + `keepEncoded: false` decoding itself.\n * Returning rows here used to crash the wrapper's `mapValues(data, col =>\n * col.map(decodeObject))` pass — `data` was an array, `col` was a row object\n * with no `.map` method — so widgets observed `records === null` forever.\n * The inline transport mirrors the same wrapper semantics in\n * `transports/inline.ts` so widget code sees identical results in both modes.\n */\nexport function createGristViewImpl(state: EmulatorDocumentState, bus: EventBus): GristViewImpl {\n return {\n async fetchSelectedTable(options) {\n const table = getSelectedTable(state)\n return rowsToColumnar(table, table.rows, { keepEncoded: options?.keepEncoded })\n },\n\n async fetchSelectedRecord(rowId, options) {\n const table = getSelectedTable(state)\n const row = findRow(table, rowId)\n if (!row) throw new Error(`No row ${rowId} in ${table.tableId}`)\n return rowToRecord(table, row, { keepEncoded: options?.keepEncoded })\n },\n\n async allowSelectBy() {\n return state.configuration?.allowSelectBy ?? false\n },\n\n async setSelectedRows(rowIds) {\n if (!rowIds || rowIds.length === 0) {\n state.selection.rowId = null\n } else {\n state.selection.rowId = rowIds[0]\n }\n bus.emit({\n type: \"cursor-change\",\n tableId: state.selection.tableId,\n rowId: state.selection.rowId,\n })\n },\n\n async setCursorPos(cursor) {\n const tableId = state.selection.tableId\n if (typeof cursor.rowId === \"number\") state.selection.rowId = cursor.rowId\n state.selection.cursor = { ...state.selection.cursor, ...cursor }\n bus.emit({\n type: \"cursor-change\",\n tableId,\n rowId: state.selection.rowId,\n cursor: state.selection.cursor,\n })\n },\n }\n}\n","import type { EventBus } from \"../core/event-bus\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport type { WidgetApiImpl } from \"./types\"\n\n/**\n * `WidgetAPI` host implementation, backing `grist.widgetApi.*`. Reads and\n * writes the per-widget options bag persisted on the emulator state. Each\n * mutation triggers an `options-change` event so subscribers (the transport\n * pushes an `onOptions` message; tests/inspector update accordingly) stay in\n * lock-step with the document.\n */\nexport function createWidgetApiImpl(state: EmulatorDocumentState, bus: EventBus): WidgetApiImpl {\n function emit() {\n bus.emit({\n type: \"options-change\",\n options: { ...state.widgetOptions },\n interaction: { ...state.widgetInteraction },\n })\n }\n\n return {\n async getOption(key) {\n return state.widgetOptions[key]\n },\n\n async setOption(key, value) {\n state.widgetOptions[key] = value\n emit()\n },\n\n async getOptions() {\n return Object.keys(state.widgetOptions).length > 0 ? { ...state.widgetOptions } : null\n },\n\n // Replaces every option, as Grist's WidgetAPI.setOptions does.\n async setOptions(options) {\n state.widgetOptions = { ...options }\n emit()\n },\n\n async clearOptions() {\n state.widgetOptions = {}\n emit()\n },\n }\n}\n","/**\n * Bundles the six host-side Grist API implementations into one record so\n * inline transport can wire them up.\n */\n\nimport type { EventBus } from \"../core/event-bus\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport { createCommandApiImpl } from \"./command-api\"\nimport { createCustomSectionApiImpl } from \"./custom-section-api\"\nimport { createGristApiImpl } from \"./grist-api\"\nimport { createGristDocApiImpl } from \"./grist-doc-api\"\nimport { createGristViewImpl } from \"./grist-view\"\nimport type {\n CommandApiImpl,\n CustomSectionApiImpl,\n GristApiImpl,\n GristDocApiImpl,\n GristViewImpl,\n WidgetApiImpl,\n} from \"./types\"\nimport { createWidgetApiImpl } from \"./widget-api\"\n\nexport type EmulatorApiBundle = {\n GristView: GristViewImpl\n GristDocAPI: GristDocApiImpl\n WidgetAPI: WidgetApiImpl\n CustomSectionAPI: CustomSectionApiImpl\n GristAPI: GristApiImpl\n CommandAPI: CommandApiImpl\n}\n\n/**\n * Build the implementations bound to a given document state and event bus.\n * Cheap to call — every method delegates to the (mutable) `state`.\n */\nexport function createApiBundle(state: EmulatorDocumentState, bus: EventBus): EmulatorApiBundle {\n return {\n GristView: createGristViewImpl(state, bus),\n GristDocAPI: createGristDocApiImpl(state, bus),\n WidgetAPI: createWidgetApiImpl(state, bus),\n CustomSectionAPI: createCustomSectionApiImpl(state, bus),\n GristAPI: createGristApiImpl(),\n CommandAPI: createCommandApiImpl(bus),\n }\n}\n\nexport type {\n CommandApiImpl,\n CustomSectionApiImpl,\n GristApiImpl,\n GristDocApiImpl,\n GristViewImpl,\n WidgetApiImpl,\n} from \"./types\"\n","/**\n * Tiny pub-sub used to broadcast every emulator state change to:\n * - the transports (which translate events into protocol messages),\n * - the React DevTools inspector (timeline view),\n * - the testing harness (assertions on emitted events).\n */\n\nimport type { GristCursorPos, GristWidgetColumnMap, GristWidgetInteraction } from \"../../sdk/types\"\n\nexport type EmulatorEvent =\n | { type: \"data-change\"; tableId: string }\n | { type: \"cursor-change\"; tableId: string; rowId: number | \"new\" | null; cursor?: GristCursorPos }\n | { type: \"options-change\"; options: Record<string, unknown>; interaction: GristWidgetInteraction }\n | { type: \"theme-change\"; message: Record<string, unknown> }\n | { type: \"ready\"; configuration: unknown }\n | { type: \"user-action\"; action: unknown[] }\n | { type: \"mappings-change\"; mappings: GristWidgetColumnMap | null }\n\nexport type EmulatorEventListener = (event: EmulatorEvent) => void\n\nexport type EventBus = {\n emit: (event: EmulatorEvent) => void\n on: (listener: EmulatorEventListener) => () => void\n history: () => readonly EmulatorEvent[]\n clear: () => void\n}\n\nexport type EventBusOptions = {\n /** Cap on history length (DevTools / tests). Defaults to 200. */\n historyLimit?: number\n}\n\nexport function createEventBus(options: EventBusOptions = {}): EventBus {\n const limit = options.historyLimit ?? 200\n const listeners = new Set<EmulatorEventListener>()\n const history: EmulatorEvent[] = []\n\n return {\n emit(event) {\n history.push(event)\n if (history.length > limit) history.shift()\n for (const fn of [...listeners]) {\n try {\n fn(event)\n } catch (err) {\n console.error(\"[grist-emulator] event listener threw:\", err)\n }\n }\n },\n on(listener) {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n history() {\n return history\n },\n clear() {\n history.length = 0\n },\n }\n}\n","export type GristThemeAppearance = \"light\" | \"dark\"\n\n/** Host → widget postMessage shape used by `grist-plugin-api.js` (`onThemeChange`). */\nexport type GristThemeHostMessage = {\n theme: {\n appearance: GristThemeAppearance\n name: string\n colors: Record<string, string>\n }\n fromReady?: boolean\n}\n\nexport function buildGristThemeHostMessage(\n appearance: GristThemeAppearance,\n options?: { fromReady?: boolean }\n): GristThemeHostMessage {\n return {\n theme: {\n appearance,\n name: appearance,\n colors: {},\n },\n ...(options?.fromReady ? { fromReady: true } : {}),\n }\n}\n","/**\n * Inline transport — synthesises a `window.grist` global wired directly to\n * the emulator state. No iframe, no postMessage, no serialization.\n *\n * Used for:\n * - SDK unit tests in jsdom (`renderWithGrist(...)`),\n * - IDE-style live previews where widget code lives in the same window\n * as the emulator host.\n *\n * The synthesised `grist` object exposes the **same** typed surface as the\n * production `grist-plugin-api.js` (see `hooks/grist-global.d.ts`). Hooks\n * call `grist.docApi.fetchTable(...)` etc. and get the answer directly from\n * the action engine.\n */\n\nimport type {\n GristCursorPos,\n GristFetchSelectedOptions,\n GristMinimalRecord,\n GristReadyOptions,\n GristTableOpOptions,\n GristTableOperations,\n GristTableUpdateRecord,\n GristTableUpsertOptions,\n GristTableUpsertRecord,\n GristWidgetColumnMap,\n GristWidgetInteraction,\n} from \"../../sdk/types\"\nimport {\n gristAddRecordAction,\n gristBulkAddRecordAction,\n gristBulkRemoveRecordAction,\n gristBulkUpdateRecordAction,\n gristRemoveRecordAction,\n gristUpdateRecordAction,\n} from \"../../sdk/helpers/grist-user-actions\"\nimport { applyUserActions } from \"../core/action-engine\"\nimport type { EmulatorEvent } from \"../core/event-bus\"\nimport { findRow, getTable } from \"../core/document\"\nimport { resolveMappings } from \"../core/mappings\"\nimport { buildGristThemeHostMessage } from \"../theme-message\"\nimport type { EmulatorTransport, TransportContext } from \"./types\"\n\n/**\n * Shape of the synthesised global. Matches `globalThis.grist` from\n * `grist-global.d.ts`.\n */\nexport type InlineGristGlobal = {\n ready: (options?: GristReadyOptions) => Promise<void>\n onRecord: (\n cb: (record: Record<string, unknown> | null, mappings?: GristWidgetColumnMap | null) => void,\n options?: GristFetchSelectedOptions\n ) => void\n onRecords: (\n cb: (records: Record<string, unknown>[], mappings?: GristWidgetColumnMap | null) => void,\n options?: GristFetchSelectedOptions\n ) => void\n onOptions: (cb: (options: Record<string, unknown> | null, interaction: GristWidgetInteraction) => void) => void\n onNewRecord: (cb: (mappings: GristWidgetColumnMap | null) => void) => void\n mapColumnNames: (data: Record<string, unknown>) => Record<string, unknown> | null\n mapColumnNamesBack: (data: Record<string, unknown>) => Record<string, unknown>\n getOptions: () => Promise<Record<string, unknown> | null>\n getOption: (key: string) => Promise<unknown>\n setOption: (key: string, value: unknown) => Promise<void>\n setOptions: (options: Record<string, unknown>) => Promise<void>\n clearOptions: () => Promise<void>\n setCursorPos: (pos: GristCursorPos) => Promise<void>\n setSelectedRows: (rowIds: number[] | null) => Promise<void>\n fetchSelectedTable: (options?: GristFetchSelectedOptions) => Promise<Record<string, unknown[]>>\n fetchSelectedRecord: (rowId: number, options?: GristFetchSelectedOptions) => Promise<Record<string, unknown>>\n docApi: {\n getDocName: () => Promise<string>\n listTables: () => Promise<string[]>\n fetchTable: (tableId: string) => Promise<Record<string, unknown[]>>\n applyUserActions: (actions: unknown[][], options?: { desc?: string }) => Promise<{ retValues: unknown[] }>\n getAccessToken?: (options?: { readOnly?: boolean }) => Promise<{ token: string; baseUrl: string }>\n fetchSelectedTable: (options?: GristFetchSelectedOptions) => Promise<Record<string, unknown[]>>\n fetchSelectedRecord: (rowId: number, options?: GristFetchSelectedOptions) => Promise<Record<string, unknown>>\n }\n selectedTable: GristTableOperations\n getTable: (tableId?: string) => GristTableOperations\n sectionApi: {\n configure: (settings: GristReadyOptions) => Promise<void>\n mappings: () => Promise<GristWidgetColumnMap | null>\n }\n on: (eventName: string, listener: (...args: unknown[]) => void) => () => void\n}\n\nexport type InlineTransportOptions = TransportContext & {\n /**\n * Where to mount the synthesised `grist` global.\n * Defaults to the current window. Pass a different target (e.g. an iframe's\n * `contentWindow`) to install it in another realm.\n */\n target?: Window & typeof globalThis\n}\n\n/**\n * Returns an {@link EmulatorTransport} **and** the synthesised `grist`\n * object. `target.grist = global` is set as a side-effect for parity with\n * the production runtime.\n */\nexport function createInlineTransport(\n options: InlineTransportOptions\n): EmulatorTransport & { grist: InlineGristGlobal } {\n const { state, bus, api } = options\n const target = options.target ?? (globalThis as unknown as Window & typeof globalThis)\n\n // The SDK's `useGristAvailability` checks `window.self !== window.top`.\n // The inline transport runs in a top-level window where that's false. We\n // shim `top` so widget code thinks it's embedded — production doesn't use\n // this transport so there's no risk of leaking the shim.\n installFakeIframeContext(target)\n\n type RecordCb = (record: Record<string, unknown> | null, mappings?: GristWidgetColumnMap | null) => void\n type RecordsCb = (records: Record<string, unknown>[], mappings?: GristWidgetColumnMap | null) => void\n type OptionsCb = (options: Record<string, unknown> | null, interaction: GristWidgetInteraction) => void\n type NewRecordCb = (mappings: GristWidgetColumnMap | null) => void\n\n const recordCbs = new Map<RecordCb, GristFetchSelectedOptions | undefined>()\n const recordsCbs = new Map<RecordsCb, GristFetchSelectedOptions | undefined>()\n const optionsCbs = new Set<OptionsCb>()\n const newRecordCbs = new Set<NewRecordCb>()\n const generic = new Map<string, Set<(...args: unknown[]) => void>>()\n\n // Replay caches — production `grist-plugin-api.js` immediately delivers the\n // latest record / records / options to a freshly-subscribed listener, so\n // hooks that subscribe **after** `grist.ready()` still get the initial\n // payload. We mirror that behaviour here.\n type LastRecord = { record: Record<string, unknown> | null; mappings: GristWidgetColumnMap | null }\n type LastRecords = { records: Record<string, unknown>[]; mappings: GristWidgetColumnMap | null }\n type LastOptions = { options: Record<string, unknown> | null; interaction: GristWidgetInteraction }\n let lastRecord: LastRecord | null = null\n let lastRecords: LastRecords | null = null\n let lastOptions: LastOptions | null = null\n let lastNewRecord: GristWidgetColumnMap | null | undefined = undefined\n\n const buildInteraction = options.buildInteraction ?? (() => ({\n access_level: state.configuration?.requiredAccess ?? \"read table\",\n ...state.widgetInteraction,\n }))\n\n async function pushRecord(rowId: number | \"new\" | null) {\n const mappings = resolveMappings(state)\n if (rowId === \"new\") {\n // Grist's onRecord ignores the add-row (rowId \"new\"): only onNewRecord fires.\n lastNewRecord = mappings\n for (const cb of newRecordCbs) {\n try { cb(mappings) } catch (err) { logErr(err) }\n }\n return\n }\n if (rowId === null) {\n lastRecord = { record: null, mappings }\n for (const [cb] of recordCbs) {\n try { cb(null, mappings) } catch (err) { logErr(err) }\n }\n return\n }\n let record: Record<string, unknown> | null = null\n try {\n record = await api.GristView.fetchSelectedRecord(rowId)\n } catch (err) {\n logErr(err)\n }\n lastRecord = { record, mappings }\n for (const [cb, opts] of recordCbs) {\n try {\n const r = opts?.keepEncoded\n ? await api.GristView.fetchSelectedRecord(rowId, { keepEncoded: true })\n : record\n cb(r, mappings)\n } catch (err) {\n logErr(err)\n }\n }\n }\n\n async function pushRecords() {\n const mappings = resolveMappings(state)\n let baseRows: Record<string, unknown>[] = []\n try {\n const columnar = await api.GristView.fetchSelectedTable({})\n baseRows = columnsToRows(columnar)\n } catch (err) {\n logErr(err)\n }\n lastRecords = { records: baseRows, mappings }\n for (const [cb, opts] of recordsCbs) {\n try {\n const fetchOptions = coerceFetchOptions(opts)\n // Re-fetch only when the subscriber asked for a different shape\n // (e.g. `keepEncoded: true`). Otherwise reuse the decoded rows we\n // already have to avoid extra work and to match production where\n // the same fetch is broadcast to every listener.\n const rows = fetchOptions?.keepEncoded\n ? columnsToRows(await api.GristView.fetchSelectedTable({ keepEncoded: true }))\n : baseRows\n cb(rows, mappings)\n } catch (err) {\n logErr(err)\n }\n }\n }\n\n /**\n * Mirror what `viewApi.fetchSelectedTable` does inside `grist-plugin-api.js`:\n * the host RPC stub always returns columnar; the wrapper applies the\n * `format: \"rows\"` transpose (and would decode encoded values when\n * `keepEncoded: false` — a no-op here because our `rowsToColumnar` already\n * emits JS-native primitives in that case).\n *\n * Keeping this logic on the inline side guarantees that widgets see the\n * same result whether they go through the iframe transport (real plugin\n * wrapper) or the inline transport (this wrapper).\n */\n async function fetchSelectedTableShaped(\n opts: GristFetchSelectedOptions | undefined\n ): Promise<Record<string, unknown[]> | Record<string, unknown>[]> {\n const fetchOptions = coerceFetchOptions(opts)\n const columnar = (await api.GristView.fetchSelectedTable(\n fetchOptions ? { keepEncoded: fetchOptions.keepEncoded } : {}\n )) as Record<string, unknown[]>\n if (fetchOptions?.format === \"rows\") return columnsToRows(columnar)\n return columnar\n }\n\n function pushOptions() {\n const opts = Object.keys(state.widgetOptions).length > 0 ? { ...state.widgetOptions } : null\n const interaction = buildInteraction()\n lastOptions = { options: opts, interaction }\n for (const cb of optionsCbs) {\n try { cb(opts, interaction) } catch (err) { logErr(err) }\n }\n }\n\n const offBus = bus.on(async (event: EmulatorEvent) => {\n switch (event.type) {\n case \"data-change\":\n await pushRecords()\n await pushRecord(state.selection.rowId)\n break\n case \"cursor-change\":\n await pushRecord(event.rowId)\n break\n case \"options-change\":\n pushOptions()\n break\n case \"ready\":\n pushOptions()\n if (options.initialTheme) {\n notify(\"message\", buildGristThemeHostMessage(options.initialTheme, { fromReady: true }))\n }\n await pushRecords()\n await pushRecord(state.selection.rowId)\n break\n case \"mappings-change\":\n await pushRecords()\n await pushRecord(state.selection.rowId)\n break\n case \"theme-change\":\n notify(\"message\", event.message)\n break\n }\n })\n\n function makeTableOps(tableId: string): GristTableOperations {\n return {\n async getTableId() { return tableId },\n async create(records, options) {\n const list = Array.isArray(records) ? records : [records]\n const ids: GristMinimalRecord[] = []\n for (const r of list) {\n const result = applyUserActions(state, bus, [\n gristAddRecordAction(tableId, parseFields(r.fields, options)),\n ])\n ids.push({ id: result.retValues[0] as number })\n }\n return Array.isArray(records) ? ids : ids[0]\n },\n async update(records: GristTableUpdateRecord | GristTableUpdateRecord[], options?: GristTableOpOptions) {\n const list = Array.isArray(records) ? records : [records]\n const actions = list.map((r) => gristUpdateRecordAction(tableId, r.id, parseFields(r.fields, options)))\n applyUserActions(state, bus, actions)\n },\n async upsert(records: GristTableUpsertRecord | GristTableUpsertRecord[], options?: GristTableUpsertOptions) {\n const list = Array.isArray(records) ? records : [records]\n const allowAdd = options?.add !== false\n const allowUpdate = options?.update !== false\n const table = getTable(state, tableId)\n const actions: unknown[][] = []\n for (const r of list) {\n const matches = table.rows.filter((row) =>\n Object.entries(r.require).every(([k, v]) => row[k] === v)\n )\n if (matches.length > 0) {\n if (!allowUpdate) continue\n const fields = parseFields(r.fields ?? {}, options)\n for (const m of matches) actions.push(gristUpdateRecordAction(tableId, m.id, fields))\n } else if (allowAdd) {\n actions.push(gristAddRecordAction(tableId, { ...r.require, ...parseFields(r.fields ?? {}, options) }))\n }\n }\n if (actions.length > 0) applyUserActions(state, bus, actions)\n },\n async destroy(recordIds: number | number[]) {\n if (Array.isArray(recordIds)) {\n applyUserActions(state, bus, [gristBulkRemoveRecordAction(tableId, recordIds)])\n } else {\n applyUserActions(state, bus, [gristRemoveRecordAction(tableId, recordIds)])\n }\n // touch the unused bulk-add reference for tree-shaking parity, no-op\n void gristBulkAddRecordAction\n void gristBulkUpdateRecordAction\n },\n }\n }\n\n function notify(event: string, ...args: unknown[]) {\n const set = generic.get(event)\n if (!set) return\n for (const fn of set) {\n try { fn(...args) } catch (err) { logErr(err) }\n }\n }\n\n const grist: InlineGristGlobal = {\n async ready(opts) {\n await api.CustomSectionAPI.configure(opts ? { ...opts, onEditOptions: undefined } as unknown as Record<string, unknown> : {})\n },\n\n onRecord(cb, opts) {\n recordCbs.set(cb, opts)\n // Replay last value so late subscribers don't miss the initial event.\n if (lastRecord) {\n try { cb(lastRecord.record, lastRecord.mappings) } catch (err) { logErr(err) }\n }\n },\n onRecords(cb, opts) {\n recordsCbs.set(cb, opts)\n if (lastRecords) {\n try { cb(lastRecords.records, lastRecords.mappings) } catch (err) { logErr(err) }\n }\n },\n onOptions(cb) {\n optionsCbs.add(cb)\n if (lastOptions) {\n try { cb(lastOptions.options, lastOptions.interaction) } catch (err) { logErr(err) }\n }\n },\n onNewRecord(cb) {\n newRecordCbs.add(cb)\n if (lastNewRecord !== undefined) {\n try { cb(lastNewRecord) } catch (err) { logErr(err) }\n }\n },\n\n mapColumnNames(data) {\n const mappings = resolveMappings(state)\n if (!mappings) return null\n const out: Record<string, unknown> = {}\n let allMapped = true\n for (const [logical, real] of Object.entries(mappings)) {\n if (Array.isArray(real)) {\n out[logical] = real.map((r) => data[r])\n } else if (typeof real === \"string\") {\n out[logical] = data[real]\n } else {\n allMapped = false\n }\n }\n return allMapped ? out : null\n },\n mapColumnNamesBack(data) {\n const mappings = resolveMappings(state)\n if (!mappings) return data\n const out: Record<string, unknown> = {}\n for (const [logical, real] of Object.entries(mappings)) {\n if (typeof real === \"string\" && logical in data) {\n out[real] = data[logical]\n }\n }\n return out\n },\n\n getOption: (k) => api.WidgetAPI.getOption(k),\n setOption: (k, v) => api.WidgetAPI.setOption(k, v),\n getOptions: () => api.WidgetAPI.getOptions(),\n setOptions: (o) => api.WidgetAPI.setOptions(o),\n clearOptions: () => api.WidgetAPI.clearOptions(),\n\n setCursorPos: (pos) => api.GristView.setCursorPos(pos),\n setSelectedRows: (rowIds) => api.GristView.setSelectedRows(rowIds),\n fetchSelectedTable: (opts) =>\n fetchSelectedTableShaped(opts) as Promise<Record<string, unknown[]>>,\n fetchSelectedRecord: (rowId, opts) => api.GristView.fetchSelectedRecord(rowId, coerceFetchOptions(opts)),\n\n docApi: {\n getDocName: () => api.GristDocAPI.getDocName(),\n listTables: () => api.GristDocAPI.listTables(),\n fetchTable: (id) => api.GristDocAPI.fetchTable(id),\n applyUserActions: (actions, options) => api.GristDocAPI.applyUserActions(actions, options),\n getAccessToken: (opts) => api.GristDocAPI.getAccessToken(opts),\n fetchSelectedTable: (opts) =>\n fetchSelectedTableShaped(opts) as Promise<Record<string, unknown[]>>,\n fetchSelectedRecord: (rowId, opts) =>\n api.GristView.fetchSelectedRecord(rowId, coerceFetchOptions(opts)),\n },\n\n get selectedTable() {\n return makeTableOps(state.selection.tableId)\n },\n\n getTable(tableId) {\n return makeTableOps(tableId ?? state.selection.tableId)\n },\n\n sectionApi: {\n configure: (settings) => api.CustomSectionAPI.configure(settings as unknown as Record<string, unknown>),\n mappings: () => api.CustomSectionAPI.mappings(),\n },\n\n on(eventName, listener) {\n let set = generic.get(eventName)\n if (!set) generic.set(eventName, (set = new Set()))\n set.add(listener)\n return () => set!.delete(listener)\n },\n }\n\n ;(target as unknown as { grist: InlineGristGlobal }).grist = grist\n\n return {\n grist,\n dispose() {\n offBus()\n // Restore the global (only if we still own it).\n const t = target as unknown as { grist?: unknown }\n if (t.grist === grist) delete t.grist\n recordCbs.clear()\n recordsCbs.clear()\n optionsCbs.clear()\n newRecordCbs.clear()\n generic.clear()\n lastRecord = null\n lastRecords = null\n lastOptions = null\n lastNewRecord = undefined\n },\n fireDataChange(tableId) {\n bus.emit({ type: \"data-change\", tableId: tableId ?? state.selection.tableId })\n },\n fireCursor(rowId) {\n const id = rowId === undefined ? state.selection.rowId : rowId\n bus.emit({ type: \"cursor-change\", tableId: state.selection.tableId, rowId: id })\n },\n fireOptions() {\n pushOptions()\n },\n fireTheme(message) {\n bus.emit({ type: \"theme-change\", message })\n },\n emitInitialState() {\n pushOptions()\n void pushRecords().then(() => pushRecord(state.selection.rowId))\n },\n }\n}\n\nfunction columnsToRows(columnar: Record<string, unknown[]>): Record<string, unknown>[] {\n const cols = Object.keys(columnar)\n if (cols.length === 0) return []\n const length = (columnar[cols[0]] ?? []).length\n const rows: Record<string, unknown>[] = []\n for (let i = 0; i < length; i++) {\n const row: Record<string, unknown> = {}\n for (const c of cols) row[c] = columnar[c][i]\n rows.push(row)\n }\n return rows\n}\n\nfunction parseFields(fields: Record<string, unknown>, _options?: GristTableOpOptions): Record<string, unknown> {\n // The emulator currently doesn't implement string-parsing; pass-through.\n // Hook into here to add date/number parsing when we surface that toggle.\n return { ...fields }\n}\n\nfunction coerceFetchOptions(\n opts: GristFetchSelectedOptions | undefined\n): { keepEncoded?: boolean; format?: \"rows\" | \"columns\" } | undefined {\n if (!opts) return undefined\n const format = opts.format === \"rows\" || opts.format === \"columns\" ? opts.format : undefined\n return { keepEncoded: opts.keepEncoded, format }\n}\n\nfunction logErr(err: unknown) {\n console.error(\"[grist-emulator/inline]\", err)\n}\n\n// Touch helpers to keep them tree-shake-friendly even if unused in current scope.\nvoid findRow\n\n/**\n * Make `window.self !== window.top` evaluate to `true`. The SDK uses this\n * exact comparison in `useGristAvailability` to detect an iframe environment.\n *\n * Inline transports run inside the host window (tests, IDE preview) and would\n * otherwise be flagged as \"not embedded\" — this shim is the same trick we use\n * in the testing harness and is safe because the inline transport is never\n * shipped to production.\n */\nfunction installFakeIframeContext(target: Window & typeof globalThis) {\n try {\n if (target.self !== target.top) return\n Object.defineProperty(target, \"top\", {\n configurable: true,\n get: () => ({}),\n })\n } catch {\n // Some environments lock these globals; ignore silently.\n }\n}\n","import { z } from \"zod\"\n\nimport type { GristReplicaDocument } from \"../sdk/replica-document\"\n\nconst emulatorRowSchema = z\n .object({ id: z.number() })\n .catchall(z.unknown())\n\nconst formulaKindSchema = z.enum([\"computed\", \"trigger\", \"none\", \"empty_slot\"])\n\nconst replicaColumnSchema = z\n .object({\n colRef: z.number().optional(),\n type: z.string().optional(),\n label: z.string().optional(),\n parentPos: z.number().optional(),\n isFormula: z.boolean().optional(),\n formulaKind: formulaKindSchema.optional(),\n formula: z.string().optional(),\n description: z.string().optional(),\n widgetOptions: z.record(z.string(), z.unknown()).optional(),\n displayColRef: z.number().optional(),\n visibleColRef: z.number().optional(),\n })\n .strict()\n\nconst replicaTableSchema = z\n .object({\n label: z.string().optional(),\n columns: z.record(z.string(), replicaColumnSchema).optional(),\n rows: z.array(emulatorRowSchema).optional(),\n rowCount: z.number().optional(),\n dataOmitted: z.boolean().optional(),\n dataOmittedReason: z.string().optional(),\n error: z.string().optional(),\n })\n .strict()\n\nconst replicaSelectionSchema = z\n .object({\n tableId: z.string().optional(),\n rowId: z.union([z.number(), z.literal(\"new\"), z.null()]).optional(),\n mappings: z.unknown().nullable().optional(),\n cursor: z.unknown().optional(),\n })\n .strict()\n\nconst replicaWidgetConfigurationSchema = z\n .object({\n requiredAccess: z.string().optional(),\n columns: z.unknown().optional(),\n allowSelectBy: z.boolean().optional(),\n hasCustomOptions: z.boolean().optional(),\n })\n .strict()\n\nconst replicaAccessTokenSchema = z\n .object({\n token: z.string(),\n baseUrl: z.string(),\n ttlMsecs: z.number(),\n })\n .strict()\n\nconst replicaDocumentSchema = z\n .object({\n generatedAt: z.string(),\n source: z.string().optional(),\n docName: z.string().optional(),\n mode: z.enum([\"schema-only\", \"schema+samples\", \"schema+data\"]).optional(),\n tables: z.record(z.string(), replicaTableSchema),\n selection: replicaSelectionSchema.optional(),\n widgetOptions: z.record(z.string(), z.unknown()).optional(),\n widgetInteraction: z.unknown().optional(),\n configuration: replicaWidgetConfigurationSchema.optional(),\n accessToken: replicaAccessTokenSchema.nullable().optional(),\n })\n .strict()\n .refine((value) => Object.keys(value.tables).length > 0, {\n message: \"at least one table is required\",\n path: [\"tables\"],\n })\n\nfunction formatZodError(prefix: string, error: z.ZodError): Error {\n const details = error.issues\n .map((issue) => {\n const where = issue.path.length > 0 ? issue.path.join(\".\") : \"<root>\"\n return `${where}: ${issue.message}`\n })\n .join(\"; \")\n return new Error(`${prefix}: ${details}`)\n}\n\nexport function safeParseDocument(input: unknown) {\n return replicaDocumentSchema.safeParse(input)\n}\n\nexport function parseDocument(input: unknown): GristReplicaDocument {\n const result = safeParseDocument(input)\n if (!result.success) {\n throw formatZodError(\"parseDocument\", result.error)\n }\n return result.data as GristReplicaDocument\n}\n","/**\n * Top-level emulator factory. Produces a fully-wired emulator instance:\n *\n * - typed in-memory document state,\n * - shared event bus,\n * - the six host API impls,\n * - the inline transport, which installs `grist` on the page,\n * - imperative helpers (`mutate`, `apply`, `selectRow`, `selectTable`)\n * that drive the document via the action engine and emit corresponding\n * events.\n *\n * The instance is multi-instance friendly: nothing is stored on `window`.\n */\n\nimport { createApiBundle } from \"./api\"\nimport type { EmulatorApiBundle } from \"./api\"\nimport { applyUserActions } from \"./core/action-engine\"\nimport { createDocument } from \"./core/document\"\nimport { createEventBus } from \"./core/event-bus\"\nimport type { EventBus } from \"./core/event-bus\"\nimport { resolveMappings } from \"./core/mappings\"\nimport type { EmulatorDocumentState } from \"./core/types\"\nimport type { GristReplicaDocument } from \"../sdk/replica-document\"\nimport type { GristWidgetColumnMap } from \"../sdk/types\"\nimport { buildGristThemeHostMessage } from \"./theme-message\"\nimport { createInlineTransport } from \"./transports\"\nimport type { EmulatorTransport, InlineGristGlobal } from \"./transports\"\nimport { parseDocument } from \"./validators\"\n\nexport type CreateGristEmulatorOptions = {\n /** The starting document (must satisfy {@link parseDocument}). */\n document: GristReplicaDocument\n /** Installs `grist` on `target` (default: the global object). */\n transport?: { kind: \"inline\"; target?: Window & typeof globalThis }\n /** Initial widget options exposed via `WidgetAPI`. */\n widgetOptions?: Record<string, unknown>\n /**\n * Initial widget interaction info (`access_level` and friends) sent\n * alongside `onOptions`. Without an `access_level`, Grist grants the access\n * the widget requests in `grist.ready()`.\n */\n widgetInteraction?: Record<string, unknown>\n /** Initial document theme replayed on widget ready (host `message` channel). */\n initialTheme?: \"light\" | \"dark\"\n}\n\nexport type GristEmulator = {\n /** Underlying mutable document. Treat as read-only outside of `mutate(...)`. */\n state: EmulatorDocumentState\n bus: EventBus\n api: EmulatorApiBundle\n transport: EmulatorTransport\n /** Synthesised `grist` global (only for the inline transport). */\n grist?: InlineGristGlobal\n\n /** Apply a list of Grist user actions; emits the matching events. */\n apply: (actions: unknown[][]) => { retValues: unknown[] }\n /** Convenience helpers for tests and demos. */\n mutate: {\n addRow: (tableId: string, fields: Record<string, unknown>) => number\n updateRow: (tableId: string, rowId: number, fields: Record<string, unknown>) => void\n removeRow: (tableId: string, rowId: number) => void\n }\n selectRow: (rowId: number | \"new\" | null) => void\n selectTable: (tableId: string) => void\n /**\n * Set logical→real column mappings, as a user mapping columns in Grist would.\n * Pass `undefined` to clear — `mappings()` becomes `null` until set again.\n */\n setColumnMappings: (mappings: GristWidgetColumnMap | undefined) => void\n setOptions: (options: Record<string, unknown>) => Promise<void>\n setInteraction: (interaction: Record<string, unknown>) => void\n /** Host theme controls (`grist.on(\"message\")` / `msg.theme`). */\n theme: {\n set: (theme: \"light\" | \"dark\") => void\n }\n /** Tear down the emulator. Idempotent. */\n dispose: () => void\n}\n\nexport function createGristEmulator(options: CreateGristEmulatorOptions): GristEmulator {\n const validatedDocument = parseDocument(options.document)\n const state = createDocument({\n ...validatedDocument,\n widgetOptions: options.widgetOptions ?? validatedDocument.widgetOptions,\n // No access_level by default: the emulator then grants the access the\n // widget asks for in grist.ready(), as a user accepting it in Grist would.\n widgetInteraction: options.widgetInteraction ?? validatedDocument.widgetInteraction ?? {},\n })\n const bus = createEventBus()\n const api = createApiBundle(state, bus)\n\n const inline = createInlineTransport({\n state,\n bus,\n api,\n initialTheme: options.initialTheme,\n target: options.transport?.target,\n })\n const transport: EmulatorTransport = inline\n const grist: InlineGristGlobal | undefined = inline.grist\n\n function apply(actions: unknown[][]) {\n return applyUserActions(state, bus, actions)\n }\n\n return {\n state,\n bus,\n api,\n transport,\n grist,\n apply,\n mutate: {\n addRow: (tableId, fields) => apply([[\"AddRecord\", tableId, null, fields]]).retValues[0] as number,\n updateRow: (tableId, rowId, fields) => {\n apply([[\"UpdateRecord\", tableId, rowId, fields]])\n },\n removeRow: (tableId, rowId) => {\n apply([[\"RemoveRecord\", tableId, rowId]])\n },\n },\n selectRow(rowId) {\n state.selection.rowId = rowId\n bus.emit({ type: \"cursor-change\", tableId: state.selection.tableId, rowId })\n },\n selectTable(tableId) {\n if (!state.tables.has(tableId)) throw new Error(`Unknown table: ${tableId}`)\n state.selection.tableId = tableId\n const first = state.tables.get(tableId)!.rows[0]?.id ?? null\n state.selection.rowId = first\n bus.emit({ type: \"data-change\", tableId })\n bus.emit({ type: \"cursor-change\", tableId, rowId: first })\n },\n setColumnMappings(mappings) {\n if (mappings === undefined) {\n delete state.selection.mappings\n } else {\n state.selection.mappings = mappings\n }\n bus.emit({ type: \"mappings-change\", mappings: resolveMappings(state) })\n },\n async setOptions(opts) {\n await api.WidgetAPI.setOptions(opts)\n },\n setInteraction(interaction) {\n state.widgetInteraction = { ...interaction }\n bus.emit({ type: \"options-change\", options: { ...state.widgetOptions }, interaction: { ...interaction } })\n },\n theme: {\n set(next) {\n bus.emit({ type: \"theme-change\", message: buildGristThemeHostMessage(next) })\n },\n },\n dispose() {\n transport.dispose()\n bus.clear()\n },\n }\n}\n","/**\n * Document templates exposed at the top of the emulator API.\n *\n * Templates return plain data — they don't allocate state, the caller passes\n * the returned value into `createGristEmulator(...)` which performs the allocation.\n */\n\nimport type { GristReplicaDocument } from \"../sdk/replica-document\"\n\nconst PRESET_GENERATED_AT = \"1970-01-01T00:00:00.000Z\"\n\nfunction replicaBase(overrides: Omit<GristReplicaDocument, \"generatedAt\">): GristReplicaDocument {\n return {\n generatedAt: PRESET_GENERATED_AT,\n ...overrides,\n }\n}\n\n/**\n * Useful templates for quick demos and tests.\n */\nexport const presets = {\n /**\n * Default starter fixture for demos / sandboxes that need a neutral document\n * without choosing a domain-specific preset.\n */\n defaultTemplate(): GristReplicaDocument {\n return replicaBase({\n docName: \"Default\",\n tables: {\n Table1: {\n label: \"Table1\",\n rows: [\n { id: 1, Name: \"Alice\" },\n { id: 2, Name: \"Bob\" },\n ],\n },\n },\n })\n },\n blank(): GristReplicaDocument {\n return replicaBase({\n docName: \"Blank\",\n tables: {\n Table1: { rows: [{ id: 1 }] },\n },\n })\n },\n todoList(): GristReplicaDocument {\n return replicaBase({\n docName: \"Todo list\",\n mode: \"schema+data\",\n tables: {\n Tasks: {\n label: \"Tasks\",\n columns: {\n title: { type: \"Text\", label: \"Title\" },\n done: { type: \"Bool\", label: \"Done\" },\n priority: { type: \"Choice\", label: \"Priority\" },\n },\n rows: [\n { id: 1, title: \"Buy milk\", done: false, priority: \"high\" },\n { id: 2, title: \"Write the SOTA emulator\", done: true, priority: \"high\" },\n { id: 3, title: \"Ship it\", done: false, priority: \"medium\" },\n ],\n },\n },\n })\n },\n contacts(): GristReplicaDocument {\n return replicaBase({\n docName: \"Contacts\",\n mode: \"schema+data\",\n tables: {\n Contacts: {\n label: \"Contacts\",\n columns: {\n firstName: { type: \"Text\" },\n lastName: { type: \"Text\" },\n email: { type: \"Text\" },\n company: { type: \"Text\" },\n },\n rows: [\n { id: 1, firstName: \"Ada\", lastName: \"Lovelace\", email: \"ada@analytical.engine\", company: \"British Crown\" },\n { id: 2, firstName: \"Linus\", lastName: \"Torvalds\", email: \"linus@kernel.org\", company: \"Linux Foundation\" },\n { id: 3, firstName: \"Margaret\", lastName: \"Hamilton\", email: \"margaret@apollo.nasa\", company: \"NASA\" },\n ],\n },\n },\n })\n },\n}\n","import { Component, type ComponentType, type ReactNode } from \"react\"\nimport { waitFor } from \"@testing-library/react\"\n\nimport { entryProps, GristWidgetApp, type GristWidgetEntry } from \"../../app/mount-grist-widget\"\nimport type { GristReplicaDocument, GristWidget, UseGristOptions } from \"../../sdk\"\nimport { declaredColumns, declaredDocument, mapEveryColumn } from \"./declared-document\"\nimport { installJsdomStubs } from \"./jsdom-stubs\"\nimport { renderWithGrist } from \"./render-with-grist\"\n\nexport type SmokeTestWidgetOptions = {\n /** The widget, as `src/main.tsx` passes it to `mountGristWidget()`. */\n App: ComponentType\n /** The widget's `GRIST_OPTIONS` (or pass `widget`). */\n options?: UseGristOptions\n /** The widget's declaration, from `defineGristWidget()` (or pass `options`). */\n widget?: GristWidget\n /**\n * The Grist document to run against. Defaults to one table with a column\n * per column the widget declares, typed after the first type it accepts,\n * and one row of sample values.\n */\n document?: GristReplicaDocument\n /** How long to wait for the widget to render, in ms. Defaults to 10 000. */\n timeout?: number\n}\n\n/**\n * Mounts the widget the way `mountGristWidget()` does inside Grist, against\n * an emulated Grist document with every column it declares mapped and the\n * access it requests granted, and waits until it renders past\n * `GristBoundary`. Resolves once it has,\n * rejects with the widget's own error if it throws, or with what the page\n * showed instead if it never gets there. Then unmounts.\n *\n * A widget's whole smoke test, given its entry module as `mountGristWidget()`\n * takes it (the widget, and its `widget` declaration or `GRIST_OPTIONS`):\n *\n * ```tsx\n * import { it } from \"vitest\"\n * import { smokeTestWidget } from \"grist-widget-sdk/emulator/testing\"\n * import * as entry from \"./App\"\n *\n * it(\"renders inside Grist\", () => smokeTestWidget(entry))\n * ```\n *\n * It only reads the declaration, so it stays valid as the widget changes,\n * and it improves with each SDK release. `smokeTestWidget({ App, options })`\n * and `smokeTestWidget({ App, widget })` work too.\n */\nexport async function smokeTestWidget(\n input: SmokeTestWidgetOptions | GristWidgetEntry,\n extra: Pick<SmokeTestWidgetOptions, \"document\" | \"timeout\"> = {}\n): Promise<void> {\n const { App, options: given, widget, document, timeout = 10_000 } =\n \"App\" in input ? input : { ...entryProps(input), ...extra }\n installJsdomStubs()\n const options = given ?? widget?.options\n if (!options) throw new Error(\"smokeTestWidget: pass the widget's `widget` (defineGristWidget) or its `options` (GRIST_OPTIONS).\")\n\n const crash: { error: unknown } = { error: undefined }\n function Probe() {\n return (\n <CatchRenderError crash={crash}>\n <div data-grist-smoke-test=\"\">\n <App />\n </div>\n </CatchRenderError>\n )\n }\n\n const columns = declaredColumns(options)\n const gristDocument = document ?? declaredDocument(columns)\n const result = renderWithGrist(<GristWidgetApp App={Probe} options={options} />, {\n emulator: {\n document: gristDocument,\n // Granted as the user would in Grist's widget panel: the access the\n // widget asks for, unless the given document says otherwise.\n widgetInteraction: gristDocument.widgetInteraction ?? { access_level: options.requiredAccess ?? \"read table\" },\n },\n })\n try {\n if (columns.length > 0) result.emulator.setColumnMappings(mapEveryColumn(columns))\n\n try {\n await waitFor(\n () => {\n if (crash.error !== undefined) return\n const probe = result.container.querySelector(\"[data-grist-smoke-test]\")\n if (!probe || !probe.hasChildNodes()) throw new Error(\"not rendered yet\")\n },\n { timeout }\n )\n } catch {\n const shown = result.container.textContent?.trim().replace(/\\s+/g, \" \") || \"nothing\"\n throw new Error(\n `smokeTestWidget: the widget didn't render past GristBoundary within ${timeout} ms. ` +\n `The page showed: \"${shown.slice(0, 300)}\".`\n )\n }\n if (crash.error !== undefined) throw crash.error\n } finally {\n result.unmount()\n }\n}\n\n/** Records the widget's render error, so the test fails with it rather than a timeout. */\nclass CatchRenderError extends Component<{ crash: { error: unknown }; children: ReactNode }, { failed: boolean }> {\n state = { failed: false }\n\n static getDerivedStateFromError() {\n return { failed: true }\n }\n\n componentDidCatch(error: unknown) {\n this.props.crash.error = error\n }\n\n render() {\n return this.state.failed ? null : this.props.children\n }\n}\n","/**\n * Browser APIs jsdom lacks but widget UI commonly uses, as inert stand-ins:\n * `ResizeObserver` (charts, virtualized lists, popovers) and\n * `window.matchMedia` (the theme, responsive hooks; it reports a light,\n * wide screen). Only installs what's missing, so a test's own mock wins.\n *\n * {@link smokeTestWidget} calls it. For a widget's other tests, call it at\n * the top of the test file or in a Vitest setup file.\n */\nexport function installJsdomStubs(): void {\n if (typeof window === \"undefined\") return\n\n globalThis.ResizeObserver ??= class ResizeObserver {\n observe() {}\n unobserve() {}\n disconnect() {}\n }\n\n window.matchMedia ??= (query: string) =>\n ({\n matches: false,\n media: query,\n onchange: null,\n addEventListener() {},\n removeEventListener() {},\n addListener() {},\n removeListener() {},\n dispatchEvent: () => false,\n }) as MediaQueryList\n}\n","/**\n * Vitest helpers to assert what the widget did to the document.\n *\n * Usage:\n *\n * const { emulator } = renderWithGrist(<MyWidget />)\n * await userEvent.click(screen.getByText(\"Add\"))\n * expect(actionsOf(emulator)).toContainEqual([\"AddRecord\", \"Tasks\", null, { title: \"X\" }])\n */\n\nimport type { GristEmulator } from \"../create-grist-emulator\"\nimport type { EmulatorEvent } from \"../core/event-bus\"\n\nexport function actionsOf(emulator: GristEmulator): unknown[][] {\n return emulator.bus\n .history()\n .filter((e: EmulatorEvent): e is Extract<EmulatorEvent, { type: \"user-action\" }> => e.type === \"user-action\")\n .map((e) => e.action as unknown[])\n}\n\nexport function eventsOf(emulator: GristEmulator): readonly EmulatorEvent[] {\n return emulator.bus.history()\n}\n\n/** Bus event kinds aligned with grist host callbacks (see inline transport). */\nexport type WaitForEventKind = \"ready\" | \"record\" | \"records\" | \"options\" | \"theme\" | \"cursor\"\n\nexport type WaitForEventOptions = {\n timeoutMs?: number\n}\n\nfunction predicateForKind(kind: WaitForEventKind): (event: EmulatorEvent) => boolean {\n switch (kind) {\n case \"ready\":\n return (e) => e.type === \"ready\"\n case \"record\":\n case \"cursor\":\n return (e) => e.type === \"cursor-change\"\n case \"records\":\n return (e) => e.type === \"data-change\"\n case \"options\":\n return (e) => e.type === \"options-change\"\n case \"theme\":\n return (e) => e.type === \"theme-change\"\n }\n}\n\nfunction waitForNextEvent(\n emulator: GristEmulator,\n predicate: (event: EmulatorEvent) => boolean,\n timeoutMs: number,\n label?: string\n): Promise<EmulatorEvent> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n off()\n const hint = label ? ` (kind: ${label})` : \"\"\n const recent = emulator.bus\n .history()\n .slice(-5)\n .map((e) => e.type)\n .join(\", \")\n reject(\n new Error(\n `waitForEvent timed out after ${timeoutMs}ms${hint}.` +\n (recent ? ` Recent bus events: ${recent}.` : \" No bus events yet.\")\n )\n )\n }, timeoutMs)\n const off = emulator.bus.on((event) => {\n if (predicate(event)) {\n clearTimeout(timer)\n off()\n resolve(event)\n }\n })\n })\n}\n\nexport function waitForEvent(\n emulator: GristEmulator,\n kind: WaitForEventKind,\n options?: WaitForEventOptions\n): Promise<EmulatorEvent>\nexport function waitForEvent(\n emulator: GristEmulator,\n predicate: (event: EmulatorEvent) => boolean,\n timeoutMs?: number\n): Promise<EmulatorEvent>\nexport function waitForEvent(\n emulator: GristEmulator,\n kindOrPredicate: WaitForEventKind | ((event: EmulatorEvent) => boolean),\n timeoutOrOptions: number | WaitForEventOptions = 1000\n): Promise<EmulatorEvent> {\n if (typeof kindOrPredicate === \"string\") {\n const opts = typeof timeoutOrOptions === \"object\" ? timeoutOrOptions : {}\n const timeoutMs = opts.timeoutMs ?? 1000\n return waitForNextEvent(emulator, predicateForKind(kindOrPredicate), timeoutMs, kindOrPredicate)\n }\n const timeoutMs = typeof timeoutOrOptions === \"number\" ? timeoutOrOptions : 1000\n return waitForNextEvent(emulator, kindOrPredicate, timeoutMs)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACaA,IAAAA,iBAA8D;;;ACb9D,IAAAC,gBAAyE;AACzE,oBAA2B;;;ACS3B,mBAAiG;;;AC2BjG,IAAM,kBAAkB,oBAAI,IAAI,CAAC,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG,CAAC;AAEnE,SAAS,kBAAkB,OAAoC;AAC7D,SACE,MAAM,QAAQ,KAAK,KACnB,OAAO,MAAM,CAAC,MAAM,YACpB,MAAM,CAAC,EAAE,UAAU,KACnB,gBAAgB,IAAI,MAAM,CAAC,CAAC;AAEhC;AAOO,SAAS,0BAA0B,OAAoC;AAC5E,MAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,EAAG,QAAO;AAChE,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,EAAG,QAAO;AACtD,QAAM,MAAM,MAAM,CAAC;AACnB,MAAI,QAAQ,OAAO,OAAO,MAAM,CAAC,MAAM,YAAY,OAAO,SAAS,MAAM,CAAC,CAAC,EAAG,QAAO,MAAM,CAAC;AAC5F,MAAI,QAAQ,OAAO,OAAO,MAAM,CAAC,MAAM,YAAY,OAAO,SAAS,MAAM,CAAC,CAAC,EAAG,QAAO,MAAM,CAAC;AAC5F,SAAO;AACT;AAEA,SAAS,0BAA0B,QAAsC;AACvE,SAAO,QAAQ,SAAS;AAC1B;AAEA,SAAS,0BAA0B,QAAsC;AACvE,SAAO,QAAQ,SAAS;AAC1B;AAEA,SAAS,uBAAuB,QAAsC;AACpE,SAAO,OAAO,QAAQ,SAAS,YAAY,OAAO,KAAK,WAAW,UAAU;AAC9E;AAEA,SAAS,mBAAmB,QAAsC;AAChE,SAAO,OAAO,QAAQ,SAAS,YAAY,OAAO,KAAK,WAAW,MAAM;AAC1E;AAEA,SAAS,oBAAoB,QAAsC;AACjE,SAAO,QAAQ,SAAS;AAC1B;AAEA,SAAS,wBAAwB,QAAsC;AACrE,SAAO,OAAO,QAAQ,SAAS,YAAY,OAAO,KAAK,WAAW,UAAU;AAC9E;AAQO,SAAS,iBAAiB,OAAgB,QAAgD;AAC/F,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAElD,MAAI,kBAAkB,KAAK,GAAG;AAC5B,UAAM,MAAM,MAAM,CAAC;AACnB,YAAQ,KAAK;AAAA,MACX,KAAK;AACH,eAAO;AAAA,UACL,SAAS;AAAA,UACT,MAAM,OAAO,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,IAAI;AAAA,UAChD,SAAS,OAAO,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,IAAI;AAAA,UACnD,WAAW,OAAO,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,IAAI;AAAA,QACvD;AAAA,MACF,KAAK;AACH,eAAO,MAAM,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,iBAAiB,GAAG,MAAS,CAAC;AAAA,MACjE,KAAK;AACH,YAAI,OAAO,MAAM,CAAC,MAAM,SAAU,QAAO,IAAI,KAAK,MAAM,CAAC,IAAI,GAAI;AACjE,eAAO;AAAA,MACT,KAAK;AACH,YAAI,OAAO,MAAM,CAAC,MAAM,SAAU,QAAO,IAAI,KAAK,MAAM,CAAC,IAAI,GAAI;AACjE,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,UACL,OAAO;AAAA,UACP,SAAS,OAAO,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,IAAI;AAAA,UACnD,OAAO,OAAO,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,IAAI;AAAA,QACnD;AAAA,MACF,KAAK;AACH,eAAO,EAAE,OAAO,MAAM,OAAO,OAAO,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,IAAI,EAAE;AAAA,MAC3E,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAEA,MAAI,oBAAoB,MAAM,KAAK,wBAAwB,MAAM,GAAG;AAClE,QAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,EAAG,QAAO,IAAI,KAAK,QAAQ,GAAI;AAAA,EACvF;AAEA,MAAI,mBAAmB,MAAM,KAAK,OAAO,UAAU,UAAU;AAC3D,WAAO,EAAE,OAAO,MAAM,OAAO,MAAM;AAAA,EACrC;AAEA,OAAK,uBAAuB,MAAM,KAAK,0BAA0B,MAAM,KAAK,0BAA0B,MAAM,MAAM,MAAM,QAAQ,KAAK,GAAG;AACtI,WAAO,MAAM,IAAI,CAAC,MAAM,iBAAiB,GAAG,MAAS,CAAC;AAAA,EACxD;AAEA,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,YAAY,OAAO,UAAU,UAAW,QAAO;AACjG,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,CAAC,MAAM,iBAAiB,GAAG,MAAS,CAAC;AAChF,SAAO;AACT;;;AC5HO,SAAS,gBAAgB,MAAyC;AACvE,QAAM,QAAQ,KAAK;AACnB,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM;AACvC,aAAW,OAAO,OAAO,KAAK,IAAI,GAAG;AACnC,UAAM,MAAM,KAAK,GAAG;AACpB,QAAI,MAAM,QAAQ,GAAG,EAAG,QAAO,IAAI;AAAA,EACrC;AACA,SAAO;AACT;AAKO,SAAS,4BACd,MACA,WACA,SACA,SACkB;AAClB,QAAM,QAAQ,gBAAgB,IAAI;AAClC,QAAM,IAAI,YAAY,SAAY,KAAK,IAAI,OAAO,OAAO,IAAI;AAC7D,QAAM,MAAwB,CAAC;AAC/B,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,MAA+B,CAAC;AACtC,eAAW,KAAK,WAAW;AACzB,YAAM,MAAM,KAAK,CAAC;AAClB,YAAM,MAAM,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,IAAI;AAC1C,UAAI,MAAM,MAAM;AACd,YAAI,CAAC,IAAI;AAAA,MACX,OAAO;AACL,YAAI,CAAC,IAAI,iBAAiB,KAAK,QAAQ,CAAC,CAAC;AAAA,MAC3C;AAAA,IACF;AACA,QAAI,KAAK,GAAqB;AAAA,EAChC;AACA,SAAO;AACT;AAGO,SAAS,gBACd,MACqB;AACrB,QAAM,QAAQ,KAAK;AACnB,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW,EAAG,QAAO,CAAC;AACzD,QAAM,OAAO,OAAO,KAAK,IAAI;AAC7B,QAAM,IAAI,MAAM;AAChB,QAAM,OAA4B,CAAC;AACnC,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,MAA+B,CAAC;AACtC,eAAW,KAAK,MAAM;AACpB,YAAM,MAAM,KAAK,CAAC;AAClB,UAAI,CAAC,IAAI,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,IAAI;AAAA,IACzC;AACA,SAAK,KAAK,GAAwB;AAAA,EACpC;AACA,SAAO;AACT;AAEA,SAAS,cAAc,KAA6C;AAClE,QAAM,IAAI,IAAI;AACd,MAAI,OAAO,MAAM,YAAY,CAAC,OAAO,MAAM,CAAC,EAAG,QAAO;AACtD,MAAI,OAAO,MAAM,YAAY,EAAE,KAAK,MAAM,IAAI;AAC5C,UAAM,IAAI,OAAO,CAAC;AAClB,QAAI,CAAC,OAAO,MAAM,CAAC,EAAG,QAAO;AAAA,EAC/B;AACA,SAAO;AACT;AAMO,SAAS,qBACd,MACqB;AACrB,QAAM,YAAY,KAAK,KAAK,CAAC,MAAM,cAAc,CAA4B,MAAM,IAAI;AACvF,MAAI,CAAC,WAAW;AACd,WAAO,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM;AAC9B,YAAM,MAAM,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC9C,YAAM,MAAM,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC9C,aAAO,MAAM;AAAA,IACf,CAAC;AAAA,EACH;AACA,SAAO,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM;AAC9B,UAAM,KAAK,cAAc,CAA4B;AACrD,UAAM,KAAK,cAAc,CAA4B;AACrD,QAAI,OAAO,QAAQ,OAAO,QAAQ,OAAO,GAAI,QAAO,KAAK;AACzD,QAAI,OAAO,QAAQ,OAAO,KAAM,QAAO;AACvC,QAAI,OAAO,QAAQ,OAAO,KAAM,QAAO;AACvC,UAAM,MAAM,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC9C,UAAM,MAAM,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC9C,WAAO,MAAM;AAAA,EACf,CAAC;AACH;AAOO,SAAS,iCACd,MACA,SACqB;AACrB,QAAM,QAAQ,SAAS,SAAS;AAChC,MAAI;AACJ,MAAI,SAAS,SAAS;AACpB,UAAM,YAAY,OAAO,KAAK,IAAI;AAClC,WAAO,4BAA4B,MAAM,WAAW,QAAQ,OAAO;AAAA,EACrE,OAAO;AACL,WAAO,gBAAmB,IAAI;AAAA,EAChC;AAEA,MAAI,UAAU,OAAQ,QAAO;AAC7B,MAAI,UAAU,MAAM;AAClB,WAAO,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM;AAC9B,YAAM,MAAM,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC9C,YAAM,MAAM,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC9C,aAAO,MAAM;AAAA,IACf,CAAC;AAAA,EACH;AACA,SAAO,qBAAqB,IAAI;AAClC;AAKA,eAAsB,oBACpB,QACA,SACA,SAC8B;AAC9B,QAAM,OAAQ,MAAM,OAAO,WAAW,OAAO;AAC7C,SAAO,iCAAoC,MAAM,OAAO;AAC1D;;;ACtIO,SAAS,4BAA4B,KAAmD;AAC7F,MAAI,OAAO,QAAQ,QAAQ,GAAI,QAAO;AACtC,MAAI,OAAO,QAAQ,UAAU;AAC3B,QAAI;AACF,YAAM,SAAkB,KAAK,MAAM,GAAG;AACtC,UAAI,UAAU,OAAO,WAAW,YAAY,CAAC,MAAM,QAAQ,MAAM,GAAG;AAClE,eAAO;AAAA,MACT;AAAA,IACF,QAAQ;AACN,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AACA,MAAI,OAAO,QAAQ,YAAY,CAAC,MAAM,QAAQ,GAAG,GAAG;AAClD,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;ACTA,SAAS,YAAY,OAAkC,KAAa,UAAsC;AACxG,QAAM,MAAM,MAAM,GAAG;AACrB,MAAI,CAAC,MAAM,QAAQ,GAAG,EAAG,QAAO;AAChC,QAAM,IAAI,IAAI,QAAQ;AACtB,MAAI,MAAM,QAAQ,MAAM,OAAW,QAAO;AAC1C,MAAI,OAAO,MAAM,SAAU,QAAO;AAClC,MAAI,OAAO,MAAM,YAAY,OAAO,MAAM,UAAW,QAAO,OAAO,CAAC;AACpE,SAAO;AACT;AAEA,SAAS,YAAY,OAAkC,KAAa,UAAsC;AACxG,QAAM,MAAM,MAAM,GAAG;AACrB,MAAI,CAAC,MAAM,QAAQ,GAAG,EAAG,QAAO;AAChC,QAAM,IAAI,IAAI,QAAQ;AACtB,MAAI,OAAO,MAAM,YAAY,CAAC,OAAO,MAAM,CAAC,EAAG,QAAO;AACtD,MAAI,OAAO,MAAM,YAAY,EAAE,KAAK,MAAM,IAAI;AAC5C,UAAM,IAAI,OAAO,CAAC;AAClB,QAAI,CAAC,OAAO,MAAM,CAAC,EAAG,QAAO;AAAA,EAC/B;AACA,SAAO;AACT;AAyBA,eAAsB,0BACpB,QAC+D;AAC/D,QAAM,UAAU,oBAAI,IAAqD;AACzE,MAAI;AACF,UAAM,SAAS,MAAM,OAAO,WAAW,eAAe;AACtD,UAAM,UAAU,MAAM,OAAO,WAAW,sBAAsB;AAC9D,UAAM,WAAW,OAAO;AACxB,UAAM,mBAAmB,OAAO;AAChC,QAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,CAAC,MAAM,QAAQ,gBAAgB,EAAG,QAAO;AAEzE,UAAM,sBAAsB,oBAAI,IAAoB;AACpD,aAAS,IAAI,GAAG,IAAI,iBAAiB,QAAQ,KAAK;AAChD,YAAM,MAAM,SAAS,CAAC;AACtB,YAAM,MAAM,0BAA0B,iBAAiB,CAAC,CAAC;AACzD,UAAI,OAAO,QAAQ,YAAY,QAAQ,OAAW,qBAAoB,IAAI,KAAK,GAAG;AAAA,IACpF;AAEA,UAAM,YAAY,QAAQ;AAC1B,UAAM,SAAS,QAAQ;AACvB,UAAM,YAAY,QAAQ;AAC1B,QACE,CAAC,MAAM,QAAQ,SAAS,KACxB,CAAC,MAAM,QAAQ,MAAM,KACrB,CAAC,MAAM,QAAQ,SAAS,KACxB,UAAU,WAAW,OAAO,UAC5B,OAAO,WAAW,UAAU,QAC5B;AACA,aAAO;AAAA,IACT;AAEA,UAAM,IAAI,UAAU;AACpB,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,YAAM,cAAc,0BAA0B,UAAU,CAAC,CAAC;AAC1D,YAAM,SAAS,0BAA0B,UAAU,CAAC,CAAC;AACrD,YAAM,QAAQ,OAAO,CAAC;AACtB,UAAI,gBAAgB,UAAa,WAAW,UAAa,OAAO,UAAU,SAAU;AACpF,YAAM,UAAU,oBAAoB,IAAI,WAAW;AACnD,UAAI,CAAC,QAAS;AAEd,UAAI,SAAS,QAAQ,IAAI,OAAO;AAChC,UAAI,CAAC,QAAQ;AACX,iBAAS,oBAAI,IAAI;AACjB,gBAAQ,IAAI,SAAS,MAAM;AAAA,MAC7B;AAEA,YAAM,YAAY,YAAY,SAAS,aAAa,CAAC;AACrD,YAAM,eAAe,QAAQ;AAC7B,YAAM,YAAY,MAAM,QAAQ,YAAY,IAAI,QAAQ,aAAa,CAAC,CAAC,IAAI;AAE3E,YAAM,QAAQ,QAAQ;AACtB,YAAM,gBACJ,MAAM,QAAQ,KAAK,KAAK,IAAI,MAAM,SAAS,4BAA4B,MAAM,CAAC,CAAC,IAAI;AACrF,YAAM,gBAAgB;AAAA,QACpB,MAAM,QAAQ,QAAQ,UAAU,IAAI,QAAQ,WAAW,CAAC,IAAI;AAAA,MAC9D;AACA,YAAM,gBAAgB;AAAA,QACpB,MAAM,QAAQ,QAAQ,UAAU,IAAI,QAAQ,WAAW,CAAC,IAAI;AAAA,MAC9D;AAEA,aAAO,IAAI,OAAO;AAAA,QAChB;AAAA,QACA,MAAM,YAAY,SAAS,QAAQ,CAAC;AAAA,QACpC,OAAO,YAAY,SAAS,SAAS,CAAC;AAAA,QACtC,WAAW,cAAc,SAAY,YAAY;AAAA,QACjD;AAAA,QACA,SAAS,YAAY,SAAS,WAAW,CAAC;AAAA,QAC1C,aAAa,YAAY,SAAS,eAAe,CAAC,KAAK,YAAY,SAAS,SAAS,CAAC;AAAA,QACtF;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;;;ACtIA,IAAM,wBAAwB,oBAAI,IAAI,CAAC,OAAO,CAAC;AAE/C,SAAS,8BAA8B,SAAyB;AAC9D,SAAO,QAAQ,KAAK,EAAE,YAAY,EAAE,QAAQ,QAAQ,EAAE;AACxD;AAUO,SAAS,mBACd,OACA,KACA,SACS;AACT,QAAM,YAAY,SAAS,aAAa;AACxC,QAAM,sBAAsB,SAAS,uBAAuB;AAC5D,QAAM,wBAAwB,SAAS,yBAAyB;AAChE,QAAM,oBAAoB,SAAS,qBAAqB;AAExD,MAAI,aAAa,UAAU,KAAM,QAAO;AACxC,MAAI,qBAAqB,UAAU,aAAc,QAAO;AACxD,MAAI,uBAAuB,MAAM,WAAW,cAAc,EAAG,QAAO;AAEpE,MAAI,uBAAuB;AACzB,UAAM,UAAU,OAAO,KAAK,YAAY,WAAW,8BAA8B,IAAI,OAAO,IAAI;AAChG,QAAI,WAAW,sBAAsB,IAAI,OAAO,EAAG,QAAO;AAC1D,QAAI,QAAQ,WAAW,OAAO,EAAG,QAAO;AAAA,EAC1C;AAEA,SAAO;AACT;;;AC8BA,eAAsB,yBACpB,QACA,cACA,SACiB;AACjB,QAAM,iBAAiB,OAAO;AAC9B,MAAI,CAAC,gBAAgB;AACnB,UAAM,IAAI,MAAM,2CAA2C;AAAA,EAC7D;AACA,QAAM,EAAE,OAAAC,QAAO,QAAQ,IAAI,MAAM,eAAe,EAAE,UAAU,SAAS,YAAY,MAAM,CAAC;AACxF,SAAO,GAAG,OAAO,gBAAgB,YAAY,kBAAkBA,MAAK;AACtE;AAeA,eAAe,kCAAkC,KAG9C;AACD,QAAM,WAAW,MAAM,MAAM,GAAG;AAChC,QAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,GAAG,KAAK,KAAK;AACpE,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI,MAAM,+BAA+B,SAAS,MAAM,GAAG;AAAA,EACnE;AACA,QAAM,SAAS,MAAM,SAAS,YAAY;AAC1C,SAAO,EAAE,QAAQ,YAAY;AAC/B;AAqBA,eAAsB,oBACpB,QACA,cACA,SACqC;AACrC,QAAM,MAAM,MAAM,yBAAyB,QAAQ,cAAc,OAAO;AACxE,QAAM,EAAE,QAAQ,YAAY,IAAI,MAAM,kCAAkC,GAAG;AAC3E,SAAO,EAAE,MAAM,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,MAAM,YAAY,CAAC,GAAG,YAAY;AACxE;;;ACtIA,IAAM,eAAe;AACrB,IAAM,QAAQ,oBAAI,IAA6B;AAC/C,IAAM,WAAW,oBAAI,IAAuC;AAE5D,SAAS,SAAS,UAA2B;AAC3C,SAAO,WAAW,OAAO;AAC3B;AAMA,eAAsB,oBACpB,QACA,SAC2B;AAC3B,MAAI,CAAC,OAAO,gBAAgB;AAC1B,UAAM,IAAI,MAAM,sEAAsE;AAAA,EACxF;AAEA,QAAM,WAAW,SAAS,YAAY;AACtC,QAAM,MAAM,SAAS,QAAQ;AAC7B,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,MAAM,MAAM,IAAI,GAAG;AACzB,MAAI,OAAO,MAAM,IAAI,YAAY,cAAc;AAC7C,WAAO,IAAI;AAAA,EACb;AAEA,QAAM,UAAU,SAAS,IAAI,GAAG;AAChC,MAAI,QAAS,QAAO;AAEpB,QAAM,OAAO,OAAO,eAAe,EAAE,SAAS,CAAC,EAAE,KAAK,CAACC,WAAU;AAC/D,UAAM,IAAI,KAAK,EAAE,OAAAA,QAAO,WAAW,KAAK,IAAI,EAAE,CAAC;AAC/C,aAAS,OAAO,GAAG;AACnB,WAAOA;AAAA,EACT,CAAC;AAED,WAAS,IAAI,KAAK,IAAI;AACtB,SAAO;AACT;AAGO,SAAS,6BAAmC;AACjD,QAAM,MAAM;AACZ,WAAS,MAAM;AACjB;AAKA,eAAsB,mBACpB,QACA,MACA,MACmB;AACnB,QAAM,WAAW,MAAM,YAAY;AACnC,MAAIA;AACJ,MAAI;AACF,IAAAA,SAAQ,MAAM,oBAAoB,QAAQ,EAAE,SAAS,CAAC;AAAA,EACxD,SAAS,KAAK;AACZ,+BAA2B;AAC3B,UAAM;AAAA,EACR;AAEA,QAAM,aAAa,gBAAgB,KAAK,IAAI;AAC5C,QAAM,YAAY,aAAa,OAAO,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI;AAE5E,QAAM,MAAM,aACR,IAAI,IAAI,IAAI,IACZ,IAAI,IAAI,GAAGA,OAAM,QAAQ,QAAQ,OAAO,EAAE,CAAC,GAAG,SAAS,EAAE;AAK7D,QAAM,cAAc,IAAI,IAAIA,OAAM,OAAO,EAAE;AAC3C,MAAI,IAAI,WAAW,aAAa;AAC9B,UAAM,IAAI;AAAA,MACR,kEAAkE,IAAI,MAAM,iEACX,WAAW;AAAA,IAE9E;AAAA,EACF;AAKA,MAAI,CAAC,IAAI,aAAa,IAAI,MAAM,EAAG,KAAI,aAAa,IAAI,QAAQA,OAAM,KAAK;AAE3E,QAAM,UAAU,IAAI,QAAQ,MAAM,WAAW,CAAC,CAAC;AAC/C,UAAQ,OAAO,eAAe;AAE9B,QAAM,WAAW,MAAM,MAAM,IAAI,SAAS,GAAG,EAAE,GAAG,MAAM,QAAQ,CAAC;AACjE,MAAI,SAAS,WAAW,KAAK;AAC3B,+BAA2B;AAC3B,UAAM,aAAa,MAAM,oBAAoB,QAAQ,EAAE,SAAS,CAAC;AACjE,QAAI,aAAa,IAAI,QAAQ,WAAW,KAAK;AAC7C,WAAO,MAAM,IAAI,SAAS,GAAG,EAAE,GAAG,MAAM,QAAQ,CAAC;AAAA,EACnD;AACA,SAAO;AACT;;;AC3FO,SAAS,sCACd,KACA,SACU;AACV,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,+CAA+C;AAAA,EACjE;AAEA,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,OAAO;AAAA,EAC7B,QAAQ;AACN,QAAI,SAAS,QAAQ;AACnB,YAAM,IAAI,MAAM,+CAA+C;AAAA,IACjE;AACA,aAAS;AAAA,EACX;AAEA,SAAO,sCAAsC,QAAQ,OAAO;AAC9D;AAaO,SAAS,sCACd,QACA,SACU;AACV,MAAI,SAAS,QAAQ;AACnB,WAAO,4CAA4C,MAAM;AAAA,EAC3D;AAEA,QAAM,QAAQ,0CAA0C,MAAM;AAC9D,MAAI,UAAU,QAAW;AACvB,QAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,YAAM,MAAgB,CAAC;AACvB,YAAM,OAAO,oBAAI,IAAY;AAC7B,iBAAW,QAAQ,QAAQ;AACzB,cAAM,KAAK,mBAAmB,IAAI;AAClC,YAAI,MAAM,CAAC,KAAK,IAAI,EAAE,GAAG;AACvB,eAAK,IAAI,EAAE;AACX,cAAI,KAAK,EAAE;AAAA,QACb;AAAA,MACF;AACA,aAAO,IAAI,SAAS,IAAI,MAAM,CAAC,KAAK;AAAA,IACtC;AACA,WAAO,CAAC,KAAK;AAAA,EACf;AAEA,QAAM,IAAI,MAAM,0DAA0D;AAC5E;AAEA,SAAS,4CAA4C,QAA2B;AAC9E,MAAI,OAAO,WAAW,YAAY,OAAO,SAAS,MAAM,GAAG;AACzD,WAAO,CAAC,OAAO,MAAM,CAAC;AAAA,EACxB;AAEA,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,UAAM,MAAgB,CAAC;AACvB,UAAM,OAAO,oBAAI,IAAY;AAC7B,eAAW,QAAQ,QAAQ;AACzB,UAAI,OAAO,SAAS,YAAY,CAAC,OAAO,SAAS,IAAI,GAAG;AACtD,cAAM,IAAI,MAAM,0DAA0D;AAAA,MAC5E;AACA,YAAM,KAAK,OAAO,IAAI;AACtB,UAAI,CAAC,KAAK,IAAI,EAAE,GAAG;AACjB,aAAK,IAAI,EAAE;AACX,YAAI,KAAK,EAAE;AAAA,MACb;AAAA,IACF;AACA,QAAI,IAAI,WAAW,GAAG;AACpB,YAAM,IAAI,MAAM,8CAA8C;AAAA,IAChE;AACA,WAAO;AAAA,EACT;AAEA,QAAM,IAAI,MAAM,0DAA0D;AAC5E;AAGO,SAAS,0CAA0C,QAAqC;AAC7F,MAAI,OAAO,WAAW,YAAY,OAAO,SAAS,MAAM,GAAG;AACzD,WAAO,OAAO,MAAM;AAAA,EACtB;AAEA,MAAI,OAAO,WAAW,YAAY,OAAO,KAAK,GAAG;AAC/C,WAAO,OAAO,KAAK;AAAA,EACrB;AAEA,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,eAAW,QAAQ,QAAQ;AACzB,YAAM,KAAK,mBAAmB,IAAI;AAClC,UAAI,GAAI,QAAO;AAAA,IACjB;AACA,WAAO;AAAA,EACT;AAEA,MAAI,UAAU,OAAO,WAAW,UAAU;AACxC,UAAM,SAAS;AACf,eAAW,OAAO,CAAC,MAAM,gBAAgB,QAAQ,GAAG;AAClD,YAAM,KAAK,mBAAmB,OAAO,GAAG,CAAC;AACzC,UAAI,GAAI,QAAO;AAAA,IACjB;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,mBAAmB,OAAoC;AAC9D,MAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,GAAG;AACvD,WAAO,OAAO,KAAK;AAAA,EACrB;AACA,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,GAAG;AAC7C,WAAO,MAAM,KAAK;AAAA,EACpB;AACA,SAAO;AACT;AAgDA,IAAM,iBAAiB;AAAA,EACrB,oBAAoB;AAAA,EACpB,QAAQ;AACV;AAQA,eAAsB,sBACpB,QACA,MACA,SACsC;AACtC,QAAM,OAAO,IAAI,SAAS;AAC1B,QAAM,WACJ,SAAS,aAAa,gBAAgB,QAAQ,KAAK,OAAO,KAAK,OAAO;AACxE,OAAK,OAAO,UAAU,MAAM,QAAQ;AAEpC,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,mBAAmB,QAAQ,gBAAgB;AAAA,MAC1D,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,IACX,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,QAAI,mBAAmB,KAAK,GAAG,GAAG;AAChC,YAAM,eACJ,OAAO,WAAW,aAAa,cAC3B,WAAW,SAAS,SACpB;AACN,YAAM,IAAI;AAAA,QACR,2FAA2F,YAAY;AAAA,QACvG,EAAE,OAAO,IAAI;AAAA,MACf;AAAA,IACF;AACA,UAAM;AAAA,EACR;AAEA,QAAM,MAAM,MAAM,SAAS,KAAK;AAChC,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI;AAAA,MACR,IAAI,KAAK,IACL,6BAA6B,SAAS,MAAM,MAAM,IAAI,MAAM,GAAG,GAAG,CAAC,KACnE,6BAA6B,SAAS,MAAM;AAAA,IAClD;AAAA,EACF;AAEA,QAAM,MAAM,sCAAsC,GAAG;AACrD,SAAO,EAAE,KAAK,SAAS,IAAI,CAAC,EAAG;AACjC;;;ACvLA,IAAM,eAAe,CAAC,uBAAuB,6BAA6B,2BAA2B,0BAA0B;AAExH,SAAS,0BAA0BC,UAA0B;AAClE,SAAO,aAAa,KAAK,CAAC,OAAO,GAAG,KAAKA,QAAO,CAAC;AACnD;AAEA,IAAM,UAAU,CAAC,QAAkB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAE3E,SAAS,eAAe,SAAiC;AAC9D,QAAM,SAAS,MAAmB;AAChC,QAAI,QAAQ,SAAS,EAAE,eAAe,WAAW,OAAO,UAAU,eAAe,CAAC,MAAM,QAAQ;AAC9F,YAAM,IAAI,MAAM,6DAA+D;AAAA,IACjF;AACA,WAAO,MAAM;AAAA,EACf;AAGA,QAAM,OAAO,OAAU,OAAqC;AAC1D,QAAI;AACF,YAAM,MAAM,MAAM,GAAG;AACrB,UAAI,QAAQ,SAAS,EAAE,UAAW,SAAQ,OAAO,EAAE,WAAW,KAAK,CAAC;AACpE,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,UAAI,0BAA0B,QAAQ,GAAG,CAAC,EAAG,SAAQ,OAAO,EAAE,WAAW,QAAQ,GAAG,EAAE,CAAC;AACvF,YAAM;AAAA,IACR;AAAA,EACF;AAUA,MAAI,UAAU;AACd,MAAI,UAAyB;AAC7B,QAAM,QAAQ,CAAI,OAAqC;AACrD,QAAI,cAAc,EAAG,WAAU;AAC/B,YAAQ,OAAO,EAAE,cAAc,WAAW,aAAa,KAAK,CAAC;AAC7D,UAAM,QAAQ,YAAY;AACxB,UAAI;AACF,eAAO,MAAM,GAAG;AAAA,MAClB,SAAS,KAAK;AACZ,kBAAU,QAAQ,GAAG;AACrB,cAAM;AAAA,MACR,UAAE;AACA,YAAI,EAAE,YAAY,EAAG,SAAQ,OAAO,UAAU,EAAE,cAAc,SAAS,aAAa,QAAQ,IAAI,EAAE,cAAc,OAAO,CAAC;AAAA,MAC1H;AAAA,IACF,GAAG;AACH,SAAK,MAAM,MAAM;AAAA,IAAC,CAAC;AACnB,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,CAAC,aAA+D;AAAA,IAC/E,YAAY,MAAM,QAAQ,EAAE,WAAW;AAAA,IACvC,SAAS,CAAC,SAAgB,SAAiB,MAAM,MAAM,QAAQ,EAAE,OAAO,SAAS,IAAI,CAAC;AAAA,IACtF,QAAQ,CAAC,SAAS,SAAS,MAAM,MAAM,QAAQ,EAAE,OAAO,SAAS,IAAI,CAAC;AAAA,IACtE,QAAQ,CAAC,SAAS,SAAS,MAAM,MAAM,QAAQ,EAAE,OAAO,SAAS,IAAI,CAAC;AAAA,IACtE,SAAS,CAAC,QAAQ,MAAM,MAAM,QAAQ,EAAE,QAAQ,GAAG,CAAC;AAAA,EACtD;AACA,QAAM,SAAS,oBAAI,IAAkC;AAErD,SAAO;AAAA,IACL,QAAQ,MAAM,QAAQ,OAAO;AAAA,IAE7B,oBAAoB,CAAC,YACnB,KAAK,YAAY;AACf,YAAM,OAAO,OAAO,EAAE,sBAAsB,MAAM;AAClD,UAAI,CAAC,KAAM,OAAM,IAAI,MAAM,2DAA2D;AACtF,aAAQ,MAAM,KAAK,EAAE,aAAa,OAAO,GAAG,QAAQ,CAAC;AAAA,IACvD,CAAC;AAAA,IACH,YAAY,CAAC,YAAY,KAAK,YAAa,MAAM,OAAO,EAAE,WAAW,OAAO,CAAwB;AAAA,IACpG,gBAAgB,CAAC,SAAS,YAAY,KAAK,MAAM,oBAAoB,OAAO,GAAG,SAAS,WAAW,CAAC,CAAC,CAAC;AAAA,IACtG,YAAY,CAAC,YACX,KAAK,YAAY;AACf,YAAM,MAAM,CAAC,GAAI,MAAM,OAAO,EAAE,WAAW,CAAE;AAC7C,aAAO,SAAS,gBAAgB,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,QAAQ,KAAK,CAAC,EAAE,WAAW,cAAc,CAAC;AAAA,IAClH,CAAC;AAAA,IACH,aAAa,CAAC,SAAS,YACrB,KAAK,YAAY;AACf,YAAM,QAAQ,MAAM,0BAA0B,OAAO,CAAC,GAAG,IAAI,OAAO;AACpE,UAAI,CAAC,KAAM,QAAO,CAAC;AACnB,YAAM,QAAkC;AAAA,QACtC,WAAW,SAAS,aAAa;AAAA,QACjC,qBAAqB,SAAS,uBAAuB;AAAA,QACrD,uBAAuB,SAAS,yBAAyB;AAAA,QACzD,mBAAmB,SAAS,qBAAqB;AAAA,MACnD;AACA,aAAO,CAAC,GAAG,IAAI,EACZ,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,SAAS,iBAAiB,CAAC,mBAAmB,OAAO,GAAG,KAAK,CAAC,EACrF,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,MAAM,EAAE,MAAM,OAAO,EAAE,OAAO,WAAW,EAAE,WAAW,SAAS,EAAE,SAAS,aAAa,EAAE,YAAY,EAAE;AAAA,IAC1I,CAAC;AAAA,IAEH,OAAO,SAAS,MAAM;AACpB,UAAI,CAAC,MAAM,cAAe,OAAM,IAAI,MAAM,4DAA4D;AACtG,aAAO,MAAM;AAAA,IACf,CAAC;AAAA,IACD,UAAU,CAAC,YAAY;AACrB,UAAI,MAAM,OAAO,IAAI,OAAO;AAC5B,UAAI,CAAC,KAAK;AACR,eAAO;AAAA,UACL;AAAA,UACC,MAAM,SAAS,MAAM;AACpB,gBAAI,OAAO,MAAM,aAAa,WAAY,OAAM,IAAI,MAAM,uDAAuD;AACjH,mBAAO,MAAM,SAAS,OAAO;AAAA,UAC/B,CAAC;AAAA,QACH;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,IACA,cAAc,CAAC,SAAS,YAAY,MAAM,MAAM,OAAO,EAAE,iBAAiB,SAAS,OAAO,CAAC;AAAA,IAE3F,kBAAkB,OAAO,YAAY;AACnC,YAAM,MAAM,WAAW,OAAO;AAAA,IAChC;AAAA,IACA,oBAAoB,OAAO,UAAU;AACnC,YAAM,UAAY,MAAM,MAAM,WAAW,KAAyC,CAAC;AACnF,YAAM,MAAM,WAAW,EAAE,GAAG,SAAS,GAAG,MAAM,CAAC;AAAA,IACjD;AAAA,IAEA,mBAAmB,OAAO,QAAQ;AAChC,UAAI,CAAC,MAAM,aAAc,OAAM,IAAI,MAAM,qDAAqD;AAC9F,YAAM,MAAM,aAAa,GAAG;AAAA,IAC9B;AAAA,IACA,uBAAuB,OAAO,WAAW;AACvC,UAAI,CAAC,MAAM,gBAAiB,OAAM,IAAI,MAAM,wDAAwD;AACpG,YAAM,MAAM,gBAAgB,MAAM;AAAA,IACpC;AAAA,IAEA,kBAAkB,CAAC,IAAI,YAAY,KAAK,MAAM,yBAAyB,OAAO,GAAG,IAAI,OAAO,CAAC;AAAA,IAC7F,qBAAqB,CAAC,IAAI,YAAY,KAAK,MAAM,oBAAoB,OAAO,GAAG,IAAI,OAAO,CAAC;AAAA,IAC3F,kBAAkB,CAAC,MAAM,YAAY,MAAM,MAAM,sBAAsB,OAAO,GAAG,MAAM,OAAO,CAAC;AAAA,IAC/F,eAAe,CAAC,MAAM,SAAS,KAAK,MAAM,mBAAmB,OAAO,GAAG,MAAM,IAAI,CAAC;AAAA,EACpF;AACF;;;ACpKA,SAAS,aAAa,OAAoD;AACxE,SAAO,OAAO,UAAU,WAAW,EAAE,MAAM,MAAM,IAAI;AACvD;AASO,SAAS,uBACd,MACA,UAC8B;AAC9B,QAAM,UAAoB,CAAC;AAC3B,QAAM,iBAA2B,CAAC;AAClC,MAAI,CAAC,KAAM,QAAO,EAAE,IAAI,MAAM,SAAS,OAAO,SAAS,eAAe;AAEtE,QAAM,IAAI,YAAY,CAAC;AACvB,aAAW,OAAO,MAAM;AACtB,UAAM,MAAM,aAAa,GAAG;AAC5B,QAAI,IAAI,SAAU;AAClB,UAAM,QAAQ,EAAE,IAAI,IAAI;AACxB,QAAI,IAAI,eAAe;AACrB,UAAI,UAAU,QAAW;AACvB,gBAAQ,KAAK,IAAI,IAAI;AAAA,MACvB,WAAW,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW,GAAG;AACtD,uBAAe,KAAK,IAAI,IAAI;AAAA,MAC9B;AAAA,IACF,OAAO;AACL,UAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GAAI,SAAQ,KAAK,IAAI,IAAI;AAAA,IAClF;AAAA,EACF;AACA,SAAO;AAAA,IACL,IAAI,QAAQ,WAAW,KAAK,eAAe,WAAW;AAAA,IACtD,SAAS;AAAA,IACT;AAAA,IACA;AAAA,EACF;AACF;;;ACjDA,IAAM,KAAK,CAAC,WAA2B,EAAE,IAAI,MAAM,MAAM;AACzD,IAAM,MAAM,CAACC,cAA4B,EAAE,IAAI,OAAO,SAAAA,SAAQ;AAG9D,SAAS,aAAa,OAA+B;AACnD,MAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,CAAC,MAAM,IAAK,QAAO,OAAO,MAAM,CAAC,KAAK,OAAO;AAC/E,MAAI,SAAS,OAAO,UAAU,YAAa,MAA8C,aAAa,SAAS,mBAAmB;AAChI,WAAO,OAAQ,MAA6B,QAAQ,OAAO;AAAA,EAC7D;AACA,SAAO;AACT;AAEA,SAAS,QAAQ,OAA2C;AAC1D,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,KAAK,EAAG,QAAO,UAAU,IAAI,OAAO;AACtF,MAAI,SAAS,OAAO,UAAU,YAAY,OAAQ,MAA8B,UAAU,UAAU;AAClG,UAAM,KAAM,MAA4B;AACxC,WAAO,OAAO,IAAI,OAAO;AAAA,EAC3B;AACA,MAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,CAAC,MAAM,OAAO,OAAO,MAAM,CAAC,MAAM,SAAU,QAAO,MAAM,CAAC,MAAM,IAAI,OAAO,MAAM,CAAC;AACpH,SAAO;AACT;AAEA,SAAS,MAAM,OAAsC;AACnD,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO,CAAC;AACnD,QAAM,OAAO,MAAM,QAAQ,KAAK,IAC5B,MAAM,CAAC,MAAM,MACX,MAAM,MAAM,CAAC,IACb,QACF,SAAS,OAAO,UAAU,YAAY,MAAM,QAAS,MAA+B,MAAM,IACvF,MAAgC,SACjC;AACN,SAAO,MAAM,MAAM,CAAC,MAAM,OAAO,MAAM,QAAQ,IAAK,OAAoB;AAC1E;AAEA,SAAS,SAAS,MAAc,OAAuB;AACrD,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,GAAG,KAAK;AAAA,IACjB,KAAK;AACH,aAAO,UAAU,QAAQ,OAAO,UAAU,WAAW,GAAG,SAAS,EAAE,IAAI,IAAI,UAAU;AAAA,IACvF,KAAK;AACH,aAAO,UAAU,QAAS,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAK,GAAG,KAAK,IAAI,IAAI,cAAc;AAAA,IACjH,KAAK;AACH,aAAO,UAAU,QAAS,OAAO,UAAU,YAAY,OAAO,UAAU,KAAK,IAAK,GAAG,KAAK,IAAI,IAAI,gBAAgB;AAAA,IACpH,KAAK;AACH,aAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,GAAG,SAAS,KAAK,IAAI,IAAI,mBAAmB;AAAA,IACpG,KAAK;AAAA,IACL,KAAK;AACH,UAAI,UAAU,KAAM,QAAO,GAAG,IAAI;AAClC,UAAI,iBAAiB,QAAQ,CAAC,OAAO,MAAM,MAAM,QAAQ,CAAC,EAAG,QAAO,GAAG,KAAK;AAE5E,UAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,EAAG,QAAO,GAAG,IAAI,KAAK,QAAQ,GAAI,CAAC;AACzF,aAAO,IAAI,YAAY;AAAA,IACzB,KAAK;AACH,aAAO,UAAU,QAAQ,OAAO,UAAU,WAAW,GAAG,KAAK,IAAI,IAAI,cAAc;AAAA,IACrF,KAAK,cAAc;AACjB,UAAI,UAAU,QAAQ,UAAU,OAAW,QAAO,GAAG,CAAC,CAAC;AACvD,YAAM,OAAO,MAAM,QAAQ,KAAK,IAAK,MAAM,CAAC,MAAM,MAAM,MAAM,MAAM,CAAC,IAAI,QAAS;AAClF,aAAO,MAAM,MAAM,CAAC,MAAM,OAAO,MAAM,QAAQ,IAAI,GAAG,IAAI,IAAI,IAAI,uBAAuB;AAAA,IAC3F;AAAA,IACA,KAAK,OAAO;AACV,UAAI,UAAU,KAAM,QAAO,GAAG,IAAI;AAClC,YAAM,KAAK,QAAQ,KAAK;AACxB,aAAO,OAAO,SAAY,IAAI,iBAAiB,IAAI,GAAG,EAAE;AAAA,IAC1D;AAAA,IACA,KAAK;AAAA,IACL,KAAK,eAAe;AAClB,YAAM,MAAM,MAAM,KAAK;AACvB,aAAO,QAAQ,SAAY,IAAI,SAAS,YAAY,6BAA6B,2BAA2B,IAAI,GAAG,GAAG;AAAA,IACxH;AAAA,IACA;AACE,aAAO,GAAG,KAAK;AAAA,EACnB;AACF;AAQA,SAAS,QAAQ,MAAoC;AACnD,UAAQ,QAAQ,OACb,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,EAAE,CAAC,CAAE,EAClC,OAAO,OAAO;AACnB;AAEO,SAAS,eAAe,MAA0B,OAAuB;AAC9E,QAAM,QAAQ,aAAa,KAAK;AAChC,MAAI,MAAO,QAAO,IAAI,kBAAkB,KAAK,GAAG;AAChD,QAAM,QAAQ,QAAQ,IAAI;AAC1B,MAAI,MAAM,WAAW,KAAK,MAAM,SAAS,KAAK,EAAG,QAAO,GAAG,UAAU,SAAY,OAAO,KAAK;AAC7F,MAAI,QAAsB;AAC1B,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,SAAS,MAAM,KAAK;AAClC,QAAI,MAAM,GAAI,QAAO;AACrB,sBAAU;AAAA,EACZ;AACA,SAAO;AACT;AAEA,IAAM,aAAa,CAAC,cAAc,WAAW,aAAa;AAcnD,SAAS,gBAAgB,MAA0B,OAAyB;AACjF,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,QAAM,QAAQ,QAAQ,IAAI;AAC1B,QAAM,UAAU,IAAI,UAAoB,MAAM,KAAK,CAAC,MAAM,MAAM,SAAS,CAAC,CAAC;AAC3E,MAAI,iBAAiB,KAAM,QAAO,QAAQ,QAAQ,UAAU,IAAI,KAAK,MAAM,MAAM,QAAQ,IAAI,GAAI,IAAI;AACrG,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,QAAI,CAAC,QAAQ,GAAG,UAAU,KAAK,MAAM,CAAC,MAAM,IAAK,QAAO;AACxD,WAAO,CAAC,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,QAAQ,IAAI,KAAK,IAAI,CAAC;AAAA,EAC5D;AACA,MAAI,QAAQ,KAAK,KAAK,OAAO,UAAU,SAAU,QAAO,QAAQ,KAAK,KAAK;AAC1E,SAAO;AACT;AAEO,IAAM,SAAS,CAAC,MAAkC,OAAO,MAAM,WAAW,IAAI,EAAE;AAChF,IAAM,SAAS,CAAC,MAAkC,OAAO,MAAM,WAAW,SAAY,EAAE;AAC/F,IAAM,aAAa,CAAC,MAAiC,OAAO,MAAM,YAAY,EAAE,aAAa;AAsBtF,SAAS,YACd,QACA,SACA,UACA,QAC+C;AAC/C,MAAI,CAAC,OAAQ,QAAO,EAAE,OAAO,MAAM,QAAQ,CAAC,EAAE;AAC9C,MAAI,CAAC,SAAS,OAAQ,QAAO,EAAE,OAAO,QAAa,QAAQ,CAAC,EAAE;AAC9D,MAAI,aAAa,KAAM,QAAO,EAAE,OAAO,MAAM,QAAQ,CAAC,EAAE;AACxD,QAAM,QAAQ,OAAO,OAAO,OAAO,WAAW,OAAO,KAAK;AAC1D,QAAM,MAA+B,EAAE,IAAI,OAAO,GAAG;AACrD,QAAM,SAA2B,CAAC;AAClC,aAAW,OAAO,SAAS;AACzB,UAAM,OAAO,OAAO,GAAG;AACvB,UAAM,OAAO,SAAS,IAAI;AAC1B,UAAM,OAAO,CAAC,QAAiB;AAC7B,YAAM,QAAQ,eAAe,OAAO,GAAG,GAAG,GAAG;AAC7C,UAAI,MAAM,GAAI,QAAO,MAAM;AAC3B,aAAO,KAAK,EAAE,OAAO,QAAQ,MAAM,SAAS,MAAM,SAAS,OAAO,IAAI,CAAC;AACvE,aAAO;AAAA,IACT;AACA,QAAI,MAAM,QAAQ,IAAI,KAAK,KAAK,SAAS,EAAG,KAAI,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC;AAAA,aAC9E,OAAO,SAAS,YAAY,KAAM,KAAI,IAAI,IAAI,KAAK,OAAO,IAAI,CAAC;AAAA,aAC/D,CAAC,WAAW,GAAG,EAAG,QAAO,EAAE,OAAO,MAAM,QAAQ,CAAC,EAAE;AAAA,EAC9D;AACA,MAAI,QAAQ;AACV,UAAM,SAAS,OAAO,WAAW,EAAE,SAAS,GAAG;AAC/C,QAAI,kBAAkB,SAAS;AAC7B,aAAO,KAAK,EAAE,OAAO,QAAQ,IAAI,SAAS,2EAA2E,OAAO,IAAI,CAAC;AAAA,IACnI,WAAW,YAAY,UAAU,OAAO,QAAQ;AAC9C,iBAAW,SAAS,OAAO,QAAQ;AACjC,cAAM,MAAM,MAAM,OAAO,CAAC;AAC1B,cAAM,SAAS,QAAQ,SAAY,KAAK,OAAO,OAAO,QAAQ,WAAW,IAAI,MAAM,GAAG;AACtF,eAAO,KAAK,EAAE,OAAO,QAAQ,SAAS,MAAM,SAAS,OAAO,SAAS,IAAI,MAAM,IAAI,IAAI,CAAC;AAAA,MAC1F;AAAA,IACF,WAAW,WAAW,QAAQ;AAC5B,aAAO,EAAE,OAAO,OAAO,OAAY,OAAO;AAAA,IAC5C;AAAA,EACF;AACA,SAAO,EAAE,OAAO,KAAU,OAAO;AACnC;;;AC/MO,IAAM,cAAmD,EAAE,MAAM,GAAG,cAAc,GAAG,MAAM,EAAE;AAE7F,SAAS,YAAY,KAA0C;AACpE,SAAO,QAAQ,UAAU,QAAQ,gBAAgB,QAAQ,SAAS,MAAM;AAC1E;AAEO,SAAS,YAAY,OAAoC;AAC9D,SAAO,UAAU,SAAS,yBAAyB,UAAU,eAAe,wBAAwB;AACtG;AAGO,SAAS,aAAa,OAAmC;AAC9D,SAAO,MAAM,kBAAkB,QAAQ,YAAY,MAAM,aAAa,IAAI,YAAY,MAAM,cAAc;AAC5G;AAEO,SAAS,aAAa,OAA6C;AACxE,UAAQ,MAAM,YAAY;AAAA,IACxB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO,aAAa,KAAK,IAAI,UAAU;AAAA,EAC3C;AACF;AAYA,IAAM,cAA4C,OAAO,OAAO,EAAE,IAAI,MAAM,SAAS,OAAO,SAAS,CAAC,GAAG,gBAAgB,CAAC,EAAE,CAAC;AAC7H,IAAM,mBAAiD,OAAO,OAAO,EAAE,IAAI,MAAM,SAAS,MAAM,SAAS,CAAC,GAAG,gBAAgB,CAAC,EAAE,CAAC;AAG1H,SAAS,0BACd,SACA,UAC8B;AAC9B,MAAI,CAAC,SAAS,OAAQ,QAAO;AAC7B,MAAI,aAAa,KAAM,QAAO;AAC9B,SAAO,uBAAuB,SAAS,QAAQ;AACjD;;;AC3DO,SAAS,4BAA4B,KAAkD;AAC5F,MAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,EAAE,cAAc,KAAM,QAAO;AACpE,QAAM,UAAU;AAChB,SAAO;AAAA,IACL,UAAU,QAAQ,YAAY,OAAO,OAAO,OAAO,QAAQ,QAAQ;AAAA,IACnE,UAAU,QAAQ,QAAQ,QAAQ;AAAA,EACpC;AACF;AAMO,SAAS,2BACd,aAC+B;AAC/B,MAAI,CAAC,eAAe,OAAO,gBAAgB,SAAU,QAAO;AAC5D,QAAM,MAAM;AACZ,QAAM,eACJ,OAAO,IAAI,iBAAiB,WACxB,IAAI,eACJ,OAAO,IAAI,gBAAgB,WACzB,IAAI,cACJ;AACR,QAAM,UAAU,4BAA4B,IAAI,OAAO;AACvD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,IACvC,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC/B;AACF;;;ACjBO,IAAM,aAAN,MAAoB;AAAA,EAMzB,YAA6B,MAA0C;AAA1C;AAL7B,SAAQ,YAAY,oBAAI,IAAiB;AACzC,SAAQ,QAAQ;AAChB,SAAQ,MAAM;AAAA,EAG0D;AAAA,EAExE,UAAU,UAAmC;AAC3C,SAAK,UAAU,IAAI,QAAQ;AAC3B,QAAI,CAAC,KAAK,OAAO;AACf,WAAK,QAAQ;AACb,UAAI;AACF,aAAK,KAAK,CAAC,UAAU,KAAK,KAAK,KAAK,CAAC;AAAA,MACvC,SAAS,KAAK;AACZ,gBAAQ,MAAM,4DAA4D,GAAG;AAAA,MAC/E;AAAA,IACF;AACA,QAAI,KAAK,IAAK,UAAS,KAAK,IAAS;AACrC,WAAO,MAAM;AACX,WAAK,UAAU,OAAO,QAAQ;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,OAAsB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,KAAK,OAAgB;AACnB,SAAK,MAAM;AACX,SAAK,OAAO;AACZ,eAAW,KAAK,CAAC,GAAG,KAAK,SAAS,EAAG,GAAE,KAAK;AAAA,EAC9C;AAAA;AAAA,EAGA,QAAc;AACZ,SAAK,UAAU,MAAM;AACrB,SAAK,QAAQ;AACb,SAAK,MAAM;AACX,SAAK,OAAO;AAAA,EACd;AACF;AAOA,IAAM,aAAa,CAAC,MAAgB,KAAK,OAAO,MAAM,WAAY,IAA6B;AAExF,IAAM,eAAe,IAAI,WAA0B,CAAC,SAAS;AAClE,QAAM,SAAS,CAAC,QAAQ,aAAa,KAAK,EAAE,QAAQ,UAAU,WAAW,QAAQ,EAAE,CAAC,GAAG,EAAE,aAAa,MAAM,CAAC;AAM7G,QAAM,sBAAsB,MAAM,uBAAuB,MAAM,QAAQ;AACvE,MAAI,OAAO,MAAM,OAAO,cAAc,OAAO,wBAAwB,WAAY;AACjF,MAAI;AACJ,QAAM,GAAG,WAAW,OAAO,QAAiB;AAC1C,UAAM,OAAO;AACb,QAAI,CAAC,MAAM,WAAW,OAAO,KAAK,UAAU,YAAY,KAAK,UAAU,UAAW;AAClF,gBAAY,KAAK;AACjB,QAAI;AACF,YAAM,SAAS,MAAM,oBAAoB,KAAK,OAAO,EAAE,aAAa,MAAM,CAAC;AAC3E,WAAK,EAAE,QAAQ,UAAU,aAAa,KAAK,GAAG,YAAY,KAAK,CAAC;AAAA,IAClE,SAAS,KAAK;AACZ,cAAQ,MAAM,mEAAmE,GAAG;AAAA,IACtF;AAAA,EACF,CAAC;AACH,CAAC;AAEM,IAAM,gBAAgB,IAAI,WAA2B,CAAC,SAAS;AACpE,QAAM,UAAU,CAAC,SAAS,aAAa,KAAK,EAAE,SAAS,UAAU,WAAW,QAAQ,EAAE,CAAC,GAAG;AAAA,IACxF,aAAa;AAAA,IACb,QAAQ;AAAA,EACV,CAAC;AACH,CAAC;AAEM,IAAM,gBAAgB,IAAI,WAA2B,CAAC,SAAS;AACpE,QAAM;AAAA,IAAU,CAAC,SAAS,gBACxB,KAAK;AAAA,MACH,SAAS,UAAU,EAAE,GAAG,QAAQ,IAAI;AAAA,MACpC,aAAa,2BAA4B,eAAiD,IAAI;AAAA,IAChG,CAAC;AAAA,EACH;AACF,CAAC;AAEM,IAAM,kBAAkB,IAAI,WAA6B,CAAC,SAAS;AACxE,MAAI,OAAO,MAAM,gBAAgB,WAAY;AAC7C,QAAM,YAAY,CAAC,aAAa,KAAK,EAAE,UAAU,WAAW,QAAQ,EAAE,CAAC,CAAC;AAC1E,CAAC;AAGM,IAAM,gBAAgB,IAAI,WAAoB,CAAC,SAAS;AAC7D,MAAI,OAAO,MAAM,OAAO,WAAY;AACpC,QAAM,GAAG,WAAW,CAAC,QAAiB,KAAK,GAAG,CAAC;AACjD,CAAC;AAEM,IAAM,cAAc,CAAC,cAAc,eAAe,eAAe,iBAAiB,aAAa;;;AC1GtG,IAAMC,eAAmD;AAAA,EACvD,MAAM;AAAA,EACN,cAAc;AAAA,EACd,MAAM;AACR;AAEA,IAAIC,YAAiC;AACrC,IAAI,aAAyC;AAC7C,IAAI,kBAA8C;AAElD,SAAS,cAAc,SAAqD;AAC1E,SAAO,IAAI,KAAK,WAAW,CAAC,GAAG,IAAI,CAAC,MAAO,OAAO,MAAM,WAAW,IAAI,EAAE,IAAK,CAAC;AACjF;AASA,SAAS,aAAa,MAA2B,aAA2C;AAC1F,MAAI,CAAC,WAAY,QAAO;AACxB,MAAID,aAAY,IAAI,IAAIA,aAAY,UAAU,EAAG,QAAO;AACxD,aAAW,QAAQ,aAAa;AAC9B,QAAI,CAAC,iBAAiB,IAAI,IAAI,EAAG,QAAO;AAAA,EAC1C;AACA,SAAO;AACT;AAOO,SAAS,iBAAiB,SAA2C;AAC1E,QAAM,SAAS,QAAQ,kBAAkB;AACzC,QAAM,UAAU,cAAc,QAAQ,OAAO;AAC7C,MAAIC,aAAY,CAAC,aAAa,QAAQ,OAAO,EAAG,QAAOA;AAEvD,eAAa;AACb,oBAAkB;AAClB,QAAM,OAAO,QAAQ,QAAQ,EAAE,KAAK,MAAM;AACxC,UAAM,SAAS,MAAM,MAAM,OAAO;AAClC,WAAO,kBAAkB,UAAU,SAAS,QAAQ,QAAQ;AAAA,EAC9D,CAAC;AAED,EAAAA,YAAW,KAAK,MAAM,CAAC,QAAQ;AAC7B,IAAAA,YAAW;AACX,iBAAa;AACb,sBAAkB;AAClB,UAAM;AAAA,EACR,CAAC;AACD,SAAOA;AACT;AAYO,SAAS,kBAAwB;AACtC,EAAAA,YAAW;AACX,eAAa;AACb,oBAAkB;AACpB;;;AC7EO,SAAS,uBAAuB,SAAyC;AAC9E,MAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAM,MAAM;AACZ,QAAM,MAAM,IAAI;AAChB,MAAI,QAAQ,WAAW,QAAQ,OAAQ,QAAO;AAC9C,MAAI,OAAO,OAAO,QAAQ,UAAU;AAClC,UAAM,aAAc,IAAgC;AACpD,QAAI,eAAe,WAAW,eAAe,OAAQ,QAAO;AAAA,EAC9D;AACA,SAAO;AACT;;;AC8DA,IAAM,mBAAmB;AAElB,SAAS,oBAAoB,UAA6B,CAAC,GAAsB;AACtF,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,iBAAiB;AAAA,IACjB,gBAAgB,QAAQ,kBAAkB;AAAA,IAC1C,eAAe;AAAA,IACf,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,aAAa;AAAA,IACb,UAAU;AAAA,IACV,eAAe;AAAA,IACf,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,OAAO;AAAA,IACP,cAAc;AAAA,IACd,aAAa;AAAA,IACb,WAAW;AAAA,IACX,gBAAgB,CAAC;AAAA,EACnB;AACF;AAEA,SAAS,aAAsB;AAC7B,MAAI;AACF,WAAO,OAAO,WAAW,eAAe,OAAO,SAAS,OAAO;AAAA,EACjE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,IAAM,WAAW,MAAM,OAAO,UAAU,eAAe,UAAU;AAE1D,SAAS,mBAAmB,UAA+B,CAAC,GAAiB;AAClF,MAAI,QAAQ,oBAAoB,OAAO;AACvC,QAAM,YAAY,oBAAI,IAAgB;AACtC,MAAI,SAAS;AACb,MAAI,cAAmC;AACvC,MAAI,UAAU;AAEd,QAAM,SAAS,CAAC,UAAsC;AACpD,QAAI,UAAU;AACd,eAAW,OAAO,OAAO,KAAK,KAAK,GAAkC;AACnE,UAAI,CAAC,OAAO,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,EAAG,WAAU;AAAA,IACpD;AACA,QAAI,CAAC,QAAS;AACd,YAAQ,EAAE,GAAG,OAAO,GAAG,MAAM;AAC7B,eAAW,KAAK,CAAC,GAAG,SAAS,EAAG,GAAE;AAAA,EACpC;AAEA,QAAM,UAA6B;AAAA,IACjC,gBAAgB,QAAQ,kBAAkB;AAAA,IAC1C,SAAS,QAAQ,WAAW,CAAC;AAAA,IAC7B,GAAI,QAAQ,kBAAkB,SAAY,EAAE,eAAe,QAAQ,cAAc,IAAI,CAAC;AAAA,IACtF,GAAI,QAAQ,qBAAqB,SAAY,EAAE,kBAAkB,QAAQ,iBAAiB,IAAI,CAAC;AAAA,IAC/F,GAAI,QAAQ,gBAAgB,EAAE,eAAe,QAAQ,cAAc,IAAI,CAAC;AAAA,EAC1E;AAEA,QAAM,eAAe,YAAY;AAC/B,QAAI;AACF,YAAM,UAAU,MAAM,MAAM,eAAe,WAAW;AACtD,UAAI,QAAS,QAAO,EAAE,gBAAgB,QAAQ,CAAC;AAAA,IACjD,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,kBAAkB,YAAY;AAClC,QAAI,OAAO,MAAM,YAAY,aAAa,WAAY;AACtD,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,WAAW,SAAS;AAEjD,UAAI,MAAM,aAAa,KAAM,QAAO,EAAE,UAAW,YAA4C,CAAC,EAAE,CAAC;AAAA,IACnG,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,UAAU,YAAY;AAC1B,UAAM,OAAO,EAAE;AACf,WAAO,EAAE,YAAY,cAAc,iBAAiB,KAAK,CAAC;AAC1D,QAAI;AACJ,QAAI;AACF,YAAM,QAAQ,KAAK;AAAA,QACjB,iBAAiB,OAAO;AAAA,QACxB,IAAI,QAAQ,CAAC,GAAG,WAAW;AACzB,kBAAQ,WAAW,MAAM,OAAO,IAAI,MAAM,6CAA6C,mBAAmB,GAAI,KAAK,CAAC,GAAG,gBAAgB;AAAA,QACzI,CAAC;AAAA,MACH,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAI,SAAS,QAAS,QAAO,EAAE,YAAY,SAAS,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AACvH;AAAA,IACF,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AACA,QAAI,SAAS,QAAS;AACtB,WAAO,EAAE,YAAY,QAAQ,CAAC;AAC9B,UAAM,QAAQ,IAAI,CAAC,gBAAgB,GAAG,aAAa,CAAC,CAAC;AAAA,EACvD;AAEA,QAAM,SAAS,MAAM;AACnB,UAAM,OAAO;AAAA;AAAA,MAEX,aAAa;AAAA,QAAU,CAAC,EAAE,QAAQ,SAAS,MACzC,OAAO;AAAA,UACL,QAAQ,SAAU,EAAE,GAAG,OAAO,IAAuB;AAAA,UACrD,aAAa;AAAA,UACb,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,QACjC,CAAC;AAAA,MACH;AAAA,MACA,cAAc,UAAU,CAAC,EAAE,SAAS,SAAS,MAAM;AACjD,eAAO,EAAE,SAAS,QAAQ,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,EAAoB,GAAG,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC,EAAG,CAAC;AACvG,aAAK,aAAa;AAAA,MACpB,CAAC;AAAA,MACD,cAAc;AAAA,QAAU,CAAC,EAAE,SAAS,eAAe,YAAY,MAC7D,OAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA,eAAe,YAAY,aAAa,YAAY,KAAK,MAAM;AAAA,QACjE,CAAC;AAAA,MACH;AAAA,MACA,gBAAgB,UAAU,CAAC,EAAE,SAAS,MAAM,OAAO,EAAE,aAAa,MAAM,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC,EAAG,CAAC,CAAC;AAAA,MAC5G,cAAc,UAAU,CAAC,QAAQ;AAC/B,cAAM,QAAQ,uBAAuB,GAAG;AACxC,YAAI,MAAO,QAAO,EAAE,MAAM,CAAC;AAAA,MAC7B,CAAC;AAAA,IACH;AACA,WAAO,MAAM,KAAK,QAAQ,CAAC,QAAQ,IAAI,CAAC;AAAA,EAC1C;AAEA,QAAM,QAAQ,MAAM;AAClB,QAAI,CAAC,WAAW,EAAG,QAAO,OAAO,EAAE,YAAY,eAAe,CAAC;AAC/D,QAAI,CAAC,SAAS,GAAG;AAGf,UAAI,OAAO,aAAa,eAAe,SAAS,eAAe,cAAc,OAAO,WAAW,aAAa;AAC1G,eAAO,iBAAiB,QAAQ,MAAO,SAAS,IAAI,MAAM,IAAI,OAAO,EAAE,YAAY,cAAc,CAAC,GAAI,EAAE,MAAM,KAAK,CAAC;AACpH;AAAA,MACF;AACA,aAAO,OAAO,EAAE,YAAY,cAAc,CAAC;AAAA,IAC7C;AAEA,kCAAgB,OAAO;AACvB,SAAK,QAAQ;AAAA,EACf;AAEA,SAAO;AAAA,IACL;AAAA,IACA,UAAU,MAAM;AAAA,IAChB,UAAU,UAAU;AAClB,gBAAU,IAAI,QAAQ;AACtB,aAAO,MAAM,UAAU,OAAO,QAAQ;AAAA,IACxC;AAAA,IACA,QAAQ;AACN,UAAI,aAAa,EAAG,OAAM;AAC1B,aAAO,MAAM;AACX,YAAI,EAAE,SAAS,EAAG;AAClB,sBAAc;AACd,sBAAc;AAAA,MAChB;AAAA,IACF;AAAA,IACA,MAAM,SAAS;AACb,UAAI,CAAC,SAAS,KAAK,CAAC,WAAW,EAAG,QAAO,MAAM;AAC/C,sBAAgB;AAChB,aAAO,EAAE,UAAU,KAAK,CAAC;AACzB,oCAAgB,OAAO;AACvB,YAAM,QAAQ;AAAA,IAChB;AAAA,IACA;AAAA,EACF;AACF;;;AjB9HA,IAAM,mBAAe,4BAAwC,IAAI;AACjE,aAAa,cAAc;AAGpB,SAAS,kBAA4C;AAC1D,aAAO,yBAAW,YAAY;AAChC;AAEA,SAAS,cAAc,SAAyD;AAC9E,QAAM,UAAU,mBAAmB,OAAO;AAC1C,SAAO,EAAE,SAAS,KAAK,eAAe,OAAO,EAAE;AACjD;AAEA,IAAI,iBAA2C;AAGxC,SAAS,qBAA2B;AACzC,mBAAiB;AACjB,kBAAgB;AAChB,aAAW,KAAK,YAAa,GAAE,MAAM;AACvC;AAEO,IAAM,uBAAuB,aAAa;AAGjD,IAAM,cAAc,MAAM,oBAAoB;AAGvC,SAAS,cAAc,YAAkD;AAC9E,QAAM,EAAE,QAAQ,IAAI;AACpB,8BAAU,MAAM,QAAQ,MAAM,GAAG,CAAC,OAAO,CAAC;AAC1C,aAAO,mCAAqB,QAAQ,WAAW,QAAQ,UAAU,WAAW;AAC9E;AAIA,IAAM,YAAuC,OAAO,OAAO,CAAC,CAAC;AAG7D,SAAS,UAAmB,OAA0B,SAA+C;AACnG,QAAM,EAAE,QAAQ,SAAS,SAAS,IAAI;AACtC,QAAM,EAAE,SAAS,OAAO,IAAI;AAC5B,aAAO,sBAAQ,MAAM;AACnB,UAAM,SAA2B,CAAC;AAClC,UAAM,OACJ,YAAY,SAAS,SAAS,aAAa,OAAO,QAC9C,QAAQ,IAAI,CAAC,MAAM;AACjB,YAAM,MAAM,YAAqB,GAAG,SAAS,UAAU,MAAM;AAC7D,aAAO,KAAK,GAAG,IAAI,MAAM;AACzB,aAAO,IAAI;AAAA,IACb,CAAC,IACD;AACN,UAAM,WAAW,YAAqB,QAAQ,SAAS,UAAU,MAAM;AACvE,QAAI,UAAU,CAAC,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,OAAO,EAAE,EAAG,QAAO,KAAK,GAAG,SAAS,MAAM;AACvF,UAAM,gBAAgB,QAAQ,KAAK,MAAM,CAAC,MAAM,MAAM,IAAI,IAAK,OAAqB;AACpF,WAAO,EAAE,QAAQ,SAAS,OAAO,SAAS,eAAe,QAAQ,OAAO,SAAS,SAAS,UAAU;AAAA,EACtG,GAAG,CAAC,QAAQ,SAAS,UAAU,SAAS,MAAM,CAAC;AACjD;AA+DA,IAAM,iBAAuC,OAAO,OAAO,CAAC,CAAC;AAoE7D,IAAM,YAA+B,MAAM;AACzC,QAAM,QAAQ,oBAAoB;AAClC,QAAM,UAAwB;AAAA,IAC5B,SAAS,CAAC;AAAA,IACV,UAAU,MAAM;AAAA,IAChB,WAAW,MAAM,MAAM;AAAA,IAAC;AAAA,IACxB,OAAO,MAAM,MAAM;AAAA,IAAC;AAAA,IACpB,QAAQ,YAAY;AAAA,IAAC;AAAA,IACrB,QAAQ,MAAM;AAAA,IAAC;AAAA,EACjB;AACA,SAAO,EAAE,SAAS,KAAK,eAAe,OAAO,EAAE;AACjD,GAAG;AAGI,SAAS,uBAId;AACA,QAAM,iBAAa,yBAAW,YAAY;AAC1C,QAAM,QAAQ,cAAc,cAAc,QAAQ;AAClD,QAAM,EAAE,OAAO,IAAI,UAAU,QAAQ,cAAc,UAAU,QAAQ,OAAO;AAC5E,SAAO,EAAE,YAAY,OAAO,YAAY,OAAO;AACjD;;;AkB7QO,SAAS,cAAc,OAAsC;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,gBAAgB,SAAS,cAAc;AAC/F;;;AClEA,IAAAC,gBAAyC;AAiBhC;AAFF,SAAS,oBAAoB,EAAE,SAAS,SAAS,GAA6B;AACnF,QAAM,CAAC,UAAU,QAAI,wBAAS,MAAM,cAAc,OAAO,CAAC;AAC1D,SAAO,4CAAC,wBAAqB,OAAO,YAAa,UAAS;AAC5D;;;AClBA,IAAAC,gBAA0E;AAyFpE,IAAAC,sBAAA;AA1EN,IAAM,aAA4B;AAAA,EAChC,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,OAAO;AAAA,EACP,SAAS;AAAA,EACT,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,SAAS;AAAA,EACT,OAAO;AACT;AAEA,IAAM,YAA2B;AAAA,EAC/B,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,WAAW;AAAA,EACX,UAAU;AAAA,EACV,SAAS;AAAA,EACT,WAAW;AAAA,EACX,OAAO;AACT;AAEA,IAAM,aAA4B;AAAA,EAChC,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,QAAQ;AACV;AAEA,IAAM,eAA8B;AAAA,EAClC,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,QAAQ;AACV;AAEA,IAAM,cAA6B;AAAA,EACjC,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,SAAS;AACX;AAcO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA,SAAAC;AAAA,EACA,OAAO;AAAA,EACP,YAAY;AAAA,EACZ;AAAA,EACA,aAAa;AAAA,EACb,iBAAiB;AACnB,GAA6B;AAC3B,SACE,6CAAC,SAAI,OAAO,YAAY,MAAM,SAAS,UAAU,UAAU,UACzD,wDAAC,SAAI,OAAO,WACV;AAAA,iDAAC,QAAG,OAAO,YAAa,iBAAM;AAAA,IAC9B,6CAAC,OAAE,OAAO,cAAe,UAAAA,UAAQ;AAAA,IAChC,aAAa,UACZ;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,QAAQ;AAAA,QAClB,SAAS,MAAM,KAAK,QAAQ,OAAO;AAAA,QACnC,OAAO;AAAA,UACL,GAAG;AAAA,UACH,QAAQ,QAAQ,cAAc,gBAAgB;AAAA,UAC9C,SAAS,QAAQ,cAAc,MAAM;AAAA,QACvC;AAAA,QACA,MAAK;AAAA,QAEJ,kBAAQ,cAAc,iBAAiB;AAAA;AAAA,IAC1C,IACE;AAAA,KACN,GACF;AAEJ;AAKO,SAAS,eAAe,OAA0B,SAAyE;AAChI,UAAQ,MAAM,YAAY;AAAA,IACxB,KAAK;AACH,aAAO,EAAE,OAAO,uBAAuB,SAAS,sDAAiD;AAAA,IACnG,KAAK;AACH,aAAO;AAAA,QACL,OAAO;AAAA,QACP,SAAS;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,OAAO;AAAA,QACP,SAAS;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,OAAO;AAAA,QACP,SAAS,MAAM,mBAAmB;AAAA,QAClC,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,EACJ;AACA,MAAI,aAAa,KAAK,GAAG;AACvB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS,iCAAiC,YAAY,MAAM,cAAc,CAAC;AAAA,MAC3E,MAAM;AAAA,MACN,OAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,UAAU,0BAA0B,SAAS,MAAM,QAAQ;AACjE,MAAI,QAAQ,QAAS,QAAO,EAAE,OAAO,uBAAuB,SAAS,uDAAkD;AACvH,MAAI,CAAC,QAAQ,IAAI;AACf,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SACE;AAAA,IACJ;AAAA,EACF;AACA,SAAO;AACT;AAQO,SAAS,cAAc,EAAE,SAAS,GAAuB;AAC9D,QAAM,aAAa,gBAAgB;AACnC,MAAI,CAAC,WAAY,OAAM,IAAI,MAAM,4FAA4F;AAC7H,QAAM,QAAQ,cAAc,UAAU;AACtC,QAAM,CAAC,aAAa,cAAc,QAAI,wBAAS,KAAK;AACpD,QAAM,aAAS,2BAAY,YAAY;AACrC,mBAAe,IAAI;AACnB,QAAI;AACF,YAAM,WAAW,QAAQ,OAAO;AAAA,IAClC,SAAS,KAAK;AACZ,cAAQ,MAAM,qCAAqC,GAAG;AAAA,IACxD,UAAE;AACA,qBAAe,KAAK;AAAA,IACtB;AAAA,EACF,GAAG,CAAC,UAAU,CAAC;AAEf,QAAMC,UAAS,eAAe,OAAO,WAAW,QAAQ,QAAQ,OAAO;AACvE,MAAI,CAACA,QAAQ,QAAO,6EAAG,UAAS;AAChC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAOA,QAAO;AAAA,MACd,SAASA,QAAO;AAAA,MAChB,MAAMA,QAAO;AAAA,MACb,WAAWA,QAAO;AAAA,MAClB,SAAS,EAAE,QAAQ,YAAY;AAAA,MAC/B,YAAYA,QAAO,SAAS,UAAU,cAAc;AAAA,MACpD,gBAAgBA,QAAO,SAAS,UAAU,mBAAc;AAAA;AAAA,EAC1D;AAEJ;;;AC3LO,SAAS,2BAAwD,OAA2C;AACjH,SAAO,EAAE,GAAG,OAAO,MAAM,MAAM,QAAQ,CAAC,EAAE;AAC5C;AAGO,SAAS,8BAA8D,KAAW;AACvF,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QAAQ,OAAO;AAAA,MACb,OAAO,QAAQ,IAAI,MAAM,EAAE,IAAI,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,2BAA2B,CAAC,CAAC,CAAC;AAAA,IAC3F;AAAA,EACF;AACF;;;AClBA,IAAAC,gBAA0B;AAOnB,SAAS,kBAAkB,OAAuC;AACvE,+BAAU,MAAM;AACd,QAAI,CAAC,MAAO;AAEZ,UAAM,EAAE,OAAO,YAAY,IAAI;AAC/B,UAAM,eAAe,OAAO,SAAS;AAErC,aAAS,QAAQ;AACjB,eAAW,QAAQ,SAAS,KAAK;AACjC,eAAW,QAAQ,eAAe,WAAW;AAC7C,eAAW,YAAY,YAAY,KAAK;AACxC,eAAW,YAAY,kBAAkB,WAAW;AACpD,eAAW,YAAY,WAAW,SAAS;AAC3C,eAAW,YAAY,UAAU,YAAY;AAC7C,eAAW,QAAQ,gBAAgB,SAAS;AAC5C,eAAW,QAAQ,iBAAiB,KAAK;AACzC,eAAW,QAAQ,uBAAuB,WAAW;AAAA,EAEvD,GAAG,CAAC,KAAK,CAAC;AACZ;AAEA,SAAS,WAAW,KAA0B,OAAe,SAAiB;AAC5E,MAAI,OAAO,SAAS,KAAK;AAAA,IACvB,QAAQ,GAAG,KAAK,KAAK;AAAA,EACvB;AACA,MAAI,CAAC,MAAM;AACT,WAAO,SAAS,cAAc,MAAM;AACpC,SAAK,aAAa,KAAK,KAAK;AAC5B,aAAS,KAAK,YAAY,IAAI;AAAA,EAChC;AACA,OAAK,aAAa,WAAW,OAAO;AACtC;;;AC9BO,SAAS,wBACd,SACA,OACA,OACsB;AACtB,SAAO,CAAC,gBAAgB,SAAS,OAAO,KAAK;AAC/C;AAGO,SAAS,qBAAqB,SAAiB,QAAuD;AAC3G,SAAO,CAAC,aAAa,SAAS,MAAM,MAAM;AAC5C;AAGO,SAAS,wBAAwB,SAAiB,OAAqC;AAC5F,SAAO,CAAC,gBAAgB,SAAS,KAAK;AACxC;AAGO,SAAS,4BACd,SACA,QACA,eACsB;AACtB,SAAO,CAAC,oBAAoB,SAAS,QAAQ,aAAa;AAC5D;AAOO,SAAS,yBACd,SACA,QACA,QACsB;AACtB,QAAM,SAAS,gBAAgB,MAAM;AACrC,QAAM,MAAM,UAAU,IAAI,MAAqB,MAAM,EAAE,KAAK,IAAI;AAChE,SAAO,CAAC,iBAAiB,SAAS,KAAK,MAAM;AAC/C;AAGO,SAAS,4BAA4B,SAAiB,QAAwC;AACnG,SAAO,CAAC,oBAAoB,SAAS,MAAM;AAC7C;AAgCA,SAAS,gBAAgB,QAA2C;AAClE,aAAW,OAAO,OAAO,OAAO,MAAM,EAAG,KAAI,MAAM,QAAQ,GAAG,EAAG,QAAO,IAAI;AAC5E,SAAO;AACT;;;ACxFA,IAAAC,gBAAoC;;;ACQpC,IAAM,QAAQ,CAAC,MAAc,aAAqB,SAAS,IAAI,KAAK,QAAQ;AAErE,IAAM,SAAS;AAAA,EACpB,YAAY,MAAM,cAAc,SAAS;AAAA,EACzC,YAAY,MAAM,cAAc,SAAS;AAAA,EACzC,MAAM,MAAM,QAAQ,SAAS;AAAA,EAC7B,iBAAiB,MAAM,oBAAoB,SAAS;AAAA,EACpD,QAAQ,MAAM,UAAU,SAAS;AAAA,EACjC,SAAS,MAAM,WAAW,SAAS;AAAA,EACnC,mBAAmB,MAAM,sBAAsB,SAAS;AAAA,EACxD,aAAa,MAAM,eAAe,SAAS;AAAA,EAC3C,QAAQ,MAAM,UAAU,UAAU;AACpC;AAEO,IAAM,YAA2B;AAAA,EACtC,WAAW;AAAA,EACX,SAAS;AAAA,EACT,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,OAAO,OAAO;AAAA,EACd,MAAM;AACR;AAEO,IAAM,eAA8B;AAAA,EACzC,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,OAAO,OAAO;AAChB;AAEO,IAAM,eAA8B;AAAA,EACzC,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,eAAe;AACjB;AAEO,IAAM,YAA2B;AAAA,EACtC,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,WAAW;AAAA,EACX,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,OAAO,OAAO;AAChB;AAEO,IAAMC,aAA2B;AAAA,EACtC,WAAW;AAAA,EACX,cAAc;AAAA,EACd,SAAS;AAAA,EACT,QAAQ,aAAa,OAAO,MAAM;AAAA,EAClC,cAAc,OAAO;AAAA,EACrB,YAAY,OAAO;AACrB;AAEO,IAAM,iBAAgC;AAAA,EAC3C,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,YAAY;AACd;AAEO,IAAM,gBAA+B;AAAA,EAC1C,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,OAAO,OAAO;AAChB;AAEO,IAAM,YAA2B;AAAA,EACtC,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,OAAO,OAAO;AAChB;;;AClFO,SAAS,cAAsB;AACpC,QAAM,QAAQ,OAAO,aAAa,cAAc,KAAK,SAAS,MAAM,KAAK;AACzE,SAAO,SAAS;AAClB;;;AFqCM,IAAAC,sBAAA;AA1BN,SAAS,aAA6B;AACpC,QAAM,CAAC,KAAK,MAAM,QAAI,wBAAyB,IAAI;AACnD,+BAAU,MAAM;AACd,QAAI,OAAO,UAAU,WAAY;AACjC,QAAI,OAAO;AACX,UAAM,mBAAmB,EAAE,QAAQ,OAAO,CAAC,EACxC,KAAK,CAAC,QAAQ,QAAQ,OAAO,IAAI,EAAE,CAAC,EACpC,MAAM,MAAM,QAAQ,OAAO,KAAK,CAAC;AACpC,WAAO,MAAM;AACX,aAAO;AAAA,IACT;AAAA,EACF,GAAG,CAAC,CAAC;AACL,SAAO;AACT;AASO,SAAS,eAAe;AAC7B,QAAM,UAAU,WAAW;AAC3B,SACE,8CAAC,UAAK,OAAO,WACX;AAAA,kDAAC,OAAE,OAAO,cAAe;AAAA,kBAAY;AAAA,MAAE;AAAA,OAAY;AAAA,IACnD,6CAAC,QAAG,OAAO,cAAc,mCAAqB;AAAA,IAC9C,6CAAC,OAAE,OAAO,WAAW,+FAAiF;AAAA,IAEtG,8CAAC,aAAQ,OAAOC,YACd;AAAA,mDAAC,QAAG,OAAO,gBAAgB,+CAAiC;AAAA,MAC3D,YAAY,QACX,8CAAC,OAAE,OAAO,eAAe;AAAA;AAAA,QACnB,6CAAC,UAAK,OAAO,WAAW,8BAAgB;AAAA,QAAO;AAAA,QAAmC;AAAA,QACtF,6CAAC,UAAK,OAAO,WAAW,0BAAY;AAAA,QAAO;AAAA,QAAmC;AAAA,QAC9E,6CAAC,OAAE,MAAK,mBAAkB,6BAAe;AAAA,QAAI;AAAA,SAE/C,IAEA,8CAAC,OAAE,OAAO,eACR;AAAA,qDAAC,OAAE,MAAK,mBAAkB,kCAAoB;AAAA,QAAI;AAAA,QACuB;AAAA,QACzE,6CAAC,UAAK,OAAO,WAAW,oCAAsB;AAAA,QAAO;AAAA,QAA2C;AAAA,QAChG,6CAAC,UAAK,OAAO,WAAW,8BAAgB;AAAA,QAAO;AAAA,SACjD;AAAA,OAEJ;AAAA,IAEA,8CAAC,aAAQ,OAAOA,YACd;AAAA,mDAAC,QAAG,OAAO,gBAAgB,yCAA2B;AAAA,MACtD,8CAAC,OAAE,OAAO,eAAe;AAAA;AAAA,QACf,6CAAC,UAAK,OAAO,WAAW,iBAAG;AAAA,QAAO;AAAA,QAAgB,6CAAC,UAAK,OAAO,WAAW,mBAAK;AAAA,QAAO;AAAA,QACA;AAAA,QAC9F,6CAAC,UAAK,OAAO,WAAW,uBAAS;AAAA,QAAO;AAAA,SAC1C;AAAA,OACF;AAAA,IAEA,8CAAC,aAAQ,OAAOA,YACd;AAAA,mDAAC,QAAG,OAAO,gBAAgB,4CAA8B;AAAA,MACzD,8CAAC,OAAE,OAAO,eACR;AAAA,qDAAC,UAAK,OAAO,WAAW,0CAA4B;AAAA,QAAO;AAAA,QAAyB;AAAA,QACpF,6CAAC,UAAK,OAAO,WAAW,mDAA2C;AAAA,QAAO;AAAA,SAC5E;AAAA,OACF;AAAA,KACF;AAEJ;;;AGrFA,IAAAC,gBAA6C;;;ACuB7C,IAAM,kBAAkB;AAOjB,SAAS,gBAAgB,UAA8B;AAC5D,QAAM,WAAW,SAAS,QAAQ,QAAQ,EAAE,EAAE,MAAM,GAAG;AACvD,QAAM,OAAO,SAAS,SAAS,SAAS,CAAC,KAAK;AAE9C,MAAI,UAAgC;AACpC,MAAI,SAAS,SAAU,WAAU,EAAE,MAAM,SAAS;AAAA,WACzC,SAAS,MAAO,WAAU,EAAE,MAAM,MAAM;AAAA,OAC5C;AACH,UAAM,QAAQ,gBAAgB,KAAK,IAAI;AACvC,QAAI,MAAO,WAAU,EAAE,MAAM,WAAW,SAAS,MAAM,CAAC,EAAE;AAAA,EAC5D;AAEA,MAAI,CAAC,QAAS,QAAO,EAAE,SAAS,EAAE,MAAM,SAAS,GAAG,UAAU,kBAAkB,QAAQ,EAAE;AAC1F,SAAO,EAAE,SAAS,UAAU,kBAAkB,SAAS,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG,CAAC,EAAE;AACjF;AAGO,SAAS,mBAAmB,SAAgC;AACjE,SAAO,QAAQ,SAAS,YAAY,IAAI,QAAQ,OAAO,KAAK,QAAQ;AACtE;AAEA,SAAS,kBAAkB,MAAsB;AAC/C,SAAO,KAAK,SAAS,GAAG,IAAI,OAAO,GAAG,IAAI;AAC5C;;;ACrDA,IAAAC,gBAAoC;AAsB7B,SAAS,oBACd,WAAmB,OAAO,WAAW,cAAc,MAAM,OAAO,SAAS,UAC9C;AAC3B,QAAM,MAAM,GAAG,gBAAgB,QAAQ,EAAE,QAAQ;AACjD,QAAM,CAAC,QAAQ,SAAS,QAAI,wBAAoC,EAAE,UAAU,MAAM,OAAO,MAAM,CAAC;AAEhG,+BAAU,MAAM;AACd,QAAI,YAAY;AAChB,UAAM,KAAK,EAAE,OAAO,WAAW,CAAC,EAC7B,KAAK,CAAC,QAAS,IAAI,KAAK,IAAI,KAAK,IAAI,QAAQ,OAAO,IAAI,MAAM,QAAQ,IAAI,MAAM,EAAE,CAAC,CAAE,EACrF,KAAK,CAAC,SAAkB;AACvB,UAAI,UAAW;AACf,UAAI,CAAC,MAAM,QAAQ,IAAI,EAAG,OAAM,IAAI,MAAM,+BAA+B;AACzE,gBAAU,EAAE,UAAU,MAA2B,OAAO,MAAM,CAAC;AAAA,IACjE,CAAC,EACA,MAAM,MAAM;AACX,UAAI,CAAC,UAAW,WAAU,EAAE,UAAU,MAAM,OAAO,KAAK,CAAC;AAAA,IAC3D,CAAC;AACH,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,GAAG,CAAC;AAER,SAAO;AACT;;;AFpBM,IAAAC,sBAAA;AAJC,SAAS,YAAY,EAAE,QAAQ,GAA+B;AACnE,QAAM,QAAQ,mBAAmB,OAAO;AACxC,SACE,8CAAC,UAAK,OAAO,WACX;AAAA,kDAAC,OAAE,OAAO,cACP;AAAA,kBAAY;AAAA,MAAE;AAAA,MAAI;AAAA,OACrB;AAAA,IACA,6CAAC,QAAG,OAAO,cAAc,qCAAuB;AAAA,IAChD,8CAAC,OAAE,OAAO,WAAW;AAAA;AAAA,MACP,6CAAC,UAAK,OAAO,WAAY,iBAAM;AAAA,MAAO;AAAA,OAEpD;AAAA,IACA,6CAAC,gBAAa,SAAS,SAAS;AAAA,IAChC,6CAAC,cAAW;AAAA,KACd;AAEJ;AAEA,SAAS,aAAa,EAAE,QAAQ,GAA+B;AAC7D,QAAM,EAAE,SAAS,IAAI,gBAAgB,OAAO,SAAS,QAAQ;AAC7D,QAAM,EAAE,SAAS,IAAI,oBAAoB;AACzC,QAAM,YAAY,CAAC,YACjB,QAAQ,SAAS,QAAQ,SAAS,QAAQ,SAAS,aAAc,QAAQ,SAAS,aAAa,QAAQ,YAAY,QAAQ;AAE7H,SACE,8CAAC,SAAI,cAAW,YAAW,OAAO,EAAE,SAAS,QAAQ,UAAU,QAAQ,gBAAgB,UAAU,KAAK,UAAU,cAAc,OAAO,GACnI;AAAA,iDAAC,eAAY,MAAM,GAAG,QAAQ,WAAW,QAAQ,UAAU,EAAE,MAAM,SAAS,CAAC,GAAG,oBAEhF;AAAA,IACA,6CAAC,eAAY,MAAM,GAAG,QAAQ,QAAQ,QAAQ,UAAU,EAAE,MAAM,MAAM,CAAC,GAAG,iBAE1E;AAAA,IACC,UAAU,IAAI,CAAC,MACd;AAAA,MAAC;AAAA;AAAA,QAEC,MAAM,GAAG,QAAQ,IAAI,EAAE,OAAO;AAAA,QAC9B,OAAO,WAAW,EAAE,WAAW;AAAA,QAC/B,QAAQ,UAAU,EAAE,MAAM,WAAW,SAAS,EAAE,QAAQ,CAAC;AAAA,QAExD,cAAI,EAAE,OAAO;AAAA;AAAA,MALT,EAAE;AAAA,IAMT,CACD;AAAA,KACH;AAEJ;AAEA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,QAAuB;AAAA,IAC3B,SAAS;AAAA,IACT,QAAQ,aAAa,SAAS,OAAO,UAAU,OAAO,MAAM;AAAA,IAC5D,cAAc;AAAA,IACd,YAAY,SAAS,OAAO,UAAU;AAAA,IACtC,OAAO,SAAS,OAAO,oBAAoB,OAAO;AAAA,IAClD,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,gBAAgB;AAAA,EAClB;AACA,SACE,6CAAC,OAAE,MAAY,OAAc,gBAAc,SAAS,SAAS,QAAW,OACrE,UACH;AAEJ;AAEA,SAAS,aAAa;AACpB,QAAM,MAAM,OAAO,SAAS;AAC5B,QAAM,CAAC,QAAQ,SAAS,QAAI,wBAAS,KAAK;AAE1C,WAAS,OAAO;AACd,SAAK,UAAU,WAAW,UAAU,GAAG,EAAE,KAAK,MAAM;AAClD,gBAAU,IAAI;AACd,iBAAW,MAAM,UAAU,KAAK,GAAG,IAAI;AAAA,IACzC,CAAC;AAAA,EACH;AAEA,SACE,8CAAC,aAAQ,OAAOC,YACd;AAAA,iDAAC,QAAG,OAAO,gBAAgB,6CAA+B;AAAA,IAC1D,6CAAC,OAAE,OAAO,EAAE,GAAG,eAAe,cAAc,OAAO,GAAG,uEAAyD;AAAA,IAC/G,8CAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,KAAK,SAAS,GAC3C;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,UAAQ;AAAA,UACR,OAAO;AAAA,UACP,cAAW;AAAA,UACX,SAAS,CAAC,UAAU,MAAM,OAAO,OAAO;AAAA,UACxC,OAAO;AAAA,YACL,MAAM;AAAA,YACN,UAAU;AAAA,YACV,SAAS;AAAA,YACT,QAAQ,aAAa,OAAO,MAAM;AAAA,YAClC,cAAc,OAAO;AAAA,YACrB,YAAY;AAAA,YACZ,OAAO,OAAO;AAAA,YACd,MAAM;AAAA,YACN,UAAU;AAAA,UACZ;AAAA;AAAA,MACF;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,OAAO;AAAA,YACL,SAAS;AAAA,YACT,QAAQ;AAAA,YACR,cAAc,OAAO;AAAA,YACrB,YAAY,OAAO;AAAA,YACnB,OAAO,OAAO;AAAA,YACd,MAAM;AAAA,YACN,UAAU;AAAA,YACV,YAAY;AAAA,YACZ,QAAQ;AAAA,UACV;AAAA,UAEC,mBAAS,WAAW;AAAA;AAAA,MACvB;AAAA,OACF;AAAA,KACF;AAEJ;AAEA,SAAS,WAAW,KAAqB;AACvC,QAAM,OAAO,IAAI,KAAK,GAAG;AACzB,SAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,IAC9B,MACA,KAAK,mBAAmB,QAAW,EAAE,MAAM,WAAW,OAAO,SAAS,KAAK,UAAU,CAAC;AAC5F;;;AGnHA,IAAM,QAA2C;AAAA,EAC/C,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,sBAAsB;AAAA,EACtB,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,uBAAuB;AAAA,EACvB,iBAAiB;AAAA,EACjB,eAAe;AACjB;AAEA,IAAM,WAA6D;AAAA,EACjE,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,sBAAsB;AAAA,EACtB,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,uBAAuB;AAAA,EACvB,iBAAiB;AAAA,EACjB,eAAe;AACjB;AAEA,IAAM,QAAQ,CAAC,MAAyBC,UAAiB,WAA+B,cAAuC;AAAA,EAC7H,IAAI;AAAA,EACJ;AAAA,EACA,UAAU,SAAS,IAAI;AAAA,EACvB,OAAO,MAAM,IAAI;AAAA,EACjB;AAAA,EACA,SAAAA;AACF;AAGO,SAAS,yBAAyB,aAAiE;AACxG,QAAM,UAAU,4BAA4B,aAAa,OAAO;AAChE,SAAO,QAAQ,OAAO,KAAK,QAAS,YAAY;AAClD;AAGO,SAAS,kBACd,OACA,QAMA,UAAiC,CAAC,GACP;AAC3B,MAAI,aAAa,KAAK,MAAM,QAAS,QAAO,CAAC;AAC7C,QAAM,MAAiC,CAAC;AAExC,QAAM,UAAU,0BAA0B,OAAO,SAAS,MAAM,QAAQ;AACxE,MAAI,QAAQ,QAAS,KAAI,KAAK,MAAM,mBAAmB,8CAA8C,CAAC;AAAA,WAC7F,CAAC,QAAQ,IAAI;AACpB,UAAM,QAAQ,CAAC,+BAA+B;AAC9C,QAAI,QAAQ,QAAQ,OAAQ,OAAM,KAAK,qBAAqB,QAAQ,QAAQ,KAAK,IAAI,CAAC,GAAG;AACzF,QAAI,QAAQ,eAAe,OAAQ,OAAM,KAAK,yCAAyC,QAAQ,eAAe,KAAK,IAAI,CAAC,GAAG;AAC3H,QAAI,KAAK,MAAM,kBAAkB,MAAM,KAAK,GAAG,CAAC,CAAC;AAAA,EACnD;AAEA,QAAM,UAAU,MAAM,eAAe,MAAM;AAC3C,MAAI,WAAW,0BAA0B,OAAO,GAAG;AACjD,QAAI;AAAA,MACF;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF,WAAW,MAAM,aAAa;AAC5B,QAAI,KAAK,MAAM,gBAAgB,MAAM,aAAa,OAAO,CAAC;AAAA,EAC5D;AAEA,MAAI,MAAM,eAAe,QAAQ;AAC/B,UAAM,OAAO,MAAM,eAAe,KAAK,IAAI;AAC3C,QAAI,KAAK,MAAM,iBAAiB,sCAAsC,MAAM,eAAe,WAAW,IAAI,KAAK,GAAG,KAAK,IAAI,GAAG,CAAC;AAAA,EACjI;AAEA,QAAM,aAAa,OAAO,cAAc,CAAC;AACzC,MAAI,WAAW,QAAQ;AACrB,UAAM,QAAQ,WAAW,CAAC;AAC1B,UAAM,QAAQ,MAAM,SAAS,GAAG,MAAM,MAAM,WAAW,MAAM,KAAK,KAAK,OAAO,MAAM,KAAK;AACzF,UAAM,OAAO,WAAW,SAAS,IAAI,SAAS,WAAW,SAAS,CAAC,WAAW;AAC9E,QAAI,KAAK,MAAM,eAAe,GAAG,KAAK,KAAK,MAAM,OAAO,GAAG,IAAI,mDAAmD,CAAC;AAAA,EACrH;AAEA,QAAM,UAAU,4BAA4B,MAAM,aAAa,OAAO;AACtE,MAAI,OAAO,eAAe;AACxB,QAAI,WAAW,CAAC,QAAQ,UAAU;AAChC,UAAI;AAAA,QACF;AAAA,UACE;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,WAAW,yBAAyB,MAAM,WAAW,GAAG;AACtD,UAAM,OAAO,QAAQ,sBAAsB,KAAK;AAChD,QAAI;AAAA,MACF;AAAA,QACE;AAAA,QACA,yIACG,OAAO,IAAI,IAAI,KAAK;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,OAAO,kBAAkB,CAAC;AAC7C,SAAO,IAAI,OAAO,CAAC,MAAM,CAAC,WAAW,SAAS,EAAE,IAAI,CAAC;AACvD;AAGO,SAAS,kBAAkB,SAA4D;AAC5F,QAAM,EAAE,YAAY,OAAO,WAAW,IAAI,qBAAqB;AAC/D,MAAI,CAAC,WAAY,QAAO,CAAC;AACzB,QAAM,EAAE,SAAS,eAAe,eAAe,IAAI,WAAW,QAAQ;AACtE,SAAO,kBAAkB,OAAO,EAAE,SAAS,eAAe,gBAAgB,WAAW,GAAG,OAAO;AACjG;;;AC7IkC,IAAAC,sBAAA;AAZlC,IAAM,gBAAuC;AAAA,EAC3C,sBACE;AACJ;AAOO,SAAS,aAAa,EAAE,SAAS,GAA4B;AAClE,QAAM,SAAS,kBAAkB,aAAa;AAC9C,MAAI,OAAO,WAAW,EAAG,QAAO,6EAAG,UAAS;AAE5C,SACE,8CAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,eAAe,UAAU,KAAK,UAAU,GACrE;AAAA,iDAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,eAAe,UAAU,KAAK,WAAW,SAAS,oBAAoB,GAClG,iBAAO,IAAI,CAACC,WACX,6CAAC,eAA2B,OAAOA,UAAjBA,OAAM,EAAkB,CAC3C,GACH;AAAA,IACC;AAAA,KACH;AAEJ;AAEA,SAAS,YAAY,EAAE,OAAAA,OAAM,GAAuC;AAClE,QAAM,WAAWA,OAAM,SAAS,wBAAwBA,OAAM,SAAS;AACvE,SACE,8CAAC,SAAI,MAAMA,OAAM,UAAU,OAAO,EAAE,GAAG,YAAY,GAAGC,UAASD,OAAM,QAAQ,EAAE,GAC7E;AAAA,iDAAC,UAAK,eAAW,MAAC,OAAO,EAAE,YAAY,GAAG,WAAW,WAAW,GAC7D,qBAAW,6CAAC,YAAS,IAAK,6CAAC,eAAY,GAC1C;AAAA,IACA,8CAAC,SAAI,OAAO,EAAE,UAAU,EAAE,GACxB;AAAA,mDAAC,OAAE,OAAO,EAAE,QAAQ,GAAG,YAAY,IAAI,GAAI,UAAAA,OAAM,OAAM;AAAA,MACvD,6CAAC,OAAE,OAAO,EAAE,QAAQ,eAAe,OAAO,OAAO,gBAAgB,GAAI,UAAAA,OAAM,SAAQ;AAAA,OACrF;AAAA,KACF;AAEJ;AAEA,IAAM,aAA4B;AAAA,EAChC,WAAW;AAAA,EACX,SAAS;AAAA,EACT,KAAK;AAAA,EACL,SAAS;AAAA,EACT,QAAQ,aAAa,OAAO,MAAM;AAAA,EAClC,cAAc,OAAO;AAAA,EACrB,OAAO,OAAO;AAAA,EACd,UAAU;AAAA,EACV,YAAY;AACd;AAEA,IAAMC,YAAuE;AAAA,EAC3E,OAAO,EAAE,aAAa,OAAO,aAAa,OAAO,OAAO,YAAY;AAAA,EACpE,SAAS,EAAE,aAAa,yBAAyB,YAAY,wBAAwB;AAAA,EACrF,MAAM,EAAE,YAAY,cAAc;AACpC;AAEA,IAAM,OAAO;AAAA,EACX,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,eAAe;AAAA,EACf,gBAAgB;AAClB;AAEA,SAAS,cAAc;AACrB,SACE,8CAAC,SAAK,GAAG,MACP;AAAA,iDAAC,UAAK,GAAE,4EAA2E;AAAA,IACnF,6CAAC,UAAK,GAAE,WAAU;AAAA,IAClB,6CAAC,UAAK,GAAE,cAAa;AAAA,KACvB;AAEJ;AAEA,SAAS,WAAW;AAClB,SACE,8CAAC,SAAK,GAAG,MACP;AAAA,iDAAC,UAAK,GAAE,2BAA0B;AAAA,IAClC,6CAAC,UAAK,GAAE,6BAA4B;AAAA,IACpC,6CAAC,UAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK,IAAG,MAAK;AAAA,KACvC;AAEJ;;;AC7FA,IAAAC,gBAAqG;AAoD5F,IAAAC,sBAAA;AA9BT,IAAM,cAAc;AACpB,IAAM,aAAa;AACnB,IAAM,SAAiC,CAAC,SAAS,QAAQ,QAAQ;AAEjE,IAAM,mBAAe,6BAAqC,IAAI;AAevD,SAAS,sBAAsB,EAAE,SAAS,GAA4B;AAC3E,QAAM,aAAa,qBAAqB,EAAE,MAAM;AAChD,QAAM,SAAS,eAAe,eAAe,IAAI;AACjD,QAAM,gBAAgB,cAAc;AAEpC,gBAAc,aAAa;AAE3B,QAAM,YAAQ;AAAA,IACZ,OAAO,EAAE,OAAO,cAAc,UAAU,eAAe,UAAU,KAAK;AAAA,IACtE,CAAC,YAAY,aAAa;AAAA,EAC5B;AACA,SAAO,6CAAC,aAAa,UAAb,EAAsB,OAAe,UAAS;AACxD;AAOO,SAAS,wBAAwB,EAAE,SAAS,GAA4B;AAC7E,QAAM,CAAC,OAAO,aAAa,QAAI,wBAAsB,MAAM,gBAAgB,KAAK,QAAQ;AACxF,QAAM,SAAS,eAAe,UAAU,QAAQ;AAChD,QAAM,gBAAgB,UAAU,WAAW,SAAS;AAEpD,gBAAc,aAAa;AAE3B,QAAM,eAAW,2BAAY,CAAC,SAAsB;AAClD,qBAAiB,IAAI;AACrB,kBAAc,IAAI;AAAA,EACpB,GAAG,CAAC,CAAC;AAGL,+BAAU,MAAM;AACd,UAAM,YAAY,CAAC,UAAyB;AAC1C,UAAI,MAAM,UAAU,MAAM,WAAW,MAAM,WAAW,MAAM,OAAQ;AACpE,UAAI,MAAM,IAAI,YAAY,MAAM,OAAO,iBAAiB,MAAM,MAAM,EAAG;AACvE,oBAAc,CAAC,YAAY;AACzB,cAAM,kBAAkB,YAAY,WAAW,YAAY,IAAI;AAC/D,cAAM,OAAoB,oBAAoB,SAAS,UAAU;AACjE,yBAAiB,IAAI;AACrB,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AACA,WAAO,iBAAiB,WAAW,SAAS;AAC5C,WAAO,MAAM,OAAO,oBAAoB,WAAW,SAAS;AAAA,EAC9D,GAAG,CAAC,CAAC;AAGL,+BAAU,MAAM;AACd,UAAM,YAAY,CAAC,UAAwB;AACzC,UAAI,MAAM,QAAQ,YAAa;AAC/B,oBAAc,QAAQ,MAAM,QAAQ,IAAI,MAAM,WAAW,QAAQ;AAAA,IACnE;AACA,WAAO,iBAAiB,WAAW,SAAS;AAC5C,WAAO,MAAM,OAAO,oBAAoB,WAAW,SAAS;AAAA,EAC9D,GAAG,CAAC,CAAC;AAEL,QAAM,YAAQ;AAAA,IACZ,OAAO,EAAE,OAAO,eAAe,SAAS;AAAA,IACxC,CAAC,OAAO,eAAe,QAAQ;AAAA,EACjC;AACA,SAAO,6CAAC,aAAa,UAAb,EAAsB,OAAe,UAAS;AACxD;AAGA,SAAS,eAAe,QAAsC;AAC5D,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAA8B,WAAW;AAEnE,+BAAU,MAAM;AACd,QAAI,CAAC,UAAU,OAAO,OAAO,eAAe,WAAY;AACxD,UAAM,QAAQ,OAAO,WAAW,UAAU;AAC1C,UAAM,WAAW,MAAM,SAAS,MAAM,UAAU,SAAS,OAAO;AAChE,aAAS;AACT,UAAM,iBAAiB,UAAU,QAAQ;AACzC,WAAO,MAAM,MAAM,oBAAoB,UAAU,QAAQ;AAAA,EAC3D,GAAG,CAAC,MAAM,CAAC;AAEX,SAAO;AACT;AAGA,SAAS,cAAc,OAA4B;AACjD,+BAAU,MAAM;AACd,UAAM,OAAO,SAAS;AACtB,QAAI,KAAK,UAAU,SAAS,KAAK,KAAK,CAAC,KAAK,UAAU,SAAS,MAAM,KAAK,CAAC,EAAG;AAC9E,UAAM,qBAAqB,mBAAmB;AAC9C,SAAK,UAAU,OAAO,MAAM,KAAK,CAAC;AAClC,SAAK,UAAU,IAAI,KAAK;AACxB,uBAAmB;AAAA,EACrB,GAAG,CAAC,KAAK,CAAC;AACZ;AAEA,SAAS,cAAmC;AAC1C,MAAI,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,WAAY,QAAO;AACrF,SAAO,OAAO,WAAW,UAAU,EAAE,UAAU,SAAS;AAC1D;AAEA,SAAS,MAAM,OAAiD;AAC9D,SAAO,UAAU,SAAS,UAAU;AACtC;AAGA,SAAS,qBAAiC;AACxC,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM;AAAA,IACJ,SAAS,eAAe,mFAAmF;AAAA,EAC7G;AACA,WAAS,KAAK,YAAY,KAAK;AAC/B,SAAO,MAAM;AACX,WAAO,iBAAiB,SAAS,IAAI;AACrC,0BAAsB,MAAM,sBAAsB,MAAM,MAAM,OAAO,CAAC,CAAC;AAAA,EACzE;AACF;AAEA,SAAS,iBAAiB,QAAqC;AAC7D,MAAI,EAAE,kBAAkB,aAAc,QAAO;AAC7C,SAAO,OAAO,qBAAqB,OAAO,QAAQ,mDAAmD,MAAM;AAC7G;AAEA,SAAS,QAAQ,OAA4C;AAC3D,SAAO,UAAU,QAAS,OAA6B,SAAS,KAAK;AACvE;AAEA,SAAS,kBAAsC;AAC7C,MAAI;AACF,UAAM,QAAQ,aAAa,QAAQ,WAAW;AAC9C,WAAO,QAAQ,KAAK,IAAI,QAAQ;AAAA,EAClC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,iBAAiB,OAAoB;AAC5C,MAAI;AACF,iBAAa,QAAQ,aAAa,KAAK;AAAA,EACzC,QAAQ;AAAA,EAER;AACF;AAEA,SAAS,OAAO;AAAC;;;AjCtDX,IAAAC,sBAAA;AA9DC,SAAS,WAAW,OAAyB,MAAM,OAA4B;AACpF,QAAM,SAAS,cAAc,MAAM,MAAM,IAAI,MAAM,SAAS;AAC5D,QAAM,UAAU,QAAQ,WAAW,MAAM;AACzC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,QAAM,QAA6B;AAAA,IACjC,KAAK,MAAM;AAAA,IACX;AAAA,IACA,UAAU,QAAQ,YAAY,MAAM;AAAA,IACpC;AAAA,EACF;AACA,MAAI,YAAY,MAAO,OAAM,SAAS,MAAM;AAC5C,MAAI,MAAM,aAAc,OAAM,eAAe,MAAM;AACnD,MAAI,MAAM,YAAa,OAAM,cAAc,MAAM;AACjD,SAAO;AACT;AAsDO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,SAAS;AAAA,EACT,cAAAC,gBAAe;AAAA,EACf,aAAAC,eAAc;AAChB,GAAwB;AACtB,QAAM,OAAO,UAAU;AACvB,MAAIC,YAAW,GAAG;AAChB,WACE,8CAAC,uBAAoB,SACnB;AAAA,mDAAC,gBAAa,UAAoB;AAAA,MAClC,6CAAC,yBACC,uDAAC,iBACC,uDAAC,SAAI,OAAO,MACV,uDAAC,QACC,uDAAC,0BAAS,UAAU,MAClB,uDAAC,OAAI,GACP,GACF,GACF,GACF,GACF;AAAA,OACF;AAAA,EAEJ;AAEA,QAAM,UAAU,gBAAgB,OAAO,SAAS,QAAQ,EAAE;AAC1D,SACE,8CAAC,2BACC;AAAA,iDAAC,gBAAa,UAAoB;AAAA,IAClC,6CAAC,SAAI,OAAO,MAAO,gBAAM,6CAACF,eAAA,EAAa,IAAK,6CAACC,cAAA,EAAY,SAAkB,GAAG;AAAA,KAChF;AAEJ;AAEA,IAAM,OAAO,EAAE,WAAW,QAAQ,OAAO,OAAO;AAGhD,SAASC,cAAsB;AAC7B,SAAO,OAAO,WAAW,eAAe,OAAO,SAAS,OAAO;AACjE;AAGA,SAAS,aAAa,EAAE,SAAS,GAAkD;AACjF,oBAAkB,UAAU,QAAQ,EAAE,OAAO,SAAS,OAAO,aAAa,SAAS,eAAe,GAAG,IAAI,IAAI;AAC7G,SAAO;AACT;AAEA,SAAS,YAAY,EAAE,SAAS,GAA4B;AAC1D,SAAO,6EAAG,UAAS;AACrB;;;AkCjLO,SAAS,gBAAgB,SAAoC;AAClE,UAAQ,QAAQ,WAAW,CAAC,GAAG;AAAA,IAAI,CAAC,WAClC,OAAO,WAAW,WACd,EAAE,MAAM,QAAQ,MAAM,OAAO,UAAU,QAAW,eAAe,MAAM,IACvE,EAAE,MAAM,OAAO,MAAM,MAAM,UAAU,OAAO,IAAI,GAAG,UAAU,OAAO,MAAM,eAAe,OAAO,kBAAkB,KAAK;AAAA,EAC7H;AACF;AAGA,SAAS,UAAU,MAAkC;AACnD,UAAQ,QAAQ,OAAO,MAAM,GAAG,EAAE,CAAC,EAAE,KAAK,KAAK;AACjD;AAEO,SAAS,eAAe,SAAyC;AACtE,SAAO,OAAO,YAAY,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,IAAI,IAAI,EAAE,IAAI,CAAC,CAAC;AAC7F;AAOO,SAAS,iBAAiB,SAAmB,MAAqE;AACvH,QAAM,QAAQ,QAAQ,CAAC,OAAO,YAAY,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;AAC5F,SAAO;AAAA,IACL,aAAa;AAAA,IACb,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,MACN,QAAQ;AAAA,QACN,SAAS,OAAO,YAAY,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;AAAA,QAC1E,MAAM,MAAM,IAAI,CAAC,KAAK,OAAO;AAAA,UAC3B,IAAI,OAAO,IAAI,OAAO,WAAW,IAAI,KAAK,IAAI;AAAA,UAC9C,GAAG,OAAO,YAAY,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,gBAAgB,EAAE,UAAU,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC;AAAA,QACtG,EAAE;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,YAAY,MAAuB;AAC1C,UAAQ,MAAM;AAAA,IACZ,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;;;ACzDO,SAAS,qBAAqB,KAA+B;AAClE,SAAO;AAAA,IACL,MAAM,IAAI,MAAM;AACd,UAAI,KAAK,EAAE,MAAM,eAAe,QAAQ,CAAC,cAAc,IAAI,EAAE,CAAC;AAAA,IAChE;AAAA,EACF;AACF;;;ACJO,SAAS,gBAAgB,OAA2D;AACzF,MAAI,MAAM,UAAU,aAAa,UAAa,MAAM,UAAU,aAAa,MAAM;AAC/E,WAAO,MAAM,UAAU;AAAA,EACzB;AACA,SAAO;AACT;;;ACCO,SAAS,2BACd,OACA,KACsB;AACtB,SAAO;AAAA,IACL,MAAM,UAAU,UAAU;AACxB,YAAM,SAAmC;AAAA,QACvC,gBAAgB,SAAS;AAAA,QACzB,SAAS,SAAS;AAAA,QAClB,eAAe,SAAS;AAAA,QACxB,kBAAkB,SAAS;AAAA,MAC7B;AACA,YAAM,gBAAgB;AACtB,UAAI,KAAK,EAAE,MAAM,SAAS,eAAe,OAAO,CAAC;AACjD,UAAI,KAAK,EAAE,MAAM,mBAAmB,UAAU,gBAAgB,KAAK,EAAE,CAAC;AAAA,IACxE;AAAA,IAEA,MAAM,WAAW;AACf,aAAO,gBAAgB,KAAK;AAAA,IAC9B;AAAA,EACF;AACF;;;ACnCO,SAAS,qBAAmC;AACjD,SAAO;AAAA,IACL,MAAM,OAAO;AACX,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;ACNO,SAAS,yBACd,SACwB;AACxB,QAAM,MAA8B,CAAC;AACrC,QAAM,gBAAgB,OAAO,QAAQ,OAAO,EAAE;AAAA,IAAO,CAAC,CAAC,KAAK,MAC1D,MAAM,WAAW,cAAc;AAAA,EACjC;AACA,QAAM,cAAc,oBAAI,IAAY;AACpC,QAAM,gBAAgB,oBAAI,IAAoB;AAC9C,aAAW,CAAC,OAAO,GAAG,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,QAAI,OAAO,KAAK,WAAW,YAAY,OAAO,SAAS,IAAI,MAAM,GAAG;AAClE,oBAAc,IAAI,IAAI,QAAQ,KAAK;AAAA,IACrC;AAAA,EACF;AACA,aAAW,CAAC,OAAO,GAAG,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,UAAM,OAAO,KAAK;AAClB,QAAI,OAAO,SAAS,YAAa,CAAC,KAAK,WAAW,MAAM,KAAK,CAAC,KAAK,WAAW,UAAU,GAAI;AAC1F;AAAA,IACF;AACA,QAAI,OAAO,IAAI,kBAAkB,YAAY,OAAO,SAAS,IAAI,aAAa,GAAG;AAC/E,YAAM,cAAc,cAAc,IAAI,IAAI,aAAa;AACvD,UAAI,aAAa;AACf,YAAI,KAAK,IAAI;AACb,oBAAY,IAAI,WAAW;AAC3B;AAAA,MACF;AAAA,IACF;AACA,UAAM,QAAQ,cAAc,KAAK,CAAC,CAAC,EAAE,MAAM,MAAM;AAC/C,YAAM,UAAU,QAAQ;AACxB,aAAO,OAAO,YAAY,aAAa,QAAQ,SAAS,IAAI,KAAK,GAAG,KAAK,QAAQ,SAAS,IAAI,KAAK,EAAE;AAAA,IACvG,CAAC;AACD,QAAI,OAAO;AACT,UAAI,KAAK,IAAI,MAAM,CAAC;AACpB,kBAAY,IAAI,MAAM,CAAC,CAAC;AAAA,IAC1B;AAAA,EACF;AAIA,QAAM,iBAAiB,OAAO,QAAQ,OAAO,EAC1C,OAAO,CAAC,CAAC,OAAO,GAAG,MAAM;AACxB,UAAM,OAAO,KAAK;AAClB,WACE,CAAC,IAAI,KAAK,KACV,OAAO,SAAS,aACf,KAAK,WAAW,MAAM,KAAK,KAAK,WAAW,UAAU;AAAA,EAE1D,CAAC,EACA,KAAK,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,aAAa,OAAO,qBAAqB,EAAE,CAAC,GAAG,aAAa,OAAO,iBAAiB;AAC7G,QAAM,cAAc,cACjB,OAAO,CAAC,CAAC,QAAQ,MAAM,CAAC,YAAY,IAAI,QAAQ,CAAC,EACjD,KAAK,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,aAAa,OAAO,qBAAqB,EAAE,CAAC,GAAG,aAAa,OAAO,iBAAiB;AAC7G,aAAW,CAAC,OAAO,MAAM,KAAK,gBAAgB;AAC5C,UAAM,SAAS,QAAQ,aAAa,OAAO;AAC3C,UAAM,YAAY,YAAY,KAAK,CAAC,CAAC,EAAE,SAAS,MAAM;AACpD,YAAM,YAAY,WAAW,aAAa,OAAO;AACjD,aAAO,YAAY;AAAA,IACrB,CAAC;AACD,QAAI,CAAC,UAAW;AAChB,QAAI,KAAK,IAAI,UAAU,CAAC;AACxB,gBAAY,IAAI,UAAU,CAAC,CAAC;AAAA,EAC9B;AAEA,aAAW,CAAC,KAAK,KAAK,gBAAgB;AACpC,QAAI,IAAI,KAAK,EAAG;AAChB,UAAM,YAAY,YAAY,KAAK,CAAC,CAAC,QAAQ,MAAM,CAAC,YAAY,IAAI,QAAQ,CAAC;AAC7E,QAAI,CAAC,UAAW;AAChB,QAAI,KAAK,IAAI,UAAU,CAAC;AACxB,gBAAY,IAAI,UAAU,CAAC,CAAC;AAAA,EAC9B;AACA,SAAO;AACT;;;ACnEA,IAAM,gBAAgB;AAEtB,IAAM,kCAAkC;AAejC,SAAS,6BAA6B,KAAqC;AAChF,QAAM,kBAAkB,IAAI,SAAS,KAAK,KAAK;AAC/C,QAAM,mBAAmB,IAAI,iBAAiB,KAAK,KAAK;AAExD,MAAI,IAAI,WAAW;AACjB,UAAM,kBACJ,oBAAoB,mBAAmB;AACzC,WAAO;AAAA,MACL,GAAG;AAAA,MACH,GAAI,kBAAkB,EAAE,SAAS,IAAI,QAAQ,IAAI,CAAC;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAEA,MAAI,oBAAoB,iBAAiB;AACvC,WAAO;AAAA,MACL,GAAG;AAAA,MACH,iBAAiB,oBAAoB,mBAAmB;AAAA,IAC1D;AAAA,EACF;AAEA,SAAO;AACT;AAGO,SAAS,+BAA+B,SAAyE;AACtH,QAAM,UAAU,OAAO,QAAQ,OAAO;AACtC,UAAQ,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM;AACjC,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,EAAE;AACb,QAAI,OAAO,UAAa,OAAO,UAAa,OAAO,GAAI,QAAO,KAAK;AACnE,QAAI,OAAO,UAAa,OAAO,OAAW,QAAO;AACjD,QAAI,OAAO,UAAa,OAAO,OAAW,QAAO;AACjD,WAAO,GAAG,cAAc,EAAE;AAAA,EAC5B,CAAC;AACD,SAAO,OAAO,YAAY,OAAO;AACnC;AAEA,SAAS,qBAAqB,MAAwD;AACpF,QAAM,UAA0C,CAAC;AACjD,aAAW,OAAO,MAAM;AACtB,eAAW,OAAO,OAAO,KAAK,GAAG,GAAG;AAClC,UAAI,QAAQ,cAAe;AAC3B,UAAI,CAAC,QAAQ,GAAG,EAAG,SAAQ,GAAG,IAAI,gBAAgB,IAAI,GAAG,CAAC;AAAA,IAC5D;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,QAAiC;AACxD,UAAQ,OAAO,QAAQ;AAAA,IACrB,KAAK;AACH,aAAO,EAAE,MAAM,UAAU;AAAA,IAC3B,KAAK;AACH,aAAO,EAAE,MAAM,OAAO;AAAA,IACxB,KAAK;AACH,aAAO,EAAE,MAAM,OAAO;AAAA,IACxB;AACE,aAAO,EAAE,MAAM,MAAM;AAAA,EACzB;AACF;AAEA,SAAS,WAAW,SAAiB,OAAgD;AACnF,QAAM,OAAO,MAAM,QAAQ,CAAC;AAC5B,QAAM,WAAW,qBAAqB,IAAI;AAC1C,QAAM,SAAyC,CAAC;AAChD,aAAW,CAAC,OAAO,GAAG,KAAK,OAAO,QAAQ,EAAE,GAAG,UAAU,GAAI,MAAM,WAAW,CAAC,EAAG,CAAC,GAAG;AACpF,WAAO,KAAK,IAAI,6BAA6B,GAAG;AAAA,EAClD;AACA,QAAM,UAAU,+BAA+B,MAAM;AACrD,SAAO;AAAA,IACL;AAAA,IACA,OAAO,MAAM;AAAA,IACb;AAAA,IACA,MAAM,KAAK,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,EAAE;AAAA,EACtC;AACF;AAOO,SAAS,eAAe,OAAmD;AAChF,MAAI,CAAC,MAAM,UAAU,OAAO,KAAK,MAAM,MAAM,EAAE,WAAW,GAAG;AAC3D,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAEA,QAAM,aAAa,8BAA8B,KAAK;AAEtD,QAAM,SAAS,oBAAI,IAA2B;AAC9C,aAAW,CAAC,SAAS,UAAU,KAAK,OAAO,QAAQ,WAAW,MAAM,GAAG;AACrE,WAAO,IAAI,SAAS,WAAW,SAAS,UAAU,CAAC;AAAA,EACrD;AAEA,QAAM,eAAe,OAAO,KAAK,EAAE,KAAK,EAAE;AAC1C,QAAM,mBAAmB,WAAW,WAAW;AAC/C,QAAM,kBACJ,oBAAoB,OAAO,IAAI,gBAAgB,IAAI,mBAAmB;AACxE,QAAM,gBAAgB,OAAO,IAAI,eAAe;AAChD,QAAM,gBACJ,OAAO,cAAc,KAAK,CAAC,GAAG,OAAO,WAAW,cAAc,KAAK,CAAC,EAAE,KAAK;AAC7E,QAAM,YAAY;AAAA,IAChB,SAAS;AAAA,IACT,OAAO,WAAW,WAAW,SAAS;AAAA,IACtC,UAAU,WAAW,WAAW;AAAA,IAChC,QAAQ,WAAW,WAAW;AAAA,EAChC;AAEA,SAAO;AAAA,IACL,SAAS,WAAW,WAAW;AAAA,IAC/B;AAAA,IACA;AAAA,IACA,eAAe,EAAE,GAAI,WAAW,iBAAiB,CAAC,EAAG;AAAA,IACrD,mBAAmB,EAAE,GAAI,WAAW,qBAAqB,CAAC,EAAG;AAAA,IAC7D,eAAe,WAAW,iBAAiB;AAAA,IAC3C,aAAa,WAAW,eAAe;AAAA,EACzC;AACF;AAEO,SAAS,SAAS,OAA8B,SAAgC;AACrF,QAAM,QAAQ,MAAM,OAAO,IAAI,OAAO;AACtC,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,kBAAkB,OAAO,EAAE;AACvD,SAAO;AACT;AAEO,SAAS,iBAAiB,OAA6C;AAC5E,SAAO,SAAS,OAAO,MAAM,UAAU,OAAO;AAChD;AAEO,SAAS,UAAU,OAA8B;AACtD,MAAI,MAAM;AACV,aAAW,OAAO,MAAM,MAAM;AAC5B,QAAI,OAAO,IAAI,OAAO,YAAY,IAAI,KAAK,IAAK,OAAM,IAAI;AAAA,EAC5D;AACA,SAAO,MAAM;AACf;AAEO,SAAS,QAAQ,OAAsB,OAA2C;AACvF,SAAO,MAAM,KAAK,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK;AAC9C;AAEO,SAAS,aAAa,OAAsB,OAAuB;AACxE,SAAO,MAAM,KAAK,UAAU,CAAC,MAAM,EAAE,OAAO,KAAK;AACnD;AAMO,SAAS,oBACd,OACA,OACA,KACM;AACN,aAAW,CAAC,OAAO,GAAG,KAAK,OAAO,QAAQ,MAAM,OAAO,GAAG;AACxD,QAAI,IAAI,WAAW;AACjB,UAAI;AACF,YAAI,KAAK,IAAI,IAAI,UAAU,KAAK,EAAE,OAAO,UAAU,MAAM,CAAC;AAAA,MAC5D,SAAS,KAAK;AACZ,YAAI,KAAK,IAAIC,cAAa,GAAG;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,aAAa,GAAmB;AACvC,SAAO,EAAE,QAAQ,uBAAuB,MAAM;AAChD;AAGA,SAAS,0BAA0B,KAAwB;AACzD,MAAI,OAAO,KAAM,QAAO,CAAC;AACzB,MAAI,CAAC,MAAM,QAAQ,GAAG,EAAG,QAAO,CAAC;AACjC,QAAM,QAAQ,IAAI,CAAC,MAAM,MAAM,IAAI,MAAM,CAAC,IAAI;AAC9C,QAAM,MAAgB,CAAC;AACvB,aAAW,QAAQ,OAAO;AACxB,QAAI,OAAO,SAAS,YAAY,OAAO,SAAS,IAAI,KAAK,OAAO,GAAG;AACjE,UAAI,KAAK,KAAK,MAAM,IAAI,CAAC;AACzB;AAAA,IACF;AACA,QAAI,QAAQ,OAAO,SAAS,YAAY,WAAW,MAAM;AACvD,YAAM,IAAK,KAA4B;AACvC,UAAI,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC,KAAK,IAAI,GAAG;AACxD,YAAI,KAAK,KAAK,MAAM,CAAC,CAAC;AACtB;AAAA,MACF;AAAA,IACF;AACA,UAAM,IAAI,0BAA0B,IAAI;AACxC,QAAI,MAAM,UAAa,IAAI,EAAG,KAAI,KAAK,KAAK,MAAM,CAAC,CAAC;AAAA,EACtD;AACA,SAAO,MAAM,KAAK,IAAI,IAAI,GAAG,CAAC;AAChC;AAEA,SAAS,8BAA8B,SAA6B,UAAiC;AACnG,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,KAAK,IAAI,OAAO,MAAM,aAAa,QAAQ,CAAC,oBAAoB;AACtE,QAAM,IAAI,QAAQ,MAAM,EAAE;AAC1B,SAAO,IAAI,CAAC,KAAK;AACnB;AAEA,SAAS,sBAAsB,SAAwD;AACrF,MAAI,OAA2C;AAC/C,aAAW,CAAC,OAAO,GAAG,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,QAAI,UAAU,QAAQ,MAAM,WAAW,cAAc,EAAG;AACxD,UAAM,IAAI,IAAI;AACd,QAAI,MAAM,UAAU,MAAM,SAAU;AACpC,UAAM,MAAM,IAAI,aAAa;AAC7B,QAAI,CAAC,QAAQ,MAAM,KAAK,IAAK,QAAO,EAAE,IAAI,OAAO,IAAI;AAAA,EACvD;AACA,SAAO,MAAM,MAAM;AACrB;AAEA,SAAS,oBAAoB,OAAwB;AACnD,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,OAAO,UAAU,SAAU,QAAO,MAAM,KAAK;AACjD,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAW,QAAO,OAAO,KAAK;AAChF,MAAI,iBAAiB,KAAM,QAAO,MAAM,YAAY;AACpD,MAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,CAAC,MAAM,IAAK,QAAO;AACrD,MAAI,OAAO,UAAU,YAAY,SAAS,WAAW,OAAO;AAC1D,UAAM,IAAK,MAA8B;AACzC,WAAO,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC,IAAI,OAAO,CAAC,IAAI;AAAA,EACnE;AACA,SAAO;AACT;AAWO,SAAS,0BACd,OACA,OACA,KACM;AACN,QAAM,sBAAsB,yBAAyB,MAAM,OAAO;AAClE,aAAW,CAAC,OAAO,GAAG,KAAK,OAAO,QAAQ,MAAM,OAAO,GAAG;AACxD,UAAM,OAAO,IAAI;AACjB,QAAI,OAAO,SAAS,YAAY,CAAC,KAAK,WAAW,UAAU,EAAG;AAC9D,UAAM,cAAc,oBAAoB,KAAK;AAC7C,QAAI,CAAC,YAAa;AAClB,UAAM,aAAa,MAAM,QAAQ,WAAW;AAC5C,QAAI,CAAC,cAAc,WAAW,UAAW;AAEzC,UAAM,gBAAgB,KAAK,MAAM,WAAW,MAAM;AAClD,UAAM,cAAc,MAAM,OAAO,IAAI,aAAa;AAClD,QAAI,CAAC,YAAa;AAElB,UAAM,MAAM,0BAA0B,IAAI,KAAK,CAAC;AAChD,QAAI,IAAI,WAAW,GAAG;AACpB,UAAI,WAAW,IAAI,CAAC;AACpB;AAAA,IACF;AAEA,UAAM,UACJ,8BAA8B,WAAW,SAAS,KAAK,KACvD,sBAAsB,YAAY,OAAO;AAE3C,UAAM,SAAS,IAAI,IAAI,CAAC,QAAQ;AAC9B,UAAI,CAAC,QAAS,QAAO,OAAO,GAAG;AAC/B,YAAM,OAAO,QAAQ,aAAa,GAAG;AACrC,UAAI,CAAC,KAAM,QAAO,OAAO,GAAG;AAC5B,YAAM,MAAM,oBAAoB,KAAK,OAAO,CAAC;AAC7C,aAAO,QAAQ,KAAK,MAAM,OAAO,GAAG;AAAA,IACtC,CAAC;AACD,QAAI,WAAW,IAAI;AAAA,EACrB;AACF;AAEA,SAASA,cAAa,KAAuB;AAE3C,QAAMC,WAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,SAAO,CAAC,KAAK,SAASA,QAAO;AAC/B;AAMO,SAAS,qBAAqB,OAAyD;AAC5F,QAAM,MAAgB,CAAC;AACvB,QAAM,WAAqB,CAAC;AAC5B,QAAM,SAA4B,CAAC;AAEnC,MAAI,SAAS;AACb,aAAW,CAAC,SAAS,KAAK,KAAK,MAAM,OAAO,QAAQ,GAAG;AACrD,QAAI,KAAK,MAAM;AACf,aAAS,KAAK,OAAO;AACrB,WAAO,KAAK,MAAM,SAAS,IAAI;AAC/B,cAAU;AAAA,EACZ;AAEA,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA;AAAA;AAAA,IAGT,OAAO;AAAA,EACT;AACF;AAMO,SAAS,2BAA2B,OAAyD;AAClG,QAAM,YAAsB,CAAC;AAC7B,QAAM,SAAmB,CAAC;AAC1B,QAAM,YAAsB,CAAC;AAC7B,QAAM,QAA2B,CAAC;AAClC,QAAM,SAA4B,CAAC;AACnC,QAAM,YAA+B,CAAC;AACtC,QAAM,YAAuB,CAAC;AAC9B,QAAM,WAA8B,CAAC;AACrC,QAAM,eAAkC,CAAC;AACzC,QAAM,gBAA2B,CAAC;AAClC,QAAM,aAAgC,CAAC;AACvC,QAAM,aAAgC,CAAC;AAGvC,QAAM,sBAAsB,oBAAI,IAAoB;AACpD;AACE,QAAI,SAAS;AACb,eAAW,CAAC,OAAO,KAAK,MAAM,OAAO,QAAQ,GAAG;AAC9C,0BAAoB,IAAI,SAAS,MAAM;AACvC,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,aAAW,CAAC,SAAS,KAAK,KAAK,MAAM,OAAO,QAAQ,GAAG;AACrD,UAAM,mBAAmB,oBAAoB,IAAI,OAAO;AACxD,QAAI,qBAAqB,OAAW;AAEpC,eAAW,CAAC,OAAO,GAAG,KAAK,OAAO,QAAQ,MAAM,OAAO,GAAG;AACxD,gBAAU,KAAK,gBAAgB;AAC/B,aAAO,KAAK,KAAK;AAEjB,YAAM,MAAM,OAAO,IAAI,WAAW,WAAW,IAAI,SAAS,UAAU,SAAS;AAC7E,gBAAU,KAAK,GAAG;AAClB,YAAM,KAAK,IAAI,QAAQ,IAAI;AAC3B,aAAO,KAAK,IAAI,SAAS,IAAI;AAC7B,gBAAU,KAAK,IAAI,aAAa,IAAI;AACpC,gBAAU,KAAK,QAAQ,IAAI,SAAS,CAAC;AACrC,YAAM,UAAU,OAAO,IAAI,YAAY,WAAW,IAAI,UAAU;AAChE,eAAS,KAAK,OAAO;AACrB,mBAAa,KAAK,IAAI,eAAe,IAAI;AACzC,oBAAc,KAAK,IAAI,iBAAiB,IAAI;AAC5C,iBAAW,KAAK,OAAO,IAAI,kBAAkB,WAAW,IAAI,gBAAgB,IAAI;AAChF,iBAAW,KAAK,OAAO,IAAI,kBAAkB,WAAW,IAAI,gBAAgB,IAAI;AAAA,IAClF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,OAAO;AAAA,IACP,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,aAAa;AAAA;AAAA,IAEb,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC7WO,IAAM,sBAAN,cAAkC,MAAM;AAAA,EAC7C,YACkB,QAChBC,UACA;AACA,UAAMA,QAAO;AAHG;AAIhB,SAAK,OAAO;AAAA,EACd;AACF;AASO,SAAS,iBACd,OACA,KACA,SACuB;AACvB,QAAM,YAAuB,CAAC;AAC9B,QAAM,UAAU,oBAAI,IAAY;AAEhC,aAAW,UAAU,SAAS;AAC5B,QAAI,KAAK,EAAE,MAAM,eAAe,OAAO,CAAC;AACxC,UAAM,MAAM,YAAY,OAAO,QAAQ,OAAO;AAC9C,cAAU,KAAK,GAAG;AAAA,EACpB;AAEA,aAAW,WAAW,SAAS;AAC7B,QAAI,KAAK,EAAE,MAAM,eAAe,QAAQ,CAAC;AAAA,EAC3C;AAEA,SAAO,EAAE,WAAW,iBAAiB,CAAC,GAAG,OAAO,EAAE;AACpD;AAEA,SAAS,YACP,OACA,QACA,SACS;AACT,QAAM,CAAC,MAAM,GAAG,IAAI,IAAI;AACxB,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,UAAU,OAAO,MAAM,OAAO;AAAA,IACvC,KAAK;AACH,aAAO,cAAc,OAAO,MAAM,OAAO;AAAA,IAC3C,KAAK;AACH,aAAO,aAAa,OAAO,MAAM,OAAO;AAAA,IAC1C,KAAK;AACH,aAAO,iBAAiB,OAAO,MAAM,OAAO;AAAA,IAC9C,KAAK;AACH,aAAO,aAAa,OAAO,MAAM,OAAO;AAAA,IAC1C,KAAK;AACH,aAAO,iBAAiB,OAAO,MAAM,OAAO;AAAA,IAC9C,KAAK;AACH,aAAO,UAAU,OAAO,IAAI;AAAA,IAC9B,KAAK;AAMH,aAAO,UAAU,OAAO,IAAI;AAAA,IAC9B,KAAK;AACH,aAAO,aAAa,OAAO,MAAM,OAAO;AAAA,IAC1C,KAAK;AACH,aAAO,aAAa,OAAO,MAAM,OAAO;AAAA,IAC1C,KAAK;AACH,aAAO,aAAa,OAAO,MAAM,OAAO;AAAA,IAC1C,KAAK;AACH,aAAO,SAAS,OAAO,IAAI;AAAA,IAC7B,KAAK;AACH,aAAO,YAAY,OAAO,IAAI;AAAA,IAChC,KAAK;AACH,aAAO,YAAY,OAAO,IAAI;AAAA,IAChC;AACE,YAAM,IAAI,oBAAoB,QAAQ,4BAA4B,OAAO,IAAI,CAAC,EAAE;AAAA,EACpF;AACF;AAIA,SAAS,UACP,OACA,CAAC,SAAS,OAAO,MAAM,GACvB,SACQ;AACR,QAAM,QAAQ,SAAS,OAAO,cAAc,SAAS,mBAAmB,CAAC;AACzE,QAAM,KAAK,OAAO,UAAU,WAAW,QAAQ,UAAU,KAAK;AAC9D,QAAM,mBAAmB;AAAA,IACvB;AAAA,IACC,UAAsC,CAAC;AAAA,EAC1C;AACA,QAAM,MAAM,EAAE,IAAI,GAAG,iBAAiB;AACtC,gBAAc,OAAO,gBAAgB;AACrC,sBAAoB,OAAO,OAAO,GAAG;AACrC,4BAA0B,OAAO,OAAO,GAAG;AAC3C,QAAM,KAAK,KAAK,GAAG;AACnB,UAAQ,IAAI,MAAM,OAAO;AACzB,SAAO;AACT;AAEA,SAAS,cACP,OACA,CAAC,SAAS,QAAQ,QAAQ,GAC1B,SACU;AACV,QAAM,QAAQ,SAAS,OAAO,cAAc,SAAS,uBAAuB,CAAC;AAC7E,QAAM,OAAO;AAAA,IACX;AAAA,IACC,YAA0C,CAAC;AAAA,EAC9C;AACA,QAAM,MAAM,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC;AAC9C,QAAM,SAAS,IAAI,UAAU,SAAS,IAAI;AAC1C,QAAM,MAAgB,CAAC;AACvB,gBAAc,OAAO,MAAM,IAAI;AAC/B,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,UAAM,KAAK,OAAO,IAAI,CAAC,MAAM,WAAY,IAAI,CAAC,IAAe,UAAU,KAAK;AAC5E,UAAM,MAAgD,EAAE,GAAG;AAC3D,eAAW,SAAS,OAAO,KAAK,IAAI,EAAG,KAAI,KAAK,IAAI,KAAK,KAAK,EAAE,CAAC;AACjE,wBAAoB,OAAO,OAAO,GAAG;AACrC,8BAA0B,OAAO,OAAO,GAAG;AAC3C,UAAM,KAAK,KAAK,GAAG;AACnB,QAAI,KAAK,EAAE;AAAA,EACb;AACA,UAAQ,IAAI,MAAM,OAAO;AACzB,SAAO;AACT;AAEA,SAAS,aACP,OACA,CAAC,SAAS,OAAO,MAAM,GACvB,SACM;AACN,QAAM,QAAQ,SAAS,OAAO,cAAc,SAAS,sBAAsB,CAAC;AAC5E,QAAM,KAAK,cAAc,OAAO,oBAAoB;AACpD,QAAM,MAAM,QAAQ,OAAO,EAAE;AAC7B,MAAI,CAAC,IAAK,OAAM,IAAI,oBAAoB,CAAC,gBAAgB,SAAS,OAAO,MAAM,GAAG,OAAO,EAAE,iBAAiB,MAAM,OAAO,EAAE;AAC3H,QAAM,mBAAmB;AAAA,IACvB;AAAA,IACC,UAAsC,CAAC;AAAA,EAC1C;AACA,gBAAc,OAAO,gBAAgB;AACrC,SAAO,OAAO,KAAK,gBAAgB;AACnC,sBAAoB,OAAO,OAAO,GAAG;AACrC,4BAA0B,OAAO,OAAO,GAAG;AAC3C,UAAQ,IAAI,MAAM,OAAO;AACzB,SAAO;AACT;AAEA,SAAS,iBACP,OACA,CAAC,SAAS,QAAQ,QAAQ,GAC1B,SACM;AACN,QAAM,QAAQ,SAAS,OAAO,cAAc,SAAS,0BAA0B,CAAC;AAChF,QAAM,MAAM;AACZ,QAAM,OAAO;AAAA,IACX;AAAA,IACC,YAA0C,CAAC;AAAA,EAC9C;AACA,gBAAc,OAAO,MAAM,IAAI;AAC/B,MAAI,QAAQ,CAAC,IAAI,QAAQ;AACvB,UAAM,MAAM,QAAQ,OAAO,EAAE;AAC7B,QAAI,CAAC,IAAK,OAAM,IAAI,oBAAoB,CAAC,oBAAoB,SAAS,KAAK,IAAI,GAAG,OAAO,EAAE,iBAAiB,MAAM,OAAO,EAAE;AAC3H,eAAW,SAAS,OAAO,KAAK,IAAI,EAAG,KAAI,KAAK,IAAI,KAAK,KAAK,EAAE,GAAG;AACnE,wBAAoB,OAAO,OAAO,GAAG;AACrC,8BAA0B,OAAO,OAAO,GAAG;AAAA,EAC7C,CAAC;AACD,UAAQ,IAAI,MAAM,OAAO;AACzB,SAAO;AACT;AAEA,SAAS,aACP,OACA,CAAC,SAAS,KAAK,GACf,SACM;AACN,QAAM,QAAQ,SAAS,OAAO,cAAc,SAAS,sBAAsB,CAAC;AAC5E,QAAM,KAAK,cAAc,OAAO,oBAAoB;AACpD,QAAM,MAAM,aAAa,OAAO,EAAE;AAClC,MAAI,OAAO,EAAG,OAAM,KAAK,OAAO,KAAK,CAAC;AACtC,MAAI,MAAM,UAAU,YAAY,MAAM,WAAW,MAAM,UAAU,UAAU,IAAI;AAC7E,UAAM,UAAU,QAAQ,MAAM,KAAK,CAAC,GAAG,MAAM;AAAA,EAC/C;AACA,UAAQ,IAAI,MAAM,OAAO;AACzB,SAAO;AACT;AAEA,SAAS,iBACP,OACA,CAAC,SAAS,MAAM,GAChB,SACM;AACN,QAAM,QAAQ,SAAS,OAAO,cAAc,SAAS,0BAA0B,CAAC;AAChF,QAAM,MAAM,IAAI,IAAI,MAAkB;AACtC,QAAM,OAAO,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;AACpD,MAAI,MAAM,UAAU,YAAY,MAAM,WAAW,OAAO,MAAM,UAAU,UAAU,YAAY,IAAI,IAAI,MAAM,UAAU,KAAK,GAAG;AAC5H,UAAM,UAAU,QAAQ,MAAM,KAAK,CAAC,GAAG,MAAM;AAAA,EAC/C;AACA,UAAQ,IAAI,MAAM,OAAO;AACzB,SAAO;AACT;AAIA,SAAS,UACP,OACA,CAAC,SAAS,OAAO,IAAI,GACf;AACN,QAAM,QAAQ,SAAS,OAAO,cAAc,SAAS,mBAAmB,CAAC;AACzE,QAAM,MAAM,cAAc,OAAO,iBAAiB;AAClD,MAAI,MAAM,QAAQ,GAAG,EAAG,OAAM,IAAI,oBAAoB,CAAC,aAAa,SAAS,KAAK,GAAG,UAAU,GAAG,iBAAiB;AACnH,QAAM,QAAQ,GAAG,IAAK,QAA2B,CAAC;AAClD,aAAW,OAAO,MAAM,MAAM;AAC5B,QAAI,EAAE,OAAO,KAAM,KAAI,GAAG,IAAI;AAAA,EAChC;AACA,SAAO;AACT;AAEA,SAAS,aACP,OACA,CAAC,SAAS,KAAK,GACf,SACM;AACN,QAAM,QAAQ,SAAS,OAAO,cAAc,SAAS,sBAAsB,CAAC;AAC5E,QAAM,MAAM,cAAc,OAAO,oBAAoB;AACrD,SAAO,MAAM,QAAQ,GAAG;AACxB,aAAW,OAAO,MAAM,KAAM,QAAO,IAAI,GAAG;AAC5C,UAAQ,IAAI,MAAM,OAAO;AACzB,SAAO;AACT;AAEA,SAAS,aACP,OACA,CAAC,SAAS,OAAO,QAAQ,GACzB,SACM;AACN,QAAM,QAAQ,SAAS,OAAO,cAAc,SAAS,sBAAsB,CAAC;AAC5E,QAAM,OAAO,cAAc,OAAO,oBAAoB;AACtD,QAAM,KAAK,cAAc,UAAU,uBAAuB;AAC1D,MAAI,CAAC,MAAM,QAAQ,IAAI,EAAG,OAAM,IAAI,oBAAoB,CAAC,gBAAgB,SAAS,MAAM,EAAE,GAAG,UAAU,IAAI,YAAY;AACvH,MAAI,SAAS,GAAI,QAAO;AACxB,QAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,IAAI;AACtC,SAAO,MAAM,QAAQ,IAAI;AACzB,aAAW,OAAO,MAAM,MAAM;AAC5B,QAAI,QAAQ,KAAK;AACf,UAAI,EAAE,IAAI,IAAI,IAAI;AAClB,aAAO,IAAI,IAAI;AAAA,IACjB;AAAA,EACF;AACA,UAAQ,IAAI,MAAM,OAAO;AACzB,SAAO;AACT;AAEA,SAAS,aACP,OACA,CAAC,SAAS,OAAO,IAAI,GACrB,SACM;AACN,QAAM,QAAQ,SAAS,OAAO,cAAc,SAAS,sBAAsB,CAAC;AAC5E,QAAM,MAAM,cAAc,OAAO,oBAAoB;AACrD,MAAI,CAAC,MAAM,QAAQ,GAAG,EAAG,OAAM,IAAI,oBAAoB,CAAC,gBAAgB,SAAS,KAAK,GAAG,UAAU,GAAG,YAAY;AAClH,QAAM,QAAQ,GAAG,IAAI,EAAE,GAAG,MAAM,QAAQ,GAAG,GAAG,GAAI,KAAwB;AAC1E,UAAQ,IAAI,MAAM,OAAO;AACzB,SAAO;AACT;AAIA,SAAS,SAAS,OAA8B,CAAC,SAAS,OAAO,GAAsB;AACrF,QAAM,KAAK,cAAc,SAAS,kBAAkB;AACpD,MAAI,MAAM,OAAO,IAAI,EAAE,EAAG,OAAM,IAAI,oBAAoB,CAAC,YAAY,OAAO,GAAG,SAAS,EAAE,iBAAiB;AAC3G,QAAM,OAAuC,CAAC;AAC9C,aAAW,KAAM,WAAsD,CAAC,GAAG;AACzE,SAAK,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE;AAAA,EACtB;AACA,QAAM,OAAO,IAAI,IAAI,EAAE,SAAS,IAAI,SAAS,MAAM,MAAM,CAAC,EAAE,CAAC;AAC7D,SAAO;AACT;AAEA,SAAS,YAAY,OAA8B,CAAC,OAAO,GAAoB;AAC7E,QAAM,KAAK,cAAc,SAAS,qBAAqB;AACvD,QAAM,OAAO,OAAO,EAAE;AACtB,MAAI,MAAM,UAAU,YAAY,IAAI;AAClC,UAAM,WAAW,MAAM,OAAO,KAAK,EAAE,KAAK,EAAE;AAC5C,QAAI,UAAU;AACZ,YAAM,UAAU,UAAU;AAC1B,YAAM,UAAU,QAAQ;AAAA,IAC1B;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,YAAY,OAA8B,CAAC,MAAM,EAAE,GAAoB;AAC9E,QAAM,SAAS,cAAc,MAAM,kBAAkB;AACrD,QAAM,OAAO,cAAc,IAAI,gBAAgB;AAC/C,QAAM,QAAQ,MAAM,OAAO,IAAI,MAAM;AACrC,MAAI,CAAC,MAAO,OAAM,IAAI,oBAAoB,CAAC,eAAe,MAAM,GAAG,SAAS,MAAM,YAAY;AAC9F,QAAM,OAAO,OAAO,MAAM;AAC1B,QAAM,UAAU;AAChB,QAAM,OAAO,IAAI,MAAM,KAAK;AAC5B,MAAI,MAAM,UAAU,YAAY,OAAQ,OAAM,UAAU,UAAU;AAClE,SAAO;AACT;AAIA,SAAS,cACP,OACA,QACA,OAAO,OACD;AACN,aAAW,OAAO,OAAO,KAAK,MAAM,GAAG;AACrC,QAAI,CAAC,MAAM,QAAQ,GAAG,GAAG;AACvB,YAAM,SAAS,OAAQ,OAAqC,GAAG,IAAI,CAAC,IAAK,OAAmC,GAAG;AAC/G,YAAM,QAAQ,GAAG,IAAI,UAAU,MAAM;AAAA,IACvC;AAAA,EACF;AACF;AAEA,SAAS,UAAU,QAAiC;AAClD,UAAQ,OAAO,QAAQ;AAAA,IACrB,KAAK;AACH,aAAO,EAAE,MAAM,UAAU;AAAA,IAC3B,KAAK;AACH,aAAO,EAAE,MAAM,OAAO;AAAA,IACxB,KAAK;AACH,aAAO,EAAE,MAAM,OAAO;AAAA,IACxB;AACE,aAAO,EAAE,MAAM,MAAM;AAAA,EACzB;AACF;AAEA,SAAS,SAAS,MAAyC;AACzD,aAAW,OAAO,OAAO,OAAO,IAAI,EAAG,KAAI,MAAM,QAAQ,GAAG,EAAG,QAAO,IAAI;AAC1E,SAAO;AACT;AAEA,SAAS,cAAc,OAAgB,MAAsB;AAC3D,MAAI,OAAO,UAAU,YAAY,CAAC,MAAO,OAAM,IAAI,MAAM,iCAAiC,IAAI,EAAE;AAChG,SAAO;AACT;AAEA,SAAS,cAAc,OAAgB,MAAsB;AAC3D,MAAI,OAAO,UAAU,YAAY,OAAO,MAAM,KAAK,EAAG,OAAM,IAAI,MAAM,uBAAuB,IAAI,EAAE;AACnG,SAAO;AACT;AAEA,SAAS,wBACP,OACA,QACyB;AACzB,QAAM,MAA+B,CAAC;AACtC,aAAW,CAAC,OAAO,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACnD,QAAI,KAAK,IAAI,0BAA0B,OAAO,MAAM,QAAQ,KAAK,GAAG,IAAI;AAAA,EAC1E;AACA,SAAO;AACT;AAEA,SAAS,0BACP,OACA,SAC2B;AAC3B,QAAM,MAAiC,CAAC;AACxC,aAAW,CAAC,OAAO,MAAM,KAAK,OAAO,QAAQ,OAAO,GAAG;AACrD,UAAM,OAAO,MAAM,QAAQ,KAAK,GAAG;AACnC,QAAI,KAAK,IAAI,MAAM,QAAQ,MAAM,IAC7B,OAAO,IAAI,CAAC,UAAU,0BAA0B,OAAO,IAAI,CAAC,IAC5D,CAAC;AAAA,EACP;AACA,SAAO;AACT;AAEA,SAAS,0BAA0B,OAAgB,MAAmC;AACpF,MAAI,UAAU,QAAQ,UAAU,UAAa,OAAO,SAAS,SAAU,QAAO;AAI9E,MAAI,iBAAiB,IAAI,KAAK,MAAM,QAAQ,KAAK,KAAK,MAAM,CAAC,MAAM,IAAK,QAAO,CAAC,KAAK,UAAU;AAC/F,MAAI,KAAK,WAAW,MAAM,EAAG,QAAO,kBAAkB,KAAK;AAC3D,MAAI,KAAK,WAAW,UAAU,EAAG,QAAO,sBAAsB,KAAK;AACnE,SAAO;AACT;AAOA,SAAS,gBAAgB,OAA+B;AACtD,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,MAAI,SAAS,OAAO,UAAU,YAAY,WAAW,OAAO;AAC1D,UAAM,QAAS,MAA8B;AAC7C,WAAO,gBAAgB,KAAK;AAAA,EAC9B;AACA,MAAI,SAAS,OAAO,UAAU,YAAY,WAAW,OAAO;AAC1D,WAAO,gBAAiB,MAA6B,KAAK;AAAA,EAC5D;AACA,QAAM,YAAY,0BAA0B,KAAK;AACjD,MAAI,cAAc,UAAa,YAAY,EAAG,QAAO,KAAK,MAAM,SAAS;AACzE,SAAO,cAAc,KAAK;AAC5B;AAEA,SAAS,iBAAiB,MAAuB;AAC/C,SAAO,SAAS,gBAAgB,SAAS,iBAAiB,KAAK,WAAW,UAAU;AACtF;AAEA,SAAS,kBAAkB,OAA+B;AACxD,SAAO,gBAAgB,KAAK;AAC9B;AAEA,SAAS,sBAAsB,OAA2B;AACxD,QAAM,WAAW,CAAC,UAChB,MAAM;AAAA,IACJ,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,gBAAgB,IAAI,CAAC,EAAE,OAAO,CAAC,SAAyB,SAAS,IAAI,CAAC;AAAA,EACpG;AAGF,MAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,CAAC,MAAM,KAAK;AAC5C,WAAO,CAAC,KAAK,GAAG,SAAS,MAAM,MAAM,CAAC,CAAC,CAAC;AAAA,EAC1C;AACA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,CAAC,KAAK,GAAG,SAAS,KAAK,CAAC;AAAA,EACjC;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAMC,UAAS,MAAM,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AACnE,WAAO,CAAC,KAAK,GAAG,SAASA,OAAM,CAAC;AAAA,EAClC;AACA,MAAI,SAAS,OAAO,UAAU,YAAY,MAAM,QAAS,MAA+B,MAAM,GAAG;AAC/F,WAAO,CAAC,KAAK,GAAG,SAAU,MAAgC,MAAM,CAAC;AAAA,EACnE;AACA,SAAO,CAAC,GAAG;AACb;AAEA,SAAS,cAAc,OAA+B;AACpD,MAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,QAAQ,EAAG,QAAO,KAAK,MAAM,KAAK;AAC7F,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,IAAI,OAAO,SAAS,MAAM,KAAK,GAAG,EAAE;AAC1C,QAAI,OAAO,SAAS,CAAC,KAAK,IAAI,EAAG,QAAO;AAAA,EAC1C;AACA,SAAO;AACT;;;ACvcO,SAAS,eACd,OACA,MACA,UAA6B,CAAC,GACf;AACf,QAAM,OAAO,OAAO,KAAK,MAAM,OAAO;AACtC,QAAM,MAAqB,EAAE,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE;AACvD,aAAW,OAAO,MAAM;AACtB,QAAI,GAAG,IAAI,KAAK,IAAI,CAAC,MAAM,cAAc,EAAE,GAAG,GAAG,MAAM,QAAQ,GAAG,GAAG,MAAM,QAAQ,WAAW,CAAC;AAAA,EACjG;AACA,SAAO;AACT;AAEO,SAAS,YACd,OACA,KACA,UAA6B,CAAC,GACL;AACzB,QAAM,MAA+B,EAAE,IAAI,IAAI,GAAG;AAClD,aAAW,OAAO,OAAO,KAAK,MAAM,OAAO,GAAG;AAC5C,QAAI,GAAG,IAAI,cAAc,IAAI,GAAG,GAAG,MAAM,QAAQ,GAAG,GAAG,MAAM,QAAQ,WAAW;AAAA,EAClF;AACA,SAAO;AACT;AAEA,SAAS,cAAc,OAAgB,MAA0B,aAA2C;AAC1G,MAAI,iBAAiB,MAAM;AACzB,UAAM,QAAQ,KAAK,MAAM,MAAM,QAAQ,IAAI,GAAI;AAC/C,QAAI,aAAa;AACf,aAAO,QAAQ,KAAK,WAAW,UAAU,IAAI,CAAC,KAAK,OAAO,KAAK,IAAI,CAAC,KAAK,KAAK;AAAA,IAChF;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;ACxCO,SAAS,sBAAsB,OAA8B,KAAgC;AAClG,SAAO;AAAA,IACL,MAAM,aAAa;AACjB,aAAO,MAAM;AAAA,IACf;AAAA,IAEA,MAAM,aAAa;AACjB,aAAO,CAAC,GAAG,MAAM,OAAO,KAAK,CAAC;AAAA,IAChC;AAAA,IAEA,MAAM,WAAW,SAAS;AACxB,UAAI,YAAY,iBAAiB;AAC/B,eAAO,qBAAqB,KAAK;AAAA,MACnC;AACA,UAAI,YAAY,wBAAwB;AACtC,eAAO,2BAA2B,KAAK;AAAA,MACzC;AACA,YAAM,QAAQ,SAAS,OAAO,OAAO;AACrC,aAAO,eAAe,OAAO,MAAM,IAAI;AAAA,IACzC;AAAA,IAEA,MAAM,iBAAiB,SAAS;AAC9B,YAAM,SAAS,iBAAiB,OAAO,KAAK,OAAO;AACnD,aAAO,EAAE,WAAW,OAAO,UAAU;AAAA,IACvC;AAAA,IAEA,MAAM,iBAAiB;AACrB,UAAI,CAAC,MAAM,aAAa;AACtB,cAAM,MAAM,IAAI,MAAM,gEAAgE;AAEtF,cAAM;AAAA,MACR;AACA,aAAO,EAAE,GAAG,MAAM,YAAY;AAAA,IAChC;AAAA,EACF;AACF;;;AC1BO,SAAS,oBAAoB,OAA8B,KAA8B;AAC9F,SAAO;AAAA,IACL,MAAM,mBAAmB,SAAS;AAChC,YAAM,QAAQ,iBAAiB,KAAK;AACpC,aAAO,eAAe,OAAO,MAAM,MAAM,EAAE,aAAa,SAAS,YAAY,CAAC;AAAA,IAChF;AAAA,IAEA,MAAM,oBAAoB,OAAO,SAAS;AACxC,YAAM,QAAQ,iBAAiB,KAAK;AACpC,YAAM,MAAM,QAAQ,OAAO,KAAK;AAChC,UAAI,CAAC,IAAK,OAAM,IAAI,MAAM,UAAU,KAAK,OAAO,MAAM,OAAO,EAAE;AAC/D,aAAO,YAAY,OAAO,KAAK,EAAE,aAAa,SAAS,YAAY,CAAC;AAAA,IACtE;AAAA,IAEA,MAAM,gBAAgB;AACpB,aAAO,MAAM,eAAe,iBAAiB;AAAA,IAC/C;AAAA,IAEA,MAAM,gBAAgB,QAAQ;AAC5B,UAAI,CAAC,UAAU,OAAO,WAAW,GAAG;AAClC,cAAM,UAAU,QAAQ;AAAA,MAC1B,OAAO;AACL,cAAM,UAAU,QAAQ,OAAO,CAAC;AAAA,MAClC;AACA,UAAI,KAAK;AAAA,QACP,MAAM;AAAA,QACN,SAAS,MAAM,UAAU;AAAA,QACzB,OAAO,MAAM,UAAU;AAAA,MACzB,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,aAAa,QAAQ;AACzB,YAAM,UAAU,MAAM,UAAU;AAChC,UAAI,OAAO,OAAO,UAAU,SAAU,OAAM,UAAU,QAAQ,OAAO;AACrE,YAAM,UAAU,SAAS,EAAE,GAAG,MAAM,UAAU,QAAQ,GAAG,OAAO;AAChE,UAAI,KAAK;AAAA,QACP,MAAM;AAAA,QACN;AAAA,QACA,OAAO,MAAM,UAAU;AAAA,QACvB,QAAQ,MAAM,UAAU;AAAA,MAC1B,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;ACzDO,SAAS,oBAAoB,OAA8B,KAA8B;AAC9F,WAAS,OAAO;AACd,QAAI,KAAK;AAAA,MACP,MAAM;AAAA,MACN,SAAS,EAAE,GAAG,MAAM,cAAc;AAAA,MAClC,aAAa,EAAE,GAAG,MAAM,kBAAkB;AAAA,IAC5C,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,MAAM,UAAU,KAAK;AACnB,aAAO,MAAM,cAAc,GAAG;AAAA,IAChC;AAAA,IAEA,MAAM,UAAU,KAAK,OAAO;AAC1B,YAAM,cAAc,GAAG,IAAI;AAC3B,WAAK;AAAA,IACP;AAAA,IAEA,MAAM,aAAa;AACjB,aAAO,OAAO,KAAK,MAAM,aAAa,EAAE,SAAS,IAAI,EAAE,GAAG,MAAM,cAAc,IAAI;AAAA,IACpF;AAAA;AAAA,IAGA,MAAM,WAAW,SAAS;AACxB,YAAM,gBAAgB,EAAE,GAAG,QAAQ;AACnC,WAAK;AAAA,IACP;AAAA,IAEA,MAAM,eAAe;AACnB,YAAM,gBAAgB,CAAC;AACvB,WAAK;AAAA,IACP;AAAA,EACF;AACF;;;ACVO,SAAS,gBAAgB,OAA8B,KAAkC;AAC9F,SAAO;AAAA,IACL,WAAW,oBAAoB,OAAO,GAAG;AAAA,IACzC,aAAa,sBAAsB,OAAO,GAAG;AAAA,IAC7C,WAAW,oBAAoB,OAAO,GAAG;AAAA,IACzC,kBAAkB,2BAA2B,OAAO,GAAG;AAAA,IACvD,UAAU,mBAAmB;AAAA,IAC7B,YAAY,qBAAqB,GAAG;AAAA,EACtC;AACF;;;ACZO,SAAS,eAAe,UAA2B,CAAC,GAAa;AACtE,QAAM,QAAQ,QAAQ,gBAAgB;AACtC,QAAM,YAAY,oBAAI,IAA2B;AACjD,QAAM,UAA2B,CAAC;AAElC,SAAO;AAAA,IACL,KAAK,OAAO;AACV,cAAQ,KAAK,KAAK;AAClB,UAAI,QAAQ,SAAS,MAAO,SAAQ,MAAM;AAC1C,iBAAW,MAAM,CAAC,GAAG,SAAS,GAAG;AAC/B,YAAI;AACF,aAAG,KAAK;AAAA,QACV,SAAS,KAAK;AACZ,kBAAQ,MAAM,0CAA0C,GAAG;AAAA,QAC7D;AAAA,MACF;AAAA,IACF;AAAA,IACA,GAAG,UAAU;AACX,gBAAU,IAAI,QAAQ;AACtB,aAAO,MAAM;AACX,kBAAU,OAAO,QAAQ;AAAA,MAC3B;AAAA,IACF;AAAA,IACA,UAAU;AACR,aAAO;AAAA,IACT;AAAA,IACA,QAAQ;AACN,cAAQ,SAAS;AAAA,IACnB;AAAA,EACF;AACF;;;AClDO,SAAS,2BACd,YACA,SACuB;AACvB,SAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA,MAAM;AAAA,MACN,QAAQ,CAAC;AAAA,IACX;AAAA,IACA,GAAI,SAAS,YAAY,EAAE,WAAW,KAAK,IAAI,CAAC;AAAA,EAClD;AACF;;;AC8EO,SAAS,sBACd,SACkD;AAClD,QAAM,EAAE,OAAO,KAAK,IAAI,IAAI;AAC5B,QAAM,SAAS,QAAQ,UAAW;AAMlC,2BAAyB,MAAM;AAO/B,QAAM,YAAY,oBAAI,IAAqD;AAC3E,QAAM,aAAa,oBAAI,IAAsD;AAC7E,QAAM,aAAa,oBAAI,IAAe;AACtC,QAAM,eAAe,oBAAI,IAAiB;AAC1C,QAAM,UAAU,oBAAI,IAA+C;AASnE,MAAI,aAAgC;AACpC,MAAI,cAAkC;AACtC,MAAI,cAAkC;AACtC,MAAI,gBAAyD;AAE7D,QAAM,mBAAmB,QAAQ,qBAAqB,OAAO;AAAA,IAC3D,cAAc,MAAM,eAAe,kBAAkB;AAAA,IACrD,GAAG,MAAM;AAAA,EACX;AAEA,iBAAe,WAAW,OAA8B;AACtD,UAAM,WAAW,gBAAgB,KAAK;AACtC,QAAI,UAAU,OAAO;AAEnB,sBAAgB;AAChB,iBAAW,MAAM,cAAc;AAC7B,YAAI;AAAE,aAAG,QAAQ;AAAA,QAAE,SAAS,KAAK;AAAE,iBAAO,GAAG;AAAA,QAAE;AAAA,MACjD;AACA;AAAA,IACF;AACA,QAAI,UAAU,MAAM;AAClB,mBAAa,EAAE,QAAQ,MAAM,SAAS;AACtC,iBAAW,CAAC,EAAE,KAAK,WAAW;AAC5B,YAAI;AAAE,aAAG,MAAM,QAAQ;AAAA,QAAE,SAAS,KAAK;AAAE,iBAAO,GAAG;AAAA,QAAE;AAAA,MACvD;AACA;AAAA,IACF;AACA,QAAI,SAAyC;AAC7C,QAAI;AACF,eAAS,MAAM,IAAI,UAAU,oBAAoB,KAAK;AAAA,IACxD,SAAS,KAAK;AACZ,aAAO,GAAG;AAAA,IACZ;AACA,iBAAa,EAAE,QAAQ,SAAS;AAChC,eAAW,CAAC,IAAI,IAAI,KAAK,WAAW;AAClC,UAAI;AACF,cAAM,IAAI,MAAM,cACZ,MAAM,IAAI,UAAU,oBAAoB,OAAO,EAAE,aAAa,KAAK,CAAC,IACpE;AACJ,WAAG,GAAG,QAAQ;AAAA,MAChB,SAAS,KAAK;AACZ,eAAO,GAAG;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAEA,iBAAe,cAAc;AAC3B,UAAM,WAAW,gBAAgB,KAAK;AACtC,QAAI,WAAsC,CAAC;AAC3C,QAAI;AACF,YAAM,WAAW,MAAM,IAAI,UAAU,mBAAmB,CAAC,CAAC;AAC1D,iBAAW,cAAc,QAAQ;AAAA,IACnC,SAAS,KAAK;AACZ,aAAO,GAAG;AAAA,IACZ;AACA,kBAAc,EAAE,SAAS,UAAU,SAAS;AAC5C,eAAW,CAAC,IAAI,IAAI,KAAK,YAAY;AACnC,UAAI;AACF,cAAM,eAAe,mBAAmB,IAAI;AAK5C,cAAM,OAAO,cAAc,cACvB,cAAc,MAAM,IAAI,UAAU,mBAAmB,EAAE,aAAa,KAAK,CAAC,CAAC,IAC3E;AACJ,WAAG,MAAM,QAAQ;AAAA,MACnB,SAAS,KAAK;AACZ,eAAO,GAAG;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAaA,iBAAe,yBACb,MACgE;AAChE,UAAM,eAAe,mBAAmB,IAAI;AAC5C,UAAM,WAAY,MAAM,IAAI,UAAU;AAAA,MACpC,eAAe,EAAE,aAAa,aAAa,YAAY,IAAI,CAAC;AAAA,IAC9D;AACA,QAAI,cAAc,WAAW,OAAQ,QAAO,cAAc,QAAQ;AAClE,WAAO;AAAA,EACT;AAEA,WAAS,cAAc;AACrB,UAAM,OAAO,OAAO,KAAK,MAAM,aAAa,EAAE,SAAS,IAAI,EAAE,GAAG,MAAM,cAAc,IAAI;AACxF,UAAM,cAAc,iBAAiB;AACrC,kBAAc,EAAE,SAAS,MAAM,YAAY;AAC3C,eAAW,MAAM,YAAY;AAC3B,UAAI;AAAE,WAAG,MAAM,WAAW;AAAA,MAAE,SAAS,KAAK;AAAE,eAAO,GAAG;AAAA,MAAE;AAAA,IAC1D;AAAA,EACF;AAEA,QAAM,SAAS,IAAI,GAAG,OAAO,UAAyB;AACpD,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK;AACH,cAAM,YAAY;AAClB,cAAM,WAAW,MAAM,UAAU,KAAK;AACtC;AAAA,MACF,KAAK;AACH,cAAM,WAAW,MAAM,KAAK;AAC5B;AAAA,MACF,KAAK;AACH,oBAAY;AACZ;AAAA,MACF,KAAK;AACH,oBAAY;AACZ,YAAI,QAAQ,cAAc;AACxB,iBAAO,WAAW,2BAA2B,QAAQ,cAAc,EAAE,WAAW,KAAK,CAAC,CAAC;AAAA,QACzF;AACA,cAAM,YAAY;AAClB,cAAM,WAAW,MAAM,UAAU,KAAK;AACtC;AAAA,MACF,KAAK;AACH,cAAM,YAAY;AAClB,cAAM,WAAW,MAAM,UAAU,KAAK;AACtC;AAAA,MACF,KAAK;AACH,eAAO,WAAW,MAAM,OAAO;AAC/B;AAAA,IACJ;AAAA,EACF,CAAC;AAED,WAAS,aAAa,SAAuC;AAC3D,WAAO;AAAA,MACL,MAAM,aAAa;AAAE,eAAO;AAAA,MAAQ;AAAA,MACpC,MAAM,OAAO,SAASC,UAAS;AAC7B,cAAM,OAAO,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO;AACxD,cAAM,MAA4B,CAAC;AACnC,mBAAW,KAAK,MAAM;AACpB,gBAAM,SAAS,iBAAiB,OAAO,KAAK;AAAA,YAC1C,qBAAqB,SAAS,YAAY,EAAE,QAAQA,QAAO,CAAC;AAAA,UAC9D,CAAC;AACD,cAAI,KAAK,EAAE,IAAI,OAAO,UAAU,CAAC,EAAY,CAAC;AAAA,QAChD;AACA,eAAO,MAAM,QAAQ,OAAO,IAAI,MAAM,IAAI,CAAC;AAAA,MAC7C;AAAA,MACA,MAAM,OAAO,SAA4DA,UAA+B;AACtG,cAAM,OAAO,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO;AACxD,cAAM,UAAU,KAAK,IAAI,CAAC,MAAM,wBAAwB,SAAS,EAAE,IAAI,YAAY,EAAE,QAAQA,QAAO,CAAC,CAAC;AACtG,yBAAiB,OAAO,KAAK,OAAO;AAAA,MACtC;AAAA,MACA,MAAM,OAAO,SAA4DA,UAAmC;AAC1G,cAAM,OAAO,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO;AACxD,cAAM,WAAWA,UAAS,QAAQ;AAClC,cAAM,cAAcA,UAAS,WAAW;AACxC,cAAM,QAAQ,SAAS,OAAO,OAAO;AACrC,cAAM,UAAuB,CAAC;AAC9B,mBAAW,KAAK,MAAM;AACpB,gBAAM,UAAU,MAAM,KAAK;AAAA,YAAO,CAAC,QACjC,OAAO,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC;AAAA,UAC1D;AACA,cAAI,QAAQ,SAAS,GAAG;AACtB,gBAAI,CAAC,YAAa;AAClB,kBAAM,SAAS,YAAY,EAAE,UAAU,CAAC,GAAGA,QAAO;AAClD,uBAAW,KAAK,QAAS,SAAQ,KAAK,wBAAwB,SAAS,EAAE,IAAI,MAAM,CAAC;AAAA,UACtF,WAAW,UAAU;AACnB,oBAAQ,KAAK,qBAAqB,SAAS,EAAE,GAAG,EAAE,SAAS,GAAG,YAAY,EAAE,UAAU,CAAC,GAAGA,QAAO,EAAE,CAAC,CAAC;AAAA,UACvG;AAAA,QACF;AACA,YAAI,QAAQ,SAAS,EAAG,kBAAiB,OAAO,KAAK,OAAO;AAAA,MAC9D;AAAA,MACA,MAAM,QAAQ,WAA8B;AAC1C,YAAI,MAAM,QAAQ,SAAS,GAAG;AAC5B,2BAAiB,OAAO,KAAK,CAAC,4BAA4B,SAAS,SAAS,CAAC,CAAC;AAAA,QAChF,OAAO;AACL,2BAAiB,OAAO,KAAK,CAAC,wBAAwB,SAAS,SAAS,CAAC,CAAC;AAAA,QAC5E;AAEA,aAAK;AACL,aAAK;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAEA,WAAS,OAAO,UAAkB,MAAiB;AACjD,UAAM,MAAM,QAAQ,IAAI,KAAK;AAC7B,QAAI,CAAC,IAAK;AACV,eAAW,MAAM,KAAK;AACpB,UAAI;AAAE,WAAG,GAAG,IAAI;AAAA,MAAE,SAAS,KAAK;AAAE,eAAO,GAAG;AAAA,MAAE;AAAA,IAChD;AAAA,EACF;AAEA,QAAMC,SAA2B;AAAA,IAC/B,MAAM,MAAM,MAAM;AAChB,YAAM,IAAI,iBAAiB,UAAU,OAAO,EAAE,GAAG,MAAM,eAAe,OAAU,IAA0C,CAAC,CAAC;AAAA,IAC9H;AAAA,IAEA,SAAS,IAAI,MAAM;AACjB,gBAAU,IAAI,IAAI,IAAI;AAEtB,UAAI,YAAY;AACd,YAAI;AAAE,aAAG,WAAW,QAAQ,WAAW,QAAQ;AAAA,QAAE,SAAS,KAAK;AAAE,iBAAO,GAAG;AAAA,QAAE;AAAA,MAC/E;AAAA,IACF;AAAA,IACA,UAAU,IAAI,MAAM;AAClB,iBAAW,IAAI,IAAI,IAAI;AACvB,UAAI,aAAa;AACf,YAAI;AAAE,aAAG,YAAY,SAAS,YAAY,QAAQ;AAAA,QAAE,SAAS,KAAK;AAAE,iBAAO,GAAG;AAAA,QAAE;AAAA,MAClF;AAAA,IACF;AAAA,IACA,UAAU,IAAI;AACZ,iBAAW,IAAI,EAAE;AACjB,UAAI,aAAa;AACf,YAAI;AAAE,aAAG,YAAY,SAAS,YAAY,WAAW;AAAA,QAAE,SAAS,KAAK;AAAE,iBAAO,GAAG;AAAA,QAAE;AAAA,MACrF;AAAA,IACF;AAAA,IACA,YAAY,IAAI;AACd,mBAAa,IAAI,EAAE;AACnB,UAAI,kBAAkB,QAAW;AAC/B,YAAI;AAAE,aAAG,aAAa;AAAA,QAAE,SAAS,KAAK;AAAE,iBAAO,GAAG;AAAA,QAAE;AAAA,MACtD;AAAA,IACF;AAAA,IAEA,eAAe,MAAM;AACnB,YAAM,WAAW,gBAAgB,KAAK;AACtC,UAAI,CAAC,SAAU,QAAO;AACtB,YAAM,MAA+B,CAAC;AACtC,UAAI,YAAY;AAChB,iBAAW,CAAC,SAAS,IAAI,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACtD,YAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,cAAI,OAAO,IAAI,KAAK,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC;AAAA,QACxC,WAAW,OAAO,SAAS,UAAU;AACnC,cAAI,OAAO,IAAI,KAAK,IAAI;AAAA,QAC1B,OAAO;AACL,sBAAY;AAAA,QACd;AAAA,MACF;AACA,aAAO,YAAY,MAAM;AAAA,IAC3B;AAAA,IACA,mBAAmB,MAAM;AACvB,YAAM,WAAW,gBAAgB,KAAK;AACtC,UAAI,CAAC,SAAU,QAAO;AACtB,YAAM,MAA+B,CAAC;AACtC,iBAAW,CAAC,SAAS,IAAI,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACtD,YAAI,OAAO,SAAS,YAAY,WAAW,MAAM;AAC/C,cAAI,IAAI,IAAI,KAAK,OAAO;AAAA,QAC1B;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,IAEA,WAAW,CAAC,MAAM,IAAI,UAAU,UAAU,CAAC;AAAA,IAC3C,WAAW,CAAC,GAAG,MAAM,IAAI,UAAU,UAAU,GAAG,CAAC;AAAA,IACjD,YAAY,MAAM,IAAI,UAAU,WAAW;AAAA,IAC3C,YAAY,CAAC,MAAM,IAAI,UAAU,WAAW,CAAC;AAAA,IAC7C,cAAc,MAAM,IAAI,UAAU,aAAa;AAAA,IAE/C,cAAc,CAAC,QAAQ,IAAI,UAAU,aAAa,GAAG;AAAA,IACrD,iBAAiB,CAAC,WAAW,IAAI,UAAU,gBAAgB,MAAM;AAAA,IACjE,oBAAoB,CAAC,SACnB,yBAAyB,IAAI;AAAA,IAC/B,qBAAqB,CAAC,OAAO,SAAS,IAAI,UAAU,oBAAoB,OAAO,mBAAmB,IAAI,CAAC;AAAA,IAEvG,QAAQ;AAAA,MACN,YAAY,MAAM,IAAI,YAAY,WAAW;AAAA,MAC7C,YAAY,MAAM,IAAI,YAAY,WAAW;AAAA,MAC7C,YAAY,CAAC,OAAO,IAAI,YAAY,WAAW,EAAE;AAAA,MACjD,kBAAkB,CAAC,SAASD,aAAY,IAAI,YAAY,iBAAiB,SAASA,QAAO;AAAA,MACzF,gBAAgB,CAAC,SAAS,IAAI,YAAY,eAAe,IAAI;AAAA,MAC7D,oBAAoB,CAAC,SACnB,yBAAyB,IAAI;AAAA,MAC/B,qBAAqB,CAAC,OAAO,SAC3B,IAAI,UAAU,oBAAoB,OAAO,mBAAmB,IAAI,CAAC;AAAA,IACrE;AAAA,IAEA,IAAI,gBAAgB;AAClB,aAAO,aAAa,MAAM,UAAU,OAAO;AAAA,IAC7C;AAAA,IAEA,SAAS,SAAS;AAChB,aAAO,aAAa,WAAW,MAAM,UAAU,OAAO;AAAA,IACxD;AAAA,IAEA,YAAY;AAAA,MACV,WAAW,CAAC,aAAa,IAAI,iBAAiB,UAAU,QAA8C;AAAA,MACtG,UAAU,MAAM,IAAI,iBAAiB,SAAS;AAAA,IAChD;AAAA,IAEA,GAAG,WAAW,UAAU;AACtB,UAAI,MAAM,QAAQ,IAAI,SAAS;AAC/B,UAAI,CAAC,IAAK,SAAQ,IAAI,WAAY,MAAM,oBAAI,IAAI,CAAE;AAClD,UAAI,IAAI,QAAQ;AAChB,aAAO,MAAM,IAAK,OAAO,QAAQ;AAAA,IACnC;AAAA,EACF;AAEC,EAAC,OAAmD,QAAQC;AAE7D,SAAO;AAAA,IACL,OAAAA;AAAA,IACA,UAAU;AACR,aAAO;AAEP,YAAM,IAAI;AACV,UAAI,EAAE,UAAUA,OAAO,QAAO,EAAE;AAChC,gBAAU,MAAM;AAChB,iBAAW,MAAM;AACjB,iBAAW,MAAM;AACjB,mBAAa,MAAM;AACnB,cAAQ,MAAM;AACd,mBAAa;AACb,oBAAc;AACd,oBAAc;AACd,sBAAgB;AAAA,IAClB;AAAA,IACA,eAAe,SAAS;AACtB,UAAI,KAAK,EAAE,MAAM,eAAe,SAAS,WAAW,MAAM,UAAU,QAAQ,CAAC;AAAA,IAC/E;AAAA,IACA,WAAW,OAAO;AAChB,YAAM,KAAK,UAAU,SAAY,MAAM,UAAU,QAAQ;AACzD,UAAI,KAAK,EAAE,MAAM,iBAAiB,SAAS,MAAM,UAAU,SAAS,OAAO,GAAG,CAAC;AAAA,IACjF;AAAA,IACA,cAAc;AACZ,kBAAY;AAAA,IACd;AAAA,IACA,UAAUC,UAAS;AACjB,UAAI,KAAK,EAAE,MAAM,gBAAgB,SAAAA,SAAQ,CAAC;AAAA,IAC5C;AAAA,IACA,mBAAmB;AACjB,kBAAY;AACZ,WAAK,YAAY,EAAE,KAAK,MAAM,WAAW,MAAM,UAAU,KAAK,CAAC;AAAA,IACjE;AAAA,EACF;AACF;AAEA,SAAS,cAAc,UAAgE;AACrF,QAAM,OAAO,OAAO,KAAK,QAAQ;AACjC,MAAI,KAAK,WAAW,EAAG,QAAO,CAAC;AAC/B,QAAM,UAAU,SAAS,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG;AACzC,QAAM,OAAkC,CAAC;AACzC,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,UAAM,MAA+B,CAAC;AACtC,eAAW,KAAK,KAAM,KAAI,CAAC,IAAI,SAAS,CAAC,EAAE,CAAC;AAC5C,SAAK,KAAK,GAAG;AAAA,EACf;AACA,SAAO;AACT;AAEA,SAAS,YAAY,QAAiC,UAAyD;AAG7G,SAAO,EAAE,GAAG,OAAO;AACrB;AAEA,SAAS,mBACP,MACoE;AACpE,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,SAAS,KAAK,WAAW,UAAU,KAAK,WAAW,YAAY,KAAK,SAAS;AACnF,SAAO,EAAE,aAAa,KAAK,aAAa,OAAO;AACjD;AAEA,SAAS,OAAO,KAAc;AAC5B,UAAQ,MAAM,2BAA2B,GAAG;AAC9C;AAcA,SAAS,yBAAyB,QAAoC;AACpE,MAAI;AACF,QAAI,OAAO,SAAS,OAAO,IAAK;AAChC,WAAO,eAAe,QAAQ,OAAO;AAAA,MACnC,cAAc;AAAA,MACd,KAAK,OAAO,CAAC;AAAA,IACf,CAAC;AAAA,EACH,QAAQ;AAAA,EAER;AACF;;;AC1gBA,iBAAkB;AAIlB,IAAM,oBAAoB,aACvB,OAAO,EAAE,IAAI,aAAE,OAAO,EAAE,CAAC,EACzB,SAAS,aAAE,QAAQ,CAAC;AAEvB,IAAM,oBAAoB,aAAE,KAAK,CAAC,YAAY,WAAW,QAAQ,YAAY,CAAC;AAE9E,IAAM,sBAAsB,aACzB,OAAO;AAAA,EACN,QAAQ,aAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,MAAM,aAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,OAAO,aAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,WAAW,aAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,WAAW,aAAE,QAAQ,EAAE,SAAS;AAAA,EAChC,aAAa,kBAAkB,SAAS;AAAA,EACxC,SAAS,aAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,aAAa,aAAE,OAAO,EAAE,SAAS;AAAA,EACjC,eAAe,aAAE,OAAO,aAAE,OAAO,GAAG,aAAE,QAAQ,CAAC,EAAE,SAAS;AAAA,EAC1D,eAAe,aAAE,OAAO,EAAE,SAAS;AAAA,EACnC,eAAe,aAAE,OAAO,EAAE,SAAS;AACrC,CAAC,EACA,OAAO;AAEV,IAAM,qBAAqB,aACxB,OAAO;AAAA,EACN,OAAO,aAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,SAAS,aAAE,OAAO,aAAE,OAAO,GAAG,mBAAmB,EAAE,SAAS;AAAA,EAC5D,MAAM,aAAE,MAAM,iBAAiB,EAAE,SAAS;AAAA,EAC1C,UAAU,aAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,aAAa,aAAE,QAAQ,EAAE,SAAS;AAAA,EAClC,mBAAmB,aAAE,OAAO,EAAE,SAAS;AAAA,EACvC,OAAO,aAAE,OAAO,EAAE,SAAS;AAC7B,CAAC,EACA,OAAO;AAEV,IAAM,yBAAyB,aAC5B,OAAO;AAAA,EACN,SAAS,aAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,OAAO,aAAE,MAAM,CAAC,aAAE,OAAO,GAAG,aAAE,QAAQ,KAAK,GAAG,aAAE,KAAK,CAAC,CAAC,EAAE,SAAS;AAAA,EAClE,UAAU,aAAE,QAAQ,EAAE,SAAS,EAAE,SAAS;AAAA,EAC1C,QAAQ,aAAE,QAAQ,EAAE,SAAS;AAC/B,CAAC,EACA,OAAO;AAEV,IAAM,mCAAmC,aACtC,OAAO;AAAA,EACN,gBAAgB,aAAE,OAAO,EAAE,SAAS;AAAA,EACpC,SAAS,aAAE,QAAQ,EAAE,SAAS;AAAA,EAC9B,eAAe,aAAE,QAAQ,EAAE,SAAS;AAAA,EACpC,kBAAkB,aAAE,QAAQ,EAAE,SAAS;AACzC,CAAC,EACA,OAAO;AAEV,IAAM,2BAA2B,aAC9B,OAAO;AAAA,EACN,OAAO,aAAE,OAAO;AAAA,EAChB,SAAS,aAAE,OAAO;AAAA,EAClB,UAAU,aAAE,OAAO;AACrB,CAAC,EACA,OAAO;AAEV,IAAM,wBAAwB,aAC3B,OAAO;AAAA,EACN,aAAa,aAAE,OAAO;AAAA,EACtB,QAAQ,aAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,SAAS,aAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,MAAM,aAAE,KAAK,CAAC,eAAe,kBAAkB,aAAa,CAAC,EAAE,SAAS;AAAA,EACxE,QAAQ,aAAE,OAAO,aAAE,OAAO,GAAG,kBAAkB;AAAA,EAC/C,WAAW,uBAAuB,SAAS;AAAA,EAC3C,eAAe,aAAE,OAAO,aAAE,OAAO,GAAG,aAAE,QAAQ,CAAC,EAAE,SAAS;AAAA,EAC1D,mBAAmB,aAAE,QAAQ,EAAE,SAAS;AAAA,EACxC,eAAe,iCAAiC,SAAS;AAAA,EACzD,aAAa,yBAAyB,SAAS,EAAE,SAAS;AAC5D,CAAC,EACA,OAAO,EACP,OAAO,CAAC,UAAU,OAAO,KAAK,MAAM,MAAM,EAAE,SAAS,GAAG;AAAA,EACvD,SAAS;AAAA,EACT,MAAM,CAAC,QAAQ;AACjB,CAAC;AAEH,SAAS,eAAe,QAAgB,OAA0B;AAChE,QAAM,UAAU,MAAM,OACnB,IAAI,CAAC,UAAU;AACd,UAAM,QAAQ,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,KAAK,GAAG,IAAI;AAC7D,WAAO,GAAG,KAAK,KAAK,MAAM,OAAO;AAAA,EACnC,CAAC,EACA,KAAK,IAAI;AACZ,SAAO,IAAI,MAAM,GAAG,MAAM,KAAK,OAAO,EAAE;AAC1C;AAEO,SAAS,kBAAkB,OAAgB;AAChD,SAAO,sBAAsB,UAAU,KAAK;AAC9C;AAEO,SAAS,cAAc,OAAsC;AAClE,QAAM,SAAS,kBAAkB,KAAK;AACtC,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,eAAe,iBAAiB,OAAO,KAAK;AAAA,EACpD;AACA,SAAO,OAAO;AAChB;;;ACvBO,SAAS,oBAAoB,SAAoD;AACtF,QAAM,oBAAoB,cAAc,QAAQ,QAAQ;AACxD,QAAM,QAAQ,eAAe;AAAA,IAC3B,GAAG;AAAA,IACH,eAAe,QAAQ,iBAAiB,kBAAkB;AAAA;AAAA;AAAA,IAG1D,mBAAmB,QAAQ,qBAAqB,kBAAkB,qBAAqB,CAAC;AAAA,EAC1F,CAAC;AACD,QAAM,MAAM,eAAe;AAC3B,QAAM,MAAM,gBAAgB,OAAO,GAAG;AAEtC,QAAM,SAAS,sBAAsB;AAAA,IACnC;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc,QAAQ;AAAA,IACtB,QAAQ,QAAQ,WAAW;AAAA,EAC7B,CAAC;AACD,QAAM,YAA+B;AACrC,QAAMC,SAAuC,OAAO;AAEpD,WAAS,MAAM,SAAsB;AACnC,WAAO,iBAAiB,OAAO,KAAK,OAAO;AAAA,EAC7C;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAAA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,MACN,QAAQ,CAAC,SAAS,WAAW,MAAM,CAAC,CAAC,aAAa,SAAS,MAAM,MAAM,CAAC,CAAC,EAAE,UAAU,CAAC;AAAA,MACtF,WAAW,CAAC,SAAS,OAAO,WAAW;AACrC,cAAM,CAAC,CAAC,gBAAgB,SAAS,OAAO,MAAM,CAAC,CAAC;AAAA,MAClD;AAAA,MACA,WAAW,CAAC,SAAS,UAAU;AAC7B,cAAM,CAAC,CAAC,gBAAgB,SAAS,KAAK,CAAC,CAAC;AAAA,MAC1C;AAAA,IACF;AAAA,IACA,UAAU,OAAO;AACf,YAAM,UAAU,QAAQ;AACxB,UAAI,KAAK,EAAE,MAAM,iBAAiB,SAAS,MAAM,UAAU,SAAS,MAAM,CAAC;AAAA,IAC7E;AAAA,IACA,YAAY,SAAS;AACnB,UAAI,CAAC,MAAM,OAAO,IAAI,OAAO,EAAG,OAAM,IAAI,MAAM,kBAAkB,OAAO,EAAE;AAC3E,YAAM,UAAU,UAAU;AAC1B,YAAM,QAAQ,MAAM,OAAO,IAAI,OAAO,EAAG,KAAK,CAAC,GAAG,MAAM;AACxD,YAAM,UAAU,QAAQ;AACxB,UAAI,KAAK,EAAE,MAAM,eAAe,QAAQ,CAAC;AACzC,UAAI,KAAK,EAAE,MAAM,iBAAiB,SAAS,OAAO,MAAM,CAAC;AAAA,IAC3D;AAAA,IACA,kBAAkB,UAAU;AAC1B,UAAI,aAAa,QAAW;AAC1B,eAAO,MAAM,UAAU;AAAA,MACzB,OAAO;AACL,cAAM,UAAU,WAAW;AAAA,MAC7B;AACA,UAAI,KAAK,EAAE,MAAM,mBAAmB,UAAU,gBAAgB,KAAK,EAAE,CAAC;AAAA,IACxE;AAAA,IACA,MAAM,WAAW,MAAM;AACrB,YAAM,IAAI,UAAU,WAAW,IAAI;AAAA,IACrC;AAAA,IACA,eAAe,aAAa;AAC1B,YAAM,oBAAoB,EAAE,GAAG,YAAY;AAC3C,UAAI,KAAK,EAAE,MAAM,kBAAkB,SAAS,EAAE,GAAG,MAAM,cAAc,GAAG,aAAa,EAAE,GAAG,YAAY,EAAE,CAAC;AAAA,IAC3G;AAAA,IACA,OAAO;AAAA,MACL,IAAI,MAAM;AACR,YAAI,KAAK,EAAE,MAAM,gBAAgB,SAAS,2BAA2B,IAAI,EAAE,CAAC;AAAA,MAC9E;AAAA,IACF;AAAA,IACA,UAAU;AACR,gBAAU,QAAQ;AAClB,UAAI,MAAM;AAAA,IACZ;AAAA,EACF;AACF;;;ACtJA,IAAM,sBAAsB;AAE5B,SAAS,YAAY,WAA4E;AAC/F,SAAO;AAAA,IACL,aAAa;AAAA,IACb,GAAG;AAAA,EACL;AACF;AAKO,IAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,EAKrB,kBAAwC;AACtC,WAAO,YAAY;AAAA,MACjB,SAAS;AAAA,MACT,QAAQ;AAAA,QACN,QAAQ;AAAA,UACN,OAAO;AAAA,UACP,MAAM;AAAA,YACJ,EAAE,IAAI,GAAG,MAAM,QAAQ;AAAA,YACvB,EAAE,IAAI,GAAG,MAAM,MAAM;AAAA,UACvB;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EACA,QAA8B;AAC5B,WAAO,YAAY;AAAA,MACjB,SAAS;AAAA,MACT,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE;AAAA,MAC9B;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EACA,WAAiC;AAC/B,WAAO,YAAY;AAAA,MACjB,SAAS;AAAA,MACT,MAAM;AAAA,MACN,QAAQ;AAAA,QACN,OAAO;AAAA,UACL,OAAO;AAAA,UACP,SAAS;AAAA,YACP,OAAO,EAAE,MAAM,QAAQ,OAAO,QAAQ;AAAA,YACtC,MAAM,EAAE,MAAM,QAAQ,OAAO,OAAO;AAAA,YACpC,UAAU,EAAE,MAAM,UAAU,OAAO,WAAW;AAAA,UAChD;AAAA,UACA,MAAM;AAAA,YACJ,EAAE,IAAI,GAAG,OAAO,YAAY,MAAM,OAAO,UAAU,OAAO;AAAA,YAC1D,EAAE,IAAI,GAAG,OAAO,2BAA2B,MAAM,MAAM,UAAU,OAAO;AAAA,YACxE,EAAE,IAAI,GAAG,OAAO,WAAW,MAAM,OAAO,UAAU,SAAS;AAAA,UAC7D;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EACA,WAAiC;AAC/B,WAAO,YAAY;AAAA,MACjB,SAAS;AAAA,MACT,MAAM;AAAA,MACN,QAAQ;AAAA,QACN,UAAU;AAAA,UACR,OAAO;AAAA,UACP,SAAS;AAAA,YACP,WAAW,EAAE,MAAM,OAAO;AAAA,YAC1B,UAAU,EAAE,MAAM,OAAO;AAAA,YACzB,OAAO,EAAE,MAAM,OAAO;AAAA,YACtB,SAAS,EAAE,MAAM,OAAO;AAAA,UAC1B;AAAA,UACA,MAAM;AAAA,YACJ,EAAE,IAAI,GAAG,WAAW,OAAO,UAAU,YAAY,OAAO,yBAAyB,SAAS,gBAAgB;AAAA,YAC1G,EAAE,IAAI,GAAG,WAAW,SAAS,UAAU,YAAY,OAAO,oBAAoB,SAAS,mBAAmB;AAAA,YAC1G,EAAE,IAAI,GAAG,WAAW,YAAY,UAAU,YAAY,OAAO,wBAAwB,SAAS,OAAO;AAAA,UACvG;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ArDnBwC,IAAAC,sBAAA;AAzBjC,SAAS,gBACd,IACA,UAAkC,CAAC,GACZ;AAIvB,oBAAkB;AAElB,qBAAmB;AAEnB,QAAM,gBAAgB,QAAQ,SAAU,cAAc,QAAQ,MAAM,IAAI,QAAQ,OAAO,UAAU,QAAQ,SAAU;AACnH,QAAM,UAAU,gBAAgB,gBAAgB,aAAa,IAAI,CAAC;AAClE,QAAM,kBACJ,iBAAiB,CAAC,QAAQ,UAAU,WAChC;AAAA,IACE,GAAG,QAAQ;AAAA,IACX,UAAU,iBAAiB,SAAS,QAAQ,IAAI;AAAA,IAChD,mBAAmB,QAAQ,UAAU,qBAAqB,EAAE,cAAc,cAAc,kBAAkB,aAAa;AAAA,EACzH,IACC,QAAQ,YAAY,EAAE,UAAU,QAAQ,MAAM,EAAE;AACvD,QAAM,WAAW,QAAQ,YAAY,oBAAoB,eAAe;AACxE,MAAI,iBAAiB,QAAQ,SAAS,EAAG,UAAS,kBAAkB,eAAe,OAAO,CAAC;AAE3F,QAAM,SAAS,MAAM;AACrB,QAAM,aAAS,uBAAO,gBAAgB,6CAAC,kBAAe,KAAK,QAAQ,SAAS,eAAe,IAAK,IAAI,OAAO;AAC3G,QAAM,kBAAkB,OAAO;AAC/B,SAAO,UAAU,MAAM;AACrB,oBAAgB;AAChB,QAAI,CAAC,QAAQ,SAAU,UAAS,QAAQ;AACxC,uBAAmB;AAAA,EACrB;AACA,SAAO,OAAO,OAAO,QAAQ,EAAE,SAAS,CAAC;AAC3C;AAEA,SAAS,oBAAoB;AAC3B,MAAI,OAAO,WAAW,YAAa;AACnC,MAAI,OAAO,SAAS,OAAO,IAAK;AAChC,MAAI;AACF,WAAO,eAAe,QAAQ,OAAO;AAAA,MACnC,cAAc;AAAA,MACd,KAAK,OAAO,CAAC;AAAA,IACf,CAAC;AAAA,EACH,QAAQ;AAAA,EAGR;AACF;;;AsD9FA,IAAAC,iBAA8D;AAC9D,IAAAA,iBAAwB;;;ACQjB,SAAS,oBAA0B;AACxC,MAAI,OAAO,WAAW,YAAa;AAEnC,aAAW,mBAAX,WAAW,iBAAmB,MAAM,eAAe;AAAA,IACjD,UAAU;AAAA,IAAC;AAAA,IACX,YAAY;AAAA,IAAC;AAAA,IACb,aAAa;AAAA,IAAC;AAAA,EAChB;AAEA,SAAO,eAAP,OAAO,aAAe,CAAC,WACpB;AAAA,IACC,SAAS;AAAA,IACT,OAAO;AAAA,IACP,UAAU;AAAA,IACV,mBAAmB;AAAA,IAAC;AAAA,IACpB,sBAAsB;AAAA,IAAC;AAAA,IACvB,cAAc;AAAA,IAAC;AAAA,IACf,iBAAiB;AAAA,IAAC;AAAA,IAClB,eAAe,MAAM;AAAA,EACvB;AACJ;;;ADmCU,IAAAC,sBAAA;AAfV,eAAsB,gBACpB,OACA,QAA8D,CAAC,GAChD;AACf,QAAM,EAAE,KAAK,SAAS,OAAO,QAAQ,UAAAC,WAAU,UAAU,IAAO,IAC9D,SAAS,QAAQ,QAAQ,EAAE,GAAG,WAAW,KAAK,GAAG,GAAG,MAAM;AAC5D,oBAAkB;AAClB,QAAM,UAAU,SAAS,QAAQ;AACjC,MAAI,CAAC,QAAS,OAAM,IAAI,MAAM,mGAAmG;AAEjI,QAAM,QAA4B,EAAE,OAAO,OAAU;AACrD,WAAS,QAAQ;AACf,WACE,6CAAC,oBAAiB,OAChB,uDAAC,SAAI,yBAAsB,IACzB,uDAAC,OAAI,GACP,GACF;AAAA,EAEJ;AAEA,QAAM,UAAU,gBAAgB,OAAO;AACvC,QAAM,gBAAgBA,aAAY,iBAAiB,OAAO;AAC1D,QAAM,SAAS,gBAAgB,6CAAC,kBAAe,KAAK,OAAO,SAAkB,GAAI;AAAA,IAC/E,UAAU;AAAA,MACR,UAAU;AAAA;AAAA;AAAA,MAGV,mBAAmB,cAAc,qBAAqB,EAAE,cAAc,QAAQ,kBAAkB,aAAa;AAAA,IAC/G;AAAA,EACF,CAAC;AACD,MAAI;AACF,QAAI,QAAQ,SAAS,EAAG,QAAO,SAAS,kBAAkB,eAAe,OAAO,CAAC;AAEjF,QAAI;AACF,gBAAM;AAAA,QACJ,MAAM;AACJ,cAAI,MAAM,UAAU,OAAW;AAC/B,gBAAM,QAAQ,OAAO,UAAU,cAAc,yBAAyB;AACtE,cAAI,CAAC,SAAS,CAAC,MAAM,cAAc,EAAG,OAAM,IAAI,MAAM,kBAAkB;AAAA,QAC1E;AAAA,QACA,EAAE,QAAQ;AAAA,MACZ;AAAA,IACF,QAAQ;AACN,YAAM,QAAQ,OAAO,UAAU,aAAa,KAAK,EAAE,QAAQ,QAAQ,GAAG,KAAK;AAC3E,YAAM,IAAI;AAAA,QACR,uEAAuE,OAAO,0BACvD,MAAM,MAAM,GAAG,GAAG,CAAC;AAAA,MAC5C;AAAA,IACF;AACA,QAAI,MAAM,UAAU,OAAW,OAAM,MAAM;AAAA,EAC7C,UAAE;AACA,WAAO,QAAQ;AAAA,EACjB;AACF;AAGA,IAAM,mBAAN,cAA+B,yBAAmF;AAAA,EAAlH;AAAA;AACE,iBAAQ,EAAE,QAAQ,MAAM;AAAA;AAAA,EAExB,OAAO,2BAA2B;AAChC,WAAO,EAAE,QAAQ,KAAK;AAAA,EACxB;AAAA,EAEA,kBAAkB,OAAgB;AAChC,SAAK,MAAM,MAAM,QAAQ;AAAA,EAC3B;AAAA,EAEA,SAAS;AACP,WAAO,KAAK,MAAM,SAAS,OAAO,KAAK,MAAM;AAAA,EAC/C;AACF;;;AE3GO,SAAS,UAAU,UAAsC;AAC9D,SAAO,SAAS,IACb,QAAQ,EACR,OAAO,CAAC,MAA2E,EAAE,SAAS,aAAa,EAC3G,IAAI,CAAC,MAAM,EAAE,MAAmB;AACrC;AAEO,SAAS,SAAS,UAAmD;AAC1E,SAAO,SAAS,IAAI,QAAQ;AAC9B;AASA,SAAS,iBAAiB,MAA2D;AACnF,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,CAAC,MAAM,EAAE,SAAS;AAAA,IAC3B,KAAK;AAAA,IACL,KAAK;AACH,aAAO,CAAC,MAAM,EAAE,SAAS;AAAA,IAC3B,KAAK;AACH,aAAO,CAAC,MAAM,EAAE,SAAS;AAAA,IAC3B,KAAK;AACH,aAAO,CAAC,MAAM,EAAE,SAAS;AAAA,IAC3B,KAAK;AACH,aAAO,CAAC,MAAM,EAAE,SAAS;AAAA,EAC7B;AACF;AAEA,SAAS,iBACP,UACA,WACA,WACA,OACwB;AACxB,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,QAAQ,WAAW,MAAM;AAC7B,UAAI;AACJ,YAAM,OAAO,QAAQ,WAAW,KAAK,MAAM;AAC3C,YAAM,SAAS,SAAS,IACrB,QAAQ,EACR,MAAM,EAAE,EACR,IAAI,CAAC,MAAM,EAAE,IAAI,EACjB,KAAK,IAAI;AACZ;AAAA,QACE,IAAI;AAAA,UACF,gCAAgC,SAAS,KAAK,IAAI,OAC/C,SAAS,uBAAuB,MAAM,MAAM;AAAA,QACjD;AAAA,MACF;AAAA,IACF,GAAG,SAAS;AACZ,UAAM,MAAM,SAAS,IAAI,GAAG,CAAC,UAAU;AACrC,UAAI,UAAU,KAAK,GAAG;AACpB,qBAAa,KAAK;AAClB,YAAI;AACJ,gBAAQ,KAAK;AAAA,MACf;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH;AAYO,SAAS,aACd,UACA,iBACA,mBAAiD,KACzB;AACxB,MAAI,OAAO,oBAAoB,UAAU;AACvC,UAAM,OAAO,OAAO,qBAAqB,WAAW,mBAAmB,CAAC;AACxE,UAAMC,aAAY,KAAK,aAAa;AACpC,WAAO,iBAAiB,UAAU,iBAAiB,eAAe,GAAGA,YAAW,eAAe;AAAA,EACjG;AACA,QAAM,YAAY,OAAO,qBAAqB,WAAW,mBAAmB;AAC5E,SAAO,iBAAiB,UAAU,iBAAiB,SAAS;AAC9D;;;AzDpEA,IAAAC,iBAQO;","names":["import_react","import_react","token","token","message","message","ACCESS_RANK","inFlight","import_react","import_react","import_jsx_runtime","message","screen","import_react","import_react","cardStyle","import_jsx_runtime","cardStyle","import_react","import_react","import_jsx_runtime","cardStyle","message","import_jsx_runtime","alert","SEVERITY","import_react","import_jsx_runtime","import_jsx_runtime","LocalDevPage","ReleasePage","isEmbedded","formulaError","message","message","tokens","options","grist","message","grist","import_jsx_runtime","import_react","import_jsx_runtime","document","timeoutMs","import_react"]}
|
|
1
|
+
{"version":3,"sources":["../../src/emulator/testing/index.ts","../../src/emulator/testing/render-with-grist.tsx","../../src/app/mount-grist-widget.tsx","../../src/sdk/use-grist.ts","../../src/sdk/helpers/deprecate.ts","../../src/sdk/helpers/grist-value-codec.ts","../../src/sdk/helpers/grist-table-data.ts","../../src/sdk/helpers/grist-widget-options.ts","../../src/sdk/helpers/build-replica-document.ts","../../src/sdk/helpers/grist-columns-filters.ts","../../src/sdk/helpers/grist-attachment-download.ts","../../src/sdk/helpers/grist-fetch-with-auth.ts","../../src/sdk/helpers/grist-attachment-upload.ts","../../src/sdk/runtime/api.ts","../../src/sdk/helpers/grist-mappings.ts","../../src/sdk/runtime/cells.ts","../../src/sdk/runtime/derive.ts","../../src/sdk/helpers/grist-widget-interaction.ts","../../src/sdk/runtime/host.ts","../../src/sdk/runtime/ready.ts","../../src/sdk/helpers/grist-theme-payload.ts","../../src/sdk/runtime/runtime.ts","../../src/sdk/define-widget.ts","../../src/sdk/components/grist-widget-provider.tsx","../../src/sdk/components/grist-boundary.tsx","../../src/sdk/helpers/replica-normalize.ts","../../src/sdk/use-widget-metadata.ts","../../src/sdk/helpers/grist-user-actions.ts","../../src/app/chrome/local-dev-page.tsx","../../src/app/chrome/tokens.ts","../../src/app/chrome/widget-title.ts","../../src/app/chrome/release-page.tsx","../../src/app/deploy-path.ts","../../src/app/released-versions.ts","../../src/sdk/helpers/grist-sdk-alerts.ts","../../src/app/chrome/widget-alerts.tsx","../../src/app/widget-theme.tsx","../../src/emulator/testing/declared-document.ts","../../src/emulator/api/command-api.ts","../../src/emulator/core/mappings.ts","../../src/emulator/api/custom-section-api.ts","../../src/emulator/api/grist-api.ts","../../src/emulator/core/display-helpers.ts","../../src/emulator/core/document.ts","../../src/emulator/core/action-engine.ts","../../src/emulator/core/columnar.ts","../../src/emulator/api/grist-doc-api.ts","../../src/emulator/api/grist-view.ts","../../src/emulator/api/widget-api.ts","../../src/emulator/api/index.ts","../../src/emulator/core/event-bus.ts","../../src/emulator/theme-message.ts","../../src/emulator/transports/inline.ts","../../src/emulator/validators.ts","../../src/emulator/create-grist-emulator.ts","../../src/emulator/templates.ts","../../src/emulator/testing/smoke-test-widget.tsx","../../src/emulator/testing/jsdom-stubs.ts","../../src/emulator/testing/matchers.ts"],"sourcesContent":["/**\n * Test entry point — `grist-widget-sdk/emulator/testing`.\n *\n * Bundles `renderWithGrist`, matchers, document presets, and the most-used\n * @testing-library/react primitives so a typical test file only needs one\n * import line:\n *\n * import {\n * renderWithGrist, presets, screen, fireEvent, waitFor, actionsOf,\n * } from \"grist-widget-sdk/emulator/testing\"\n */\n\nexport { renderWithGrist } from \"./render-with-grist\"\nexport type {\n RenderWithGristOptions,\n RenderWithGristResult,\n} from \"./render-with-grist\"\n\nexport { smokeTestWidget, type SmokeTestWidgetOptions } from \"./smoke-test-widget\"\nexport { installJsdomStubs } from \"./jsdom-stubs\"\n\nexport {\n actionsOf,\n eventsOf,\n waitForEvent,\n type WaitForEventKind,\n type WaitForEventOptions,\n} from \"./matchers\"\n\n// Document fixtures (re-export from the emulator entry for convenience).\nexport { presets } from \"../templates\"\n\n// @testing-library/react convenience re-exports — see AGENTS.md\nexport {\n act,\n cleanup,\n fireEvent,\n render,\n screen,\n waitFor,\n within,\n} from \"@testing-library/react\"\nexport type { RenderOptions, RenderResult } from \"@testing-library/react\"\n","/**\n * `renderWithGrist(ui, options)` — drop-in replacement for\n * `@testing-library/react`'s `render(ui)` that boots a Grist emulator\n * (inline transport) and exposes it to the test.\n *\n * The emulator is mounted as `window.grist`. The SDK hooks (`useGrist`,\n * `useGristReady`, etc.) detect it via the same path they use in production.\n *\n * Cleanup is automatic when the test's container unmounts.\n */\n\nimport type { ReactElement } from \"react\"\n\nimport { render, type RenderOptions, type RenderResult } from \"@testing-library/react\"\n\nimport { GristWidgetApp } from \"../../app/mount-grist-widget\"\nimport type { GristWidget, UseGristOptions } from \"../../sdk\"\nimport { isGristWidget } from \"../../sdk/define-widget\"\nimport { resetGristForTests } from \"../../sdk/use-grist\"\nimport { declaredColumns, declaredDocument, mapEveryColumn } from \"./declared-document\"\nimport { createGristEmulator } from \"../create-grist-emulator\"\nimport type { CreateGristEmulatorOptions, GristEmulator } from \"../create-grist-emulator\"\nimport { presets } from \"../templates\"\n\nexport type RenderWithGristOptions = RenderOptions & {\n emulator?: CreateGristEmulatorOptions\n /** Skip mounting the emulator; you bring your own. Useful for shared fixtures. */\n existing?: GristEmulator\n /**\n * The widget's declaration (`defineGristWidget()`) or its `GRIST_OPTIONS`.\n * Given, the test runs the widget as `mountGristWidget()` does inside\n * Grist (provider, boundary, alerts), against a table with a column per\n * declared column, every one mapped, and the access it asks for granted.\n */\n widget?: GristWidget | UseGristOptions\n /**\n * With `widget`: the table's rows, under the declared names, as typed\n * reads give them (`{ Title: \"Ship\", Due: new Date(...) }`). The first is\n * selected. Defaults to one row of sample values.\n */\n rows?: ReadonlyArray<Record<string, unknown>>\n}\n\nexport type RenderWithGristResult = RenderResult & {\n emulator: GristEmulator\n}\n\nexport function renderWithGrist(\n ui: ReactElement,\n options: RenderWithGristOptions = {}\n): RenderWithGristResult {\n // Make `window.self !== window.top` evaluate to `true` so\n // `useGristAvailability` reports the widget as embedded. We only do this in\n // jsdom; real browsers already enforce this distinction for iframes.\n fakeIframeContext()\n\n resetGristForTests()\n\n const widgetOptions = options.widget ? (isGristWidget(options.widget) ? options.widget.options : options.widget) : undefined\n const columns = widgetOptions ? declaredColumns(widgetOptions) : []\n const emulatorOptions: CreateGristEmulatorOptions =\n widgetOptions && !options.emulator?.document\n ? {\n ...options.emulator,\n document: declaredDocument(columns, options.rows),\n widgetInteraction: options.emulator?.widgetInteraction ?? { access_level: widgetOptions.requiredAccess ?? \"read table\" },\n }\n : (options.emulator ?? { document: presets.blank() })\n const emulator = options.existing ?? createGristEmulator(emulatorOptions)\n if (widgetOptions && columns.length > 0) emulator.setColumnMappings(mapEveryColumn(columns))\n\n const Widget = () => ui\n const result = render(widgetOptions ? <GristWidgetApp App={Widget} options={widgetOptions} /> : ui, options)\n const originalUnmount = result.unmount\n result.unmount = () => {\n originalUnmount()\n if (!options.existing) emulator.dispose()\n resetGristForTests()\n }\n return Object.assign(result, { emulator })\n}\n\nfunction fakeIframeContext() {\n if (typeof window === \"undefined\") return\n if (window.self !== window.top) return // already iframe-like\n try {\n Object.defineProperty(window, \"top\", {\n configurable: true,\n get: () => ({}),\n })\n } catch {\n // Some jsdom versions block redefinition; fail silently — tests using\n // `useGristAvailability` will need to bypass it explicitly in that case.\n }\n}\n","import { StrictMode, Suspense, type ComponentType, type ReactNode } from \"react\"\nimport { createRoot } from \"react-dom/client\"\n\nimport { GristBoundary, GristWidgetProvider, useWidgetMetadata } from \"../sdk\"\nimport type { GristWidget, UseGristOptions } from \"../sdk\"\nimport { isGristWidget } from \"../sdk/define-widget\"\nimport { LocalDevPage as DefaultLocalDevPage } from \"./chrome/local-dev-page\"\nimport { ReleasePage as DefaultReleasePage } from \"./chrome/release-page\"\nimport { WidgetAlerts } from \"./chrome/widget-alerts\"\nimport { parseDeployPath, type DeployChannel } from \"./deploy-path\"\nimport { EmbeddedThemeProvider, StandaloneThemeProvider } from \"./widget-theme\"\n\nexport type GristWidgetAppProps = {\n /** The widget. A `React.lazy()` component works too: its code then loads only inside Grist. */\n App: ComponentType\n /** The widget's `GRIST_OPTIONS`: access level, columns, and so on. */\n options: UseGristOptions\n /** The page's title and description (the widget's `WIDGET_METADATA`, or its declaration's). */\n metadata?: { title?: string; description?: string }\n /**\n * Whether this is the local dev server. Pass `import.meta.env.DEV`.\n * Outside Grist it picks the local-dev page over the release page.\n */\n dev?: boolean\n /**\n * Wraps the widget inside Grist, under {@link GristBoundary}. The default\n * lists what needs the user's attention (column mapping, access level,\n * failed writes) above the widget; `null` renders the widget alone.\n */\n Alerts?: ComponentType<{ children: ReactNode }> | null\n /** Shown outside Grist on the local dev server. Defaults to a page pointing at `pnpm test` and the `dev` loop. */\n LocalDevPage?: ComponentType\n /**\n * Shown outside Grist on a deployed URL (`/latest/`, `/dev/`, `/v<version>/`).\n * Defaults to a page linking every channel and version, with the URL to\n * paste into Grist.\n */\n ReleasePage?: ComponentType<{ channel: DeployChannel }>\n}\n\nexport type MountGristWidgetConfig = GristWidgetAppProps & {\n /** The element to render into, or its CSS selector. Defaults to `#root`. */\n root?: Element | string\n}\n\n/**\n * A widget's entry module, `src/app/App.tsx`, as `import * as entry` gives\n * it: the widget as its default export, its declaration as `widget` (or, in\n * a widget made before `defineGristWidget`, `GRIST_OPTIONS` and\n * `WIDGET_METADATA`), and optionally its own `Alerts`, `LocalDevPage` and\n * `ReleasePage`. Everything a widget customises lives there, in its own\n * file: the template's `src/main.tsx` stays the same in every widget, and\n * `create-grist-widget upgrade` can rewrite it without losing anything.\n */\nexport type GristWidgetEntry = {\n default: ComponentType\n widget?: GristWidget\n GRIST_OPTIONS?: UseGristOptions\n WIDGET_METADATA?: { title?: string; description?: string }\n Alerts?: GristWidgetAppProps[\"Alerts\"]\n LocalDevPage?: GristWidgetAppProps[\"LocalDevPage\"]\n ReleasePage?: GristWidgetAppProps[\"ReleasePage\"]\n}\n\n/**\n * @internal An entry module, as opposed to `{ App, options }`: it has a\n * default export. A widget's module may also export its component as `App`,\n * so `App` alone doesn't tell them apart.\n */\nexport function isGristWidgetEntry(value: object): value is GristWidgetEntry {\n return \"default\" in value && value.default != null\n}\n\n/** The props {@link GristWidgetApp} takes, from a widget's entry module. */\nexport function entryProps(entry: GristWidgetEntry, dev = false): GristWidgetAppProps {\n const widget = isGristWidget(entry.widget) ? entry.widget : undefined\n const options = widget?.options ?? entry.GRIST_OPTIONS\n if (!options) {\n throw new Error(\n \"mountGristWidget: src/app/App.tsx exports neither `widget` (defineGristWidget) nor `GRIST_OPTIONS`.\"\n )\n }\n const props: GristWidgetAppProps = {\n App: entry.default,\n options,\n metadata: widget?.metadata ?? entry.WIDGET_METADATA,\n dev,\n }\n if (\"Alerts\" in entry) props.Alerts = entry.Alerts\n if (entry.LocalDevPage) props.LocalDevPage = entry.LocalDevPage\n if (entry.ReleasePage) props.ReleasePage = entry.ReleasePage\n return props\n}\n\nexport type MountedGristWidget = {\n unmount: () => void\n}\n\n/**\n * Render a widget into the page: everything `src/main.tsx` used to wire by\n * hand.\n *\n * ```tsx\n * import { mountGristWidget } from \"grist-widget-sdk/app\"\n * import \"./index.css\"\n * import * as entry from \"./app/App\"\n *\n * mountGristWidget(entry, { dev: import.meta.env.DEV })\n * ```\n *\n * It reads the entry module's exports ({@link GristWidgetEntry}): the widget,\n * its declaration and any page it replaces. The older form,\n * `mountGristWidget({ App, options: GRIST_OPTIONS, dev })`, still works.\n *\n * Inside Grist, the widget renders in {@link GristWidgetProvider} and\n * {@link GristBoundary}, which gates on its mapped columns when it declares\n * any, and follows Grist's light/dark theme. Outside Grist, where there is\n * nothing to connect to, the page shows `LocalDevPage` on the dev server and\n * `ReleasePage` on a deployed URL.\n */\nexport function mountGristWidget(entry: GristWidgetEntry, options?: { dev?: boolean; root?: Element | string }): MountedGristWidget\nexport function mountGristWidget(config: MountGristWidgetConfig): MountedGristWidget\nexport function mountGristWidget(\n config: MountGristWidgetConfig | GristWidgetEntry,\n entryOptions: { dev?: boolean; root?: Element | string } = {}\n): MountedGristWidget {\n const { root = \"#root\", ...props } =\n isGristWidgetEntry(config) ? { ...entryProps(config, entryOptions.dev), root: entryOptions.root } : config\n const container = typeof root === \"string\" ? document.querySelector(root) : root\n if (!container) {\n throw new Error(`mountGristWidget: no element matches \"${String(root)}\" to render the widget into.`)\n }\n\n const reactRoot = createRoot(container)\n reactRoot.render(\n <StrictMode>\n <GristWidgetApp {...props} />\n </StrictMode>\n )\n return { unmount: () => reactRoot.unmount() }\n}\n\n/**\n * The tree {@link mountGristWidget} renders, as a component: for a test, or\n * for a page that manages its own React root.\n */\nexport function GristWidgetApp({\n App,\n options,\n metadata,\n dev = false,\n Alerts = WidgetAlerts,\n LocalDevPage = DefaultLocalDevPage,\n ReleasePage = DefaultReleasePage,\n}: GristWidgetAppProps) {\n const Wrap = Alerts ?? PassThrough\n if (isEmbedded()) {\n return (\n <GristWidgetProvider options={options}>\n <PageMetadata metadata={metadata} />\n <EmbeddedThemeProvider>\n <GristBoundary>\n <div style={FILL}>\n <Wrap>\n <Suspense fallback={null}>\n <App />\n </Suspense>\n </Wrap>\n </div>\n </GristBoundary>\n </EmbeddedThemeProvider>\n </GristWidgetProvider>\n )\n }\n\n const channel = parseDeployPath(window.location.pathname).channel\n return (\n <StandaloneThemeProvider>\n <PageMetadata metadata={metadata} />\n <div style={FILL}>{dev ? <LocalDevPage /> : <ReleasePage channel={channel} />}</div>\n </StandaloneThemeProvider>\n )\n}\n\nconst FILL = { minHeight: \"100%\", width: \"100%\" } as const\n\n/** A Grist custom widget only ever runs in Grist's iframe. */\nfunction isEmbedded(): boolean {\n return typeof window !== \"undefined\" && window.self !== window.top\n}\n\n/** The page's title and description, from the widget's declaration. */\nfunction PageMetadata({ metadata }: { metadata: GristWidgetAppProps[\"metadata\"] }) {\n useWidgetMetadata(metadata?.title ? { title: metadata.title, description: metadata.description ?? \"\" } : null)\n return null\n}\n\nfunction PassThrough({ children }: { children: ReactNode }) {\n return <>{children}</>\n}\n","/**\n * `useGrist()`: the widget's one object for Grist — its connection, the\n * selected record and the section's records, column mapping, writes, widget\n * options, linking and the document's REST API.\n *\n * Inside `<GristWidgetProvider>` (what `mountGristWidget()` renders) it reads\n * the provider's connection; outside one, a page-wide connection made with\n * the first caller's options.\n */\n\nimport { createContext, useCallback, useContext, useEffect, useMemo, useSyncExternalStore } from \"react\"\n\nimport { warnDeprecated } from \"./helpers/deprecate\"\nimport type { ValidateColumnMappingsResult } from \"./helpers/grist-mappings\"\nimport { createGristApi, type GristApi } from \"./runtime/api\"\nimport {\n deriveColumnMappingStatus,\n deriveError,\n deriveStatus,\n mapBackPatch,\n type GristWidgetStatus,\n} from \"./runtime/derive\"\nimport { mapAndCheck, type GristCellIssue } from \"./runtime/cells\"\nimport { ALL_STREAMS } from \"./runtime/host\"\nimport { resetGristReady } from \"./runtime/ready\"\nimport {\n createGristRuntime,\n initialRuntimeState,\n type GristRuntime,\n type GristRuntimeOptions,\n type GristRuntimeState,\n type GristTheme,\n type GristWidgetActionStatus,\n} from \"./runtime/runtime\"\nimport type { GristRowRecord, GristWidgetColumnMap } from \"./types\"\n\nexport type { GristTheme, GristWidgetActionStatus, GristWidgetStatus }\nexport type { FetchRows, FetchRowsOptions, GristColumnInfo, ListColumnsOptions, ListTablesOptions } from \"./runtime/api\"\n\n/** What the widget asks Grist for: access, columns to map, and the alerts it doesn't want. */\nexport type UseGristOptions = GristRuntimeOptions\n\n/** A write under declared names: any of the mapped record's fields but its `id`. */\nexport type GristRecordPatch<TMapped> = Partial<Omit<TMapped, \"id\">>\n\n/** Derived from the selection: no row, a row, or the add-row placeholder. */\nexport type GristWidgetMode = \"empty\" | \"row\" | \"new-row\"\n\n/**\n * The widget's Grist state and API. Every method is referentially stable for\n * the widget's lifetime: safe in effect dependencies. The object itself is\n * new whenever a value changes; depend on the members you use, not on it.\n */\nexport type UseGristResult<TRow = Record<string, unknown>, TMapped = Record<string, unknown>> = Omit<\n GristApi,\n \"fetchTableRows\"\n> & {\n /** `\"booting\"` until Grist answers, then `\"ready\"`; `\"unavailable\"` outside Grist; `\"error\"` otherwise. */\n status: GristWidgetStatus\n /** @deprecated Use `status`: `status !== \"unavailable\"` once it isn't `\"booting\"`. */\n isAvailable: boolean | null\n /** @deprecated Use `status === \"ready\"`. */\n isReady: boolean\n /** Why the widget can't run (status `\"error\"` or `\"unavailable\"`), else null. */\n error: string | null\n /** Grist's light or dark theme, null until Grist sends it. */\n theme: GristTheme | null\n\n /** The selected row, raw column ids. */\n record: GristRowRecord<TRow> | null\n /** The section's rows (what its filters show), raw column ids. */\n records: GristRowRecord<TRow>[] | null\n /**\n * The selected row under the declared column names, each cell the JS value\n * its declared type promises (a cell that doesn't match is null, and in\n * `cellIssues`); null until every required column is mapped.\n */\n mappedRecord: TMapped | null\n /** Every row of the section, like `mappedRecord`. */\n mappedRecords: TMapped[] | null\n /** The mapped cells that didn't match their declared type (or the widget's `schema`), by row. */\n cellIssues: readonly GristCellIssue[]\n /** Declared column name → the Grist column id(s) mapped to it. */\n mappings: GristWidgetColumnMap\n /** Whether every required declared column is mapped (`pending` until Grist reports mappings). */\n columnMappingStatus: ValidateColumnMappingsResult\n mode: GristWidgetMode\n /** The Grist column id mapped to a declared name, or the name itself. */\n resolveMappedColumnId: (name: string) => string\n /**\n * A patch under declared names, as real column ids for a write, each value\n * encoded for its declared type (multi-column mappings are skipped).\n */\n mapBack: (patch: Partial<TMapped>) => Record<string, unknown>\n /**\n * Writes a patch under declared names to the selected row (or to `rowId`),\n * encoded for each declared type: `mapBack` + `table.update` in one call.\n * Rejects when no row is selected.\n */\n updateRecord: {\n (patch: GristRecordPatch<TMapped>): Promise<void>\n (rowId: number, patch: GristRecordPatch<TMapped>): Promise<void>\n }\n /** Adds a row to the section's table from a patch under declared names; resolves to its row id. */\n addRecord: (patch: GristRecordPatch<TMapped>) => Promise<number>\n /** The section's table id. */\n currentTableId: string | null\n\n /** @deprecated Use `fetchRows(tableId, options)`. */\n fetchTableRows: <T extends Record<string, unknown> = Record<string, unknown>>(\n tableId: string,\n options?: Parameters<GristApi[\"fetchTableRows\"]>[1]\n ) => Promise<GristRowRecord<T>[]>\n\n /** The last write's state. */\n actionStatus: GristWidgetActionStatus\n actionError: string | null\n\n /** The options Grist stores for this widget, null until it sends them. */\n widgetOptions: Record<string, unknown> | null\n}\n\ntype GristContextValue = { runtime: GristRuntime; api: GristApi }\n\nconst GristContext = createContext<GristContextValue | null>(null)\nGristContext.displayName = \"GristContext\"\n\n/** @internal The provider's (or the page's) runtime, for the SDK's own components. */\nexport function useGristRuntime(): GristContextValue | null {\n return useContext(GristContext)\n}\n\nfunction newConnection(options: UseGristOptions | undefined): GristContextValue {\n const runtime = createGristRuntime(options)\n return { runtime, api: createGristApi(runtime) }\n}\n\nlet pageConnection: GristContextValue | null = null\n\n/** @internal Tests: forget the page's connection and every Grist binding. */\nexport function resetGristForTests(): void {\n pageConnection = null\n resetGristReady()\n for (const s of ALL_STREAMS) s.reset()\n}\n\nexport const GristContextProvider = GristContext.Provider\nexport { newConnection }\n\nconst serverState = () => initialRuntimeState()\n\n/** The connection's state, re-rendering on every change. */\nexport function useGristState(connection: GristContextValue): GristRuntimeState {\n const { runtime } = connection\n useEffect(() => runtime.start(), [runtime])\n return useSyncExternalStore(runtime.subscribe, runtime.getState, serverState)\n}\n\ntype Mapped<TMapped> = { record: TMapped | null; records: TMapped[] | null; issues: readonly GristCellIssue[] }\n\nconst NO_ISSUES: readonly GristCellIssue[] = Object.freeze([])\n\n/** The mapped, checked record and records; recomputed only when they, the mappings or the options change. */\nfunction useMapped<TMapped>(state: GristRuntimeState, options: GristRuntimeOptions): Mapped<TMapped> {\n const { record, records, mappings } = state\n const { columns, schema } = options\n return useMemo(() => {\n const issues: GristCellIssue[] = []\n const rows =\n records && (columns?.length ? mappings !== null : true)\n ? records.map((r) => {\n const out = mapAndCheck<TMapped>(r, columns, mappings, schema)\n issues.push(...out.issues)\n return out.value\n })\n : null\n const selected = mapAndCheck<TMapped>(record, columns, mappings, schema)\n if (record && !records?.some((r) => r.id === record.id)) issues.push(...selected.issues)\n const mappedRecords = rows && rows.every((r) => r !== null) ? (rows as TMapped[]) : null\n return { record: selected.value, records: mappedRecords, issues: issues.length ? issues : NO_ISSUES }\n }, [record, records, mappings, columns, schema])\n}\n\ntype RecordWrites = Pick<UseGristResult, \"updateRecord\" | \"addRecord\">\n\n/** `updateRecord` / `addRecord`: stable, reading the mappings and the selection when called. */\nfunction recordWrites(connection: GristContextValue): RecordWrites {\n const { runtime, api } = connection\n const fieldsOf = (patch: Record<string, unknown>) => {\n const { id: _id, ...rest } = patch\n return mapBackPatch(rest, runtime.getState().mappings ?? EMPTY_MAPPINGS, runtime.options.columns).fields\n }\n const updateRecord = ((a: number | Record<string, unknown>, b?: Record<string, unknown>) => {\n const rowId = typeof a === \"number\" ? a : runtime.getState().record?.id\n const patch = typeof a === \"number\" ? (b ?? {}) : a\n if (typeof rowId !== \"number\") {\n return Promise.reject(new Error(\"updateRecord(): no row is selected. Pass the row id: updateRecord(rowId, patch).\"))\n }\n return api.table.update({ id: rowId, fields: fieldsOf(patch) })\n }) as RecordWrites[\"updateRecord\"]\n const addRecord = async (patch: Record<string, unknown>) => {\n const created = await api.table.create({ fields: fieldsOf(patch) })\n return (Array.isArray(created) ? created[0]! : created).id\n }\n return { updateRecord, addRecord }\n}\n\nfunction buildResult<TRow, TMapped>(\n state: GristRuntimeState,\n mapped: Mapped<TMapped>,\n connection: GristContextValue,\n mapBack: (patch: Partial<TMapped>) => Record<string, unknown>,\n resolveMappedColumnId: (name: string) => string,\n writes: RecordWrites\n): UseGristResult<TRow, TMapped> {\n const { runtime, api } = connection\n const status = deriveStatus(state)\n const columns = runtime.options.columns\n const result = {\n ...api,\n status,\n error: deriveError(state),\n theme: state.theme,\n record: state.record as GristRowRecord<TRow> | null,\n records: state.records as GristRowRecord<TRow>[] | null,\n mappedRecord: mapped.record,\n mappedRecords: mapped.records,\n cellIssues: mapped.issues,\n mappings: state.mappings ?? EMPTY_MAPPINGS,\n columnMappingStatus: deriveColumnMappingStatus(columns, state.mappings),\n mode: state.isNewRecord ? \"new-row\" : state.record ? \"row\" : \"empty\",\n resolveMappedColumnId,\n mapBack,\n updateRecord: writes.updateRecord as UseGristResult<TRow, TMapped>[\"updateRecord\"],\n addRecord: writes.addRecord as UseGristResult<TRow, TMapped>[\"addRecord\"],\n currentTableId: state.currentTableId,\n actionStatus: state.actionStatus,\n actionError: state.actionError,\n widgetOptions: state.widgetOptions,\n } as UseGristResult<TRow, TMapped>\n // Deprecated flags: getters that warn once, kept out of spreads and equality checks.\n const isAvailable = state.connection === \"connecting\" ? null : state.connection !== \"not-embedded\" && state.connection !== \"unavailable\"\n Object.defineProperties(result, {\n isAvailable: {\n get() {\n warnDeprecated(\"useGrist().isAvailable\", 'read status: \"unavailable\" outside Grist, \"booting\" while connecting')\n return isAvailable\n },\n },\n isReady: {\n get() {\n warnDeprecated(\"useGrist().isReady\", 'use status === \"ready\"')\n return status === \"ready\"\n },\n },\n })\n return result\n}\n\nconst EMPTY_MAPPINGS: GristWidgetColumnMap = Object.freeze({}) as GristWidgetColumnMap\n\nfunction useGristResult<TRow, TMapped>(connection: GristContextValue): UseGristResult<TRow, TMapped> {\n const state = useGristState(connection)\n const mappings = state.mappings ?? EMPTY_MAPPINGS\n const { runtime } = connection\n const resolveMappedColumnId = useCallback(\n (name: string) => {\n const real = mappings[name]\n if (typeof real === \"string\" && real) return real\n if (Array.isArray(real) && typeof real[0] === \"string\") return real[0]\n return name\n },\n [mappings]\n )\n const mapBack = useCallback(\n (patch: Partial<TMapped>) => {\n const { fields, skipped } = mapBackPatch(patch as Record<string, unknown>, mappings, runtime.options.columns)\n const previous = runtime.getState().mapBackSkipped\n if (previous.join(\"\\0\") !== skipped.join(\"\\0\")) runtime.update({ mapBackSkipped: skipped })\n return fields\n },\n [mappings, runtime]\n )\n const mapped = useMapped<TMapped>(state, runtime.options)\n const writes = useMemo(() => recordWrites(connection), [connection])\n return useMemo(\n () => buildResult<TRow, TMapped>(state, mapped, connection, mapBack, resolveMappedColumnId, writes),\n [state, mapped, connection, mapBack, resolveMappedColumnId, writes]\n )\n}\n\n/**\n * The widget's Grist state and API. Inside `<GristWidgetProvider>` it uses the\n * provider's connection and ignores `options`; outside one, the page's, made\n * with the first caller's `options`.\n */\nexport function useGrist<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>(\n options?: UseGristOptions\n): UseGristResult<TRow, TMapped> {\n const fromProvider = useContext(GristContext)\n const connection = fromProvider ?? (pageConnection ??= newConnection(options))\n return useGristResult<TRow, TMapped>(connection)\n}\n\n/** `useGrist()` inside a provider, or null outside one: for components that also work without Grist. */\nexport function useGristOptional<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>(): UseGristResult<\n TRow,\n TMapped\n> | null {\n const fromProvider = useContext(GristContext)\n // The hooks below run in both branches; the provider only decides which connection they read.\n const result = useGristResult<TRow, TMapped>(fromProvider ?? DETACHED)\n return fromProvider ? result : null\n}\n\n/**\n * `useGrist()` inside `<GristWidgetProvider>`; throws outside one.\n * @deprecated Use `widget.useGrist()` (or `useGrist()`): `mountGristWidget()` always renders the provider.\n */\nexport function useGristContext<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>(): UseGristResult<\n TRow,\n TMapped\n> {\n warnDeprecated(\"useGristContext()\", \"use widget.useGrist() (or useGrist()): mountGristWidget() always renders the provider\")\n if (!useContext(GristContext)) {\n throw new Error(\"useGristContext() must be used inside <GristWidgetProvider> (mountGristWidget renders one).\")\n }\n return useGrist<TRow, TMapped>()\n}\n\n/** A connection that never starts: what useGristOptional reads outside a provider. */\nconst DETACHED: GristContextValue = (() => {\n const state = initialRuntimeState()\n const runtime: GristRuntime = {\n options: {},\n getState: () => state,\n subscribe: () => () => {},\n start: () => () => {},\n reload: async () => {},\n update: () => {},\n }\n return { runtime, api: createGristApi(runtime) }\n})()\n\n/** @internal The nearest provider's connection and its state (idle outside one). */\nexport function useNearestGristState(): {\n connection: GristContextValue | null\n state: GristRuntimeState\n cellIssues: readonly GristCellIssue[]\n} {\n const connection = useContext(GristContext)\n const state = useGristState(connection ?? DETACHED)\n const { issues } = useMapped(state, (connection ?? DETACHED).runtime.options)\n return { connection, state, cellIssues: issues }\n}\n","/**\n * Deprecation warnings: a name on its way out still works, and says so once,\n * in development only (`process.env.NODE_ENV !== \"production\"`, which Vite\n * and every bundler set). A production build stays silent.\n */\n\ndeclare const process: { env: { NODE_ENV?: string } }\n\nfunction isDevelopment(): boolean {\n try {\n return process.env.NODE_ENV !== \"production\"\n } catch {\n // No bundler and no `process` (a page loading the SDK as a plain module): stay silent.\n return false\n }\n}\n\nconst warned = new Set<string>()\n\n/** Warns once per `name` that it is deprecated, and what to use instead. */\nexport function warnDeprecated(name: string, instead: string): void {\n if (warned.has(name) || !isDevelopment()) return\n warned.add(name)\n console.warn(`[grist-widget-sdk] ${name} is deprecated and goes in 1.0: ${instead}. https://gristwidgets.com/docs/sdk/api/deprecated`)\n}\n\n/** @internal Tests: warn again. */\nexport function resetDeprecationWarnings(): void {\n warned.clear()\n}\n\n/** `fn`, warning once (as `name`) when it is first called. */\nexport function deprecatedFunction<F extends (...args: never[]) => unknown>(name: string, instead: string, fn: F): F {\n return ((...args: Parameters<F>) => {\n warnDeprecated(name, instead)\n return fn(...args)\n }) as F\n}\n","/**\n * Encoding helpers for Grist cell values.\n *\n * Grist sends some types as marshalled tuples or numeric epochs. This file\n * exposes pure decode/encode functions so widget code never has to spelunk\n * Grist's wire format.\n *\n * References: Grist `grist/RowRecord` and `grist/DocActions` typings.\n */\n\nimport type { GristReplicaColumn } from \"../types\"\n\n/** `[\"E\", \"ErrorClass\", \"message\", traceback?]` — Grist error sentinel. */\nexport type GristEncodedError = [\"E\", string, string?, string?]\n/** `[\"L\", ...items]` — list (used for ChoiceList, RefList, Attachments). */\nexport type GristEncodedList = [\"L\", ...unknown[]]\n/** `[\"D\", epochSeconds, \"tz/Name\"]` — DateTime with timezone. */\nexport type GristEncodedDateTime = [\"D\", number, string]\n/** `[\"d\", epochSeconds]` — Date (no time). */\nexport type GristEncodedDate = [\"d\", number]\n/** `[\"R\", tableId, rowId]` — explicit reference. */\nexport type GristEncodedRef = [\"R\", string, number]\n/** `[\"r\", rowId]` — bare reference (when table is contextual). */\nexport type GristEncodedBareRef = [\"r\", number]\n/** `[\"P\", encoded]` — pending marker. */\nexport type GristEncodedPending = [\"P\"]\n\nexport type GristDecodedValue =\n | null\n | string\n | number\n | boolean\n | Date\n | GristDecodedValue[]\n | { __error: true; type: string; message?: string; traceback?: string }\n | { __ref: true; tableId?: string; rowId: number }\n\nconst MARSHALLED_TAGS = new Set([\"E\", \"L\", \"D\", \"d\", \"R\", \"r\", \"P\"])\n\nfunction isMarshalledTuple(value: unknown): value is unknown[] {\n return (\n Array.isArray(value) &&\n typeof value[0] === \"string\" &&\n value[0].length <= 2 &&\n MARSHALLED_TAGS.has(value[0])\n )\n}\n\n/**\n * Normalises a Grist `fetchTable` cell that points at a row in another table.\n * Most payloads use a bare numeric row id, but `Ref:*` values may appear as\n * `[\"R\", tableId, rowId]` or `[\"r\", rowId]` (same shape as {@link decodeGristValue}).\n */\nexport function coerceGristDocApiRefRowId(value: unknown): number | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) return value\n if (!Array.isArray(value) || value.length < 2) return undefined\n const tag = value[0]\n if (tag === \"R\" && typeof value[2] === \"number\" && Number.isFinite(value[2])) return value[2]\n if (tag === \"r\" && typeof value[1] === \"number\" && Number.isFinite(value[1])) return value[1]\n return undefined\n}\n\nfunction looksLikeAttachmentColumn(column?: GristReplicaColumn): boolean {\n return column?.type === \"Attachments\"\n}\n\nfunction looksLikeChoiceListColumn(column?: GristReplicaColumn): boolean {\n return column?.type === \"ChoiceList\"\n}\n\nfunction looksLikeRefListColumn(column?: GristReplicaColumn): boolean {\n return typeof column?.type === \"string\" && column.type.startsWith(\"RefList:\")\n}\n\nfunction looksLikeRefColumn(column?: GristReplicaColumn): boolean {\n return typeof column?.type === \"string\" && column.type.startsWith(\"Ref:\")\n}\n\nfunction looksLikeDateColumn(column?: GristReplicaColumn): boolean {\n return column?.type === \"Date\"\n}\n\nfunction looksLikeDateTimeColumn(column?: GristReplicaColumn): boolean {\n return typeof column?.type === \"string\" && column.type.startsWith(\"DateTime\")\n}\n\n/**\n * Decodes a Grist cell value into an idiomatic JS value.\n *\n * Pass the column's metadata (from `useGristSchema` or `_grist_Tables_column`)\n * for type-aware decoding (e.g. `Date` columns return `Date` even when stored as a number).\n */\nexport function decodeGristValue(value: unknown, column?: GristReplicaColumn): GristDecodedValue {\n if (value === null || value === undefined) return null\n\n if (isMarshalledTuple(value)) {\n const tag = value[0] as string\n switch (tag) {\n case \"E\":\n return {\n __error: true,\n type: typeof value[1] === \"string\" ? value[1] : \"Error\",\n message: typeof value[2] === \"string\" ? value[2] : undefined,\n traceback: typeof value[3] === \"string\" ? value[3] : undefined,\n }\n case \"L\":\n return value.slice(1).map((v) => decodeGristValue(v, undefined)) as GristDecodedValue[]\n case \"D\":\n if (typeof value[1] === \"number\") return new Date(value[1] * 1000)\n return null\n case \"d\":\n if (typeof value[1] === \"number\") return new Date(value[1] * 1000)\n return null\n case \"R\":\n return {\n __ref: true,\n tableId: typeof value[1] === \"string\" ? value[1] : undefined,\n rowId: typeof value[2] === \"number\" ? value[2] : 0,\n }\n case \"r\":\n return { __ref: true, rowId: typeof value[1] === \"number\" ? value[1] : 0 }\n case \"P\":\n return null\n default:\n return null\n }\n }\n\n if (looksLikeDateColumn(column) || looksLikeDateTimeColumn(column)) {\n if (typeof value === \"number\" && Number.isFinite(value)) return new Date(value * 1000)\n }\n\n if (looksLikeRefColumn(column) && typeof value === \"number\") {\n return { __ref: true, rowId: value }\n }\n\n if ((looksLikeRefListColumn(column) || looksLikeChoiceListColumn(column) || looksLikeAttachmentColumn(column)) && Array.isArray(value)) {\n return value.map((v) => decodeGristValue(v, undefined)) as GristDecodedValue[]\n }\n\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") return value\n if (Array.isArray(value)) return value.map((v) => decodeGristValue(v, undefined)) as GristDecodedValue[]\n return null\n}\n\n/** Convenience: true when the cell is a Grist error sentinel. */\nexport function isGristCellError(value: unknown): value is GristEncodedError {\n return Array.isArray(value) && value[0] === \"E\"\n}\n\n/**\n * Encodes a JS value into Grist's expected wire form for a given column type.\n *\n * Use before passing values to `applyUserActions` or `TableOperations.update`\n * for `Date`, `DateTime`, `Ref`, `RefList`, and `ChoiceList` columns.\n */\nexport function encodeGristValue(value: unknown, column?: GristReplicaColumn): unknown {\n if (value === null || value === undefined) return null\n\n if (looksLikeDateColumn(column) || looksLikeDateTimeColumn(column)) {\n if (value instanceof Date) return Math.floor(value.getTime() / 1000)\n if (typeof value === \"string\") {\n const parsed = Date.parse(value)\n if (!Number.isNaN(parsed)) return Math.floor(parsed / 1000)\n }\n if (typeof value === \"number\") return Math.floor(value)\n }\n\n if (looksLikeRefColumn(column)) {\n if (typeof value === \"number\") return value\n if (value && typeof value === \"object\" && \"rowId\" in value) {\n return (value as { rowId: number }).rowId\n }\n }\n\n if (looksLikeRefListColumn(column) || looksLikeChoiceListColumn(column) || looksLikeAttachmentColumn(column)) {\n if (Array.isArray(value)) {\n const items = value.map((v) => {\n if (v && typeof v === \"object\" && \"rowId\" in v) return (v as { rowId: number }).rowId\n return v\n })\n return [\"L\", ...items]\n }\n }\n\n return value\n}\n","import type { GristDocApi, GristReplicaColumn, GristRowRecord } from \"../types\"\nimport { decodeGristValue } from \"./grist-value-codec\"\n\n/** Column-oriented table payload (`fetchTable`, `fetchSelectedTable`): `{ id: [...], Name: [...] }`. */\nexport type GristColumnarTable = Record<string, unknown[]>\nexport type GristTableRowsOrder = \"none\" | \"id\" | \"grist\"\nexport type FetchGristTableRowsOptions = {\n /** Column metadata, to decode each cell (except `id`) with `decodeGristValue`. */\n columns?: Record<string, GristReplicaColumn>\n /**\n * Row order:\n * - `grist` (default): `manualSort` ascending when present, then `id`.\n * - `id`: numeric `id` ascending.\n * - `none`: as `fetchTable` returned them.\n */\n order?: GristTableRowsOrder\n}\n\n/** Row count from columnar `fetchTable` data (prefers `id` column length). */\nexport function computeRowCount(data: Record<string, unknown[]>): number {\n const idCol = data.id\n if (Array.isArray(idCol)) return idCol.length\n for (const key of Object.keys(data)) {\n const col = data[key]\n if (Array.isArray(col)) return col.length\n }\n return 0\n}\n\n/**\n * Decode columnar `fetchTable` into replica row objects (`{ id, ...cells }`, one per row).\n */\nexport function decodeColumnarToReplicaRows(\n data: GristColumnarTable,\n columnIds: string[],\n columns: Record<string, GristReplicaColumn>,\n maxRows?: number\n): GristRowRecord[] {\n const nFull = computeRowCount(data)\n const n = maxRows !== undefined ? Math.min(nFull, maxRows) : nFull\n const out: GristRowRecord[] = []\n for (let i = 0; i < n; i++) {\n const row: Record<string, unknown> = {}\n for (const k of columnIds) {\n const arr = data[k]\n const raw = Array.isArray(arr) ? arr[i] : undefined\n if (k === \"id\") {\n row[k] = raw\n } else {\n row[k] = decodeGristValue(raw, columns[k]) as unknown\n }\n }\n out.push(row as GristRowRecord)\n }\n return out\n}\n\n/** Turn `fetchTable` output into row objects (order follows the `id` column). */\nexport function tableDataToRows<T = Record<string, unknown>>(\n data: GristColumnarTable\n): GristRowRecord<T>[] {\n const idCol = data.id\n if (!Array.isArray(idCol) || idCol.length === 0) return []\n const keys = Object.keys(data)\n const n = idCol.length\n const rows: GristRowRecord<T>[] = []\n for (let i = 0; i < n; i++) {\n const row: Record<string, unknown> = {}\n for (const k of keys) {\n const col = data[k]\n row[k] = Array.isArray(col) ? col[i] : undefined\n }\n rows.push(row as GristRowRecord<T>)\n }\n return rows\n}\n\nfunction manualSortKey(row: Record<string, unknown>): number | null {\n const v = row.manualSort\n if (typeof v === \"number\" && !Number.isNaN(v)) return v\n if (typeof v === \"string\" && v.trim() !== \"\") {\n const n = Number(v)\n if (!Number.isNaN(n)) return n\n }\n return null\n}\n\n/**\n * Sort rows by Grist's display order: `manualSort` ascending when present on\n * any row, otherwise numeric `id` ascending.\n */\nexport function sortRowsByGristOrder<T = Record<string, unknown>>(\n rows: readonly GristRowRecord<T>[]\n): GristRowRecord<T>[] {\n const hasManual = rows.some((r) => manualSortKey(r as Record<string, unknown>) !== null)\n if (!hasManual) {\n return [...rows].sort((a, b) => {\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n })\n }\n return [...rows].sort((a, b) => {\n const ma = manualSortKey(a as Record<string, unknown>)\n const mb = manualSortKey(b as Record<string, unknown>)\n if (ma !== null && mb !== null && ma !== mb) return ma - mb\n if (ma !== null && mb === null) return -1\n if (ma === null && mb !== null) return 1\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n })\n}\n\n/**\n * Same row materialization as {@link fetchGristTableRows} after `fetchTable`\n * returns columnar data. Hosts that already have columnar data (e.g. the\n * emulator building from in-memory rows) can use this and skip `docApi.fetchTable`.\n */\nexport function materializeGristRowsFromColumnar<T extends Record<string, unknown> = Record<string, unknown>>(\n data: GristColumnarTable,\n options?: FetchGristTableRowsOptions\n): GristRowRecord<T>[] {\n const order = options?.order ?? \"grist\"\n let rows: GristRowRecord<T>[]\n if (options?.columns) {\n const columnIds = Object.keys(data)\n rows = decodeColumnarToReplicaRows(data, columnIds, options.columns) as GristRowRecord<T>[]\n } else {\n rows = tableDataToRows<T>(data)\n }\n\n if (order === \"none\") return rows\n if (order === \"id\") {\n return [...rows].sort((a, b) => {\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n })\n }\n return sortRowsByGristOrder(rows)\n}\n\n/**\n * Fetch a table and return rows as objects, optionally decoded from schema and sorted.\n */\nexport async function fetchGristTableRows<T extends Record<string, unknown> = Record<string, unknown>>(\n docApi: GristDocApi,\n tableId: string,\n options?: FetchGristTableRowsOptions\n): Promise<GristRowRecord<T>[]> {\n const data = (await docApi.fetchTable(tableId)) as GristColumnarTable\n return materializeGristRowsFromColumnar<T>(data, options)\n}\n","/**\n * Grist stores column widget configuration in `_grist_Tables_column.widgetOptions`\n * as a JSON string. Choice fields use `choices: string[]` plus optional\n * `choiceOptions: Record<string, Style>` (e.g. `fillColor`, `textColor`).\n *\n * @see https://github.com/gristlabs/grist-core/blob/main/app/client/widgets/ChoiceEditor.js\n */\n\n/** One selectable choice for UI (value stored in the cell is `value`). */\nexport type GristChoiceListEntry = {\n value: string\n label: string\n fillColor?: string\n textColor?: string\n}\n\n/**\n * Parse a cell value from `_grist_Tables_column.widgetOptions` into a plain object.\n */\nexport function parseGristWidgetOptionsCell(raw: unknown): Record<string, unknown> | undefined {\n if (raw == null || raw === \"\") return undefined\n if (typeof raw === \"string\") {\n try {\n const parsed: unknown = JSON.parse(raw)\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>\n }\n } catch {\n return undefined\n }\n return undefined\n }\n if (typeof raw === \"object\" && !Array.isArray(raw)) {\n return raw as Record<string, unknown>\n }\n return undefined\n}\n\nfunction readStyleColor(style: Record<string, unknown>, key: string): string | undefined {\n const v = style[key]\n return typeof v === \"string\" ? v : undefined\n}\n\n/**\n * Normalizes Grist Choice / ChoiceList widgetOptions into a flat list for dropdowns.\n * `choices` entries are string labels (the stored cell value). Per-choice styling\n * lives in `choiceOptions[label]`.\n */\nexport function normalizeGristChoiceListEntries(\n widgetOptions: Record<string, unknown> | undefined\n): GristChoiceListEntry[] {\n if (!widgetOptions) return []\n const rawChoices = widgetOptions.choices\n if (!Array.isArray(rawChoices)) return []\n\n const choiceOptionsRaw = widgetOptions.choiceOptions\n const choiceOptions: Record<string, Record<string, unknown>> =\n choiceOptionsRaw &&\n typeof choiceOptionsRaw === \"object\" &&\n !Array.isArray(choiceOptionsRaw)\n ? (choiceOptionsRaw as Record<string, Record<string, unknown>>)\n : {}\n\n const out: GristChoiceListEntry[] = []\n for (const c of rawChoices) {\n const value = typeof c === \"string\" ? c : c != null ? String(c) : \"\"\n if (!value) continue\n const style = choiceOptions[value] ?? {}\n out.push({\n value,\n label: value,\n fillColor: readStyleColor(style, \"fillColor\"),\n textColor: readStyleColor(style, \"textColor\"),\n })\n }\n return out\n}\n","import type {\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","export type GristColumnLike = {\n formula?: string\n}\n\nexport type GristNoiseColumnsOptions = {\n excludeId?: boolean\n excludeGristHelpers?: boolean\n excludeLoggingColumns?: boolean\n /**\n * When `true`, treat Grist's `manualSort` column as noise (omit from filtered replicas).\n * Default `false` — `manualSort` is kept unless you opt in.\n */\n excludeManualSort?: boolean\n}\n\nconst NOISE_COLUMN_FORMULAS = new Set([\"now()\"])\n\nfunction normalizeFormulaForComparison(formula: string): string {\n return formula.trim().toLowerCase().replace(/\\s+/g, \"\")\n}\n\n/**\n * Grist-centric \"technical column\" detection used by document hooks and widgets.\n *\n * - `id` (when {@link GristNoiseColumnsOptions.excludeId} is true — default)\n * - `manualSort` (only when {@link GristNoiseColumnsOptions.excludeManualSort} is true)\n * - `gristHelper_*` (when `excludeGristHelpers` is true — default)\n * - trigger/logging formulas (`NOW()`, `user.*`) (when `excludeLoggingColumns` is true — default)\n */\nexport function isGristNoiseColumn(\n colId: string,\n col?: GristColumnLike,\n options?: GristNoiseColumnsOptions\n): boolean {\n const excludeId = options?.excludeId ?? true\n const excludeGristHelpers = options?.excludeGristHelpers ?? true\n const excludeLoggingColumns = options?.excludeLoggingColumns ?? true\n const excludeManualSort = options?.excludeManualSort ?? false\n\n if (excludeId && colId === \"id\") return true\n if (excludeManualSort && colId === \"manualSort\") return true\n if (excludeGristHelpers && colId.startsWith(\"gristHelper_\")) return true\n\n if (excludeLoggingColumns) {\n const formula = typeof col?.formula === \"string\" ? normalizeFormulaForComparison(col.formula) : \"\"\n if (formula && NOISE_COLUMN_FORMULAS.has(formula)) return true\n if (formula.startsWith(\"user.\")) return true\n }\n\n return false\n}\n","import type { GristDocApi } from \"../types\"\n\nexport type GristFetchedAttachment = {\n base64: string\n contentType: string\n}\n\nexport type GristFetchedAttachmentBlob = {\n blob: Blob\n contentType: string\n}\n\nfunction attachmentIdFromObjectRecord(record: Record<string, unknown>): string | undefined {\n for (const candidate of [record.id, record.attachmentId, record.fileId]) {\n if (candidate === undefined || candidate === null) continue\n return String(candidate)\n }\n return undefined\n}\n\n/**\n * All attachment ids found in a Grist attachment cell value (ordered, deduped).\n * Attachment columns are usually an **array** of file refs; a single id or one JSON object is also supported.\n */\nexport function extractGristAttachmentIdsFromCell(value: unknown): string[] {\n const out: string[] = []\n const seen = new Set<string>()\n const push = (id: string) => {\n if (seen.has(id)) return\n seen.add(id)\n out.push(id)\n }\n\n const walk = (v: unknown): void => {\n if (v === undefined || v === null) return\n if (typeof v === \"number\") {\n push(String(v))\n return\n }\n if (typeof v === \"string\") {\n const trimmed = v.trim()\n if (!trimmed) return\n if (/^\\d+$/.test(trimmed)) {\n push(trimmed)\n return\n }\n try {\n walk(JSON.parse(trimmed) as unknown)\n } catch {\n /* ignore */\n }\n return\n }\n if (Array.isArray(v)) {\n for (const item of v) walk(item)\n return\n }\n if (typeof v === \"object\") {\n const record = v as Record<string, unknown>\n const direct = attachmentIdFromObjectRecord(record)\n if (direct !== undefined) {\n push(direct)\n return\n }\n for (const nested of Object.values(record)) walk(nested)\n }\n }\n\n walk(value)\n return out\n}\n\n/** First attachment id in the cell, if any (see {@link extractGristAttachmentIdsFromCell}). */\nexport function extractGristAttachmentId(value: unknown): string | undefined {\n return extractGristAttachmentIdsFromCell(value)[0]\n}\n\n/**\n * Signed Grist download URL for a single attachment id (`getAccessToken` + query auth).\n */\nexport async function getAttachmentDownloadUrl(\n docApi: GristDocApi,\n attachmentId: string,\n options?: { readOnly?: boolean }\n): Promise<string> {\n const getAccessToken = docApi.getAccessToken\n if (!getAccessToken) {\n throw new Error(\"getAccessToken is not available on docApi\")\n }\n const { token, baseUrl } = await getAccessToken({ readOnly: options?.readOnly ?? false })\n return `${baseUrl}/attachments/${attachmentId}/download?auth=${token}`\n}\n\n/** URL for the `index`’th attachment in a cell value (0-based). */\nexport async function getAttachmentDownloadUrlForCell(\n docApi: GristDocApi,\n cellValue: unknown,\n index: number,\n options?: { readOnly?: boolean }\n): Promise<string | null> {\n const ids = extractGristAttachmentIdsFromCell(cellValue)\n const id = ids[index]\n if (!id) return null\n return getAttachmentDownloadUrl(docApi, id, options)\n}\n\nasync function fetchBytesFromSignedAttachmentUrl(url: string): Promise<{\n buffer: ArrayBuffer\n contentType: string\n}> {\n const response = await fetch(url)\n const contentType = response.headers.get(\"content-type\")?.trim() || \"application/octet-stream\"\n if (!response.ok) {\n throw new Error(`Attachment download failed (${response.status})`)\n }\n const buffer = await response.arrayBuffer()\n return { buffer, contentType }\n}\n\nfunction bufferToBase64(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer)\n let binary = \"\"\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i])\n return btoa(binary)\n}\n\n/** Token + URL + fetch for one attachment id. */\nexport async function fetchAttachmentBase64(\n docApi: GristDocApi,\n attachmentId: string,\n options?: { readOnly?: boolean }\n): Promise<GristFetchedAttachment> {\n const url = await getAttachmentDownloadUrl(docApi, attachmentId, options)\n const { buffer, contentType } = await fetchBytesFromSignedAttachmentUrl(url)\n return { base64: bufferToBase64(buffer), contentType }\n}\n\n/** Download attachment bytes as a `Blob` (preferred for large files). */\nexport async function fetchAttachmentBlob(\n docApi: GristDocApi,\n attachmentId: string,\n options?: { readOnly?: boolean }\n): Promise<GristFetchedAttachmentBlob> {\n const url = await getAttachmentDownloadUrl(docApi, attachmentId, options)\n const { buffer, contentType } = await fetchBytesFromSignedAttachmentUrl(url)\n return { blob: new Blob([buffer], { type: contentType }), contentType }\n}\n\n/** Download the `index`’th attachment in a cell (0-based). */\nexport async function fetchAttachmentBase64ForCell(\n docApi: GristDocApi,\n cellValue: unknown,\n index: number,\n options?: { readOnly?: boolean }\n): Promise<GristFetchedAttachment | null> {\n const url = await getAttachmentDownloadUrlForCell(docApi, cellValue, index, options)\n if (!url) return null\n const { buffer, contentType } = await fetchBytesFromSignedAttachmentUrl(url)\n return { base64: bufferToBase64(buffer), contentType }\n}\n","import type { GristDocApi } from \"../types\"\n\nexport type GristAccessToken = {\n token: string\n baseUrl: string\n}\n\ntype TokenCacheEntry = {\n token: GristAccessToken\n fetchedAt: number\n}\n\nconst TOKEN_TTL_MS = 45_000\nconst cache = new Map<string, TokenCacheEntry>()\nconst inFlight = new Map<string, Promise<GristAccessToken>>()\n\nfunction cacheKey(readOnly: boolean): string {\n return readOnly ? \"ro\" : \"rw\"\n}\n\n/**\n * Returns an access token suitable for calling Grist's REST API directly.\n * Tokens are short-lived; results are cached briefly and coalesced per readOnly flag.\n */\nexport async function getGristAccessToken(\n docApi: GristDocApi,\n options?: { readOnly?: boolean }\n): Promise<GristAccessToken> {\n if (!docApi.getAccessToken) {\n throw new Error(\"getAccessToken is not available on docApi (need higher access level)\")\n }\n\n const readOnly = options?.readOnly ?? false\n const key = cacheKey(readOnly)\n const now = Date.now()\n const hit = cache.get(key)\n if (hit && now - hit.fetchedAt < TOKEN_TTL_MS) {\n return hit.token\n }\n\n const pending = inFlight.get(key)\n if (pending) return pending\n\n const next = docApi.getAccessToken({ readOnly }).then((token) => {\n cache.set(key, { token, fetchedAt: Date.now() })\n inFlight.delete(key)\n return token\n })\n\n inFlight.set(key, next)\n return next\n}\n\n/** Clear cached tokens (tests or after auth errors). */\nexport function clearGristAccessTokenCache(): void {\n cache.clear()\n inFlight.clear()\n}\n\n/**\n * `fetch()` against Grist's REST API with the doc access token attached.\n */\nexport async function fetchWithGristAuth(\n docApi: GristDocApi,\n path: string,\n init?: RequestInit & { readOnly?: boolean }\n): Promise<Response> {\n const readOnly = init?.readOnly ?? false\n let token: GristAccessToken\n try {\n token = await getGristAccessToken(docApi, { readOnly })\n } catch (err) {\n clearGristAccessTokenCache()\n throw err\n }\n\n const isAbsolute = /^https?:\\/\\//i.test(path)\n const cleanPath = isAbsolute ? path : path.startsWith(\"/\") ? path : `/${path}`\n\n const url = isAbsolute\n ? new URL(path)\n : new URL(`${token.baseUrl.replace(/\\/$/, \"\")}${cleanPath}`)\n\n // The token goes into the URL, so it may only go to the Grist instance that\n // issued it. An absolute URL to any other origin (one read from a cell, say)\n // would hand the document's access token to that host.\n const gristOrigin = new URL(token.baseUrl).origin\n if (url.origin !== gristOrigin) {\n throw new Error(\n `fetchWithGristAuth: refusing to send the Grist access token to ${url.origin}; ` +\n `absolute URLs must point at this document's Grist instance (${gristOrigin}). ` +\n `Use plain fetch() for other hosts.`\n )\n }\n\n // Grist signs widget REST calls with a short-lived `auth` query parameter.\n // Do not send `Authorization: Bearer` from the browser: many Grist deployments\n // omit it from Access-Control-Allow-Headers, which breaks POST (e.g. attachment upload).\n if (!url.searchParams.has(\"auth\")) url.searchParams.set(\"auth\", token.token)\n\n const headers = new Headers(init?.headers ?? {})\n headers.delete(\"Authorization\")\n\n const response = await fetch(url.toString(), { ...init, headers })\n if (response.status === 401) {\n clearGristAccessTokenCache()\n const retryToken = await getGristAccessToken(docApi, { readOnly })\n url.searchParams.set(\"auth\", retryToken.token)\n return fetch(url.toString(), { ...init, headers })\n }\n return response\n}\n","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 { cause: err }\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","/**\n * `useGrist()`'s methods, created once per runtime: every one is\n * referentially stable for the widget's lifetime, and reads `grist` when\n * called (the emulator installs and removes it in tests).\n */\n\nimport { loadColumnMetadataByTable } from \"../helpers/build-replica-document\"\nimport { isGristNoiseColumn, type GristNoiseColumnsOptions } from \"../helpers/grist-columns-filters\"\nimport { fetchAttachmentBlob, getAttachmentDownloadUrl, type GristFetchedAttachmentBlob } from \"../helpers/grist-attachment-download\"\nimport { uploadGristAttachment, type GristAttachmentUploadResult } from \"../helpers/grist-attachment-upload\"\nimport { fetchWithGristAuth } from \"../helpers/grist-fetch-with-auth\"\nimport { deprecatedFunction } from \"../helpers/deprecate\"\nimport {\n fetchGristTableRows,\n materializeGristRowsFromColumnar,\n type FetchGristTableRowsOptions,\n type GristColumnarTable,\n} from \"../helpers/grist-table-data\"\nimport type { GristUserActionTuple } from \"../helpers/grist-user-actions\"\nimport type {\n GristApplyUserActionsOptions,\n GristCursorPos,\n GristDocApi,\n GristFetchSelectedOptions,\n GristRowRecord,\n GristTableOperations,\n} from \"../types\"\nimport type { GristRuntime } from \"./runtime\"\n\nexport type ListTablesOptions = {\n /** Include Grist's own tables (`_grist_*`, `GristHidden_*`). */\n includeSystem?: boolean\n}\n\nexport type ListColumnsOptions = GristNoiseColumnsOptions & {\n /** Include every column, Grist's helper and bookkeeping ones too. */\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\n/** `fetchRows()` options: rows (the default) or Grist's columns. */\nexport type FetchRowsOptions = FetchGristTableRowsOptions & {\n /** Grist's column-oriented payload (`{ id: [...], Name: [...] }`) instead of rows. */\n columnar?: boolean\n}\n\n/**\n * A table's rows, each `{ id, ...cells }` under real column ids. Without a\n * table id, the widget's own table as its section shows it (filters and\n * sort applied); with one, any table (full access), in Grist's row order.\n * `{ columnar: true }` gives Grist's columns instead.\n */\nexport type FetchRows = {\n <T extends Record<string, unknown> = Record<string, unknown>>(\n tableId?: string | null,\n options?: FetchRowsOptions & { columnar?: false }\n ): Promise<GristRowRecord<T>[]>\n <T extends Record<string, unknown> = Record<string, unknown>>(options: FetchRowsOptions & { columnar?: false }): Promise<\n GristRowRecord<T>[]\n >\n (tableId: string | null | undefined, options: FetchRowsOptions & { columnar: true }): Promise<GristColumnarTable>\n (options: FetchRowsOptions & { columnar: true }): Promise<GristColumnarTable>\n}\n\nexport type GristApi = {\n reload: () => Promise<void>\n fetchRows: FetchRows\n /** @deprecated Use `fetchRows({ columnar: true })` (or `fetchRows()` for rows). */\n fetchSelectedTable: (options?: GristFetchSelectedOptions) => Promise<GristColumnarTable>\n /** @deprecated Use `fetchRows(tableId, { columnar: true })` (or `fetchRows(tableId)` for rows). */\n fetchTable: (tableId: string) => Promise<GristColumnarTable>\n /** @deprecated Use `fetchRows(tableId, options)`. */\n fetchTableRows: <T extends Record<string, unknown> = Record<string, unknown>>(\n tableId: string,\n options?: FetchGristTableRowsOptions\n ) => Promise<GristRowRecord<T>[]>\n listTables: (options?: ListTablesOptions) => Promise<string[]>\n listColumns: (tableId: string, options?: ListColumnsOptions) => Promise<GristColumnInfo[]>\n table: GristTableOperations\n getTable: (tableId: string) => GristTableOperations\n applyActions: (actions: GristUserActionTuple[], options?: GristApplyUserActionsOptions) => Promise<unknown>\n setWidgetOptions: (options: Record<string, unknown>) => Promise<void>\n patchWidgetOptions: (patch: Record<string, unknown>) => Promise<void>\n setCursorPosition: (pos: GristCursorPos) => Promise<void>\n setLinkedRowSelection: (rowIds: number[] | null) => Promise<void>\n getAttachmentUrl: (attachmentId: string, options?: { readOnly?: boolean }) => Promise<string>\n fetchAttachmentBlob: (attachmentId: string, options?: { readOnly?: boolean }) => Promise<GristFetchedAttachmentBlob>\n uploadAttachment: (file: Blob | File, options?: { fileName?: string }) => Promise<GristAttachmentUploadResult>\n fetchWithAuth: (path: string, init?: RequestInit & { readOnly?: boolean }) => Promise<Response>\n}\n\nconst ACCESS_ERROR = [/access not granted/i, /need higher access level/i, /requires.*full.*access/i, /RPC_ONCALL_ERROR Access/i]\n\nexport function isAccessInsufficientError(message: string): boolean {\n return ACCESS_ERROR.some((re) => re.test(message))\n}\n\nconst message = (err: unknown) => (err instanceof Error ? err.message : String(err))\n\nexport function createGristApi(runtime: GristRuntime): GristApi {\n const docApi = (): GristDocApi => {\n if (runtime.getState().connection !== \"ready\" || typeof grist === \"undefined\" || !grist.docApi) {\n throw new Error(\"Grist is not ready: wait for useGrist().status === \\\"ready\\\".\")\n }\n return grist.docApi\n }\n\n /** A read: an access refusal is kept for the alerts, cleared by the next read that succeeds. */\n const read = async <T>(fn: () => Promise<T>): Promise<T> => {\n try {\n const out = await fn()\n if (runtime.getState().readError) runtime.update({ readError: null })\n return out\n } catch (err) {\n if (isAccessInsufficientError(message(err))) runtime.update({ readError: message(err) })\n throw err\n }\n }\n\n /**\n * A write: tracked in `actionStatus` / `actionError`. Overlapping writes\n * count as one run: `actionStatus` stays `\"running\"` until the last one\n * ends, then is `\"error\"` if any of them failed. A failure is shown in the\n * alerts and rejects the returned promise, which the SDK already handles:\n * a write nobody awaits (`onClick={() => w.table.update(...)}`) doesn't log\n * an unhandled rejection.\n */\n let running = 0\n let failure: string | null = null\n const write = <T>(fn: () => Promise<T>): Promise<T> => {\n if (running++ === 0) failure = null\n runtime.update({ actionStatus: \"running\", actionError: null })\n const done = (async () => {\n try {\n return await fn()\n } catch (err) {\n failure = message(err)\n throw err\n } finally {\n if (--running === 0) runtime.update(failure ? { actionStatus: \"error\", actionError: failure } : { actionStatus: \"idle\" })\n }\n })()\n done.catch(() => {})\n return done\n }\n\n const tableOps = (resolve: () => GristTableOperations): GristTableOperations => ({\n getTableId: () => resolve().getTableId(),\n create: ((records: never, opts?: never) => write(() => resolve().create(records, opts))) as GristTableOperations[\"create\"],\n update: (records, opts) => write(() => resolve().update(records, opts)),\n upsert: (records, opts) => write(() => resolve().upsert(records, opts)),\n destroy: (ids) => write(() => resolve().destroy(ids)),\n })\n const tables = new Map<string, GristTableOperations>()\n\n const selectedColumns = (options?: GristFetchSelectedOptions): Promise<GristColumnarTable> =>\n read(async () => {\n const impl = docApi().fetchSelectedTable ?? grist.fetchSelectedTable\n if (!impl) throw new Error(\"fetchSelectedTable is not available in this Grist version\")\n return (await impl({ keepEncoded: false, ...options })) as GristColumnarTable\n })\n const tableColumns = (tableId: string): Promise<GristColumnarTable> =>\n read(async () => (await docApi().fetchTable(tableId)) as GristColumnarTable)\n\n const fetchRows = (async (a?: string | null | FetchRowsOptions, b?: FetchRowsOptions) => {\n const tableId = typeof a === \"string\" ? a : null\n const { columnar, ...rowOptions } = (typeof a === \"object\" && a !== null ? a : b) ?? {}\n if (tableId === null) {\n // The section's rows: Grist decodes them unless `columns` asks for the SDK's decoding.\n const data = await selectedColumns(rowOptions.columns ? { keepEncoded: true } : undefined)\n return columnar ? data : materializeGristRowsFromColumnar(data, { order: \"none\", ...rowOptions })\n }\n if (columnar) return tableColumns(tableId)\n return read(() => fetchGristTableRows(docApi(), tableId, rowOptions))\n }) as FetchRows\n\n return {\n reload: () => runtime.reload(),\n\n fetchRows,\n fetchSelectedTable: deprecatedFunction(\"useGrist().fetchSelectedTable()\", \"use fetchRows({ columnar: true }), or fetchRows() for rows\", selectedColumns),\n fetchTable: deprecatedFunction(\"useGrist().fetchTable()\", \"use fetchRows(tableId, { columnar: true }), or fetchRows(tableId) for rows\", tableColumns),\n fetchTableRows: deprecatedFunction(\"useGrist().fetchTableRows()\", \"use fetchRows(tableId, options)\", (tableId: string, options?: FetchGristTableRowsOptions) =>\n read(() => fetchGristTableRows(docApi(), tableId, options ?? {}))\n ) as never,\n listTables: (options) =>\n read(async () => {\n const all = [...(await docApi().listTables())]\n return options?.includeSystem ? all : all.filter((t) => !t.startsWith(\"_grist\") && !t.startsWith(\"GristHidden_\"))\n }),\n listColumns: (tableId, options) =>\n read(async () => {\n const meta = (await loadColumnMetadataByTable(docApi())).get(tableId)\n if (!meta) return []\n const noise: GristNoiseColumnsOptions = {\n excludeId: options?.excludeId ?? true,\n excludeGristHelpers: options?.excludeGristHelpers ?? true,\n excludeLoggingColumns: options?.excludeLoggingColumns ?? true,\n excludeManualSort: options?.excludeManualSort ?? true,\n }\n return [...meta]\n .filter(([colId, m]) => options?.includeSystem || !isGristNoiseColumn(colId, m, noise))\n .map(([colId, m]) => ({ colId, type: m.type, label: m.label, isFormula: m.isFormula, formula: m.formula, description: m.description }))\n }),\n\n table: tableOps(() => {\n if (!grist.selectedTable) throw new Error(\"grist.selectedTable is not available in this Grist version\")\n return grist.selectedTable\n }),\n getTable: (tableId) => {\n let ops = tables.get(tableId)\n if (!ops) {\n tables.set(\n tableId,\n (ops = tableOps(() => {\n if (typeof grist.getTable !== \"function\") throw new Error(\"grist.getTable is not available in this Grist version\")\n return grist.getTable(tableId)\n }))\n )\n }\n return ops\n },\n applyActions: (actions, options) => write(() => docApi().applyUserActions(actions, options)),\n\n setWidgetOptions: async (options) => {\n await grist.setOptions(options)\n },\n patchWidgetOptions: async (patch) => {\n const current = ((await grist.getOptions()) as Record<string, unknown> | null) ?? {}\n await grist.setOptions({ ...current, ...patch })\n },\n\n setCursorPosition: async (pos) => {\n if (!grist.setCursorPos) throw new Error(\"setCursorPos is not available in this Grist version\")\n await grist.setCursorPos(pos)\n },\n setLinkedRowSelection: async (rowIds) => {\n if (!grist.setSelectedRows) throw new Error(\"setSelectedRows is not available in this Grist version\")\n await grist.setSelectedRows(rowIds)\n },\n\n getAttachmentUrl: (id, options) => read(() => getAttachmentDownloadUrl(docApi(), id, options)),\n fetchAttachmentBlob: (id, options) => read(() => fetchAttachmentBlob(docApi(), id, options)),\n uploadAttachment: (file, options) => write(() => uploadGristAttachment(docApi(), file, options)),\n fetchWithAuth: (path, init) => read(() => fetchWithGristAuth(docApi(), path, init)),\n }\n}\n","import type { GristColumnsToMap, GristColumnToMap, GristWidgetColumnMap } from \"../types\"\n\nexport type ValidateColumnMappingsResult = {\n ok: boolean\n /**\n * `true` while the host has not yet reported column mappings (e.g. between\n * `grist.ready()` resolving and the first `onRecord` / `onRecords` callback,\n * or before `sectionApi.mappings()` returns). Callers should not gate UI or\n * emit mapping alerts while pending.\n */\n pending?: boolean\n /** Logical names of required columns the user has not yet mapped. */\n missing: string[]\n /** Logical names of `allowMultiple` columns mapped to an empty list. */\n emptyMultiples: string[]\n}\n\n/**\n * Merges mapping payloads from `onRecord`, `onRecords`, and `sectionApi.mappings()`.\n * Later sources win; `undefined` sources are skipped; `null` means \"host reported\n * no mappings\" but still counts as a known (empty) payload.\n */\nexport function mergeWidgetColumnMaps(\n ...sources: (GristWidgetColumnMap | null | undefined)[]\n): GristWidgetColumnMap | null | undefined {\n let merged: GristWidgetColumnMap = {}\n let sawDefined = false\n for (const src of sources) {\n if (src === undefined) continue\n sawDefined = true\n if (src === null) continue\n merged = { ...merged, ...src }\n }\n if (!sawDefined) return undefined\n return merged\n}\n\nfunction asColumnSpec(entry: string | GristColumnToMap): GristColumnToMap {\n return typeof entry === \"string\" ? { name: entry } : entry\n}\n\n/**\n * Verifies that the current Grist mappings cover every required column declared\n * in `grist.ready({ columns })`.\n *\n * Use this before reading `mappedRecord` so you can render a \"please configure\n * the widget\" prompt instead of a confusing `null`.\n */\nexport function validateColumnMappings(\n spec: GristColumnsToMap | undefined | null,\n mappings: GristWidgetColumnMap | null | undefined\n): ValidateColumnMappingsResult {\n const missing: string[] = []\n const emptyMultiples: string[] = []\n if (!spec) return { ok: true, pending: false, missing, emptyMultiples }\n\n const m = mappings ?? {}\n for (const raw of spec) {\n const col = asColumnSpec(raw)\n if (col.optional) continue\n const value = m[col.name]\n if (col.allowMultiple) {\n if (value === undefined) {\n missing.push(col.name)\n } else if (!Array.isArray(value) || value.length === 0) {\n emptyMultiples.push(col.name)\n }\n } else {\n if (value === undefined || value === null || value === \"\") missing.push(col.name)\n }\n }\n return {\n ok: missing.length === 0 && emptyMultiples.length === 0,\n pending: false,\n missing,\n emptyMultiples,\n }\n}\n\n/** Status while waiting for the host to report mappings (see `pending`). */\nexport const pendingColumnMappingStatus: ValidateColumnMappingsResult = {\n ok: true,\n pending: true,\n missing: [],\n emptyMultiples: [],\n}\n","/**\n * Typed reads, with read-only access: each mapped cell checked against the\n * type its column declares in `GRIST_OPTIONS.columns`.\n *\n * Grist's mapping panel only offers the columns of the declared type, so for\n * a mapped column the declaration is the contract; and the plugin API's\n * decoded values already say what they are (a `Date`, a `Reference` with a\n * `rowId`, a list of ids, a `RaisedException` for a formula error, the raw\n * text of an invalid cell). Checked in Grist 1.7.22, every type, both\n * `cellFormat`s. So a cell is turned into the JS value its type promises, or\n * into `null` with an issue: no schema to fetch, no full access, no\n * dependency.\n */\n\nimport type { GristColumnsToMap, GristWidgetColumnMap } from \"../types\"\n\n/** A mapped cell that didn't match its declared type, or a rule of the widget's schema. */\nexport type GristCellIssue = {\n rowId: number\n /** The declared column name, or \"\" for a schema rule on the whole record. */\n column: string\n message: string\n /** The value Grist sent. */\n value: unknown\n}\n\ntype Check = { ok: true; value: unknown } | { ok: false; message: string }\n\nconst ok = (value: unknown): Check => ({ ok: true, value })\nconst bad = (message: string): Check => ({ ok: false, message })\n\n/** A formula error, as the plugin API decodes it (`RaisedException`) or encodes it (`[\"E\", name, …]`). */\nfunction formulaError(value: unknown): string | null {\n if (Array.isArray(value) && value[0] === \"E\") return String(value[1] ?? \"error\")\n if (value && typeof value === \"object\" && (value as { constructor?: { name?: string } }).constructor?.name === \"RaisedException\") {\n return String((value as { name?: unknown }).name ?? \"error\")\n }\n return null\n}\n\nfunction rowIdOf(value: unknown): number | null | undefined {\n if (typeof value === \"number\" && Number.isInteger(value)) return value === 0 ? null : value\n if (value && typeof value === \"object\" && typeof (value as { rowId?: unknown }).rowId === \"number\") {\n const id = (value as { rowId: number }).rowId\n return id === 0 ? null : id\n }\n if (Array.isArray(value) && value[0] === \"R\" && typeof value[2] === \"number\") return value[2] === 0 ? null : value[2]\n return undefined\n}\n\nfunction idsOf(value: unknown): number[] | undefined {\n if (value === null || value === undefined) return []\n const list = Array.isArray(value)\n ? value[0] === \"L\"\n ? value.slice(1)\n : value\n : value && typeof value === \"object\" && Array.isArray((value as { rowIds?: unknown }).rowIds)\n ? (value as { rowIds: unknown[] }).rowIds\n : undefined\n return list?.every((v) => typeof v === \"number\") ? (list as number[]) : undefined\n}\n\nfunction checkOne(base: string, value: unknown): Check {\n switch (base) {\n case \"Any\":\n return ok(value)\n case \"Text\":\n return value === null || typeof value === \"string\" ? ok(value ?? \"\") : bad(\"not text\")\n case \"Numeric\":\n return value === null || (typeof value === \"number\" && Number.isFinite(value)) ? ok(value) : bad(\"not a number\")\n case \"Int\":\n return value === null || (typeof value === \"number\" && Number.isInteger(value)) ? ok(value) : bad(\"not an integer\")\n case \"Bool\":\n return value === null || typeof value === \"boolean\" ? ok(value ?? false) : bad(\"not true or false\")\n case \"Date\":\n case \"DateTime\":\n if (value === null) return ok(null)\n if (value instanceof Date && !Number.isNaN(value.getTime())) return ok(value)\n // Seconds since the epoch: Grist's \"normal\" format, and the emulator's raw rows.\n if (typeof value === \"number\" && Number.isFinite(value)) return ok(new Date(value * 1000))\n return bad(\"not a date\")\n case \"Choice\":\n return value === null || typeof value === \"string\" ? ok(value) : bad(\"not a choice\")\n case \"ChoiceList\": {\n if (value === null || value === undefined) return ok([])\n const list = Array.isArray(value) ? (value[0] === \"L\" ? value.slice(1) : value) : undefined\n return list?.every((v) => typeof v === \"string\") ? ok(list) : bad(\"not a list of choices\")\n }\n case \"Ref\": {\n if (value === null) return ok(null)\n const id = rowIdOf(value)\n return id === undefined ? bad(\"not a reference\") : ok(id)\n }\n case \"RefList\":\n case \"Attachments\": {\n const ids = idsOf(value)\n return ids === undefined ? bad(base === \"RefList\" ? \"not a list of references\" : \"not a list of attachments\") : ok(ids)\n }\n default:\n return ok(value)\n }\n}\n\n/**\n * `value` as its declared `type` promises (\"Numeric\", \"Ref:Tasks\",\n * \"Text,Ref\"…): a match of any listed type, or a failure that says why.\n * Without a type (or \"Any\"), the value as it is.\n */\n/** The base types a declared type accepts: `\"Text,Ref:People\"` → `[\"Text\", \"Ref\"]`. */\nfunction basesOf(type: string | undefined): string[] {\n return (type ?? \"Any\")\n .split(\",\")\n .map((t) => t.trim().split(\":\")[0]!)\n .filter(Boolean)\n}\n\nexport function checkGristCell(type: string | undefined, value: unknown): Check {\n const error = formulaError(value)\n if (error) return bad(`formula error (${error})`)\n const bases = basesOf(type)\n if (bases.length === 0 || bases.includes(\"Any\")) return ok(value === undefined ? null : value)\n let first: Check | null = null\n for (const base of bases) {\n const check = checkOne(base, value)\n if (check.ok) return check\n first ??= check\n }\n return first!\n}\n\nconst LIST_BASES = [\"ChoiceList\", \"RefList\", \"Attachments\"]\n\n/**\n * A value as Grist stores it in a column of the declared `type`: the\n * reverse of what typed reads give. Lists become `[\"L\", ...]` (a RefList's\n * `Reference` items become their row ids), a `Date` for a Date or DateTime\n * column becomes seconds since the epoch, a `Reference` for a Ref column its\n * row id. A list already encoded (`[\"L\", ...]`, as the attachment helpers\n * return it) and every other value pass through, so it is safe to call twice.\n *\n * Grist's plugin API writes values as given: a bare array written to a\n * ChoiceList or RefList column is stored as an error cell. Checked in\n * Grist 1.7.22.\n */\nexport function encodeGristCell(type: string | undefined, value: unknown): unknown {\n if (value === null || value === undefined) return value\n const bases = basesOf(type)\n const accepts = (...names: string[]) => names.some((n) => bases.includes(n))\n if (value instanceof Date) return accepts(\"Date\", \"DateTime\") ? Math.floor(value.getTime() / 1000) : value\n if (Array.isArray(value)) {\n if (!accepts(...LIST_BASES) || value[0] === \"L\") return value\n return [\"L\", ...value.map((item) => rowIdOf(item) ?? item)]\n }\n if (accepts(\"Ref\") && typeof value === \"object\") return rowIdOf(value) ?? value\n return value\n}\n\nexport const nameOf = (c: GristColumnsToMap[number]) => (typeof c === \"string\" ? c : c.name)\nexport const typeOf = (c: GristColumnsToMap[number]) => (typeof c === \"string\" ? undefined : c.type)\nconst isOptional = (c: GristColumnsToMap[number]) => typeof c === \"object\" && c.optional === true\n\n/** Minimal Standard Schema (https://standardschema.dev): zod 4, valibot, arktype implement it. */\nexport type StandardSchema<T = unknown> = {\n readonly \"~standard\": {\n readonly version: 1\n readonly vendor: string\n readonly validate: (\n value: unknown\n ) =>\n | { readonly value: T; readonly issues?: undefined }\n | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray<PropertyKey | { key: PropertyKey }> }> }\n | Promise<unknown>\n }\n}\n\n/**\n * A record under the widget's declared names, each cell checked against its\n * column's declared type, then the record against `schema` if given. Returns\n * null (no issues) while a required column isn't mapped, like Grist's\n * `mapColumnNames`; the record itself without declared columns.\n */\nexport function mapAndCheck<T>(\n record: Record<string, unknown> | null,\n columns: GristColumnsToMap | undefined,\n mappings: GristWidgetColumnMap | null,\n schema?: StandardSchema\n): { value: T | null; issues: GristCellIssue[] } {\n if (!record) return { value: null, issues: [] }\n if (!columns?.length) return { value: record as T, issues: [] }\n if (mappings === null) return { value: null, issues: [] }\n const rowId = typeof record.id === \"number\" ? record.id : 0\n const out: Record<string, unknown> = { id: record.id }\n const issues: GristCellIssue[] = []\n for (const col of columns) {\n const name = nameOf(col)\n const real = mappings[name]\n const take = (raw: unknown) => {\n const check = checkGristCell(typeOf(col), raw)\n if (check.ok) return check.value\n issues.push({ rowId, column: name, message: check.message, value: raw })\n return null\n }\n if (Array.isArray(real) && real.length > 0) out[name] = real.map((r) => take(record[r]))\n else if (typeof real === \"string\" && real) out[name] = take(record[real])\n else if (!isOptional(col)) return { value: null, issues: [] }\n }\n if (schema) {\n const result = schema[\"~standard\"].validate(out)\n if (result instanceof Promise) {\n issues.push({ rowId, column: \"\", message: \"the schema validates asynchronously; useGrist() needs a synchronous one\", value: out })\n } else if (\"issues\" in result && result.issues) {\n for (const issue of result.issues) {\n const key = issue.path?.[0]\n const column = key === undefined ? \"\" : String(typeof key === \"object\" ? key.key : key)\n issues.push({ rowId, column, message: issue.message, value: column ? out[column] : out })\n }\n } else if (\"value\" in result) {\n return { value: result.value as T, issues }\n }\n }\n return { value: out as T, issues }\n}\n\n// ---------------------------------------------------------------------------\n// Types from a declaration\n// ---------------------------------------------------------------------------\n\ntype BaseOf<T extends string> = T extends `${infer B}:${string}` ? B : T\n\ntype CellOf<T extends string> = T extends `${infer A},${infer Rest}`\n ? CellOf<A> | CellOf<Rest>\n : BaseOf<T> extends \"Text\"\n ? string\n : BaseOf<T> extends \"Numeric\" | \"Int\"\n ? number | null\n : BaseOf<T> extends \"Bool\"\n ? boolean\n : BaseOf<T> extends \"Date\" | \"DateTime\"\n ? Date | null\n : BaseOf<T> extends \"Choice\"\n ? string | null\n : BaseOf<T> extends \"ChoiceList\"\n ? string[]\n : BaseOf<T> extends \"Ref\"\n ? number | null\n : BaseOf<T> extends \"RefList\" | \"Attachments\"\n ? number[]\n : unknown\n\n// Every checked cell is `| null`: a cell that doesn't match its declared type\n// is null in mappedRecord (and listed in cellIssues), whatever the type.\ntype ColumnValue<C> = C extends { type: infer T extends string; allowMultiple: true }\n ? (CellOf<T> | null)[]\n : C extends { type: infer T extends string }\n ? CellOf<T> | null\n : C extends { allowMultiple: true }\n ? unknown[]\n : unknown\n\ntype RequiredName<C> = C extends { optional: true } ? never : C extends string ? C : C extends { name: infer N extends string } ? N : never\ntype OptionalName<C> = C extends { optional: true; name: infer N extends string } ? N : never\ntype ByName<Cs, N> = Extract<Cs, N | { name: N }>\n\n/**\n * The mapped record a `GRIST_OPTIONS` declaration gives, for `useGrist`'s\n * second type argument. Declare the options with `as const satisfies\n * UseGristOptions` so the column names and types stay literal:\n *\n * ```ts\n * export const GRIST_OPTIONS = {\n * requiredAccess: \"read table\",\n * columns: [{ name: \"Title\", type: \"Text\" }, { name: \"Due\", type: \"Date\", optional: true }],\n * } as const satisfies UseGristOptions\n *\n * const w = useGrist<GristRowRecord, GristMappedRow<typeof GRIST_OPTIONS>>()\n * w.mappedRecord?.Due // Date | null | undefined\n * ```\n */\nexport type GristMappedRow<O extends { columns?: readonly unknown[] }> = O[\"columns\"] extends readonly (infer C)[]\n ? { id: number } & { [N in RequiredName<C>]: ColumnValue<ByName<C, N>> } & { [N in OptionalName<C>]?: ColumnValue<ByName<C, N>> }\n : Record<string, unknown>\n","/**\n * What `useGrist()` shows, derived from the runtime state: status, error,\n * column-mapping status, the mapped record, and the access check. Pure\n * functions, so they are tested without React or Grist.\n */\n\nimport { validateColumnMappings, type ValidateColumnMappingsResult } from \"../helpers/grist-mappings\"\nimport type { GristColumnsToMap, GristRequiredAccess, GristWidgetColumnMap } from \"../types\"\nimport { encodeGristCell, nameOf, typeOf } from \"./cells\"\nimport type { GristRuntimeState } from \"./runtime\"\n\n/** The widget's connection to Grist, as `useGrist().status` reports it. */\nexport type GristWidgetStatus = \"booting\" | \"ready\" | \"unavailable\" | \"error\"\n\nexport const ACCESS_RANK: Record<GristRequiredAccess, number> = { none: 0, \"read table\": 1, full: 2 }\n\nexport function parseAccess(raw: unknown): GristRequiredAccess | null {\n return raw === \"none\" || raw === \"read table\" || raw === \"full\" ? raw : null\n}\n\nexport function accessLabel(level: GristRequiredAccess): string {\n return level === \"full\" ? \"Full document access\" : level === \"read table\" ? \"Read selected table\" : \"No document access\"\n}\n\n/** Grist granted less than the widget declared (Grist reports it with the widget options). */\nexport function accessDenied(state: GristRuntimeState): boolean {\n return state.grantedAccess !== null && ACCESS_RANK[state.grantedAccess] < ACCESS_RANK[state.declaredAccess]\n}\n\nexport function deriveStatus(state: GristRuntimeState): GristWidgetStatus {\n switch (state.connection) {\n case \"connecting\":\n return \"booting\"\n case \"not-embedded\":\n case \"unavailable\":\n return \"unavailable\"\n case \"error\":\n return \"error\"\n case \"ready\":\n return accessDenied(state) ? \"error\" : \"ready\"\n }\n}\n\nexport function deriveError(state: GristRuntimeState): string | null {\n if (state.connection === \"not-embedded\") return \"This page is not embedded in a Grist document.\"\n if (state.connection === \"unavailable\") return \"The Grist plugin API (grist-plugin-api.js) did not load.\"\n if (state.connection === \"error\") return state.connectionError\n if (state.connection === \"ready\" && accessDenied(state)) {\n return `Grist granted \"${accessLabel(state.grantedAccess!)}\"; this widget needs \"${accessLabel(state.declaredAccess)}\". Set the access level in the Custom widget settings.`\n }\n return null\n}\n\nconst MAPPINGS_OK: ValidateColumnMappingsResult = Object.freeze({ ok: true, pending: false, missing: [], emptyMultiples: [] }) as ValidateColumnMappingsResult\nconst MAPPINGS_PENDING: ValidateColumnMappingsResult = Object.freeze({ ok: true, pending: true, missing: [], emptyMultiples: [] }) as ValidateColumnMappingsResult\n\n/** Whether the declared columns are mapped: pending until Grist reports mappings. */\nexport function deriveColumnMappingStatus(\n columns: GristColumnsToMap | undefined,\n mappings: GristWidgetColumnMap | null\n): ValidateColumnMappingsResult {\n if (!columns?.length) return MAPPINGS_OK\n if (mappings === null) return MAPPINGS_PENDING\n return validateColumnMappings(columns, mappings)\n}\n\n/**\n * A logical-name patch as real column ids, for a write, each value encoded\n * for its declared type (`encodeGristCell`: lists, dates, references), so\n * what `mappedRecord` gave can be written back as is. A column mapped to\n * several Grist columns (`allowMultiple`) can't be written back and is\n * reported in `skipped`; a name with no mapping passes through unchanged.\n */\nexport function mapBackPatch(\n patch: Record<string, unknown>,\n mappings: GristWidgetColumnMap,\n columns?: GristColumnsToMap\n): { fields: Record<string, unknown>; skipped: string[] } {\n const fields: Record<string, unknown> = {}\n const skipped: string[] = []\n for (const [name, value] of Object.entries(patch)) {\n if (value === undefined) continue\n const real = mappings[name]\n if (Array.isArray(real)) {\n skipped.push(name)\n continue\n }\n const declared = columns?.find((c) => nameOf(c) === name)\n fields[typeof real === \"string\" && real ? real : name] = declared ? encodeGristCell(typeOf(declared), value) : value\n }\n return { fields, skipped }\n}\n","import type { GristWidgetInteraction, GristWidgetLinkingInfo } from \"../types\"\n\n/**\n * Parse `InteractionOptions.linking` from a Grist `onOptions` settings payload.\n */\nexport function parseGristWidgetLinkingInfo(raw: unknown): GristWidgetLinkingInfo | undefined {\n if (!raw || typeof raw !== \"object\" || !(\"asTarget\" in raw)) return undefined\n const linking = raw as { asTarget: unknown; asSource?: unknown }\n return {\n asTarget: linking.asTarget == null ? null : String(linking.asTarget),\n asSource: Boolean(linking.asSource),\n }\n}\n\n/**\n * Normalize the second argument to `grist.onOptions` (Grist `InteractionOptions`).\n * Hosts use `accessLevel` (camelCase); the emulator uses `access_level`.\n */\nexport function normalizeWidgetInteraction(\n interaction: GristWidgetInteraction | null\n): GristWidgetInteraction | null {\n if (!interaction || typeof interaction !== \"object\") return interaction\n const raw = interaction as Record<string, unknown>\n const access_level =\n typeof raw.access_level === \"string\"\n ? raw.access_level\n : typeof raw.accessLevel === \"string\"\n ? raw.accessLevel\n : undefined\n const linking = parseGristWidgetLinkingInfo(raw.linking)\n return {\n ...interaction,\n ...(access_level ? { access_level } : {}),\n ...(linking ? { linking } : {}),\n }\n}\n","/**\n * Grist's event streams, bound once per page.\n *\n * `grist.onRecord`, `onRecords`, `onOptions`, `onNewRecord` and `on(\"message\")`\n * are add-only: there is no `off`. Binding them in every provider (React's\n * StrictMode mounts twice; a widget may remount) would stack handlers for the\n * page's lifetime. Each stream here binds at its first subscriber and fans out\n * to the current ones; a late subscriber gets the last value at once.\n *\n * Records are bound with the plugin API's decoded rows (`keepEncoded: false`,\n * rows for `onRecords`), the shape widget code reads.\n */\n\nimport { normalizeWidgetInteraction } from \"../helpers/grist-widget-interaction\"\nimport type { GristWidgetColumnMap, GristWidgetInteraction } from \"../types\"\n\ntype Listener<T> = (value: T) => void\n\nexport class HostStream<T> {\n private listeners = new Set<Listener<T>>()\n private bound = false\n private has = false\n private last: T | undefined\n\n constructor(private readonly bind: (emit: (value: T) => void) => void) {}\n\n subscribe(listener: Listener<T>): () => void {\n this.listeners.add(listener)\n if (!this.bound) {\n this.bound = true\n try {\n this.bind((value) => this.emit(value))\n } catch (err) {\n console.error(\"[grist-widget-sdk] could not subscribe to a Grist event:\", err)\n }\n }\n if (this.has) listener(this.last as T)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n peek(): T | undefined {\n return this.last\n }\n\n /** Tests: deliver a value as if Grist had sent it. */\n emit(value: T): void {\n this.has = true\n this.last = value\n for (const l of [...this.listeners]) l(value)\n }\n\n /** Tests: forget the binding, so a new `window.grist` binds afresh. */\n reset(): void {\n this.listeners.clear()\n this.bound = false\n this.has = false\n this.last = undefined\n }\n}\n\nexport type RecordPayload = { record: Record<string, unknown> | null; mappings: GristWidgetColumnMap | null }\nexport type RecordsPayload = { records: Record<string, unknown>[]; mappings: GristWidgetColumnMap | null }\nexport type OptionsPayload = { options: Record<string, unknown> | null; interaction: GristWidgetInteraction | null }\nexport type NewRecordPayload = { mappings: GristWidgetColumnMap | null }\n\nconst asMappings = (m: unknown) => (m && typeof m === \"object\" ? (m as GristWidgetColumnMap) : null)\n\nexport const recordStream = new HostStream<RecordPayload>((emit) => {\n grist.onRecord((record, mappings) => emit({ record, mappings: asMappings(mappings) }), { keepEncoded: false })\n\n // Grist's RecordNotifier posts `{ tableId, rowId }` on a cursor move. The\n // plugin API's onRecord handles it, but refetching here when the row\n // changes keeps a widget from sticking on its first row if that path is\n // skipped (seen in production iframes).\n const fetchSelectedRecord = grist.fetchSelectedRecord ?? grist.docApi?.fetchSelectedRecord\n if (typeof grist.on !== \"function\" || typeof fetchSelectedRecord !== \"function\") return\n let lastRowId: number | undefined\n grist.on(\"message\", async (msg: unknown) => {\n const host = msg as { tableId?: string; rowId?: unknown } | null\n if (!host?.tableId || typeof host.rowId !== \"number\" || host.rowId === lastRowId) return\n lastRowId = host.rowId\n try {\n const record = await fetchSelectedRecord(host.rowId, { keepEncoded: false })\n emit({ record, mappings: recordStream.peek()?.mappings ?? null })\n } catch (err) {\n console.error(\"[grist-widget-sdk] fetchSelectedRecord on a cursor move failed:\", err)\n }\n })\n})\n\nexport const recordsStream = new HostStream<RecordsPayload>((emit) => {\n grist.onRecords((records, mappings) => emit({ records, mappings: asMappings(mappings) }), {\n keepEncoded: false,\n format: \"rows\",\n })\n})\n\nexport const optionsStream = new HostStream<OptionsPayload>((emit) => {\n grist.onOptions((options, interaction) =>\n emit({\n options: options ? { ...options } : null,\n interaction: normalizeWidgetInteraction((interaction as GristWidgetInteraction | null) ?? null),\n })\n )\n})\n\nexport const newRecordStream = new HostStream<NewRecordPayload>((emit) => {\n if (typeof grist.onNewRecord !== \"function\") return\n grist.onNewRecord((mappings) => emit({ mappings: asMappings(mappings) }))\n})\n\n/** Grist's host messages (`grist.on(\"message\")`): the theme travels here. */\nexport const messageStream = new HostStream<unknown>((emit) => {\n if (typeof grist.on !== \"function\") return\n grist.on(\"message\", (msg: unknown) => emit(msg))\n})\n\nexport const ALL_STREAMS = [recordStream, recordsStream, optionsStream, newRecordStream, messageStream] as const\n","/**\n * Single-call wrapper around `grist.ready()`.\n *\n * Grist's contract is \"call ready once\". Multiple `useGristReady` calls (or\n * `useGristWidget` from sibling components) would otherwise race. We:\n *\n * - Coalesce concurrent calls into one in-flight promise.\n * - Re-call `grist.ready` only when `requiredAccess` widens (so an action-capable\n * hook can upgrade a previously read-only handshake).\n */\n\nimport type { GristColumnsToMap, GristReadyOptions, GristRequiredAccess } from \"../types\"\n\nconst ACCESS_RANK: Record<GristRequiredAccess, number> = {\n none: 0,\n \"read table\": 1,\n full: 2,\n}\n\nlet inFlight: Promise<void> | null = null\nlet lastAccess: GristRequiredAccess | null = null\nlet lastColumnNames: ReadonlySet<string> | null = null\n\nfunction columnNamesOf(columns: GristColumnsToMap | undefined): Set<string> {\n return new Set((columns ?? []).map((c) => (typeof c === \"string\" ? c : c.name)))\n}\n\n/**\n * Re-init whenever the new payload asks for strictly more than what's\n * already cached: a higher access level, or a column name the cached\n * payload didn't declare. Prevents a bare fallback caller (e.g. a status\n * chip with no declared columns) from permanently sticking a widget's real,\n * richer requirements to the host once it happens to win the initial race.\n */\nfunction shouldReinit(next: GristRequiredAccess, nextColumns: ReadonlySet<string>): boolean {\n if (!lastAccess) return true\n if (ACCESS_RANK[next] > ACCESS_RANK[lastAccess]) return true\n for (const name of nextColumns) {\n if (!lastColumnNames?.has(name)) return true\n }\n return false\n}\n\n/**\n * Calls `grist.ready` at most once per page (re-called only if access widens\n * or previously-undeclared columns are requested).\n * Returns the same promise for all concurrent callers.\n */\nexport function ensureGristReady(payload: GristReadyOptions): Promise<void> {\n const access = payload.requiredAccess ?? \"read table\"\n const columns = columnNamesOf(payload.columns)\n if (inFlight && !shouldReinit(access, columns)) return inFlight\n\n lastAccess = access\n lastColumnNames = columns\n const next = Promise.resolve().then(() => {\n const result = grist.ready(payload)\n return result instanceof Promise ? result : Promise.resolve()\n })\n\n inFlight = next.catch((err) => {\n inFlight = null\n lastAccess = null\n lastColumnNames = null\n throw err\n })\n return inFlight\n}\n\n/**\n * Forget the cached ready state. Subsequent calls to {@link ensureGristReady}\n * will re-issue `grist.ready` even at the same access level.\n *\n * Production uses: the handshake manager's `reload()` clears the singleton so\n * a soft retry triggers a fresh `grist.ready` (otherwise the cached promise\n * would short-circuit and the user-visible reload would be a no-op).\n *\n * Tests use this between test cases when swapping `window.grist`.\n */\nexport function resetGristReady(): void {\n inFlight = null\n lastAccess = null\n lastColumnNames = null\n}\n\n/** @deprecated Use {@link resetGristReadySingleton}. Kept for test back-compat. */\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","/**\n * The widget's connection to Grist: one store, one `connect()`.\n *\n * The template loads `grist-plugin-api.js` with a classic blocking script, so\n * `window.grist` is there when the widget starts, or it never will be: the\n * check is synchronous (with one more look at `load`, for a page that loads\n * the script asynchronously). Then `grist.ready()` once, and every Grist\n * stream (records, options, mappings, theme) feeds one immutable state that\n * React reads through `useSyncExternalStore`. No polling, no heartbeat: the\n * iframe lives and dies with the Grist page, and a failed call fails where it\n * was made.\n */\n\nimport { parseGristThemePayload } from \"../helpers/grist-theme-payload\"\nimport type { GristSdkAlertKind } from \"../helpers/grist-sdk-alerts\"\nimport type { StandardSchema } from \"./cells\"\nimport type {\n GristReadyOptions,\n GristRequiredAccess,\n GristRowRecord,\n GristWidgetColumnMap,\n GristWidgetInteraction,\n} from \"../types\"\nimport { parseAccess } from \"./derive\"\nimport { messageStream, newRecordStream, optionsStream, recordsStream, recordStream } from \"./host\"\nimport { ensureGristReady, resetGristReady } from \"./ready\"\n\nexport type GristConnection = \"connecting\" | \"ready\" | \"not-embedded\" | \"unavailable\" | \"error\"\nexport type GristTheme = \"light\" | \"dark\"\nexport type GristWidgetActionStatus = \"idle\" | \"running\" | \"error\"\n\nexport type GristRuntimeState = {\n connection: GristConnection\n /** Why the connection failed (`connection === \"error\"`). */\n connectionError: string | null\n declaredAccess: GristRequiredAccess\n /** The access Grist reports with the widget options; null before it does. */\n grantedAccess: GristRequiredAccess | null\n record: GristRowRecord | null\n records: GristRowRecord[] | null\n isNewRecord: boolean\n /** Logical → real column ids; null until Grist reports them. */\n mappings: GristWidgetColumnMap | null\n widgetOptions: Record<string, unknown> | null\n interaction: GristWidgetInteraction | null\n currentTableId: string | null\n theme: GristTheme | null\n actionStatus: GristWidgetActionStatus\n actionError: string | null\n /** The last read that Grist refused for lack of access, for the alerts. */\n readError: string | null\n /** Logical columns the last `mapBack` couldn't write (allowMultiple), for the alerts. */\n mapBackSkipped: readonly string[]\n}\n\n/** What a widget asks Grist for (`UseGristOptions`). */\nexport type GristRuntimeOptions = GristReadyOptions & {\n /** Alert kinds mountGristWidget() never shows for this widget, e.g. [\"section-not-linked\"]. */\n suppressAlerts?: GristSdkAlertKind[]\n /**\n * Extra rules for the mapped records, as a Standard Schema (zod 4,\n * valibot, arktype…), checked after each cell's declared type. A record\n * that fails keeps its typed values; its issues go to `cellIssues`.\n */\n schema?: StandardSchema\n}\n\nexport type GristRuntime = {\n readonly options: GristRuntimeOptions\n getState(): GristRuntimeState\n subscribe(listener: () => void): () => void\n /** Connects (idempotent). Returns a function that stops listening. */\n start(): () => void\n /** Re-runs `grist.ready()` and re-reads mappings and the table. */\n reload(): Promise<void>\n update(patch: Partial<GristRuntimeState>): void\n}\n\nconst READY_TIMEOUT_MS = 30_000\n\nexport function initialRuntimeState(options: GristReadyOptions = {}): GristRuntimeState {\n return {\n connection: \"connecting\",\n connectionError: null,\n declaredAccess: options.requiredAccess ?? \"read table\",\n grantedAccess: null,\n record: null,\n records: null,\n isNewRecord: false,\n mappings: null,\n widgetOptions: null,\n interaction: null,\n currentTableId: null,\n theme: null,\n actionStatus: \"idle\",\n actionError: null,\n readError: null,\n mapBackSkipped: [],\n }\n}\n\nfunction isEmbedded(): boolean {\n try {\n return typeof window !== \"undefined\" && window.self !== window.top\n } catch {\n return true // a cross-origin parent throws: we are in an iframe\n }\n}\n\nconst hasGrist = () => typeof grist !== \"undefined\" && grist !== null\n\nexport function createGristRuntime(options: GristRuntimeOptions = {}): GristRuntime {\n let state = initialRuntimeState(options)\n const listeners = new Set<() => void>()\n let starts = 0\n let stopStreams: (() => void) | null = null\n let attempt = 0\n\n const update = (patch: Partial<GristRuntimeState>) => {\n let changed = false\n for (const key of Object.keys(patch) as (keyof GristRuntimeState)[]) {\n if (!Object.is(state[key], patch[key])) changed = true\n }\n if (!changed) return\n state = { ...state, ...patch }\n for (const l of [...listeners]) l()\n }\n\n const payload: GristReadyOptions = {\n requiredAccess: options.requiredAccess ?? \"read table\",\n columns: options.columns ?? [],\n ...(options.allowSelectBy !== undefined ? { allowSelectBy: options.allowSelectBy } : {}),\n ...(options.hasCustomOptions !== undefined ? { hasCustomOptions: options.hasCustomOptions } : {}),\n ...(options.onEditOptions ? { onEditOptions: options.onEditOptions } : {}),\n }\n\n const refreshTable = async () => {\n try {\n const tableId = await grist.selectedTable?.getTableId()\n if (tableId) update({ currentTableId: tableId })\n } catch {\n // Not every host answers; currentTableId stays as it was.\n }\n }\n\n const refreshMappings = async () => {\n if (typeof grist.sectionApi?.mappings !== \"function\") return\n try {\n const mappings = await grist.sectionApi.mappings()\n // A stream may have reported newer mappings while this was in flight.\n if (state.mappings === null) update({ mappings: (mappings as GristWidgetColumnMap | null) ?? {} })\n } catch {\n // The streams report mappings too.\n }\n }\n\n const connect = async () => {\n const mine = ++attempt\n update({ connection: \"connecting\", connectionError: null })\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n await Promise.race([\n ensureGristReady(payload),\n new Promise((_, reject) => {\n timer = setTimeout(() => reject(new Error(`Grist did not answer grist.ready() within ${READY_TIMEOUT_MS / 1000} s.`)), READY_TIMEOUT_MS)\n }),\n ])\n } catch (err) {\n if (mine === attempt) update({ connection: \"error\", connectionError: err instanceof Error ? err.message : String(err) })\n return\n } finally {\n clearTimeout(timer)\n }\n if (mine !== attempt) return\n update({ connection: \"ready\" })\n await Promise.all([refreshMappings(), refreshTable()])\n }\n\n const listen = () => {\n const offs = [\n // Copies: a host may reuse one record object and mutate it in place.\n recordStream.subscribe(({ record, mappings }) =>\n update({\n record: record ? ({ ...record } as GristRowRecord) : null,\n isNewRecord: false,\n ...(mappings ? { mappings } : {}),\n })\n ),\n recordsStream.subscribe(({ records, mappings }) => {\n update({ records: records.map((r) => ({ ...r }) as GristRowRecord), ...(mappings ? { mappings } : {}) })\n void refreshTable()\n }),\n optionsStream.subscribe(({ options: widgetOptions, interaction }) =>\n update({\n widgetOptions,\n interaction,\n grantedAccess: parseAccess(interaction?.access_level) ?? state.grantedAccess,\n })\n ),\n newRecordStream.subscribe(({ mappings }) => update({ isNewRecord: true, ...(mappings ? { mappings } : {}) })),\n messageStream.subscribe((msg) => {\n const theme = parseGristThemePayload(msg)\n if (theme) update({ theme })\n }),\n ]\n return () => offs.forEach((off) => off())\n }\n\n const begin = () => {\n if (!isEmbedded()) return update({ connection: \"not-embedded\" })\n if (!hasGrist()) {\n // A page that loads the plugin API asynchronously: one more look once\n // everything has loaded, then it is unavailable.\n if (typeof document !== \"undefined\" && document.readyState !== \"complete\" && typeof window !== \"undefined\") {\n window.addEventListener(\"load\", () => (hasGrist() ? begin() : update({ connection: \"unavailable\" })), { once: true })\n return\n }\n return update({ connection: \"unavailable\" })\n }\n // Bound before ready(): Grist may push the first record during it.\n stopStreams ??= listen()\n void connect()\n }\n\n return {\n options,\n getState: () => state,\n subscribe(listener) {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n start() {\n if (starts++ === 0) begin()\n return () => {\n if (--starts > 0) return\n stopStreams?.()\n stopStreams = null\n }\n },\n async reload() {\n if (!hasGrist() || !isEmbedded()) return begin()\n resetGristReady()\n update({ mappings: null })\n stopStreams ??= listen()\n await connect()\n },\n update,\n }\n}\n","/**\n * `defineGristWidget()`: a widget's whole declaration in one typed value.\n * Everything else reads it: `widget.useGrist()` types the mapped records and\n * the writes from it, `mountGristWidget()` takes the access level, the\n * columns and the title from it, and the tests map its columns.\n *\n * ```ts\n * export const widget = defineGristWidget({\n * title: \"Tasks\",\n * requiredAccess: \"full\",\n * columns: [{ name: \"Title\", type: \"Text\" }, { name: \"Done\", type: \"Bool\" }],\n * })\n *\n * const w = widget.useGrist() // w.mappedRecord: { id; Title: string | null; Done: boolean | null } | null\n * await w.updateRecord({ Done: true })\n * ```\n */\n\nimport type { GristMappedRow } from \"./runtime/cells\"\nimport type { GristRowRecord } from \"./types\"\nimport { useGrist, type UseGristOptions, type UseGristResult } from \"./use-grist\"\n\n/** What a widget declares: `UseGristOptions`, plus its title and description. */\nexport type GristWidgetDefinition = UseGristOptions & {\n /** The widget's name: the page's title, and its manifest's. */\n title?: string\n /** One sentence: the page's description, and its manifest's. */\n description?: string\n}\n\n/** The widget's mapped record type, from its declaration. */\nexport type GristWidgetRow<W> = W extends GristWidget<infer D> ? GristMappedRow<D> : never\n\n/** A declared widget. Pass it to `mountGristWidget()` (as `widget`, exported from `src/app/App.tsx`). */\nexport type GristWidget<D extends GristWidgetDefinition = GristWidgetDefinition> = {\n /** The declaration, as written. */\n readonly definition: D\n /** What the widget asks Grist for: the declaration without its title and description. */\n readonly options: UseGristOptions\n readonly metadata: { title?: string; description?: string }\n /**\n * `useGrist()`, typed from the declaration: `mappedRecord`, `mappedRecords`,\n * `mapBack`, `updateRecord` and `addRecord` use the declared names and the\n * value each declared type gives. A hook: call it in a component.\n */\n useGrist: () => UseGristResult<GristRowRecord, GristMappedRow<D>>\n}\n\n/**\n * Declares a widget. The `const` type parameter keeps the column names and\n * types literal, so the mapped record is typed with no annotation, no\n * `as const` and no generics.\n */\nexport function defineGristWidget<const D extends GristWidgetDefinition>(definition: D): GristWidget<D> {\n const { title, description, ...options } = definition\n return {\n definition,\n options,\n metadata: { title, description },\n useGrist: () => useGrist<GristRowRecord, GristMappedRow<D>>(options),\n }\n}\n\n/** True for a declared widget (as opposed to plain `GRIST_OPTIONS`). */\nexport function isGristWidget(value: unknown): value is GristWidget {\n return typeof value === \"object\" && value !== null && \"definition\" in value && \"useGrist\" in value\n}\n","import { useState, type ReactNode } from \"react\"\n\nimport { GristContextProvider, newConnection, type UseGristOptions } from \"../use-grist\"\n\nexport type GristWidgetProviderProps = {\n /** Read once, at mount: what the widget asks Grist for. */\n options?: UseGristOptions\n children: ReactNode\n}\n\n/**\n * Connects to Grist for the widgets below it: `useGrist()` under it reads this\n * connection. `mountGristWidget()` renders it; render it yourself only for a\n * page that manages its own React root.\n */\nexport function GristWidgetProvider({ options, children }: GristWidgetProviderProps) {\n const [connection] = useState(() => newConnection(options))\n return <GristContextProvider value={connection}>{children}</GristContextProvider>\n}\n","import { useCallback, useState, type CSSProperties, type ReactNode } from \"react\"\n\nimport { accessDenied, accessLabel, deriveColumnMappingStatus } from \"../runtime/derive\"\nimport type { GristRuntimeState } from \"../runtime/runtime\"\nimport { useGristRuntime, useGristState } from \"../use-grist\"\n\nexport type GristBoundaryProps = {\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\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\ntype Screen = { title: string; message: string; tone?: \"default\" | \"error\"; retry?: boolean }\n\n/** What the boundary shows instead of the widget, or null to render it. */\nexport function boundaryScreen(state: GristRuntimeState, columns: Parameters<typeof deriveColumnMappingStatus>[0]): Screen | null {\n switch (state.connection) {\n case \"connecting\":\n return { title: \"Connecting to Grist\", message: \"Asking Grist for the access this widget needs…\" }\n case \"not-embedded\":\n return {\n title: \"Open inside Grist\",\n message: \"Open this page as a custom widget inside a Grist document (it runs in an embedded panel, not on its own).\",\n retry: true,\n }\n case \"unavailable\":\n return {\n title: \"Open inside Grist\",\n message: \"The Grist plugin did not load. Reload the page, or open this URL as a custom widget inside a Grist document.\",\n retry: true,\n }\n case \"error\":\n return {\n title: \"Something went wrong\",\n message: state.connectionError ?? \"Something went wrong connecting to Grist. Try again, or reload the page.\",\n tone: \"error\",\n retry: true,\n }\n }\n if (accessDenied(state)) {\n return {\n title: \"More access needed\",\n message: `Set Access level to at least \"${accessLabel(state.declaredAccess)}\" in the Custom widget settings.`,\n tone: \"error\",\n retry: true,\n }\n }\n const mapping = deriveColumnMappingStatus(columns, state.mappings)\n if (mapping.pending) return { title: \"Connecting to Grist\", message: \"Waiting for Grist to report the column mapping…\" }\n if (!mapping.ok) {\n return {\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 }\n }\n return null\n}\n\n/**\n * Renders the widget once Grist is connected, has granted the access it\n * declares, and every required declared column is mapped; until then, a\n * screen that says what is missing (with a retry where one can help).\n * Requires `<GristWidgetProvider>`; `mountGristWidget()` renders both.\n */\nexport function GristBoundary({ children }: GristBoundaryProps) {\n const connection = useGristRuntime()\n if (!connection) throw new Error(\"<GristBoundary> must be used inside <GristWidgetProvider> (mountGristWidget renders both).\")\n const state = useGristState(connection)\n const [isReloading, setIsReloading] = useState(false)\n const reload = useCallback(async () => {\n setIsReloading(true)\n try {\n await connection.runtime.reload()\n } catch (err) {\n console.error(\"[grist-widget-sdk] reload failed:\", err)\n } finally {\n setIsReloading(false)\n }\n }, [connection])\n\n const screen = boundaryScreen(state, connection.runtime.options.columns)\n if (!screen) return <>{children}</>\n return (\n <GristBoundaryScreen\n title={screen.title}\n message={screen.message}\n tone={screen.tone}\n showRetry={screen.retry}\n actions={{ reload, isReloading }}\n retryLabel={screen.tone === \"error\" ? \"Try again\" : \"Try reconnecting\"}\n retryBusyLabel={screen.tone === \"error\" ? \"Retrying…\" : \"Reconnecting…\"}\n />\n )\n}\n","import type { GristReplicaDocument, GristReplicaRow, GristReplicaTable } from \"../replica-document\"\n\n/**\n * Ensure `rows` is a concrete array for emulator / merge logic.\n * Call at host boundaries (`createDocument`, tests); JSON may still omit `rows` for schema-only.\n */\nexport function normalizeReplicaTableInput<T extends GristReplicaTable>(table: T): T & { rows: GristReplicaRow[] } {\n return { ...table, rows: table.rows ?? [] }\n}\n\n/** Apply {@link normalizeReplicaTableInput} to every table; shallow-copies the document shell. */\nexport function normalizeReplicaDocumentInput<T extends GristReplicaDocument>(doc: T): T {\n return {\n ...doc,\n tables: Object.fromEntries(\n Object.entries(doc.tables).map(([tableId, t]) => [tableId, normalizeReplicaTableInput(t)])\n ),\n } as T\n}\n\n/** How row arrays appear in serialized replica JSON from {@link buildReplicaJsonPayload}. */\nexport type ReplicaJsonIncludeRows = \"none\" | \"samples\" | \"full\"\n\n/**\n * Clone a replica document for JSON output: strip rows, cap to first N, or pass through.\n * Does not mutate the source document.\n */\nexport function buildReplicaJsonPayload(\n doc: GristReplicaDocument,\n options: { includeRows: ReplicaJsonIncludeRows; sampleRowLimit?: number }\n): GristReplicaDocument {\n const limit = options.sampleRowLimit ?? 10\n const tables = Object.fromEntries(\n Object.entries(doc.tables).map(([tid, t]) => {\n if (options.includeRows === \"none\") {\n const { rows: _r, ...rest } = t\n return [tid, rest]\n }\n if (options.includeRows === \"samples\") {\n const r = t.rows ?? []\n return [tid, { ...t, rows: r.slice(0, limit) }]\n }\n return [tid, { ...t, rows: t.rows }]\n })\n ) as GristReplicaDocument[\"tables\"]\n return { ...doc, tables }\n}\n","import { useEffect } from \"react\"\n\nexport type UseWidgetMetadataInput = {\n title: string\n description: string\n}\n\nexport function useWidgetMetadata(input?: UseWidgetMetadataInput | null) {\n useEffect(() => {\n if (!input) return\n\n const { title, description } = 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 }, [input])\n}\n\nfunction setMetaTag(key: \"name\" | \"property\", value: string, content: string) {\n let meta = document.head.querySelector<HTMLMetaElement>(\n `meta[${key}=\"${value}\"]`\n )\n if (!meta) {\n meta = document.createElement(\"meta\")\n meta.setAttribute(key, value)\n document.head.appendChild(meta)\n }\n meta.setAttribute(\"content\", content)\n}\n","/**\n * Grist `docApi.applyUserActions` payloads are arrays of user-action tuples.\n * @see https://support.getgrist.com/code/interfaces/grist_plugin_api.GristDocAPI/#applyuseractions\n */\n\nexport type GristUserActionTuple = unknown[]\n\n/** `[\"UpdateRecord\", tableId, rowId, { col: value, ... }]` */\nexport function gristUpdateRecordAction(\n tableId: string,\n rowId: number,\n patch: Record<string, unknown>\n): GristUserActionTuple {\n return [\"UpdateRecord\", tableId, rowId, patch]\n}\n\n/** `[\"AddRecord\", tableId, null, { col: value, ... }]` */\nexport function gristAddRecordAction(tableId: string, values: Record<string, unknown>): GristUserActionTuple {\n return [\"AddRecord\", tableId, null, values]\n}\n\n/** `[\"RemoveRecord\", tableId, rowId]` */\nexport function gristRemoveRecordAction(tableId: string, rowId: number): GristUserActionTuple {\n return [\"RemoveRecord\", tableId, rowId]\n}\n\n/** `[\"BulkUpdateRecord\", tableId, rowIds, { col: value[], ... }]` */\nexport function gristBulkUpdateRecordAction(\n tableId: string,\n rowIds: number[],\n columnarPatch: Record<string, unknown[]>\n): GristUserActionTuple {\n return [\"BulkUpdateRecord\", tableId, rowIds, columnarPatch]\n}\n\n/**\n * `[\"BulkAddRecord\", tableId, rowIds | nullArray, { col: value[], ... }]`.\n * Pass `null` (or omit) for `rowIds` to let Grist allocate ids; in user-action\n * format Grist expects an array of nulls of the same length as the value arrays.\n */\nexport function gristBulkAddRecordAction(\n tableId: string,\n values: Record<string, unknown[]>,\n rowIds?: Array<number | null>\n): GristUserActionTuple {\n const length = inferBulkLength(values)\n const ids = rowIds ?? new Array<number | null>(length).fill(null)\n return [\"BulkAddRecord\", tableId, ids, values]\n}\n\n/** `[\"BulkRemoveRecord\", tableId, rowIds]` */\nexport function gristBulkRemoveRecordAction(tableId: string, rowIds: number[]): GristUserActionTuple {\n return [\"BulkRemoveRecord\", tableId, rowIds]\n}\n\n/** `[\"AddColumn\", tableId, colId, colInfo]` — `colInfo` shape depends on Grist version / column type. */\nexport function gristAddColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"AddVisibleColumn\", tableId, colId, colInfo]` — like `AddColumn` but also adds the column to the current view section. */\nexport function gristAddVisibleColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddVisibleColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"RenameColumn\", tableId, colId, newColId]` */\nexport function gristRenameColumnAction(tableId: string, colId: string, newColId: string): GristUserActionTuple {\n return [\"RenameColumn\", tableId, colId, newColId]\n}\n\n/** `[\"ModifyColumn\", tableId, colId, colInfo]` */\nexport function gristModifyColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"ModifyColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"RemoveColumn\", tableId, colId]` */\nexport function gristRemoveColumnAction(tableId: string, colId: string): GristUserActionTuple {\n return [\"RemoveColumn\", tableId, colId]\n}\n\n/** `[\"AddTable\", tableId, tableInfo]` */\nexport function gristAddTableAction(tableId: string, tableInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddTable\", tableId, tableInfo]\n}\n\nfunction inferBulkLength(values: Record<string, unknown[]>): number {\n for (const arr of Object.values(values)) if (Array.isArray(arr)) return arr.length\n return 0\n}\n","import { useEffect, useState } from \"react\"\n\nimport {\n cardStyle,\n cardTextStyle,\n cardTitleStyle,\n codeStyle,\n eyebrowStyle,\n headingStyle,\n leadStyle,\n pageStyle,\n} from \"./tokens\"\nimport { widgetTitle } from \"./widget-title\"\n\n/**\n * Whether the widget has a demo page (`public/demo/`). The dev server serves\n * it at `demo/index.html` (Vite answers a bare `demo/` with the app's own page).\n */\nfunction useHasDemo(): boolean | null {\n const [has, setHas] = useState<boolean | null>(null)\n useEffect(() => {\n if (typeof fetch !== \"function\") return\n let live = true\n fetch(\"demo/demo.grist\", { method: \"HEAD\" })\n .then((res) => live && setHas(res.ok))\n .catch(() => live && setHas(false))\n return () => {\n live = false\n }\n }, [])\n return has\n}\n\n/**\n * Shown outside Grist on the dev server. Deliberately not a preview of the\n * widget: an emulator can't match real Grist. It points at the loops worth\n * trusting: the widget in real Grist running in this browser (the demo page,\n * grist-static, on this dev server's build, so edits reload in place),\n * `pnpm test`, and the `dev` branch's preview inside a Grist document.\n */\nexport function LocalDevPage() {\n const hasDemo = useHasDemo()\n return (\n <main style={pageStyle}>\n <p style={eyebrowStyle}>{widgetTitle()} · local dev</p>\n <h1 style={headingStyle}>Not embedded in Grist</h1>\n <p style={leadStyle}>This is the local dev server: there's no Grist here to render the widget against.</p>\n\n <section style={cardStyle}>\n <h2 style={cardTitleStyle}>Open it in Grist, in this browser</h2>\n {hasDemo === false ? (\n <p style={cardTextStyle}>\n Run <code style={codeStyle}>pnpm demo --save</code> once (it needs Docker): it writes{\" \"}\n <code style={codeStyle}>public/demo/</code>, a document for this widget. Then{\" \"}\n <a href=\"demo/index.html\">demo/index.html</a> opens it in real Grist, running in the browser, on this dev server's\n widget: edits reload in place.\n </p>\n ) : (\n <p style={cardTextStyle}>\n <a href=\"demo/index.html\">Open demo/index.html</a>: real Grist running in the browser (no server, nothing saved), with\n this dev server's widget, so edits reload in place. Its document is{\" \"}\n <code style={codeStyle}>public/demo/demo.grist</code>: after changing the declared columns, run{\" \"}\n <code style={codeStyle}>pnpm demo --save</code> (Docker) to regenerate it.\n </p>\n )}\n </section>\n\n <section style={cardStyle}>\n <h2 style={cardTitleStyle}>Check it against real Grist</h2>\n <p style={cardTextStyle}>\n Push to <code style={codeStyle}>dev</code>, then open its <code style={codeStyle}>/dev/</code> URL in a\n custom widget of a real Grist document: later pushes reload it there within seconds. Locally,{\" \"}\n <code style={codeStyle}>pnpm test</code> runs the widget against an emulated Grist.\n </p>\n </section>\n\n <section style={cardStyle}>\n <h2 style={cardTitleStyle}>Starting from another example?</h2>\n <p style={cardTextStyle}>\n <code style={codeStyle}>npx create-grist-widget list</code> shows the examples, and{\" \"}\n <code style={codeStyle}>npx create-grist-widget use <example></code> swaps this widget for one.\n </p>\n </section>\n </main>\n )\n}\n","import type { CSSProperties } from \"react\"\n\n/**\n * The chrome's colours and radius: shadcn's CSS variables, so the pages\n * follow a widget's theme (light, dark, its own palette) without depending\n * on its Tailwind config, with neutral fallbacks for a widget without them.\n * Same approach as GristBoundaryScreen.\n */\nconst token = (name: string, fallback: string) => `var(--${name}, ${fallback})`\n\nexport const tokens = {\n background: token(\"background\", \"#ffffff\"),\n foreground: token(\"foreground\", \"#0a0a0a\"),\n card: token(\"card\", \"#ffffff\"),\n mutedForeground: token(\"muted-foreground\", \"#737373\"),\n border: token(\"border\", \"#e5e5e5\"),\n primary: token(\"primary\", \"#171717\"),\n primaryForeground: token(\"primary-foreground\", \"#fafafa\"),\n destructive: token(\"destructive\", \"#dc2626\"),\n radius: token(\"radius\", \"0.625rem\"),\n} as const\n\nexport const pageStyle: CSSProperties = {\n boxSizing: \"border-box\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n maxWidth: \"28rem\",\n minHeight: \"100%\",\n margin: \"0 auto\",\n padding: \"4rem 1.5rem\",\n color: tokens.foreground,\n font: \"inherit\",\n}\n\nexport const eyebrowStyle: CSSProperties = {\n margin: \"0 0 0.5rem\",\n textAlign: \"center\",\n fontSize: \"0.875rem\",\n fontWeight: 500,\n color: tokens.mutedForeground,\n}\n\nexport const headingStyle: CSSProperties = {\n margin: 0,\n textAlign: \"center\",\n fontSize: \"1.5rem\",\n fontWeight: 600,\n letterSpacing: \"-0.01em\",\n}\n\nexport const leadStyle: CSSProperties = {\n margin: \"0.75rem auto 2rem\",\n maxWidth: \"24rem\",\n textAlign: \"center\",\n fontSize: \"0.875rem\",\n lineHeight: 1.5,\n color: tokens.mutedForeground,\n}\n\nexport const cardStyle: CSSProperties = {\n boxSizing: \"border-box\",\n marginBottom: \"1rem\",\n padding: \"1.25rem\",\n border: `1px solid ${tokens.border}`,\n borderRadius: tokens.radius,\n background: tokens.card,\n}\n\nexport const cardTitleStyle: CSSProperties = {\n margin: \"0 0 0.375rem\",\n fontSize: \"1rem\",\n fontWeight: 600,\n}\n\nexport const cardTextStyle: CSSProperties = {\n margin: 0,\n fontSize: \"0.875rem\",\n lineHeight: 1.5,\n color: tokens.mutedForeground,\n}\n\nexport const codeStyle: CSSProperties = {\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, monospace\",\n fontSize: \"0.8125rem\",\n color: tokens.foreground,\n}\n","/**\n * The widget's name for the pages shown outside Grist: the page title,\n * which `create-grist-widget` sets to the widget's title in `index.html`.\n */\nexport function widgetTitle(): string {\n const title = typeof document === \"undefined\" ? \"\" : document.title.trim()\n return title || \"Grist widget\"\n}\n","import { useState, type CSSProperties } from \"react\"\n\nimport { deployChannelLabel, parseDeployPath, type DeployChannel } from \"../deploy-path\"\nimport { useReleasedVersions } from \"../released-versions\"\nimport {\n cardStyle,\n cardTextStyle,\n cardTitleStyle,\n codeStyle,\n eyebrowStyle,\n headingStyle,\n leadStyle,\n pageStyle,\n tokens,\n} from \"./tokens\"\nimport { widgetTitle } from \"./widget-title\"\n\n/**\n * Shown outside Grist on a deployed URL (`/latest/`, `/dev/`, `/v<version>/`\n * or the root): which build this is, links to the others, and the URL to\n * paste into a Grist custom widget.\n */\nexport function ReleasePage({ channel }: { channel: DeployChannel }) {\n const label = deployChannelLabel(channel)\n return (\n <main style={pageStyle}>\n <p style={eyebrowStyle}>\n {widgetTitle()} · {label}\n </p>\n <h1 style={headingStyle}>Grist isn't loaded here</h1>\n <p style={leadStyle}>\n This is the <code style={codeStyle}>{label}</code> build, opened outside Grist. Hover a version to see when it\n was released.\n </p>\n <ChannelLinks current={channel} />\n <InstallUrl />\n </main>\n )\n}\n\nfunction ChannelLinks({ current }: { current: DeployChannel }) {\n const { basePath } = parseDeployPath(window.location.pathname)\n const { versions } = useReleasedVersions()\n const isCurrent = (channel: DeployChannel) =>\n channel.kind === current.kind && (channel.kind !== \"version\" || (current.kind === \"version\" && channel.version === current.version))\n\n return (\n <nav aria-label=\"Versions\" style={{ display: \"flex\", flexWrap: \"wrap\", justifyContent: \"center\", gap: \"0.5rem\", marginBottom: \"2rem\" }}>\n <ChannelLink href={`${basePath}latest/`} active={isCurrent({ kind: \"latest\" })}>\n latest\n </ChannelLink>\n <ChannelLink href={`${basePath}dev/`} active={isCurrent({ kind: \"dev\" })}>\n dev\n </ChannelLink>\n {versions?.map((v) => (\n <ChannelLink\n key={v.version}\n href={`${basePath}v${v.version}/`}\n title={formatDate(v.publishedAt)}\n active={isCurrent({ kind: \"version\", version: v.version })}\n >\n {`v${v.version}`}\n </ChannelLink>\n ))}\n </nav>\n )\n}\n\nfunction ChannelLink({\n href,\n title,\n active,\n children,\n}: {\n href: string\n title?: string\n active: boolean\n children: string\n}) {\n const style: CSSProperties = {\n padding: \"0.25rem 0.75rem\",\n border: `1px solid ${active ? tokens.primary : tokens.border}`,\n borderRadius: \"9999px\",\n background: active ? tokens.primary : \"transparent\",\n color: active ? tokens.primaryForeground : tokens.mutedForeground,\n fontSize: \"0.75rem\",\n fontWeight: 500,\n textDecoration: \"none\",\n }\n return (\n <a href={href} title={title} aria-current={active ? \"page\" : undefined} style={style}>\n {children}\n </a>\n )\n}\n\nfunction InstallUrl() {\n const url = window.location.href\n const [copied, setCopied] = useState(false)\n\n function copy() {\n void navigator.clipboard?.writeText(url).then(() => {\n setCopied(true)\n setTimeout(() => setCopied(false), 1500)\n })\n }\n\n return (\n <section style={cardStyle}>\n <h2 style={cardTitleStyle}>Use it as a Grist custom widget</h2>\n <p style={{ ...cardTextStyle, marginBottom: \"1rem\" }}>Paste this URL into a custom widget's URL field in Grist.</p>\n <div style={{ display: \"flex\", gap: \"0.5rem\" }}>\n <input\n readOnly\n value={url}\n aria-label=\"Widget URL\"\n onFocus={(event) => event.target.select()}\n style={{\n flex: 1,\n minWidth: 0,\n padding: \"0.5rem 0.75rem\",\n border: `1px solid ${tokens.border}`,\n borderRadius: tokens.radius,\n background: \"transparent\",\n color: tokens.foreground,\n font: \"inherit\",\n fontSize: \"0.875rem\",\n }}\n />\n <button\n type=\"button\"\n onClick={copy}\n style={{\n padding: \"0.5rem 1rem\",\n border: \"none\",\n borderRadius: tokens.radius,\n background: tokens.primary,\n color: tokens.primaryForeground,\n font: \"inherit\",\n fontSize: \"0.875rem\",\n fontWeight: 500,\n cursor: \"pointer\",\n }}\n >\n {copied ? \"Copied\" : \"Copy\"}\n </button>\n </div>\n </section>\n )\n}\n\nfunction formatDate(iso: string): string {\n const date = new Date(iso)\n return Number.isNaN(date.getTime())\n ? iso\n : date.toLocaleDateString(undefined, { year: \"numeric\", month: \"short\", day: \"numeric\" })\n}\n","/**\n * Where a deployed build is being served from.\n *\n * A widget's deploy pipeline publishes the same build at its root and at\n * `/latest/`, a preview at `/dev/`, and each release at `/v<version>/`, all\n * under one base path (e.g. `/my-widget/` on GitHub Pages). Opened outside\n * Grist, the page tells them apart from `window.location.pathname` alone.\n */\nexport type DeployChannel =\n | { kind: \"latest\" }\n | { kind: \"dev\" }\n | { kind: \"version\"; version: string }\n\nexport type DeployPath = {\n channel: DeployChannel\n /**\n * The path the channels live under, always ending in `/`: the current\n * path without its channel segment. `\"/my-widget/v1.2.0/\"` gives\n * `\"/my-widget/\"`.\n */\n basePath: string\n}\n\nconst VERSION_SEGMENT = /^v(\\d+\\.\\d+\\.\\d+(?:-[\\w.]+)?)$/\n\n/**\n * Parse a pathname into its deploy channel and base path. A path without a\n * channel segment (the deployed root, or a local dev server) is `latest`:\n * the deploy places the latest release at the root too.\n */\nexport function parseDeployPath(pathname: string): DeployPath {\n const segments = pathname.replace(/\\/+$/, \"\").split(\"/\")\n const last = segments[segments.length - 1] ?? \"\"\n\n let channel: DeployChannel | null = null\n if (last === \"latest\") channel = { kind: \"latest\" }\n else if (last === \"dev\") channel = { kind: \"dev\" }\n else {\n const match = VERSION_SEGMENT.exec(last)\n if (match) channel = { kind: \"version\", version: match[1] }\n }\n\n if (!channel) return { channel: { kind: \"latest\" }, basePath: withTrailingSlash(pathname) }\n return { channel, basePath: withTrailingSlash(segments.slice(0, -1).join(\"/\")) }\n}\n\n/** `\"latest\"`, `\"dev\"` or `\"v1.2.0\"`. */\nexport function deployChannelLabel(channel: DeployChannel): string {\n return channel.kind === \"version\" ? `v${channel.version}` : channel.kind\n}\n\nfunction withTrailingSlash(path: string): string {\n return path.endsWith(\"/\") ? path : `${path}/`\n}\n","import { useEffect, useState } from \"react\"\n\nimport { parseDeployPath } from \"./deploy-path\"\n\n/** One entry of the `versions.json` a widget's deploy pipeline maintains. */\nexport type ReleasedVersion = {\n version: string\n publishedAt: string\n}\n\nexport type UseReleasedVersionsResult = {\n /** Newest first, as the deploy writes them; `null` until loaded. */\n versions: ReleasedVersion[] | null\n /** `true` when `versions.json` couldn't be fetched or read. */\n error: boolean\n}\n\n/**\n * The widget's released versions, read from the `versions.json` next to its\n * channels (see {@link parseDeployPath}). For a page shown outside Grist,\n * such as a release page linking to each version.\n */\nexport function useReleasedVersions(\n pathname: string = typeof window === \"undefined\" ? \"/\" : window.location.pathname\n): UseReleasedVersionsResult {\n const url = `${parseDeployPath(pathname).basePath}versions.json`\n const [result, setResult] = useState<UseReleasedVersionsResult>({ versions: null, error: false })\n\n useEffect(() => {\n let cancelled = false\n fetch(url, { cache: \"no-store\" })\n .then((res) => (res.ok ? res.json() : Promise.reject(new Error(`HTTP ${res.status}`))))\n .then((data: unknown) => {\n if (cancelled) return\n if (!Array.isArray(data)) throw new Error(\"versions.json is not an array\")\n setResult({ versions: data as ReleasedVersion[], error: false })\n })\n .catch(() => {\n if (!cancelled) setResult({ versions: null, error: true })\n })\n return () => {\n cancelled = true\n }\n }, [url])\n\n return result\n}\n","/**\n * The alerts `mountGristWidget()` shows above a running widget: what needs the\n * user's attention in Grist (column mapping, access, a failed write, an\n * unlinked section). The blocking states (not connected, access refused,\n * required columns unmapped) are `<GristBoundary>`'s, not alerts.\n */\n\nimport { useNearestGristState } from \"../use-grist\"\nimport { deriveColumnMappingStatus, deriveStatus } from \"../runtime/derive\"\nimport { isAccessInsufficientError } from \"../runtime/api\"\nimport type { GristCellIssue } from \"../runtime/cells\"\nimport type { GristRuntimeState } from \"../runtime/runtime\"\nimport type { GristColumnsToMap, GristWidgetInteraction } from \"../types\"\nimport { parseGristWidgetLinkingInfo } from \"./grist-widget-interaction\"\n\nexport type GristSdkAlertKind =\n | \"column-mapping\"\n | \"mapping-pending\"\n | \"section-not-linked\"\n | \"source-not-wired\"\n | \"action-error\"\n | \"access-insufficient\"\n | \"map-back-skip\"\n | \"cell-issues\"\n\nexport type GristSdkAlertSeverity = \"info\" | \"warning\" | \"error\"\n\nexport type GristSdkAlertDescriptor = {\n id: string\n kind: GristSdkAlertKind\n severity: GristSdkAlertSeverity\n title: string\n ariaRole: \"status\" | \"alert\"\n message: string\n}\n\nexport type GristSdkAlertsOptions = {\n /** Added to the \"section not linked\" message, e.g. how to link in Grist. */\n sectionNotLinkedHint?: string\n}\n\nconst TITLE: Record<GristSdkAlertKind, string> = {\n \"column-mapping\": \"Column mapping\",\n \"mapping-pending\": \"Column mapping\",\n \"section-not-linked\": \"Widget linking\",\n \"source-not-wired\": \"Widget linking\",\n \"action-error\": \"Action error\",\n \"access-insufficient\": \"Access level\",\n \"map-back-skip\": \"Write skipped\",\n \"cell-issues\": \"Unexpected values\",\n}\n\nconst SEVERITY: Record<GristSdkAlertKind, GristSdkAlertSeverity> = {\n \"column-mapping\": \"warning\",\n \"mapping-pending\": \"info\",\n \"section-not-linked\": \"warning\",\n \"source-not-wired\": \"warning\",\n \"action-error\": \"error\",\n \"access-insufficient\": \"error\",\n \"map-back-skip\": \"warning\",\n \"cell-issues\": \"warning\",\n}\n\nconst alert = (kind: GristSdkAlertKind, message: string, ariaRole: \"status\" | \"alert\" = \"status\"): GristSdkAlertDescriptor => ({\n id: kind,\n kind,\n severity: SEVERITY[kind],\n title: TITLE[kind],\n ariaRole,\n message,\n})\n\n/** A widget section Grist says is linked to nothing. */\nexport function isWidgetSectionNotLinked(interaction: GristWidgetInteraction | null | undefined): boolean {\n const linking = parseGristWidgetLinkingInfo(interaction?.linking)\n return Boolean(linking) && linking!.asTarget == null\n}\n\n/** The alerts for a widget in `state`, pure (tested without React). */\nexport function getGristSdkAlerts(\n state: GristRuntimeState,\n widget: {\n columns?: GristColumnsToMap\n allowSelectBy?: boolean\n suppressAlerts?: readonly GristSdkAlertKind[]\n cellIssues?: readonly GristCellIssue[]\n },\n options: GristSdkAlertsOptions = {}\n): GristSdkAlertDescriptor[] {\n if (deriveStatus(state) !== \"ready\") return []\n const out: GristSdkAlertDescriptor[] = []\n\n const mapping = deriveColumnMappingStatus(widget.columns, state.mappings)\n if (mapping.pending) out.push(alert(\"mapping-pending\", \"Waiting for Grist to report column mappings.\"))\n else if (!mapping.ok) {\n const parts = [\"Column mapping is incomplete.\"]\n if (mapping.missing.length) parts.push(`Required columns: ${mapping.missing.join(\", \")}.`)\n if (mapping.emptyMultiples.length) parts.push(`Assign at least one sheet column for: ${mapping.emptyMultiples.join(\", \")}.`)\n out.push(alert(\"column-mapping\", parts.join(\" \")))\n }\n\n const failure = state.actionError ?? state.readError\n if (failure && isAccessInsufficientError(failure)) {\n out.push(\n alert(\n \"access-insufficient\",\n 'This operation requires \"Full document access\". Set the Access level to \"Full document access\" in the Custom widget configuration panel.',\n \"alert\"\n )\n )\n } else if (state.actionError) {\n out.push(alert(\"action-error\", state.actionError, \"alert\"))\n }\n\n if (state.mapBackSkipped.length) {\n const list = state.mapBackSkipped.join(\", \")\n out.push(alert(\"map-back-skip\", `mapBack skipped multi-mapped column${state.mapBackSkipped.length === 1 ? \"\" : \"s\"}: ${list}.`))\n }\n\n const cellIssues = widget.cellIssues ?? []\n if (cellIssues.length) {\n const first = cellIssues[0]!\n const where = first.column ? `${first.column} in row ${first.rowId}` : `row ${first.rowId}`\n const more = cellIssues.length > 1 ? ` (and ${cellIssues.length - 1} more)` : \"\"\n out.push(alert(\"cell-issues\", `${where}: ${first.message}${more}. Check the column's type, or the cell, in Grist.`))\n }\n\n const linking = parseGristWidgetLinkingInfo(state.interaction?.linking)\n if (widget.allowSelectBy) {\n if (linking && !linking.asSource) {\n out.push(\n alert(\n \"source-not-wired\",\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 )\n )\n }\n } else if (isWidgetSectionNotLinked(state.interaction)) {\n const hint = options.sectionNotLinkedHint?.trim()\n out.push(\n alert(\n \"section-not-linked\",\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 (hint ? ` ${hint}` : \"\")\n )\n )\n }\n\n const suppressed = widget.suppressAlerts ?? []\n return out.filter((a) => !suppressed.includes(a.kind))\n}\n\n/** @internal The alerts for the widget under the nearest `<GristWidgetProvider>`; [] outside one. */\nexport function useGristSdkAlerts(options?: GristSdkAlertsOptions): GristSdkAlertDescriptor[] {\n const { connection, state, cellIssues } = useNearestGristState()\n if (!connection) return []\n const { columns, allowSelectBy, suppressAlerts } = connection.runtime.options\n return getGristSdkAlerts(state, { columns, allowSelectBy, suppressAlerts, cellIssues }, options)\n}\n","import type { CSSProperties, ReactNode } from \"react\"\n\nimport { useGristSdkAlerts, type GristSdkAlertDescriptor, type GristSdkAlertsOptions } from \"../../sdk/helpers/grist-sdk-alerts\"\nimport { tokens } from \"./tokens\"\n\nconst ALERT_OPTIONS: GristSdkAlertsOptions = {\n sectionNotLinkedHint:\n \"In Grist, select this widget section on the page, then use Link to connect a table, card, or chart view as the selector.\",\n}\n\n/**\n * The default `Alerts` of {@link mountGristWidget}: what needs the user's\n * attention (column mapping, access level, failed writes, an unlinked\n * section), above the widget. Renders nothing extra when all is well.\n */\nexport function WidgetAlerts({ children }: { children: ReactNode }) {\n const alerts = useGristSdkAlerts(ALERT_OPTIONS)\n if (alerts.length === 0) return <>{children}</>\n\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: \"0.75rem\" }}>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: \"0.75rem\", padding: \"0.75rem 0.75rem 0\" }}>\n {alerts.map((alert) => (\n <WidgetAlert key={alert.id} alert={alert} />\n ))}\n </div>\n {children}\n </div>\n )\n}\n\nfunction WidgetAlert({ alert }: { alert: GristSdkAlertDescriptor }) {\n const linkIcon = alert.kind === \"section-not-linked\" || alert.kind === \"source-not-wired\"\n return (\n <div role={alert.ariaRole} style={{ ...alertStyle, ...SEVERITY[alert.severity] }}>\n <span aria-hidden style={{ flexShrink: 0, marginTop: \"0.125rem\" }}>\n {linkIcon ? <LinkIcon /> : <WarningIcon />}\n </span>\n <div style={{ minWidth: 0 }}>\n <p style={{ margin: 0, fontWeight: 500 }}>{alert.title}</p>\n <p style={{ margin: \"0.25rem 0 0\", color: tokens.mutedForeground }}>{alert.message}</p>\n </div>\n </div>\n )\n}\n\nconst alertStyle: CSSProperties = {\n boxSizing: \"border-box\",\n display: \"flex\",\n gap: \"0.75rem\",\n padding: \"0.75rem 1rem\",\n border: `1px solid ${tokens.border}`,\n borderRadius: tokens.radius,\n color: tokens.foreground,\n fontSize: \"0.875rem\",\n lineHeight: 1.5,\n}\n\nconst SEVERITY: Record<GristSdkAlertDescriptor[\"severity\"], CSSProperties> = {\n error: { borderColor: tokens.destructive, color: tokens.destructive },\n warning: { borderColor: \"rgb(245 158 11 / 0.4)\", background: \"rgb(245 158 11 / 0.1)\" },\n info: { background: \"transparent\" },\n}\n\nconst ICON = {\n width: 16,\n height: 16,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n} as const\n\nfunction WarningIcon() {\n return (\n <svg {...ICON}>\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n </svg>\n )\n}\n\nfunction LinkIcon() {\n return (\n <svg {...ICON}>\n <path d=\"M9 17H7A5 5 0 0 1 7 7h2\" />\n <path d=\"M15 7h2a5 5 0 1 1 0 10h-2\" />\n <line x1=\"8\" x2=\"16\" y1=\"12\" y2=\"12\" />\n </svg>\n )\n}\n","import { createContext, useCallback, useContext, useEffect, useMemo, useState, type ReactNode } from \"react\"\n\nimport { useNearestGristState } from \"../sdk/use-grist\"\n\nexport type WidgetTheme = \"light\" | \"dark\" | \"system\"\nexport type ResolvedWidgetTheme = \"light\" | \"dark\"\n\nexport type UseThemeResult = {\n /**\n * Inside Grist: Grist's theme, or `\"system\"` until Grist has sent it.\n * Outside Grist: the saved choice, `\"system\"` by default.\n */\n theme: WidgetTheme\n /** The theme applied to `<html class>`: `\"system\"` resolved to light or dark. */\n resolvedTheme: ResolvedWidgetTheme\n /**\n * Choose a theme outside Grist; it is saved in `localStorage`. Inside Grist\n * this does nothing: the widget follows Grist's theme.\n */\n setTheme: (theme: WidgetTheme) => void\n}\n\nconst STORAGE_KEY = \"theme\"\nconst DARK_QUERY = \"(prefers-color-scheme: dark)\"\nconst THEMES: readonly WidgetTheme[] = [\"light\", \"dark\", \"system\"]\n\nconst ThemeContext = createContext<UseThemeResult | null>(null)\n\n/**\n * The widget's current theme, for components that need it in JavaScript\n * (a toaster, a chart). Same shape as shadcn's `useTheme()`. Styles should\n * rely on the `dark` class that {@link mountGristWidget} keeps on `<html>`.\n * Outside a mounted widget (a unit test, for instance) it reports the\n * system theme and `setTheme` does nothing.\n */\nexport function useTheme(): UseThemeResult {\n const value = useContext(ThemeContext)\n return value ?? { theme: \"system\", resolvedTheme: systemTheme(), setTheme: noop }\n}\n\n/** Inside Grist: follows Grist's theme, and the OS setting until Grist sends one. */\nexport function EmbeddedThemeProvider({ children }: { children: ReactNode }) {\n const gristTheme = useNearestGristState().state.theme\n const system = useSystemTheme(gristTheme === null)\n const resolvedTheme = gristTheme ?? system\n\n useApplyTheme(resolvedTheme)\n\n const value = useMemo<UseThemeResult>(\n () => ({ theme: gristTheme ?? \"system\", resolvedTheme, setTheme: noop }),\n [gristTheme, resolvedTheme]\n )\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>\n}\n\n/**\n * Outside Grist (`pnpm dev`, the deployed release page): the saved choice,\n * the OS setting by default, and the `d` key to switch between light and\n * dark, as shadcn's theme provider does.\n */\nexport function StandaloneThemeProvider({ children }: { children: ReactNode }) {\n const [theme, setThemeState] = useState<WidgetTheme>(() => readStoredTheme() ?? \"system\")\n const system = useSystemTheme(theme === \"system\")\n const resolvedTheme = theme === \"system\" ? system : theme\n\n useApplyTheme(resolvedTheme)\n\n const setTheme = useCallback((next: WidgetTheme) => {\n writeStoredTheme(next)\n setThemeState(next)\n }, [])\n\n // `d` switches between light and dark, unless typing or using a shortcut.\n useEffect(() => {\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.repeat || event.metaKey || event.ctrlKey || event.altKey) return\n if (event.key.toLowerCase() !== \"d\" || isEditableTarget(event.target)) return\n setThemeState((current) => {\n const currentResolved = current === \"system\" ? systemTheme() : current\n const next: WidgetTheme = currentResolved === \"dark\" ? \"light\" : \"dark\"\n writeStoredTheme(next)\n return next\n })\n }\n window.addEventListener(\"keydown\", onKeyDown)\n return () => window.removeEventListener(\"keydown\", onKeyDown)\n }, [])\n\n // Another tab saving a choice applies here too.\n useEffect(() => {\n const onStorage = (event: StorageEvent) => {\n if (event.key !== STORAGE_KEY) return\n setThemeState(isTheme(event.newValue) ? event.newValue : \"system\")\n }\n window.addEventListener(\"storage\", onStorage)\n return () => window.removeEventListener(\"storage\", onStorage)\n }, [])\n\n const value = useMemo<UseThemeResult>(\n () => ({ theme, resolvedTheme, setTheme }),\n [theme, resolvedTheme, setTheme]\n )\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>\n}\n\n/** The OS setting, kept current while `active`. */\nfunction useSystemTheme(active: boolean): ResolvedWidgetTheme {\n const [theme, setTheme] = useState<ResolvedWidgetTheme>(systemTheme)\n\n useEffect(() => {\n if (!active || typeof window.matchMedia !== \"function\") return\n const query = window.matchMedia(DARK_QUERY)\n const onChange = () => setTheme(query.matches ? \"dark\" : \"light\")\n onChange()\n query.addEventListener(\"change\", onChange)\n return () => query.removeEventListener(\"change\", onChange)\n }, [active])\n\n return theme\n}\n\n/** Keep `light` or `dark` on `<html class>`, which Tailwind's dark variant reads. */\nfunction useApplyTheme(theme: ResolvedWidgetTheme) {\n useEffect(() => {\n const root = document.documentElement\n if (root.classList.contains(theme) && !root.classList.contains(other(theme))) return\n const restoreTransitions = suspendTransitions()\n root.classList.remove(other(theme))\n root.classList.add(theme)\n restoreTransitions()\n }, [theme])\n}\n\nfunction systemTheme(): ResolvedWidgetTheme {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") return \"light\"\n return window.matchMedia(DARK_QUERY).matches ? \"dark\" : \"light\"\n}\n\nfunction other(theme: ResolvedWidgetTheme): ResolvedWidgetTheme {\n return theme === \"dark\" ? \"light\" : \"dark\"\n}\n\n/** Switch themes without every color transition animating at once. */\nfunction suspendTransitions(): () => void {\n const style = document.createElement(\"style\")\n style.appendChild(\n document.createTextNode(\"*,*::before,*::after{-webkit-transition:none!important;transition:none!important}\")\n )\n document.head.appendChild(style)\n return () => {\n window.getComputedStyle(document.body)\n requestAnimationFrame(() => requestAnimationFrame(() => style.remove()))\n }\n}\n\nfunction isEditableTarget(target: EventTarget | null): boolean {\n if (!(target instanceof HTMLElement)) return false\n return target.isContentEditable || target.closest(\"input, textarea, select, [contenteditable='true']\") !== null\n}\n\nfunction isTheme(value: string | null): value is WidgetTheme {\n return value !== null && (THEMES as readonly string[]).includes(value)\n}\n\nfunction readStoredTheme(): WidgetTheme | null {\n try {\n const value = localStorage.getItem(STORAGE_KEY)\n return isTheme(value) ? value : null\n } catch {\n return null\n }\n}\n\nfunction writeStoredTheme(theme: WidgetTheme) {\n try {\n localStorage.setItem(STORAGE_KEY, theme)\n } catch {\n // Storage blocked (private mode, sandboxed iframe): the choice lasts for this page only.\n }\n}\n\nfunction noop() {}\n","/**\n * A test document from a widget's declared columns: one table, `Table1`,\n * with a column per declared column (typed after the first type it accepts)\n * and the given rows, each value stored as Grist stores it; and the mappings\n * that map every declared column to its namesake. Shared by\n * `smokeTestWidget` and `renderWithGrist({ widget })`.\n */\n\nimport { encodeGristCell } from \"../../sdk/runtime/cells\"\nimport type { GristColumnToMap, GristReplicaDocument, GristWidgetColumnMap, UseGristOptions } from \"../../sdk\"\n\nexport type Column = { name: string; type: string; declared: string | undefined; allowMultiple: boolean }\n\nexport function declaredColumns(options: UseGristOptions): Column[] {\n return (options.columns ?? []).map((column: string | GristColumnToMap) =>\n typeof column === \"string\"\n ? { name: column, type: \"Any\", declared: undefined, allowMultiple: false }\n : { name: column.name, type: firstType(column.type), declared: column.type, allowMultiple: column.allowMultiple === true }\n )\n}\n\n/** The first Grist type a column accepts: `\"Text,Ref,Choice\"` gives `\"Text\"`. */\nfunction firstType(type: string | undefined): string {\n return (type ?? \"Any\").split(\",\")[0].trim() || \"Any\"\n}\n\nexport function mapEveryColumn(columns: Column[]): GristWidgetColumnMap {\n return Object.fromEntries(columns.map((c) => [c.name, c.allowMultiple ? [c.name] : c.name]))\n}\n\n/**\n * One table with a column per declared column, and `rows` (under the declared\n * names, as typed reads give them: a `Date`, a `string[]`…), or one row of\n * sample values.\n */\nexport function declaredDocument(columns: Column[], rows?: ReadonlyArray<Record<string, unknown>>): GristReplicaDocument {\n const given = rows ?? [Object.fromEntries(columns.map((c) => [c.name, sampleValue(c.type)]))]\n return {\n generatedAt: \"1970-01-01T00:00:00.000Z\",\n docName: \"Test document\",\n mode: \"schema+data\",\n tables: {\n Table1: {\n columns: Object.fromEntries(columns.map((c) => [c.name, { type: c.type }])),\n rows: given.map((row, i) => ({\n id: typeof row.id === \"number\" ? row.id : i + 1,\n ...Object.fromEntries(columns.map((c) => [c.name, encodeGristCell(c.declared, row[c.name] ?? null)])),\n })),\n },\n },\n }\n}\n\nfunction sampleValue(type: string): unknown {\n switch (type) {\n case \"Numeric\":\n case \"Int\":\n return 42\n case \"Bool\":\n return true\n case \"Date\":\n case \"DateTime\":\n return 1767225600 // 2026-01-01, as Grist stores it: epoch seconds\n default:\n return \"Sample\"\n }\n}\n","import type { EventBus } from \"../core/event-bus\"\nimport type { CommandApiImpl } from \"./types\"\n\n/**\n * `CommandAPI` host implementation. The widget's \"Edit Options\" gear and a\n * few keyboard shortcuts call into this. We forward the call name on the bus\n * so the inspector and tests can observe it; useful to assert\n * `onEditOptions` flows.\n */\nexport function createCommandApiImpl(bus: EventBus): CommandApiImpl {\n return {\n async run(name) {\n bus.emit({ type: \"user-action\", action: [\"RunCommand\", name] })\n },\n }\n}\n","/**\n * Resolves the `mappings` payload that `CustomSectionAPI.mappings()` returns.\n *\n * The emulator does **not** infer logical → real columns from names, as\n * real Grist doesn't: mappings come only from `state.selection.mappings`\n * (a test's `emulator.setColumnMappings(...)`). When unset, returns `null`.\n */\n\nimport type { GristWidgetColumnMap } from \"../../sdk/types\"\nimport type { EmulatorDocumentState } from \"./types\"\n\nexport function resolveMappings(state: EmulatorDocumentState): GristWidgetColumnMap | null {\n if (state.selection.mappings !== undefined && state.selection.mappings !== null) {\n return state.selection.mappings\n }\n return null\n}\n","import { resolveMappings } from \"../core/mappings\"\nimport type { EventBus } from \"../core/event-bus\"\nimport type { GristWidgetConfiguration } from \"../../sdk/types\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport type { CustomSectionApiImpl } from \"./types\"\n\n/**\n * `CustomSectionAPI` host implementation, called by `grist-plugin-api.js`\n * after `grist.ready()` to hand the host the widget's preferences:\n * required access, declared columns, allowSelectBy, hasCustomOptions, etc.\n *\n * Implementation:\n * - persists the configuration onto `state.configuration`,\n * - emits a `ready` event so the transport knows it is safe to push\n * initial cursor / data / options messages,\n * - re-emits a `mappings-change` so the inspector and tests can react.\n */\nexport function createCustomSectionApiImpl(\n state: EmulatorDocumentState,\n bus: EventBus\n): CustomSectionApiImpl {\n return {\n async configure(settings) {\n const config: GristWidgetConfiguration = {\n requiredAccess: settings.requiredAccess as GristWidgetConfiguration[\"requiredAccess\"],\n columns: settings.columns as GristWidgetConfiguration[\"columns\"],\n allowSelectBy: settings.allowSelectBy as boolean | undefined,\n hasCustomOptions: settings.hasCustomOptions as boolean | undefined,\n }\n state.configuration = config\n bus.emit({ type: \"ready\", configuration: config })\n bus.emit({ type: \"mappings-change\", mappings: resolveMappings(state) })\n },\n\n async mappings() {\n return resolveMappings(state)\n },\n }\n}\n","import type { GristApiImpl } from \"./types\"\n\n/** `_grist_api` host implementation. Minimal v1 — extend as needed. */\nexport function createGristApiImpl(): GristApiImpl {\n return {\n async ping() {\n return \"pong\"\n },\n }\n}\n","import type { GristReplicaColumn } from \"../../sdk/types\"\n\n/** Ref / RefList column → the gristHelper_ column holding its display values. */\nexport function inferDisplayHelpersByRef(\n columns: Record<string, GristReplicaColumn>\n): Record<string, string> {\n const out: Record<string, string> = {}\n const helperColumns = Object.entries(columns).filter(([colId]) =>\n colId.startsWith(\"gristHelper_\")\n )\n const usedHelpers = new Set<string>()\n const colRefToColId = new Map<number, string>()\n for (const [colId, col] of Object.entries(columns)) {\n if (typeof col?.colRef === \"number\" && Number.isFinite(col.colRef)) {\n colRefToColId.set(col.colRef, colId)\n }\n }\n for (const [colId, col] of Object.entries(columns)) {\n const type = col?.type\n if (typeof type !== \"string\" || (!type.startsWith(\"Ref:\") && !type.startsWith(\"RefList:\"))) {\n continue\n }\n if (typeof col.displayColRef === \"number\" && Number.isFinite(col.displayColRef)) {\n const helperColId = colRefToColId.get(col.displayColRef)\n if (helperColId) {\n out[colId] = helperColId\n usedHelpers.add(helperColId)\n continue\n }\n }\n const match = helperColumns.find(([, helper]) => {\n const formula = helper?.formula\n return typeof formula === \"string\" && (formula.includes(`$${colId}.`) || formula.includes(`$${colId}`))\n })\n if (match) {\n out[colId] = match[0]\n usedHelpers.add(match[0])\n }\n }\n\n // Secondary fallback for schemas where helper formulas are unavailable:\n // pair unresolved Ref/RefList columns with nearest following gristHelper_*.\n const unresolvedRefs = Object.entries(columns)\n .filter(([colId, col]) => {\n const type = col?.type\n return (\n !out[colId] &&\n typeof type === \"string\" &&\n (type.startsWith(\"Ref:\") || type.startsWith(\"RefList:\"))\n )\n })\n .sort((a, b) => (a[1]?.parentPos ?? Number.MAX_SAFE_INTEGER) - (b[1]?.parentPos ?? Number.MAX_SAFE_INTEGER))\n const helperByPos = helperColumns\n .filter(([helperId]) => !usedHelpers.has(helperId))\n .sort((a, b) => (a[1]?.parentPos ?? Number.MAX_SAFE_INTEGER) - (b[1]?.parentPos ?? Number.MAX_SAFE_INTEGER))\n for (const [refId, refCol] of unresolvedRefs) {\n const refPos = refCol?.parentPos ?? Number.MAX_SAFE_INTEGER\n const candidate = helperByPos.find(([, helperCol]) => {\n const helperPos = helperCol?.parentPos ?? Number.MAX_SAFE_INTEGER\n return helperPos > refPos\n })\n if (!candidate) continue\n out[refId] = candidate[0]\n usedHelpers.add(candidate[0])\n }\n // If multiple unresolved refs remain, greedily map by order.\n for (const [refId] of unresolvedRefs) {\n if (out[refId]) continue\n const candidate = helperByPos.find(([helperId]) => !usedHelpers.has(helperId))\n if (!candidate) continue\n out[refId] = candidate[0]\n usedHelpers.add(candidate[0])\n }\n return out\n}\n","import { inferDisplayHelpersByRef } from \"./display-helpers\"\nimport { normalizeReplicaDocumentInput } from \"../../sdk/helpers/replica-normalize\"\nimport { coerceGristDocApiRefRowId } from \"../../sdk/helpers/grist-value-codec\"\nimport type { GristReplicaDocument, GristReplicaTable } from \"../../sdk/replica-document\"\nimport type { GristRowRecord } from \"../../sdk/types\"\nimport type { EmulatorColumn, EmulatorDocumentState, EmulatorTable } from \"./types\"\n\nconst SYSTEM_COLUMN = \"id\"\n\nconst EMULATOR_JS_FORMULA_PLACEHOLDER = \"(emulator JavaScript formula)\"\n\n/** Replica table for {@link createDocument}; columns may include `formulaFn` / `inferredFormula` (emulator-only). */\nexport type CreateDocumentTableInput = Omit<GristReplicaTable, \"columns\"> & {\n columns?: Record<string, EmulatorColumn>\n}\n\n/** Replica document for {@link createDocument}; widens table columns to {@link EmulatorColumn}. */\nexport type CreateDocumentInput = Omit<GristReplicaDocument, \"tables\"> & {\n tables: Record<string, CreateDocumentTableInput>\n}\n\n/**\n * Ensure `formula` (original) and `inferredFormula` strings exist alongside optional `formulaFn`.\n */\nexport function enrichEmulatorColumnMetadata(col: EmulatorColumn): EmulatorColumn {\n const originalTrimmed = col.formula?.trim() ?? \"\"\n const explicitInferred = col.inferredFormula?.trim() ?? \"\"\n\n if (col.formulaFn) {\n const inferredFormula =\n explicitInferred || originalTrimmed || EMULATOR_JS_FORMULA_PLACEHOLDER\n return {\n ...col,\n ...(originalTrimmed ? { formula: col.formula } : {}),\n inferredFormula,\n }\n }\n\n if (explicitInferred || originalTrimmed) {\n return {\n ...col,\n inferredFormula: explicitInferred || originalTrimmed || undefined,\n }\n }\n\n return col\n}\n\n/** Order merged column metadata for stable `fetchTable` / RDG column order. */\nexport function sortEmulatorColumnsByParentPos(columns: Record<string, EmulatorColumn>): Record<string, EmulatorColumn> {\n const entries = Object.entries(columns)\n entries.sort(([ka, a], [kb, b]) => {\n const pa = a.parentPos\n const pb = 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 ka.localeCompare(kb)\n })\n return Object.fromEntries(entries)\n}\n\nfunction inferColumnsFromRows(rows: GristRowRecord[]): Record<string, EmulatorColumn> {\n const columns: Record<string, EmulatorColumn> = {}\n for (const row of rows) {\n for (const key of Object.keys(row)) {\n if (key === SYSTEM_COLUMN) continue\n if (!columns[key]) columns[key] = inferColumnType(row[key])\n }\n }\n return columns\n}\n\nfunction inferColumnType(sample: unknown): EmulatorColumn {\n switch (typeof sample) {\n case \"number\":\n return { type: \"Numeric\" }\n case \"boolean\":\n return { type: \"Bool\" }\n case \"string\":\n return { type: \"Text\" }\n default:\n return { type: \"Any\" }\n }\n}\n\nfunction buildTable(tableId: string, input: CreateDocumentTableInput): EmulatorTable {\n const rows = input.rows ?? []\n const inferred = inferColumnsFromRows(rows)\n const merged: Record<string, EmulatorColumn> = {}\n for (const [colId, col] of Object.entries({ ...inferred, ...(input.columns ?? {}) })) {\n merged[colId] = enrichEmulatorColumnMetadata(col)\n }\n const columns = sortEmulatorColumnsByParentPos(merged)\n return {\n tableId,\n label: input.label,\n columns,\n rows: rows.map((row) => ({ ...row })),\n }\n}\n\n/**\n * Build an immutable initial document state from a user-provided\n * {@link GristReplicaDocument}. The state is **not** frozen — the action\n * engine mutates it in place under deterministic event diffusion.\n */\nexport function createDocument(input: CreateDocumentInput): EmulatorDocumentState {\n if (!input.tables || Object.keys(input.tables).length === 0) {\n throw new Error(\"createDocument: at least one table is required\")\n }\n\n const normalized = normalizeReplicaDocumentInput(input)\n\n const tables = new Map<string, EmulatorTable>()\n for (const [tableId, tableInput] of Object.entries(normalized.tables)) {\n tables.set(tableId, buildTable(tableId, tableInput))\n }\n\n const firstTableId = tables.keys().next().value as string\n const requestedTableId = normalized.selection?.tableId\n const selectedTableId =\n requestedTableId && tables.has(requestedTableId) ? requestedTableId : firstTableId\n const selectedTable = tables.get(selectedTableId)!\n const fallbackRowId =\n typeof selectedTable.rows[0]?.id === \"number\" ? selectedTable.rows[0].id : null\n const selection = {\n tableId: selectedTableId,\n rowId: normalized.selection?.rowId ?? fallbackRowId,\n mappings: normalized.selection?.mappings,\n cursor: normalized.selection?.cursor,\n } as EmulatorDocumentState[\"selection\"]\n\n return {\n docName: normalized.docName ?? \"Untitled emulator document\",\n tables,\n selection,\n widgetOptions: { ...(normalized.widgetOptions ?? {}) },\n widgetInteraction: { ...(normalized.widgetInteraction ?? {}) },\n configuration: normalized.configuration ?? null,\n accessToken: normalized.accessToken ?? null,\n }\n}\n\nexport function getTable(state: EmulatorDocumentState, tableId: string): EmulatorTable {\n const table = state.tables.get(tableId)\n if (!table) throw new Error(`Unknown table: ${tableId}`)\n return table\n}\n\nexport function getSelectedTable(state: EmulatorDocumentState): EmulatorTable {\n return getTable(state, state.selection.tableId)\n}\n\nexport function nextRowId(table: EmulatorTable): number {\n let max = 0\n for (const row of table.rows) {\n if (typeof row.id === \"number\" && row.id > max) max = row.id\n }\n return max + 1\n}\n\nexport function findRow(table: EmulatorTable, rowId: number): GristRowRecord | undefined {\n return table.rows.find((r) => r.id === rowId)\n}\n\nexport function findRowIndex(table: EmulatorTable, rowId: number): number {\n return table.rows.findIndex((r) => r.id === rowId)\n}\n\n/**\n * Re-evaluate every formula column for a given row in-place. Called by the\n * action engine after Add/Update operations.\n */\nexport function evaluateRowFormulas(\n state: EmulatorDocumentState,\n table: EmulatorTable,\n row: GristRowRecord\n): void {\n for (const [colId, col] of Object.entries(table.columns)) {\n if (col.formulaFn) {\n try {\n row[colId] = col.formulaFn(row, { table, document: state })\n } catch (err) {\n row[colId] = formulaError(err)\n }\n }\n }\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\n}\n\n/** Pull stored row ids from a `RefList` cell (`[\"L\", ...]` or legacy shapes). */\nfunction extractRefListIdsFromWire(raw: unknown): number[] {\n if (raw == null) return []\n if (!Array.isArray(raw)) return []\n const items = raw[0] === \"L\" ? raw.slice(1) : raw\n const out: number[] = []\n for (const item of items) {\n if (typeof item === \"number\" && Number.isFinite(item) && item > 0) {\n out.push(Math.trunc(item))\n continue\n }\n if (item && typeof item === \"object\" && \"rowId\" in item) {\n const r = (item as { rowId: unknown }).rowId\n if (typeof r === \"number\" && Number.isFinite(r) && r > 0) {\n out.push(Math.trunc(r))\n continue\n }\n }\n const t = coerceGristDocApiRefRowId(item)\n if (t !== undefined && t > 0) out.push(Math.trunc(t))\n }\n return Array.from(new Set(out))\n}\n\nfunction fieldFromRefListHelperFormula(formula: string | undefined, refColId: string): string | null {\n if (!formula) return null\n const re = new RegExp(`\\\\$${escapeRegExp(refColId)}\\\\.([A-Za-z_]\\\\w*)`)\n const m = formula.match(re)\n return m?.[1] ?? null\n}\n\nfunction firstTextLikeColumnId(columns: Record<string, EmulatorColumn>): string | null {\n let best: { id: string; pos: number } | null = null\n for (const [colId, col] of Object.entries(columns)) {\n if (colId === \"id\" || colId.startsWith(\"gristHelper_\")) continue\n const t = col.type\n if (t !== \"Text\" && t !== \"Choice\") continue\n const pos = col.parentPos ?? 99999\n if (!best || pos < best.pos) best = { id: colId, pos }\n }\n return best?.id ?? null\n}\n\nfunction formatLabelFromCell(value: unknown): string {\n if (value == null) return \"\"\n if (typeof value === \"string\") return value.trim()\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value)\n if (value instanceof Date) return value.toISOString()\n if (Array.isArray(value) && value[0] === \"E\") return \"\"\n if (typeof value === \"object\" && value && \"__ref\" in value) {\n const r = (value as { rowId?: unknown }).rowId\n return typeof r === \"number\" && Number.isFinite(r) ? String(r) : \"\"\n }\n return \"\"\n}\n\n/**\n * Keep `gristHelper_*` display columns aligned with `RefList:*` ids after writes.\n *\n * Real Grist evaluates helper formulas (`$multiref.Nom`); replica JSON only\n * carries the formula string (no `formulaFn`), so helpers would stay stale and\n * a widget reading them would see empty labels.\n *\n * Skips helpers that define `formulaFn` so custom JS formulas keep ownership.\n */\nexport function syncRefListDisplayHelpers(\n state: EmulatorDocumentState,\n table: EmulatorTable,\n row: GristRowRecord\n): void {\n const displayHelpersByRef = inferDisplayHelpersByRef(table.columns)\n for (const [colId, col] of Object.entries(table.columns)) {\n const type = col.type\n if (typeof type !== \"string\" || !type.startsWith(\"RefList:\")) continue\n const helperColId = displayHelpersByRef[colId]\n if (!helperColId) continue\n const helperMeta = table.columns[helperColId]\n if (!helperMeta || helperMeta.formulaFn) continue\n\n const targetTableId = type.slice(\"RefList:\".length)\n const targetTable = state.tables.get(targetTableId)\n if (!targetTable) continue\n\n const ids = extractRefListIdsFromWire(row[colId])\n if (ids.length === 0) {\n row[helperColId] = []\n continue\n }\n\n const fieldId =\n fieldFromRefListHelperFormula(helperMeta.formula, colId) ??\n firstTextLikeColumnId(targetTable.columns)\n\n const labels = ids.map((rid) => {\n if (!fieldId) return String(rid)\n const trow = findRow(targetTable, rid)\n if (!trow) return String(rid)\n const lbl = formatLabelFromCell(trow[fieldId])\n return lbl !== \"\" ? lbl : String(rid)\n })\n row[helperColId] = labels\n }\n}\n\nfunction formulaError(err: unknown): unknown {\n // Match Grist's encoded error format: [\"E\", code, message]\n const message = err instanceof Error ? err.message : String(err)\n return [\"E\", \"Error\", message]\n}\n\n/**\n * Synthesise `_grist_Tables` metadata from the emulator's in-memory tables.\n * Returns Grist's columnar wire shape.\n */\nexport function synthesizeTablesMeta(state: EmulatorDocumentState): Record<string, unknown[]> {\n const ids: number[] = []\n const tableIds: string[] = []\n const labels: (string | null)[] = []\n\n let nextId = 1\n for (const [tableId, table] of state.tables.entries()) {\n ids.push(nextId)\n tableIds.push(tableId)\n labels.push(table.label ?? null)\n nextId += 1\n }\n\n return {\n id: ids,\n tableId: tableIds,\n // Optional human-readable label; real Grist keeps more fields, but these\n // are sufficient for `buildReplicaDocumentFromDocApi` to resolve table ids.\n label: labels,\n }\n}\n\n/**\n * Synthesise `_grist_Tables_column` metadata from emulator tables/columns.\n * Mirrors the subset of fields consumed by `buildReplicaDocumentFromDocApi`.\n */\nexport function synthesizeTablesColumnMeta(state: EmulatorDocumentState): Record<string, unknown[]> {\n const parentIds: number[] = []\n const colIds: string[] = []\n const columnIds: number[] = []\n const types: (string | null)[] = []\n const labels: (string | null)[] = []\n const parentPos: (number | null)[] = []\n const isFormula: boolean[] = []\n const formulas: (string | null)[] = []\n const descriptions: (string | null)[] = []\n const widgetOptions: unknown[] = []\n const displayCol: (number | null)[] = []\n const visibleCol: (number | null)[] = []\n\n // Mirror the synthetic table ids from `synthesizeTablesMeta`.\n const tableIdToInternalId = new Map<string, number>()\n {\n let nextId = 1\n for (const [tableId] of state.tables.entries()) {\n tableIdToInternalId.set(tableId, nextId)\n nextId += 1\n }\n }\n\n for (const [tableId, table] of state.tables.entries()) {\n const parentInternalId = tableIdToInternalId.get(tableId)\n if (parentInternalId === undefined) continue\n\n for (const [colId, col] of Object.entries(table.columns)) {\n parentIds.push(parentInternalId)\n colIds.push(colId)\n // Prefer explicit `colRef` when present; fall back to 1-based index of insertion.\n const ref = typeof col.colRef === \"number\" ? col.colRef : columnIds.length + 1\n columnIds.push(ref)\n types.push(col.type ?? null)\n labels.push(col.label ?? null)\n parentPos.push(col.parentPos ?? null)\n isFormula.push(Boolean(col.isFormula))\n const formula = typeof col.formula === \"string\" ? col.formula : null\n formulas.push(formula)\n descriptions.push(col.description ?? null)\n widgetOptions.push(col.widgetOptions ?? null)\n displayCol.push(typeof col.displayColRef === \"number\" ? col.displayColRef : null)\n visibleCol.push(typeof col.visibleColRef === \"number\" ? col.visibleColRef : null)\n }\n }\n\n return {\n parentId: parentIds,\n colId: colIds,\n id: columnIds,\n type: types,\n label: labels,\n parentPos,\n isFormula,\n formula: formulas,\n description: descriptions,\n // Also expose legacy `descr` for robustness.\n descr: descriptions,\n widgetOptions,\n displayCol,\n visibleCol,\n }\n}\n","/**\n * Pure action engine: applies Grist user actions to an\n * {@link EmulatorDocumentState} and emits the resulting events on the bus.\n *\n * This is the single place where state mutates. Every API impl ultimately\n * routes through `applyUserActions` so behaviour is consistent regardless of\n * the surface (`grist.docApi.applyUserActions`, `selectedTable.create`,\n * `setCursorPos`, etc.).\n *\n * Supported user actions:\n * - AddRecord, BulkAddRecord\n * - UpdateRecord, BulkUpdateRecord\n * - RemoveRecord, BulkRemoveRecord\n * - AddColumn, RemoveColumn, RenameColumn, ModifyColumn\n * - AddTable, RemoveTable, RenameTable\n *\n * Unknown actions throw a structured error instead of silently succeeding,\n * which surfaces protocol gaps loudly during widget development.\n */\n\nimport { coerceGristDocApiRefRowId } from \"../../sdk/helpers/grist-value-codec\"\nimport {\n evaluateRowFormulas,\n findRow,\n findRowIndex,\n getTable,\n nextRowId,\n syncRefListDisplayHelpers,\n} from \"./document\"\nimport type { EventBus } from \"./event-bus\"\nimport type { EmulatorColumn, EmulatorDocumentState, EmulatorTable } from \"./types\"\n\nexport class EmulatorActionError extends Error {\n constructor(\n public readonly action: unknown,\n message: string\n ) {\n super(message)\n this.name = \"EmulatorActionError\"\n }\n}\n\nexport type ApplyUserActionResult = {\n /** Result mirroring Grist's `applyUserActions`: per-action retValues. */\n retValues: unknown[]\n /** Tables that received row-level changes (de-duped). */\n changedTableIds: string[]\n}\n\nexport function applyUserActions(\n state: EmulatorDocumentState,\n bus: EventBus,\n actions: unknown[][]\n): ApplyUserActionResult {\n const retValues: unknown[] = []\n const changed = new Set<string>()\n\n for (const action of actions) {\n bus.emit({ type: \"user-action\", action })\n const ret = applySingle(state, action, changed)\n retValues.push(ret)\n }\n\n for (const tableId of changed) {\n bus.emit({ type: \"data-change\", tableId })\n }\n\n return { retValues, changedTableIds: [...changed] }\n}\n\nfunction applySingle(\n state: EmulatorDocumentState,\n action: unknown[],\n changed: Set<string>\n): unknown {\n const [name, ...args] = action\n switch (name) {\n case \"AddRecord\":\n return addRecord(state, args, changed)\n case \"BulkAddRecord\":\n return bulkAddRecord(state, args, changed)\n case \"UpdateRecord\":\n return updateRecord(state, args, changed)\n case \"BulkUpdateRecord\":\n return bulkUpdateRecord(state, args, changed)\n case \"RemoveRecord\":\n return removeRecord(state, args, changed)\n case \"BulkRemoveRecord\":\n return bulkRemoveRecord(state, args, changed)\n case \"AddColumn\":\n return addColumn(state, args)\n case \"AddVisibleColumn\":\n // The emulator has no concept of section view fields, so the \"visible\"\n // part of `AddVisibleColumn` is a no-op here. We still create the\n // column so widgets that issue this user action (the higher-level form\n // recommended by Grist for \"add a column to the active view\") work\n // identically against the emulator.\n return addColumn(state, args)\n case \"RemoveColumn\":\n return removeColumn(state, args, changed)\n case \"RenameColumn\":\n return renameColumn(state, args, changed)\n case \"ModifyColumn\":\n return modifyColumn(state, args, changed)\n case \"AddTable\":\n return addTable(state, args)\n case \"RemoveTable\":\n return removeTable(state, args)\n case \"RenameTable\":\n return renameTable(state, args)\n default:\n throw new EmulatorActionError(action, `Unsupported user action: ${String(name)}`)\n }\n}\n\n// ---------- row ops ----------\n\nfunction addRecord(\n state: EmulatorDocumentState,\n [tableId, rowId, values]: unknown[],\n changed: Set<string>\n): number {\n const table = getTable(state, requireString(tableId, \"AddRecord.tableId\"))\n const id = typeof rowId === \"number\" ? rowId : nextRowId(table)\n const normalizedValues = normalizeValuesForTable(\n table,\n (values as Record<string, unknown>) ?? {}\n )\n const row = { id, ...normalizedValues }\n ensureColumns(table, normalizedValues)\n evaluateRowFormulas(state, table, row)\n syncRefListDisplayHelpers(state, table, row)\n table.rows.push(row)\n changed.add(table.tableId)\n return id\n}\n\nfunction bulkAddRecord(\n state: EmulatorDocumentState,\n [tableId, rowIds, columnar]: unknown[],\n changed: Set<string>\n): number[] {\n const table = getTable(state, requireString(tableId, \"BulkAddRecord.tableId\"))\n const cols = normalizeColumnarForTable(\n table,\n (columnar as Record<string, unknown[]>) ?? {}\n )\n const ids = Array.isArray(rowIds) ? rowIds : []\n const length = ids.length || lengthOf(cols)\n const out: number[] = []\n ensureColumns(table, cols, true)\n for (let i = 0; i < length; i++) {\n const id = typeof ids[i] === \"number\" ? (ids[i] as number) : nextRowId(table)\n const row: Record<string, unknown> & { id: number } = { id }\n for (const colId of Object.keys(cols)) row[colId] = cols[colId][i]\n evaluateRowFormulas(state, table, row)\n syncRefListDisplayHelpers(state, table, row)\n table.rows.push(row)\n out.push(id)\n }\n changed.add(table.tableId)\n return out\n}\n\nfunction updateRecord(\n state: EmulatorDocumentState,\n [tableId, rowId, values]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"UpdateRecord.tableId\"))\n const id = requireNumber(rowId, \"UpdateRecord.rowId\")\n const row = findRow(table, id)\n if (!row) throw new EmulatorActionError([\"UpdateRecord\", tableId, rowId, values], `Row ${id} not found in ${table.tableId}`)\n const normalizedValues = normalizeValuesForTable(\n table,\n (values as Record<string, unknown>) ?? {}\n )\n ensureColumns(table, normalizedValues)\n Object.assign(row, normalizedValues)\n evaluateRowFormulas(state, table, row)\n syncRefListDisplayHelpers(state, table, row)\n changed.add(table.tableId)\n return null\n}\n\nfunction bulkUpdateRecord(\n state: EmulatorDocumentState,\n [tableId, rowIds, columnar]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"BulkUpdateRecord.tableId\"))\n const ids = rowIds as number[]\n const cols = normalizeColumnarForTable(\n table,\n (columnar as Record<string, unknown[]>) ?? {}\n )\n ensureColumns(table, cols, true)\n ids.forEach((id, idx) => {\n const row = findRow(table, id)\n if (!row) throw new EmulatorActionError([\"BulkUpdateRecord\", tableId, ids, cols], `Row ${id} not found in ${table.tableId}`)\n for (const colId of Object.keys(cols)) row[colId] = cols[colId][idx]\n evaluateRowFormulas(state, table, row)\n syncRefListDisplayHelpers(state, table, row)\n })\n changed.add(table.tableId)\n return null\n}\n\nfunction removeRecord(\n state: EmulatorDocumentState,\n [tableId, rowId]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"RemoveRecord.tableId\"))\n const id = requireNumber(rowId, \"RemoveRecord.rowId\")\n const idx = findRowIndex(table, id)\n if (idx >= 0) table.rows.splice(idx, 1)\n if (state.selection.tableId === table.tableId && state.selection.rowId === id) {\n state.selection.rowId = table.rows[0]?.id ?? null\n }\n changed.add(table.tableId)\n return null\n}\n\nfunction bulkRemoveRecord(\n state: EmulatorDocumentState,\n [tableId, rowIds]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"BulkRemoveRecord.tableId\"))\n const ids = new Set(rowIds as number[])\n table.rows = table.rows.filter((r) => !ids.has(r.id))\n if (state.selection.tableId === table.tableId && typeof state.selection.rowId === \"number\" && ids.has(state.selection.rowId)) {\n state.selection.rowId = table.rows[0]?.id ?? null\n }\n changed.add(table.tableId)\n return null\n}\n\n// ---------- column ops ----------\n\nfunction addColumn(\n state: EmulatorDocumentState,\n [tableId, colId, info]: unknown[]\n): null {\n const table = getTable(state, requireString(tableId, \"AddColumn.tableId\"))\n const col = requireString(colId, \"AddColumn.colId\")\n if (table.columns[col]) throw new EmulatorActionError([\"AddColumn\", tableId, colId], `Column ${col} already exists`)\n table.columns[col] = (info as EmulatorColumn) ?? {}\n for (const row of table.rows) {\n if (!(col in row)) row[col] = null\n }\n return null\n}\n\nfunction removeColumn(\n state: EmulatorDocumentState,\n [tableId, colId]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"RemoveColumn.tableId\"))\n const col = requireString(colId, \"RemoveColumn.colId\")\n delete table.columns[col]\n for (const row of table.rows) delete row[col]\n changed.add(table.tableId)\n return null\n}\n\nfunction renameColumn(\n state: EmulatorDocumentState,\n [tableId, colId, newColId]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"RenameColumn.tableId\"))\n const from = requireString(colId, \"RenameColumn.colId\")\n const to = requireString(newColId, \"RenameColumn.newColId\")\n if (!table.columns[from]) throw new EmulatorActionError([\"RenameColumn\", tableId, from, to], `Column ${from} not found`)\n if (from === to) return null\n table.columns[to] = table.columns[from]\n delete table.columns[from]\n for (const row of table.rows) {\n if (from in row) {\n row[to] = row[from]\n delete row[from]\n }\n }\n changed.add(table.tableId)\n return null\n}\n\nfunction modifyColumn(\n state: EmulatorDocumentState,\n [tableId, colId, info]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"ModifyColumn.tableId\"))\n const col = requireString(colId, \"ModifyColumn.colId\")\n if (!table.columns[col]) throw new EmulatorActionError([\"ModifyColumn\", tableId, colId], `Column ${col} not found`)\n table.columns[col] = { ...table.columns[col], ...(info as EmulatorColumn) }\n changed.add(table.tableId)\n return null\n}\n\n// ---------- table ops ----------\n\nfunction addTable(state: EmulatorDocumentState, [tableId, columns]: unknown[]): string {\n const id = requireString(tableId, \"AddTable.tableId\")\n if (state.tables.has(id)) throw new EmulatorActionError([\"AddTable\", tableId], `Table ${id} already exists`)\n const cols: Record<string, EmulatorColumn> = {}\n for (const c of (columns as Array<{ id: string } & EmulatorColumn>) ?? []) {\n cols[c.id] = { ...c }\n }\n state.tables.set(id, { tableId: id, columns: cols, rows: [] })\n return id\n}\n\nfunction removeTable(state: EmulatorDocumentState, [tableId]: unknown[]): null {\n const id = requireString(tableId, \"RemoveTable.tableId\")\n state.tables.delete(id)\n if (state.selection.tableId === id) {\n const fallback = state.tables.keys().next().value as string | undefined\n if (fallback) {\n state.selection.tableId = fallback\n state.selection.rowId = null\n }\n }\n return null\n}\n\nfunction renameTable(state: EmulatorDocumentState, [from, to]: unknown[]): null {\n const fromId = requireString(from, \"RenameTable.from\")\n const toId = requireString(to, \"RenameTable.to\")\n const table = state.tables.get(fromId)\n if (!table) throw new EmulatorActionError([\"RenameTable\", fromId], `Table ${fromId} not found`)\n state.tables.delete(fromId)\n table.tableId = toId\n state.tables.set(toId, table)\n if (state.selection.tableId === fromId) state.selection.tableId = toId\n return null\n}\n\n// ---------- helpers ----------\n\nfunction ensureColumns(\n table: EmulatorTable,\n values: Record<string, unknown> | Record<string, unknown[]>,\n bulk = false\n): void {\n for (const col of Object.keys(values)) {\n if (!table.columns[col]) {\n const sample = bulk ? (values as Record<string, unknown[]>)[col]?.[0] : (values as Record<string, unknown>)[col]\n table.columns[col] = inferType(sample)\n }\n }\n}\n\nfunction inferType(sample: unknown): EmulatorColumn {\n switch (typeof sample) {\n case \"number\":\n return { type: \"Numeric\" }\n case \"boolean\":\n return { type: \"Bool\" }\n case \"string\":\n return { type: \"Text\" }\n default:\n return { type: \"Any\" }\n }\n}\n\nfunction lengthOf(cols: Record<string, unknown[]>): number {\n for (const arr of Object.values(cols)) if (Array.isArray(arr)) return arr.length\n return 0\n}\n\nfunction requireString(value: unknown, name: string): string {\n if (typeof value !== \"string\" || !value) throw new Error(`Expected non-empty string for ${name}`)\n return value\n}\n\nfunction requireNumber(value: unknown, name: string): number {\n if (typeof value !== \"number\" || Number.isNaN(value)) throw new Error(`Expected number for ${name}`)\n return value\n}\n\nfunction normalizeValuesForTable(\n table: EmulatorTable,\n values: Record<string, unknown>\n): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const [colId, value] of Object.entries(values)) {\n out[colId] = normalizeCellValueForType(value, table.columns[colId]?.type)\n }\n return out\n}\n\nfunction normalizeColumnarForTable(\n table: EmulatorTable,\n columns: Record<string, unknown[]>\n): Record<string, unknown[]> {\n const out: Record<string, unknown[]> = {}\n for (const [colId, values] of Object.entries(columns)) {\n const type = table.columns[colId]?.type\n out[colId] = Array.isArray(values)\n ? values.map((value) => normalizeCellValueForType(value, type))\n : []\n }\n return out\n}\n\nfunction normalizeCellValueForType(value: unknown, type: string | undefined): unknown {\n if (value === null || value === undefined || typeof type !== \"string\") return value\n\n // As Grist does (checked in 1.7.22): a list column takes `[\"L\", ...]`; a\n // bare array written to it is stored as an error cell, not as the list.\n if (isListColumnType(type) && Array.isArray(value) && value[0] !== \"L\") return [\"E\", \"KeyError\"]\n if (type.startsWith(\"Ref:\")) return normalizeRefValue(value)\n if (type.startsWith(\"RefList:\")) return normalizeRefListValue(value)\n return value\n}\n\n/**\n * Canonical ref row id for emulator storage (`Ref:*` columns).\n * Accepts bare ids, `\"12\"`, Grist tuples `[\"r\", id]` / `[\"R\", tableId, id]`,\n * and detailed-ref shapes `{ rowId }` (decoded `Reference` values, grid edits).\n */\nfunction extractRefRowId(value: unknown): number | null {\n if (value === null || value === undefined) return null\n if (value && typeof value === \"object\" && \"__ref\" in value) {\n const inner = (value as { rowId?: unknown }).rowId\n return extractRefRowId(inner)\n }\n if (value && typeof value === \"object\" && \"rowId\" in value) {\n return extractRefRowId((value as { rowId: unknown }).rowId)\n }\n const fromTuple = coerceGristDocApiRefRowId(value)\n if (fromTuple !== undefined && fromTuple > 0) return Math.trunc(fromTuple)\n return toPositiveInt(value)\n}\n\nfunction isListColumnType(type: string): boolean {\n return type === \"ChoiceList\" || type === \"Attachments\" || type.startsWith(\"RefList:\")\n}\n\nfunction normalizeRefValue(value: unknown): number | null {\n return extractRefRowId(value)\n}\n\nfunction normalizeRefListValue(value: unknown): unknown[] {\n const toIdList = (items: unknown[]): number[] =>\n Array.from(\n new Set(items.map((item) => extractRefRowId(item)).filter((item): item is number => item !== null))\n )\n\n // Grist tuple form: [\"L\", ...ids]\n if (Array.isArray(value) && value[0] === \"L\") {\n return [\"L\", ...toIdList(value.slice(1))]\n }\n if (Array.isArray(value)) {\n return [\"L\", ...toIdList(value)]\n }\n if (typeof value === \"string\") {\n const tokens = value.split(\",\").map((t) => t.trim()).filter(Boolean)\n return [\"L\", ...toIdList(tokens)]\n }\n if (value && typeof value === \"object\" && Array.isArray((value as { rowIds?: unknown }).rowIds)) {\n return [\"L\", ...toIdList((value as { rowIds: unknown[] }).rowIds)]\n }\n return [\"L\"]\n}\n\nfunction toPositiveInt(value: unknown): number | null {\n if (typeof value === \"number\" && Number.isFinite(value) && value > 0) return Math.trunc(value)\n if (typeof value === \"string\") {\n const n = Number.parseInt(value.trim(), 10)\n if (Number.isFinite(n) && n > 0) return n\n }\n return null\n}\n","/**\n * Helpers to project an {@link EmulatorTable}'s row-array storage into Grist's\n * columnar wire format expected by `fetchTable` / `fetchSelectedTable`:\n *\n * { id: number[], colA: unknown[], colB: unknown[], ... }\n *\n * When `keepEncoded` is `false` (Grist's default for these APIs), values are\n * passed through as-is — JS-native primitives (string / number / boolean /\n * Date / arrays) are valid Grist plugin values. When `keepEncoded` is `true`,\n * Date columns are emitted in tuple form (`[\"d\", epoch]`) so callers can\n * round-trip them.\n */\n\nimport type { GristRowRecord } from \"../../sdk/types\"\nimport type { EmulatorTable } from \"./types\"\n\nexport type ColumnarTable = Record<string, unknown[]>\n\nexport type ToColumnarOptions = {\n keepEncoded?: boolean\n}\n\nexport function rowsToColumnar(\n table: EmulatorTable,\n rows: readonly GristRowRecord[],\n options: ToColumnarOptions = {}\n): ColumnarTable {\n const cols = Object.keys(table.columns)\n const out: ColumnarTable = { id: rows.map((r) => r.id) }\n for (const col of cols) {\n out[col] = rows.map((r) => encodeForWire(r[col], table.columns[col]?.type, options.keepEncoded))\n }\n return out\n}\n\nexport function rowToRecord(\n table: EmulatorTable,\n row: GristRowRecord,\n options: ToColumnarOptions = {}\n): Record<string, unknown> {\n const out: Record<string, unknown> = { id: row.id }\n for (const col of Object.keys(table.columns)) {\n out[col] = encodeForWire(row[col], table.columns[col]?.type, options.keepEncoded)\n }\n return out\n}\n\nfunction encodeForWire(value: unknown, type: string | undefined, keepEncoded: boolean | undefined): unknown {\n if (value instanceof Date) {\n const epoch = Math.floor(value.getTime() / 1000)\n if (keepEncoded) {\n return type && type.startsWith(\"DateTime\") ? [\"D\", epoch, \"UTC\"] : [\"d\", epoch]\n }\n return epoch\n }\n return value\n}\n","import { applyUserActions } from \"../core/action-engine\"\nimport { rowsToColumnar } from \"../core/columnar\"\nimport { getTable, synthesizeTablesColumnMeta, synthesizeTablesMeta } from \"../core/document\"\nimport type { EventBus } from \"../core/event-bus\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport type { GristDocApiImpl } from \"./types\"\n\n/**\n * `GristDocAPI` host implementation. Backs `grist.docApi.*` methods such as\n * `getDocName`, `listTables`, `fetchTable`, `applyUserActions` and\n * `getAccessToken`.\n *\n * `applyUserActions` is the only mutation entry point — every widget write\n * lands here, so tests can listen on the bus for `user-action` events to\n * assert exactly which actions a UI flow generated.\n */\nexport function createGristDocApiImpl(state: EmulatorDocumentState, bus: EventBus): GristDocApiImpl {\n return {\n async getDocName() {\n return state.docName\n },\n\n async listTables() {\n return [...state.tables.keys()]\n },\n\n async fetchTable(tableId) {\n if (tableId === \"_grist_Tables\") {\n return synthesizeTablesMeta(state)\n }\n if (tableId === \"_grist_Tables_column\") {\n return synthesizeTablesColumnMeta(state)\n }\n const table = getTable(state, tableId)\n return rowsToColumnar(table, table.rows)\n },\n\n async applyUserActions(actions) {\n const result = applyUserActions(state, bus, actions)\n return { retValues: result.retValues }\n },\n\n async getAccessToken() {\n if (!state.accessToken) {\n const err = new Error(\"getAccessToken not available (no token configured on emulator)\")\n // Mirror Grist's protocol: rejected stub call.\n throw err\n }\n return { ...state.accessToken }\n },\n }\n}\n","import { rowToRecord, rowsToColumnar } from \"../core/columnar\"\nimport { findRow, getSelectedTable } from \"../core/document\"\nimport type { EventBus } from \"../core/event-bus\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport type { GristViewImpl } from \"./types\"\n\n/**\n * `GristView` host implementation.\n *\n * Exposes the section-scoped data API the widget uses through\n * `grist.docApi.fetchSelectedTable()`, `fetchSelectedRecord()` and\n * `setCursorPos()`. Reads from the emulator state, writes to the same state\n * via the action engine where applicable, and emits events on the bus so\n * subscribers (transports, inspector, tests) stay in sync.\n *\n * IMPORTANT: `fetchSelectedTable` always returns Grist's **columnar** wire\n * shape. The production `grist-plugin-api.js` wrapper (which the iframe\n * transport talks to) expects the raw RPC stub to return columnar and does\n * the `format: \"rows\"` transposition + `keepEncoded: false` decoding itself.\n * Returning rows here used to crash the wrapper's `mapValues(data, col =>\n * col.map(decodeObject))` pass — `data` was an array, `col` was a row object\n * with no `.map` method — so widgets observed `records === null` forever.\n * The inline transport mirrors the same wrapper semantics in\n * `transports/inline.ts` so widget code sees identical results in both modes.\n */\nexport function createGristViewImpl(state: EmulatorDocumentState, bus: EventBus): GristViewImpl {\n return {\n async fetchSelectedTable(options) {\n const table = getSelectedTable(state)\n return rowsToColumnar(table, table.rows, { keepEncoded: options?.keepEncoded })\n },\n\n async fetchSelectedRecord(rowId, options) {\n const table = getSelectedTable(state)\n const row = findRow(table, rowId)\n if (!row) throw new Error(`No row ${rowId} in ${table.tableId}`)\n return rowToRecord(table, row, { keepEncoded: options?.keepEncoded })\n },\n\n async allowSelectBy() {\n return state.configuration?.allowSelectBy ?? false\n },\n\n async setSelectedRows(rowIds) {\n if (!rowIds || rowIds.length === 0) {\n state.selection.rowId = null\n } else {\n state.selection.rowId = rowIds[0]\n }\n bus.emit({\n type: \"cursor-change\",\n tableId: state.selection.tableId,\n rowId: state.selection.rowId,\n })\n },\n\n async setCursorPos(cursor) {\n const tableId = state.selection.tableId\n if (typeof cursor.rowId === \"number\") state.selection.rowId = cursor.rowId\n state.selection.cursor = { ...state.selection.cursor, ...cursor }\n bus.emit({\n type: \"cursor-change\",\n tableId,\n rowId: state.selection.rowId,\n cursor: state.selection.cursor,\n })\n },\n }\n}\n","import type { EventBus } from \"../core/event-bus\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport type { WidgetApiImpl } from \"./types\"\n\n/**\n * `WidgetAPI` host implementation, backing `grist.widgetApi.*`. Reads and\n * writes the per-widget options bag persisted on the emulator state. Each\n * mutation triggers an `options-change` event so subscribers (the transport\n * pushes an `onOptions` message; tests/inspector update accordingly) stay in\n * lock-step with the document.\n */\nexport function createWidgetApiImpl(state: EmulatorDocumentState, bus: EventBus): WidgetApiImpl {\n function emit() {\n bus.emit({\n type: \"options-change\",\n options: { ...state.widgetOptions },\n interaction: { ...state.widgetInteraction },\n })\n }\n\n return {\n async getOption(key) {\n return state.widgetOptions[key]\n },\n\n async setOption(key, value) {\n state.widgetOptions[key] = value\n emit()\n },\n\n async getOptions() {\n return Object.keys(state.widgetOptions).length > 0 ? { ...state.widgetOptions } : null\n },\n\n // Replaces every option, as Grist's WidgetAPI.setOptions does.\n async setOptions(options) {\n state.widgetOptions = { ...options }\n emit()\n },\n\n async clearOptions() {\n state.widgetOptions = {}\n emit()\n },\n }\n}\n","/**\n * Bundles the six host-side Grist API implementations into one record so\n * inline transport can wire them up.\n */\n\nimport type { EventBus } from \"../core/event-bus\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport { createCommandApiImpl } from \"./command-api\"\nimport { createCustomSectionApiImpl } from \"./custom-section-api\"\nimport { createGristApiImpl } from \"./grist-api\"\nimport { createGristDocApiImpl } from \"./grist-doc-api\"\nimport { createGristViewImpl } from \"./grist-view\"\nimport type {\n CommandApiImpl,\n CustomSectionApiImpl,\n GristApiImpl,\n GristDocApiImpl,\n GristViewImpl,\n WidgetApiImpl,\n} from \"./types\"\nimport { createWidgetApiImpl } from \"./widget-api\"\n\nexport type EmulatorApiBundle = {\n GristView: GristViewImpl\n GristDocAPI: GristDocApiImpl\n WidgetAPI: WidgetApiImpl\n CustomSectionAPI: CustomSectionApiImpl\n GristAPI: GristApiImpl\n CommandAPI: CommandApiImpl\n}\n\n/**\n * Build the implementations bound to a given document state and event bus.\n * Cheap to call — every method delegates to the (mutable) `state`.\n */\nexport function createApiBundle(state: EmulatorDocumentState, bus: EventBus): EmulatorApiBundle {\n return {\n GristView: createGristViewImpl(state, bus),\n GristDocAPI: createGristDocApiImpl(state, bus),\n WidgetAPI: createWidgetApiImpl(state, bus),\n CustomSectionAPI: createCustomSectionApiImpl(state, bus),\n GristAPI: createGristApiImpl(),\n CommandAPI: createCommandApiImpl(bus),\n }\n}\n\nexport type {\n CommandApiImpl,\n CustomSectionApiImpl,\n GristApiImpl,\n GristDocApiImpl,\n GristViewImpl,\n WidgetApiImpl,\n} from \"./types\"\n","/**\n * Tiny pub-sub used to broadcast every emulator state change to:\n * - the transports (which translate events into protocol messages),\n * - the React DevTools inspector (timeline view),\n * - the testing harness (assertions on emitted events).\n */\n\nimport type { GristCursorPos, GristWidgetColumnMap, GristWidgetInteraction } from \"../../sdk/types\"\n\nexport type EmulatorEvent =\n | { type: \"data-change\"; tableId: string }\n | { type: \"cursor-change\"; tableId: string; rowId: number | \"new\" | null; cursor?: GristCursorPos }\n | { type: \"options-change\"; options: Record<string, unknown>; interaction: GristWidgetInteraction }\n | { type: \"theme-change\"; message: Record<string, unknown> }\n | { type: \"ready\"; configuration: unknown }\n | { type: \"user-action\"; action: unknown[] }\n | { type: \"mappings-change\"; mappings: GristWidgetColumnMap | null }\n\nexport type EmulatorEventListener = (event: EmulatorEvent) => void\n\nexport type EventBus = {\n emit: (event: EmulatorEvent) => void\n on: (listener: EmulatorEventListener) => () => void\n history: () => readonly EmulatorEvent[]\n clear: () => void\n}\n\nexport type EventBusOptions = {\n /** Cap on history length (DevTools / tests). Defaults to 200. */\n historyLimit?: number\n}\n\nexport function createEventBus(options: EventBusOptions = {}): EventBus {\n const limit = options.historyLimit ?? 200\n const listeners = new Set<EmulatorEventListener>()\n const history: EmulatorEvent[] = []\n\n return {\n emit(event) {\n history.push(event)\n if (history.length > limit) history.shift()\n for (const fn of [...listeners]) {\n try {\n fn(event)\n } catch (err) {\n console.error(\"[grist-emulator] event listener threw:\", err)\n }\n }\n },\n on(listener) {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n history() {\n return history\n },\n clear() {\n history.length = 0\n },\n }\n}\n","export type GristThemeAppearance = \"light\" | \"dark\"\n\n/** Host → widget postMessage shape used by `grist-plugin-api.js` (`onThemeChange`). */\nexport type GristThemeHostMessage = {\n theme: {\n appearance: GristThemeAppearance\n name: string\n colors: Record<string, string>\n }\n fromReady?: boolean\n}\n\nexport function buildGristThemeHostMessage(\n appearance: GristThemeAppearance,\n options?: { fromReady?: boolean }\n): GristThemeHostMessage {\n return {\n theme: {\n appearance,\n name: appearance,\n colors: {},\n },\n ...(options?.fromReady ? { fromReady: true } : {}),\n }\n}\n","/**\n * Inline transport — synthesises a `window.grist` global wired directly to\n * the emulator state. No iframe, no postMessage, no serialization.\n *\n * Used for:\n * - SDK unit tests in jsdom (`renderWithGrist(...)`),\n * - IDE-style live previews where widget code lives in the same window\n * as the emulator host.\n *\n * The synthesised `grist` object exposes the **same** typed surface as the\n * production `grist-plugin-api.js` (see `hooks/grist-global.d.ts`). Hooks\n * call `grist.docApi.fetchTable(...)` etc. and get the answer directly from\n * the action engine.\n */\n\nimport type {\n GristCursorPos,\n GristFetchSelectedOptions,\n GristMinimalRecord,\n GristReadyOptions,\n GristTableOpOptions,\n GristTableOperations,\n GristTableUpdateRecord,\n GristTableUpsertOptions,\n GristTableUpsertRecord,\n GristWidgetColumnMap,\n GristWidgetInteraction,\n} from \"../../sdk/types\"\nimport {\n gristAddRecordAction,\n gristBulkAddRecordAction,\n gristBulkRemoveRecordAction,\n gristBulkUpdateRecordAction,\n gristRemoveRecordAction,\n gristUpdateRecordAction,\n} from \"../../sdk/helpers/grist-user-actions\"\nimport { applyUserActions } from \"../core/action-engine\"\nimport type { EmulatorEvent } from \"../core/event-bus\"\nimport { findRow, getTable } from \"../core/document\"\nimport { resolveMappings } from \"../core/mappings\"\nimport { buildGristThemeHostMessage } from \"../theme-message\"\nimport type { EmulatorTransport, TransportContext } from \"./types\"\n\n/**\n * Shape of the synthesised global. Matches `globalThis.grist` from\n * `grist-global.d.ts`.\n */\nexport type InlineGristGlobal = {\n ready: (options?: GristReadyOptions) => Promise<void>\n onRecord: (\n cb: (record: Record<string, unknown> | null, mappings?: GristWidgetColumnMap | null) => void,\n options?: GristFetchSelectedOptions\n ) => void\n onRecords: (\n cb: (records: Record<string, unknown>[], mappings?: GristWidgetColumnMap | null) => void,\n options?: GristFetchSelectedOptions\n ) => void\n onOptions: (cb: (options: Record<string, unknown> | null, interaction: GristWidgetInteraction) => void) => void\n onNewRecord: (cb: (mappings: GristWidgetColumnMap | null) => void) => void\n mapColumnNames: (data: Record<string, unknown>) => Record<string, unknown> | null\n mapColumnNamesBack: (data: Record<string, unknown>) => Record<string, unknown>\n getOptions: () => Promise<Record<string, unknown> | null>\n getOption: (key: string) => Promise<unknown>\n setOption: (key: string, value: unknown) => Promise<void>\n setOptions: (options: Record<string, unknown>) => Promise<void>\n clearOptions: () => Promise<void>\n setCursorPos: (pos: GristCursorPos) => Promise<void>\n setSelectedRows: (rowIds: number[] | null) => Promise<void>\n fetchSelectedTable: (options?: GristFetchSelectedOptions) => Promise<Record<string, unknown[]>>\n fetchSelectedRecord: (rowId: number, options?: GristFetchSelectedOptions) => Promise<Record<string, unknown>>\n docApi: {\n getDocName: () => Promise<string>\n listTables: () => Promise<string[]>\n fetchTable: (tableId: string) => Promise<Record<string, unknown[]>>\n applyUserActions: (actions: unknown[][], options?: { desc?: string }) => Promise<{ retValues: unknown[] }>\n getAccessToken?: (options?: { readOnly?: boolean }) => Promise<{ token: string; baseUrl: string }>\n fetchSelectedTable: (options?: GristFetchSelectedOptions) => Promise<Record<string, unknown[]>>\n fetchSelectedRecord: (rowId: number, options?: GristFetchSelectedOptions) => Promise<Record<string, unknown>>\n }\n selectedTable: GristTableOperations\n getTable: (tableId?: string) => GristTableOperations\n sectionApi: {\n configure: (settings: GristReadyOptions) => Promise<void>\n mappings: () => Promise<GristWidgetColumnMap | null>\n }\n on: (eventName: string, listener: (...args: unknown[]) => void) => () => void\n}\n\nexport type InlineTransportOptions = TransportContext & {\n /**\n * Where to mount the synthesised `grist` global.\n * Defaults to the current window. Pass a different target (e.g. an iframe's\n * `contentWindow`) to install it in another realm.\n */\n target?: Window & typeof globalThis\n}\n\n/**\n * Returns an {@link EmulatorTransport} **and** the synthesised `grist`\n * object. `target.grist = global` is set as a side-effect for parity with\n * the production runtime.\n */\nexport function createInlineTransport(\n options: InlineTransportOptions\n): EmulatorTransport & { grist: InlineGristGlobal } {\n const { state, bus, api } = options\n const target = options.target ?? (globalThis as unknown as Window & typeof globalThis)\n\n // The SDK's `useGristAvailability` checks `window.self !== window.top`.\n // The inline transport runs in a top-level window where that's false. We\n // shim `top` so widget code thinks it's embedded — production doesn't use\n // this transport so there's no risk of leaking the shim.\n installFakeIframeContext(target)\n\n type RecordCb = (record: Record<string, unknown> | null, mappings?: GristWidgetColumnMap | null) => void\n type RecordsCb = (records: Record<string, unknown>[], mappings?: GristWidgetColumnMap | null) => void\n type OptionsCb = (options: Record<string, unknown> | null, interaction: GristWidgetInteraction) => void\n type NewRecordCb = (mappings: GristWidgetColumnMap | null) => void\n\n const recordCbs = new Map<RecordCb, GristFetchSelectedOptions | undefined>()\n const recordsCbs = new Map<RecordsCb, GristFetchSelectedOptions | undefined>()\n const optionsCbs = new Set<OptionsCb>()\n const newRecordCbs = new Set<NewRecordCb>()\n const generic = new Map<string, Set<(...args: unknown[]) => void>>()\n\n // Replay caches — production `grist-plugin-api.js` immediately delivers the\n // latest record / records / options to a freshly-subscribed listener, so\n // hooks that subscribe **after** `grist.ready()` still get the initial\n // payload. We mirror that behaviour here.\n type LastRecord = { record: Record<string, unknown> | null; mappings: GristWidgetColumnMap | null }\n type LastRecords = { records: Record<string, unknown>[]; mappings: GristWidgetColumnMap | null }\n type LastOptions = { options: Record<string, unknown> | null; interaction: GristWidgetInteraction }\n let lastRecord: LastRecord | null = null\n let lastRecords: LastRecords | null = null\n let lastOptions: LastOptions | null = null\n let lastNewRecord: GristWidgetColumnMap | null | undefined = undefined\n\n const buildInteraction = options.buildInteraction ?? (() => ({\n access_level: state.configuration?.requiredAccess ?? \"read table\",\n ...state.widgetInteraction,\n }))\n\n async function pushRecord(rowId: number | \"new\" | null) {\n const mappings = resolveMappings(state)\n if (rowId === \"new\") {\n // Grist's onRecord ignores the add-row (rowId \"new\"): only onNewRecord fires.\n lastNewRecord = mappings\n for (const cb of newRecordCbs) {\n try { cb(mappings) } catch (err) { logErr(err) }\n }\n return\n }\n if (rowId === null) {\n lastRecord = { record: null, mappings }\n for (const [cb] of recordCbs) {\n try { cb(null, mappings) } catch (err) { logErr(err) }\n }\n return\n }\n let record: Record<string, unknown> | null = null\n try {\n record = await api.GristView.fetchSelectedRecord(rowId)\n } catch (err) {\n logErr(err)\n }\n lastRecord = { record, mappings }\n for (const [cb, opts] of recordCbs) {\n try {\n const r = opts?.keepEncoded\n ? await api.GristView.fetchSelectedRecord(rowId, { keepEncoded: true })\n : record\n cb(r, mappings)\n } catch (err) {\n logErr(err)\n }\n }\n }\n\n async function pushRecords() {\n const mappings = resolveMappings(state)\n let baseRows: Record<string, unknown>[] = []\n try {\n const columnar = await api.GristView.fetchSelectedTable({})\n baseRows = columnsToRows(columnar)\n } catch (err) {\n logErr(err)\n }\n lastRecords = { records: baseRows, mappings }\n for (const [cb, opts] of recordsCbs) {\n try {\n const fetchOptions = coerceFetchOptions(opts)\n // Re-fetch only when the subscriber asked for a different shape\n // (e.g. `keepEncoded: true`). Otherwise reuse the decoded rows we\n // already have to avoid extra work and to match production where\n // the same fetch is broadcast to every listener.\n const rows = fetchOptions?.keepEncoded\n ? columnsToRows(await api.GristView.fetchSelectedTable({ keepEncoded: true }))\n : baseRows\n cb(rows, mappings)\n } catch (err) {\n logErr(err)\n }\n }\n }\n\n /**\n * Mirror what `viewApi.fetchSelectedTable` does inside `grist-plugin-api.js`:\n * the host RPC stub always returns columnar; the wrapper applies the\n * `format: \"rows\"` transpose (and would decode encoded values when\n * `keepEncoded: false` — a no-op here because our `rowsToColumnar` already\n * emits JS-native primitives in that case).\n *\n * Keeping this logic on the inline side guarantees that widgets see the\n * same result whether they go through the iframe transport (real plugin\n * wrapper) or the inline transport (this wrapper).\n */\n async function fetchSelectedTableShaped(\n opts: GristFetchSelectedOptions | undefined\n ): Promise<Record<string, unknown[]> | Record<string, unknown>[]> {\n const fetchOptions = coerceFetchOptions(opts)\n const columnar = (await api.GristView.fetchSelectedTable(\n fetchOptions ? { keepEncoded: fetchOptions.keepEncoded } : {}\n )) as Record<string, unknown[]>\n if (fetchOptions?.format === \"rows\") return columnsToRows(columnar)\n return columnar\n }\n\n function pushOptions() {\n const opts = Object.keys(state.widgetOptions).length > 0 ? { ...state.widgetOptions } : null\n const interaction = buildInteraction()\n lastOptions = { options: opts, interaction }\n for (const cb of optionsCbs) {\n try { cb(opts, interaction) } catch (err) { logErr(err) }\n }\n }\n\n const offBus = bus.on(async (event: EmulatorEvent) => {\n switch (event.type) {\n case \"data-change\":\n await pushRecords()\n await pushRecord(state.selection.rowId)\n break\n case \"cursor-change\":\n await pushRecord(event.rowId)\n break\n case \"options-change\":\n pushOptions()\n break\n case \"ready\":\n pushOptions()\n if (options.initialTheme) {\n notify(\"message\", buildGristThemeHostMessage(options.initialTheme, { fromReady: true }))\n }\n await pushRecords()\n await pushRecord(state.selection.rowId)\n break\n case \"mappings-change\":\n await pushRecords()\n await pushRecord(state.selection.rowId)\n break\n case \"theme-change\":\n notify(\"message\", event.message)\n break\n }\n })\n\n function makeTableOps(tableId: string): GristTableOperations {\n return {\n async getTableId() { return tableId },\n async create(records, options) {\n const list = Array.isArray(records) ? records : [records]\n const ids: GristMinimalRecord[] = []\n for (const r of list) {\n const result = applyUserActions(state, bus, [\n gristAddRecordAction(tableId, parseFields(r.fields, options)),\n ])\n ids.push({ id: result.retValues[0] as number })\n }\n return Array.isArray(records) ? ids : ids[0]\n },\n async update(records: GristTableUpdateRecord | GristTableUpdateRecord[], options?: GristTableOpOptions) {\n const list = Array.isArray(records) ? records : [records]\n const actions = list.map((r) => gristUpdateRecordAction(tableId, r.id, parseFields(r.fields, options)))\n applyUserActions(state, bus, actions)\n },\n async upsert(records: GristTableUpsertRecord | GristTableUpsertRecord[], options?: GristTableUpsertOptions) {\n const list = Array.isArray(records) ? records : [records]\n const allowAdd = options?.add !== false\n const allowUpdate = options?.update !== false\n const table = getTable(state, tableId)\n const actions: unknown[][] = []\n for (const r of list) {\n const matches = table.rows.filter((row) =>\n Object.entries(r.require).every(([k, v]) => row[k] === v)\n )\n if (matches.length > 0) {\n if (!allowUpdate) continue\n const fields = parseFields(r.fields ?? {}, options)\n for (const m of matches) actions.push(gristUpdateRecordAction(tableId, m.id, fields))\n } else if (allowAdd) {\n actions.push(gristAddRecordAction(tableId, { ...r.require, ...parseFields(r.fields ?? {}, options) }))\n }\n }\n if (actions.length > 0) applyUserActions(state, bus, actions)\n },\n async destroy(recordIds: number | number[]) {\n if (Array.isArray(recordIds)) {\n applyUserActions(state, bus, [gristBulkRemoveRecordAction(tableId, recordIds)])\n } else {\n applyUserActions(state, bus, [gristRemoveRecordAction(tableId, recordIds)])\n }\n // touch the unused bulk-add reference for tree-shaking parity, no-op\n void gristBulkAddRecordAction\n void gristBulkUpdateRecordAction\n },\n }\n }\n\n function notify(event: string, ...args: unknown[]) {\n const set = generic.get(event)\n if (!set) return\n for (const fn of set) {\n try { fn(...args) } catch (err) { logErr(err) }\n }\n }\n\n const grist: InlineGristGlobal = {\n async ready(opts) {\n await api.CustomSectionAPI.configure(opts ? { ...opts, onEditOptions: undefined } as unknown as Record<string, unknown> : {})\n },\n\n onRecord(cb, opts) {\n recordCbs.set(cb, opts)\n // Replay last value so late subscribers don't miss the initial event.\n if (lastRecord) {\n try { cb(lastRecord.record, lastRecord.mappings) } catch (err) { logErr(err) }\n }\n },\n onRecords(cb, opts) {\n recordsCbs.set(cb, opts)\n if (lastRecords) {\n try { cb(lastRecords.records, lastRecords.mappings) } catch (err) { logErr(err) }\n }\n },\n onOptions(cb) {\n optionsCbs.add(cb)\n if (lastOptions) {\n try { cb(lastOptions.options, lastOptions.interaction) } catch (err) { logErr(err) }\n }\n },\n onNewRecord(cb) {\n newRecordCbs.add(cb)\n if (lastNewRecord !== undefined) {\n try { cb(lastNewRecord) } catch (err) { logErr(err) }\n }\n },\n\n mapColumnNames(data) {\n const mappings = resolveMappings(state)\n if (!mappings) return null\n const out: Record<string, unknown> = {}\n let allMapped = true\n for (const [logical, real] of Object.entries(mappings)) {\n if (Array.isArray(real)) {\n out[logical] = real.map((r) => data[r])\n } else if (typeof real === \"string\") {\n out[logical] = data[real]\n } else {\n allMapped = false\n }\n }\n return allMapped ? out : null\n },\n mapColumnNamesBack(data) {\n const mappings = resolveMappings(state)\n if (!mappings) return data\n const out: Record<string, unknown> = {}\n for (const [logical, real] of Object.entries(mappings)) {\n if (typeof real === \"string\" && logical in data) {\n out[real] = data[logical]\n }\n }\n return out\n },\n\n getOption: (k) => api.WidgetAPI.getOption(k),\n setOption: (k, v) => api.WidgetAPI.setOption(k, v),\n getOptions: () => api.WidgetAPI.getOptions(),\n setOptions: (o) => api.WidgetAPI.setOptions(o),\n clearOptions: () => api.WidgetAPI.clearOptions(),\n\n setCursorPos: (pos) => api.GristView.setCursorPos(pos),\n setSelectedRows: (rowIds) => api.GristView.setSelectedRows(rowIds),\n fetchSelectedTable: (opts) =>\n fetchSelectedTableShaped(opts) as Promise<Record<string, unknown[]>>,\n fetchSelectedRecord: (rowId, opts) => api.GristView.fetchSelectedRecord(rowId, coerceFetchOptions(opts)),\n\n docApi: {\n getDocName: () => api.GristDocAPI.getDocName(),\n listTables: () => api.GristDocAPI.listTables(),\n fetchTable: (id) => api.GristDocAPI.fetchTable(id),\n applyUserActions: (actions, options) => api.GristDocAPI.applyUserActions(actions, options),\n getAccessToken: (opts) => api.GristDocAPI.getAccessToken(opts),\n fetchSelectedTable: (opts) =>\n fetchSelectedTableShaped(opts) as Promise<Record<string, unknown[]>>,\n fetchSelectedRecord: (rowId, opts) =>\n api.GristView.fetchSelectedRecord(rowId, coerceFetchOptions(opts)),\n },\n\n get selectedTable() {\n return makeTableOps(state.selection.tableId)\n },\n\n getTable(tableId) {\n return makeTableOps(tableId ?? state.selection.tableId)\n },\n\n sectionApi: {\n configure: (settings) => api.CustomSectionAPI.configure(settings as unknown as Record<string, unknown>),\n mappings: () => api.CustomSectionAPI.mappings(),\n },\n\n on(eventName, listener) {\n let set = generic.get(eventName)\n if (!set) generic.set(eventName, (set = new Set()))\n set.add(listener)\n return () => set!.delete(listener)\n },\n }\n\n ;(target as unknown as { grist: InlineGristGlobal }).grist = grist\n\n return {\n grist,\n dispose() {\n offBus()\n // Restore the global (only if we still own it).\n const t = target as unknown as { grist?: unknown }\n if (t.grist === grist) delete t.grist\n recordCbs.clear()\n recordsCbs.clear()\n optionsCbs.clear()\n newRecordCbs.clear()\n generic.clear()\n lastRecord = null\n lastRecords = null\n lastOptions = null\n lastNewRecord = undefined\n },\n fireDataChange(tableId) {\n bus.emit({ type: \"data-change\", tableId: tableId ?? state.selection.tableId })\n },\n fireCursor(rowId) {\n const id = rowId === undefined ? state.selection.rowId : rowId\n bus.emit({ type: \"cursor-change\", tableId: state.selection.tableId, rowId: id })\n },\n fireOptions() {\n pushOptions()\n },\n fireTheme(message) {\n bus.emit({ type: \"theme-change\", message })\n },\n emitInitialState() {\n pushOptions()\n void pushRecords().then(() => pushRecord(state.selection.rowId))\n },\n }\n}\n\nfunction columnsToRows(columnar: Record<string, unknown[]>): Record<string, unknown>[] {\n const cols = Object.keys(columnar)\n if (cols.length === 0) return []\n const length = (columnar[cols[0]] ?? []).length\n const rows: Record<string, unknown>[] = []\n for (let i = 0; i < length; i++) {\n const row: Record<string, unknown> = {}\n for (const c of cols) row[c] = columnar[c][i]\n rows.push(row)\n }\n return rows\n}\n\nfunction parseFields(fields: Record<string, unknown>, _options?: GristTableOpOptions): Record<string, unknown> {\n // The emulator currently doesn't implement string-parsing; pass-through.\n // Hook into here to add date/number parsing when we surface that toggle.\n return { ...fields }\n}\n\nfunction coerceFetchOptions(\n opts: GristFetchSelectedOptions | undefined\n): { keepEncoded?: boolean; format?: \"rows\" | \"columns\" } | undefined {\n if (!opts) return undefined\n const format = opts.format === \"rows\" || opts.format === \"columns\" ? opts.format : undefined\n return { keepEncoded: opts.keepEncoded, format }\n}\n\nfunction logErr(err: unknown) {\n console.error(\"[grist-emulator/inline]\", err)\n}\n\n// Touch helpers to keep them tree-shake-friendly even if unused in current scope.\nvoid findRow\n\n/**\n * Make `window.self !== window.top` evaluate to `true`. The SDK uses this\n * exact comparison in `useGristAvailability` to detect an iframe environment.\n *\n * Inline transports run inside the host window (tests, IDE preview) and would\n * otherwise be flagged as \"not embedded\" — this shim is the same trick we use\n * in the testing harness and is safe because the inline transport is never\n * shipped to production.\n */\nfunction installFakeIframeContext(target: Window & typeof globalThis) {\n try {\n if (target.self !== target.top) return\n Object.defineProperty(target, \"top\", {\n configurable: true,\n get: () => ({}),\n })\n } catch {\n // Some environments lock these globals; ignore silently.\n }\n}\n","import { z } from \"zod\"\n\nimport type { GristReplicaDocument } from \"../sdk/replica-document\"\n\nconst emulatorRowSchema = z\n .object({ id: z.number() })\n .catchall(z.unknown())\n\nconst formulaKindSchema = z.enum([\"computed\", \"trigger\", \"none\", \"empty_slot\"])\n\nconst replicaColumnSchema = z\n .object({\n colRef: z.number().optional(),\n type: z.string().optional(),\n label: z.string().optional(),\n parentPos: z.number().optional(),\n isFormula: z.boolean().optional(),\n formulaKind: formulaKindSchema.optional(),\n formula: z.string().optional(),\n description: z.string().optional(),\n widgetOptions: z.record(z.string(), z.unknown()).optional(),\n displayColRef: z.number().optional(),\n visibleColRef: z.number().optional(),\n })\n .strict()\n\nconst replicaTableSchema = z\n .object({\n label: z.string().optional(),\n columns: z.record(z.string(), replicaColumnSchema).optional(),\n rows: z.array(emulatorRowSchema).optional(),\n rowCount: z.number().optional(),\n dataOmitted: z.boolean().optional(),\n dataOmittedReason: z.string().optional(),\n error: z.string().optional(),\n })\n .strict()\n\nconst replicaSelectionSchema = z\n .object({\n tableId: z.string().optional(),\n rowId: z.union([z.number(), z.literal(\"new\"), z.null()]).optional(),\n mappings: z.unknown().nullable().optional(),\n cursor: z.unknown().optional(),\n })\n .strict()\n\nconst replicaWidgetConfigurationSchema = z\n .object({\n requiredAccess: z.string().optional(),\n columns: z.unknown().optional(),\n allowSelectBy: z.boolean().optional(),\n hasCustomOptions: z.boolean().optional(),\n })\n .strict()\n\nconst replicaAccessTokenSchema = z\n .object({\n token: z.string(),\n baseUrl: z.string(),\n ttlMsecs: z.number(),\n })\n .strict()\n\nconst replicaDocumentSchema = z\n .object({\n generatedAt: z.string(),\n source: z.string().optional(),\n docName: z.string().optional(),\n mode: z.enum([\"schema-only\", \"schema+samples\", \"schema+data\"]).optional(),\n tables: z.record(z.string(), replicaTableSchema),\n selection: replicaSelectionSchema.optional(),\n widgetOptions: z.record(z.string(), z.unknown()).optional(),\n widgetInteraction: z.unknown().optional(),\n configuration: replicaWidgetConfigurationSchema.optional(),\n accessToken: replicaAccessTokenSchema.nullable().optional(),\n })\n .strict()\n .refine((value) => Object.keys(value.tables).length > 0, {\n message: \"at least one table is required\",\n path: [\"tables\"],\n })\n\nfunction formatZodError(prefix: string, error: z.ZodError): Error {\n const details = error.issues\n .map((issue) => {\n const where = issue.path.length > 0 ? issue.path.join(\".\") : \"<root>\"\n return `${where}: ${issue.message}`\n })\n .join(\"; \")\n return new Error(`${prefix}: ${details}`)\n}\n\nexport function safeParseDocument(input: unknown) {\n return replicaDocumentSchema.safeParse(input)\n}\n\nexport function parseDocument(input: unknown): GristReplicaDocument {\n const result = safeParseDocument(input)\n if (!result.success) {\n throw formatZodError(\"parseDocument\", result.error)\n }\n return result.data as GristReplicaDocument\n}\n","/**\n * Top-level emulator factory. Produces a fully-wired emulator instance:\n *\n * - typed in-memory document state,\n * - shared event bus,\n * - the six host API impls,\n * - the inline transport, which installs `grist` on the page,\n * - imperative helpers (`mutate`, `apply`, `selectRow`, `selectTable`)\n * that drive the document via the action engine and emit corresponding\n * events.\n *\n * The instance is multi-instance friendly: nothing is stored on `window`.\n */\n\nimport { createApiBundle } from \"./api\"\nimport type { EmulatorApiBundle } from \"./api\"\nimport { applyUserActions } from \"./core/action-engine\"\nimport { createDocument } from \"./core/document\"\nimport { createEventBus } from \"./core/event-bus\"\nimport type { EventBus } from \"./core/event-bus\"\nimport { resolveMappings } from \"./core/mappings\"\nimport type { EmulatorDocumentState } from \"./core/types\"\nimport type { GristReplicaDocument } from \"../sdk/replica-document\"\nimport type { GristWidgetColumnMap } from \"../sdk/types\"\nimport { buildGristThemeHostMessage } from \"./theme-message\"\nimport { createInlineTransport } from \"./transports\"\nimport type { EmulatorTransport, InlineGristGlobal } from \"./transports\"\nimport { parseDocument } from \"./validators\"\n\nexport type CreateGristEmulatorOptions = {\n /** The starting document (must satisfy {@link parseDocument}). */\n document: GristReplicaDocument\n /** Installs `grist` on `target` (default: the global object). */\n transport?: { kind: \"inline\"; target?: Window & typeof globalThis }\n /** Initial widget options exposed via `WidgetAPI`. */\n widgetOptions?: Record<string, unknown>\n /**\n * Initial widget interaction info (`access_level` and friends) sent\n * alongside `onOptions`. Without an `access_level`, Grist grants the access\n * the widget requests in `grist.ready()`.\n */\n widgetInteraction?: Record<string, unknown>\n /** Initial document theme replayed on widget ready (host `message` channel). */\n initialTheme?: \"light\" | \"dark\"\n}\n\nexport type GristEmulator = {\n /** Underlying mutable document. Treat as read-only outside of `mutate(...)`. */\n state: EmulatorDocumentState\n bus: EventBus\n api: EmulatorApiBundle\n transport: EmulatorTransport\n /** Synthesised `grist` global (only for the inline transport). */\n grist?: InlineGristGlobal\n\n /** Apply a list of Grist user actions; emits the matching events. */\n apply: (actions: unknown[][]) => { retValues: unknown[] }\n /** Convenience helpers for tests and demos. */\n mutate: {\n addRow: (tableId: string, fields: Record<string, unknown>) => number\n updateRow: (tableId: string, rowId: number, fields: Record<string, unknown>) => void\n removeRow: (tableId: string, rowId: number) => void\n }\n selectRow: (rowId: number | \"new\" | null) => void\n selectTable: (tableId: string) => void\n /**\n * Set logical→real column mappings, as a user mapping columns in Grist would.\n * Pass `undefined` to clear — `mappings()` becomes `null` until set again.\n */\n setColumnMappings: (mappings: GristWidgetColumnMap | undefined) => void\n setOptions: (options: Record<string, unknown>) => Promise<void>\n setInteraction: (interaction: Record<string, unknown>) => void\n /** Host theme controls (`grist.on(\"message\")` / `msg.theme`). */\n theme: {\n set: (theme: \"light\" | \"dark\") => void\n }\n /** Tear down the emulator. Idempotent. */\n dispose: () => void\n}\n\nexport function createGristEmulator(options: CreateGristEmulatorOptions): GristEmulator {\n const validatedDocument = parseDocument(options.document)\n const state = createDocument({\n ...validatedDocument,\n widgetOptions: options.widgetOptions ?? validatedDocument.widgetOptions,\n // No access_level by default: the emulator then grants the access the\n // widget asks for in grist.ready(), as a user accepting it in Grist would.\n widgetInteraction: options.widgetInteraction ?? validatedDocument.widgetInteraction ?? {},\n })\n const bus = createEventBus()\n const api = createApiBundle(state, bus)\n\n const inline = createInlineTransport({\n state,\n bus,\n api,\n initialTheme: options.initialTheme,\n target: options.transport?.target,\n })\n const transport: EmulatorTransport = inline\n const grist: InlineGristGlobal | undefined = inline.grist\n\n function apply(actions: unknown[][]) {\n return applyUserActions(state, bus, actions)\n }\n\n return {\n state,\n bus,\n api,\n transport,\n grist,\n apply,\n mutate: {\n addRow: (tableId, fields) => apply([[\"AddRecord\", tableId, null, fields]]).retValues[0] as number,\n updateRow: (tableId, rowId, fields) => {\n apply([[\"UpdateRecord\", tableId, rowId, fields]])\n },\n removeRow: (tableId, rowId) => {\n apply([[\"RemoveRecord\", tableId, rowId]])\n },\n },\n selectRow(rowId) {\n state.selection.rowId = rowId\n bus.emit({ type: \"cursor-change\", tableId: state.selection.tableId, rowId })\n },\n selectTable(tableId) {\n if (!state.tables.has(tableId)) throw new Error(`Unknown table: ${tableId}`)\n state.selection.tableId = tableId\n const first = state.tables.get(tableId)!.rows[0]?.id ?? null\n state.selection.rowId = first\n bus.emit({ type: \"data-change\", tableId })\n bus.emit({ type: \"cursor-change\", tableId, rowId: first })\n },\n setColumnMappings(mappings) {\n if (mappings === undefined) {\n delete state.selection.mappings\n } else {\n state.selection.mappings = mappings\n }\n bus.emit({ type: \"mappings-change\", mappings: resolveMappings(state) })\n },\n async setOptions(opts) {\n await api.WidgetAPI.setOptions(opts)\n },\n setInteraction(interaction) {\n state.widgetInteraction = { ...interaction }\n bus.emit({ type: \"options-change\", options: { ...state.widgetOptions }, interaction: { ...interaction } })\n },\n theme: {\n set(next) {\n bus.emit({ type: \"theme-change\", message: buildGristThemeHostMessage(next) })\n },\n },\n dispose() {\n transport.dispose()\n bus.clear()\n },\n }\n}\n","/**\n * Document templates exposed at the top of the emulator API.\n *\n * Templates return plain data — they don't allocate state, the caller passes\n * the returned value into `createGristEmulator(...)` which performs the allocation.\n */\n\nimport type { GristReplicaDocument } from \"../sdk/replica-document\"\n\nconst PRESET_GENERATED_AT = \"1970-01-01T00:00:00.000Z\"\n\nfunction replicaBase(overrides: Omit<GristReplicaDocument, \"generatedAt\">): GristReplicaDocument {\n return {\n generatedAt: PRESET_GENERATED_AT,\n ...overrides,\n }\n}\n\n/**\n * Useful templates for quick demos and tests.\n */\nexport const presets = {\n /**\n * Default starter fixture for demos / sandboxes that need a neutral document\n * without choosing a domain-specific preset.\n */\n defaultTemplate(): GristReplicaDocument {\n return replicaBase({\n docName: \"Default\",\n tables: {\n Table1: {\n label: \"Table1\",\n rows: [\n { id: 1, Name: \"Alice\" },\n { id: 2, Name: \"Bob\" },\n ],\n },\n },\n })\n },\n blank(): GristReplicaDocument {\n return replicaBase({\n docName: \"Blank\",\n tables: {\n Table1: { rows: [{ id: 1 }] },\n },\n })\n },\n todoList(): GristReplicaDocument {\n return replicaBase({\n docName: \"Todo list\",\n mode: \"schema+data\",\n tables: {\n Tasks: {\n label: \"Tasks\",\n columns: {\n title: { type: \"Text\", label: \"Title\" },\n done: { type: \"Bool\", label: \"Done\" },\n priority: { type: \"Choice\", label: \"Priority\" },\n },\n rows: [\n { id: 1, title: \"Buy milk\", done: false, priority: \"high\" },\n { id: 2, title: \"Write the SOTA emulator\", done: true, priority: \"high\" },\n { id: 3, title: \"Ship it\", done: false, priority: \"medium\" },\n ],\n },\n },\n })\n },\n contacts(): GristReplicaDocument {\n return replicaBase({\n docName: \"Contacts\",\n mode: \"schema+data\",\n tables: {\n Contacts: {\n label: \"Contacts\",\n columns: {\n firstName: { type: \"Text\" },\n lastName: { type: \"Text\" },\n email: { type: \"Text\" },\n company: { type: \"Text\" },\n },\n rows: [\n { id: 1, firstName: \"Ada\", lastName: \"Lovelace\", email: \"ada@analytical.engine\", company: \"British Crown\" },\n { id: 2, firstName: \"Linus\", lastName: \"Torvalds\", email: \"linus@kernel.org\", company: \"Linux Foundation\" },\n { id: 3, firstName: \"Margaret\", lastName: \"Hamilton\", email: \"margaret@apollo.nasa\", company: \"NASA\" },\n ],\n },\n },\n })\n },\n}\n","import { Component, type ComponentType, type ReactNode } from \"react\"\nimport { waitFor } from \"@testing-library/react\"\n\nimport { entryProps, GristWidgetApp, isGristWidgetEntry, type GristWidgetEntry } from \"../../app/mount-grist-widget\"\nimport type { GristReplicaDocument, GristWidget, UseGristOptions } from \"../../sdk\"\nimport { declaredColumns, declaredDocument, mapEveryColumn } from \"./declared-document\"\nimport { installJsdomStubs } from \"./jsdom-stubs\"\nimport { renderWithGrist } from \"./render-with-grist\"\n\nexport type SmokeTestWidgetOptions = {\n /** The widget, as `src/main.tsx` passes it to `mountGristWidget()`. */\n App: ComponentType\n /** The widget's `GRIST_OPTIONS` (or pass `widget`). */\n options?: UseGristOptions\n /** The widget's declaration, from `defineGristWidget()` (or pass `options`). */\n widget?: GristWidget\n /**\n * The Grist document to run against. Defaults to one table with a column\n * per column the widget declares, typed after the first type it accepts,\n * and one row of sample values.\n */\n document?: GristReplicaDocument\n /** How long to wait for the widget to render, in ms. Defaults to 10 000. */\n timeout?: number\n}\n\n/**\n * Mounts the widget the way `mountGristWidget()` does inside Grist, against\n * an emulated Grist document with every column it declares mapped and the\n * access it requests granted, and waits until it renders past\n * `GristBoundary`. Resolves once it has,\n * rejects with the widget's own error if it throws, or with what the page\n * showed instead if it never gets there. Then unmounts.\n *\n * A widget's whole smoke test, given its entry module as `mountGristWidget()`\n * takes it (the widget, and its `widget` declaration or `GRIST_OPTIONS`):\n *\n * ```tsx\n * import { it } from \"vitest\"\n * import { smokeTestWidget } from \"grist-widget-sdk/emulator/testing\"\n * import * as entry from \"./App\"\n *\n * it(\"renders inside Grist\", () => smokeTestWidget(entry))\n * ```\n *\n * It only reads the declaration, so it stays valid as the widget changes,\n * and it improves with each SDK release. `smokeTestWidget({ App, options })`\n * and `smokeTestWidget({ App, widget })` work too.\n */\nexport async function smokeTestWidget(\n input: SmokeTestWidgetOptions | GristWidgetEntry,\n extra: Pick<SmokeTestWidgetOptions, \"document\" | \"timeout\"> = {}\n): Promise<void> {\n const { App, options: given, widget, document, timeout = 10_000 } =\n isGristWidgetEntry(input) ? { ...entryProps(input), ...extra } : input\n installJsdomStubs()\n const options = given ?? widget?.options\n if (!options) throw new Error(\"smokeTestWidget: pass the widget's `widget` (defineGristWidget) or its `options` (GRIST_OPTIONS).\")\n\n const crash: { error: unknown } = { error: undefined }\n function Probe() {\n return (\n <CatchRenderError crash={crash}>\n <div data-grist-smoke-test=\"\">\n <App />\n </div>\n </CatchRenderError>\n )\n }\n\n const columns = declaredColumns(options)\n const gristDocument = document ?? declaredDocument(columns)\n const result = renderWithGrist(<GristWidgetApp App={Probe} options={options} />, {\n emulator: {\n document: gristDocument,\n // Granted as the user would in Grist's widget panel: the access the\n // widget asks for, unless the given document says otherwise.\n widgetInteraction: gristDocument.widgetInteraction ?? { access_level: options.requiredAccess ?? \"read table\" },\n },\n })\n try {\n if (columns.length > 0) result.emulator.setColumnMappings(mapEveryColumn(columns))\n\n try {\n await waitFor(\n () => {\n if (crash.error !== undefined) return\n const probe = result.container.querySelector(\"[data-grist-smoke-test]\")\n if (!probe || !probe.hasChildNodes()) throw new Error(\"not rendered yet\")\n },\n { timeout }\n )\n } catch {\n const shown = result.container.textContent?.trim().replace(/\\s+/g, \" \") || \"nothing\"\n throw new Error(\n `smokeTestWidget: the widget didn't render past GristBoundary within ${timeout} ms. ` +\n `The page showed: \"${shown.slice(0, 300)}\".`\n )\n }\n if (crash.error !== undefined) throw crash.error\n } finally {\n result.unmount()\n }\n}\n\n/** Records the widget's render error, so the test fails with it rather than a timeout. */\nclass CatchRenderError extends Component<{ crash: { error: unknown }; children: ReactNode }, { failed: boolean }> {\n state = { failed: false }\n\n static getDerivedStateFromError() {\n return { failed: true }\n }\n\n componentDidCatch(error: unknown) {\n this.props.crash.error = error\n }\n\n render() {\n return this.state.failed ? null : this.props.children\n }\n}\n","/**\n * Browser APIs jsdom lacks but widget UI commonly uses, as inert stand-ins:\n * `ResizeObserver` (charts, virtualized lists, popovers) and\n * `window.matchMedia` (the theme, responsive hooks; it reports a light,\n * wide screen). Only installs what's missing, so a test's own mock wins.\n *\n * {@link smokeTestWidget} calls it. For a widget's other tests, call it at\n * the top of the test file or in a Vitest setup file.\n */\nexport function installJsdomStubs(): void {\n if (typeof window === \"undefined\") return\n\n globalThis.ResizeObserver ??= class ResizeObserver {\n observe() {}\n unobserve() {}\n disconnect() {}\n }\n\n window.matchMedia ??= (query: string) =>\n ({\n matches: false,\n media: query,\n onchange: null,\n addEventListener() {},\n removeEventListener() {},\n addListener() {},\n removeListener() {},\n dispatchEvent: () => false,\n }) as MediaQueryList\n}\n","/**\n * Vitest helpers to assert what the widget did to the document.\n *\n * Usage:\n *\n * const { emulator } = renderWithGrist(<MyWidget />)\n * await userEvent.click(screen.getByText(\"Add\"))\n * expect(actionsOf(emulator)).toContainEqual([\"AddRecord\", \"Tasks\", null, { title: \"X\" }])\n */\n\nimport type { GristEmulator } from \"../create-grist-emulator\"\nimport type { EmulatorEvent } from \"../core/event-bus\"\n\nexport function actionsOf(emulator: GristEmulator): unknown[][] {\n return emulator.bus\n .history()\n .filter((e: EmulatorEvent): e is Extract<EmulatorEvent, { type: \"user-action\" }> => e.type === \"user-action\")\n .map((e) => e.action as unknown[])\n}\n\nexport function eventsOf(emulator: GristEmulator): readonly EmulatorEvent[] {\n return emulator.bus.history()\n}\n\n/** Bus event kinds aligned with grist host callbacks (see inline transport). */\nexport type WaitForEventKind = \"ready\" | \"record\" | \"records\" | \"options\" | \"theme\" | \"cursor\"\n\nexport type WaitForEventOptions = {\n timeoutMs?: number\n}\n\nfunction predicateForKind(kind: WaitForEventKind): (event: EmulatorEvent) => boolean {\n switch (kind) {\n case \"ready\":\n return (e) => e.type === \"ready\"\n case \"record\":\n case \"cursor\":\n return (e) => e.type === \"cursor-change\"\n case \"records\":\n return (e) => e.type === \"data-change\"\n case \"options\":\n return (e) => e.type === \"options-change\"\n case \"theme\":\n return (e) => e.type === \"theme-change\"\n }\n}\n\nfunction waitForNextEvent(\n emulator: GristEmulator,\n predicate: (event: EmulatorEvent) => boolean,\n timeoutMs: number,\n label?: string\n): Promise<EmulatorEvent> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n off()\n const hint = label ? ` (kind: ${label})` : \"\"\n const recent = emulator.bus\n .history()\n .slice(-5)\n .map((e) => e.type)\n .join(\", \")\n reject(\n new Error(\n `waitForEvent timed out after ${timeoutMs}ms${hint}.` +\n (recent ? ` Recent bus events: ${recent}.` : \" No bus events yet.\")\n )\n )\n }, timeoutMs)\n const off = emulator.bus.on((event) => {\n if (predicate(event)) {\n clearTimeout(timer)\n off()\n resolve(event)\n }\n })\n })\n}\n\nexport function waitForEvent(\n emulator: GristEmulator,\n kind: WaitForEventKind,\n options?: WaitForEventOptions\n): Promise<EmulatorEvent>\nexport function waitForEvent(\n emulator: GristEmulator,\n predicate: (event: EmulatorEvent) => boolean,\n timeoutMs?: number\n): Promise<EmulatorEvent>\nexport function waitForEvent(\n emulator: GristEmulator,\n kindOrPredicate: WaitForEventKind | ((event: EmulatorEvent) => boolean),\n timeoutOrOptions: number | WaitForEventOptions = 1000\n): Promise<EmulatorEvent> {\n if (typeof kindOrPredicate === \"string\") {\n const opts = typeof timeoutOrOptions === \"object\" ? timeoutOrOptions : {}\n const timeoutMs = opts.timeoutMs ?? 1000\n return waitForNextEvent(emulator, predicateForKind(kindOrPredicate), timeoutMs, kindOrPredicate)\n }\n const timeoutMs = typeof timeoutOrOptions === \"number\" ? timeoutOrOptions : 1000\n return waitForNextEvent(emulator, kindOrPredicate, timeoutMs)\n}\n"],"mappings":"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","names":["import_react","import_react","token","token","message","message","ACCESS_RANK","inFlight","import_react","import_react","import_jsx_runtime","message","screen","import_react","import_react","cardStyle","import_jsx_runtime","cardStyle","import_react","import_react","import_jsx_runtime","cardStyle","message","import_jsx_runtime","alert","SEVERITY","import_react","import_jsx_runtime","import_jsx_runtime","LocalDevPage","ReleasePage","isEmbedded","formulaError","message","message","tokens","options","grist","message","grist","import_jsx_runtime","import_react","import_jsx_runtime","document","timeoutMs","import_react"]}
|