import * as React from 'react'; import { ComponentType, AnchorHTMLAttributes, ReactNode, PropsWithChildren, ErrorInfo } from 'react'; import { FallbackProps } from 'react-error-boundary'; type AuthToken = string | undefined; interface Auth { /** * Which part of the request do we use to send the auth? * * @default 'header' */ in?: 'header' | 'query' | 'cookie'; /** * A unique identifier for the security scheme. * * Defined only when there are multiple security schemes whose `Auth` * shape would otherwise be identical. */ key?: string; /** * Header or query parameter name. * * @default 'Authorization' */ name?: string; scheme?: 'basic' | 'bearer'; type: 'apiKey' | 'http'; } interface SerializerOptions { /** * @default true */ explode: boolean; style: T; } type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited'; type ObjectStyle = 'form' | 'deepObject'; type QuerySerializer = (query: Record) => string; type BodySerializer = (body: unknown) => unknown; type QuerySerializerOptionsObject = { allowReserved?: boolean; array?: Partial>; object?: Partial>; }; type QuerySerializerOptions = QuerySerializerOptionsObject & { /** * Per-parameter serialization overrides. When provided, these settings * override the global array/object settings for specific parameter names. */ parameters?: Record; }; type HttpMethod = 'connect' | 'delete' | 'get' | 'head' | 'options' | 'patch' | 'post' | 'put' | 'trace'; type Client$1 = { /** * Returns the final request URL. */ buildUrl: BuildUrlFn; getConfig: () => Config; request: RequestFn; setConfig: (config: Config) => Config; } & { [K in HttpMethod]: MethodFn; } & ([SseFn] extends [never] ? { sse?: never; } : { sse: { [K in HttpMethod]: SseFn; }; }); interface Config$1 { /** * Auth token or a function returning auth token. The resolved value will be * added to the request payload as defined by its `security` array. */ auth?: ((auth: Auth) => Promise | AuthToken) | AuthToken; /** * A function for serializing request body parameter. By default, * {@link JSON.stringify()} will be used. */ bodySerializer?: BodySerializer | null; /** * An object containing any HTTP headers that you want to pre-populate your * `Headers` object with. * * {@link https://developer.mozilla.org/docs/Web/API/Headers/Headers#init See more} */ headers?: RequestInit['headers'] | Record; /** * The request method. * * {@link https://developer.mozilla.org/docs/Web/API/fetch#method See more} */ method?: Uppercase; /** * A function for serializing request query parameters. By default, arrays * will be exploded in form style, objects will be exploded in deepObject * style, and reserved characters are percent-encoded. * * This method will have no effect if the native `paramsSerializer()` Axios * API function is used. * * {@link https://swagger.io/docs/specification/serialization/#query View examples} */ querySerializer?: QuerySerializer | QuerySerializerOptions; /** * A function validating request data. This is useful if you want to ensure * the request conforms to the desired shape, so it can be safely sent to * the server. */ requestValidator?: (data: unknown) => Promise; /** * A function transforming response data before it's returned. This is useful * for post-processing data, e.g., converting ISO strings into Date objects. */ responseTransformer?: (data: unknown) => Promise; /** * A function validating response data. This is useful if you want to ensure * the response conforms to the desired shape, so it can be safely passed to * the transformers and returned to the user. */ responseValidator?: (data: unknown) => Promise; } type ServerSentEventsOptions = Omit & Pick & { /** * Fetch API implementation. You can use this option to provide a custom * fetch instance. * * @default globalThis.fetch */ fetch?: typeof fetch; /** * Implementing clients can call request interceptors inside this hook. */ onRequest?: (url: string, init: RequestInit) => Promise; /** * Callback invoked when a network or parsing error occurs during streaming. * * This option applies only if the endpoint returns a stream of events. * * @param error The error that occurred. */ onSseError?: (error: unknown) => void; /** * Callback invoked when an event is streamed from the server. * * This option applies only if the endpoint returns a stream of events. * * @param event Event streamed from the server. * @returns Nothing (void). */ onSseEvent?: (event: StreamEvent) => void; serializedBody?: RequestInit['body']; /** * Default retry delay in milliseconds. * * This option applies only if the endpoint returns a stream of events. * * @default 3000 */ sseDefaultRetryDelay?: number; /** * Maximum number of retry attempts before giving up. */ sseMaxRetryAttempts?: number; /** * Maximum retry delay in milliseconds. * * Applies only when exponential backoff is used. * * This option applies only if the endpoint returns a stream of events. * * @default 30000 */ sseMaxRetryDelay?: number; /** * Optional sleep function for retry backoff. * * Defaults to using `setTimeout`. */ sseSleepFn?: (ms: number) => Promise; url: string; }; interface StreamEvent { data: TData; event?: string; id?: string; retry?: number; } type ServerSentEventsResult = { stream: AsyncGenerator ? TData[keyof TData] : TData, TReturn, TNext>; }; type ErrInterceptor = (error: Err, /** response may be undefined due to a network error where no response object is produced */ response: Res | undefined, /** request may be undefined, because error may be from building the request object itself */ request: Req | undefined, options: Options) => Err | Promise; type ReqInterceptor = (request: Req, options: Options) => Req | Promise; type ResInterceptor = (response: Res, request: Req, options: Options) => Res | Promise; declare class Interceptors { fns: Array; clear(): void; eject(id: number | Interceptor): void; exists(id: number | Interceptor): boolean; getInterceptorIndex(id: number | Interceptor): number; update(id: number | Interceptor, fn: Interceptor): number | Interceptor | false; use(fn: Interceptor): number; } interface Middleware { error: Interceptors>; request: Interceptors>; response: Interceptors>; } type ResponseStyle = 'data' | 'fields'; interface Config extends Omit, Config$1 { /** * Base URL for all requests made by this client. */ baseUrl?: T['baseUrl']; /** * Fetch API implementation. You can use this option to provide a custom * fetch instance. * * @default globalThis.fetch */ fetch?: typeof fetch; /** * Please don't use the Fetch client for Next.js applications. The `next` * options won't have any effect. * * Install {@link https://www.npmjs.com/package/@hey-api/client-next `@hey-api/client-next`} instead. */ next?: never; /** * Return the response data parsed in a specified format. By default, `auto` * will infer the appropriate method from the `Content-Type` response header. * You can override this behavior with any of the {@link Body} methods. * Select `stream` if you don't want to parse response data at all. * * @default 'auto' */ parseAs?: 'arrayBuffer' | 'auto' | 'blob' | 'formData' | 'json' | 'stream' | 'text'; /** * Should we return only data or multiple fields (data, error, response, etc.)? * * @default 'fields' */ responseStyle?: ResponseStyle; /** * Throw an error instead of returning it in the response? * * @default false */ throwOnError?: T['throwOnError']; } interface RequestOptions extends Config<{ responseStyle: TResponseStyle; throwOnError: ThrowOnError; }>, Pick, 'onRequest' | 'onSseError' | 'onSseEvent' | 'sseDefaultRetryDelay' | 'sseMaxRetryAttempts' | 'sseMaxRetryDelay'> { /** * Any body that you want to add to your request. * * {@link https://developer.mozilla.org/docs/Web/API/fetch#body} */ body?: unknown; path?: Record; query?: Record; /** * Security mechanism(s) to use for the request. */ security?: ReadonlyArray; url: Url; } interface ResolvedRequestOptions extends RequestOptions { headers: Headers; serializedBody?: string; } type RequestResult = ThrowOnError extends true ? Promise ? TData[keyof TData] : TData : { data: TData extends Record ? TData[keyof TData] : TData; request: Request; response: Response; }> : Promise ? TData[keyof TData] : TData) | undefined : ({ data: TData extends Record ? TData[keyof TData] : TData; error: undefined; } | { data: undefined; error: TError extends Record ? TError[keyof TError] : TError; }) & { /** request may be undefined, because error may be from building the request object itself */ request?: Request; /** response may be undefined, because error may be from building the request object itself or from a network error */ response?: Response; }>; interface ClientOptions$1 { baseUrl?: string; responseStyle?: ResponseStyle; throwOnError?: boolean; } type MethodFn = (options: Omit, 'method'>) => RequestResult; type SseFn = (options: Omit, 'method'>) => Promise>; type RequestFn = (options: Omit, 'method'> & Pick>, 'method'>) => RequestResult; type BuildUrlFn = ; query?: Record; url: string; }>(options: TData & Options) => string; type Client = Client$1 & { interceptors: Middleware; }; interface TDataShape { body?: unknown; headers?: unknown; path?: unknown; query?: unknown; url: string; } type OmitKeys = Pick>; type Options = OmitKeys, 'body' | 'path' | 'query' | 'url'> & ([TData] extends [never] ? unknown : Omit); type ClientOptions = { baseUrl: 'https://api.stage.tesouro.com' | 'https://api.sandbox.stage.tesouro.com' | 'https://api.stage.business-banking.app' | 'https://api.tesouro.com' | 'https://api.sandbox.tesouro.com' | 'https://api.business-banking.app' | (string & {}); }; type DisclosureRequirement = 'NOT_REQUIRED' | 'REQUIRED'; type OrganizationType = 'BANK' | 'EMBEDDED' | 'PLATFORM' | 'TRANSACTOR' | 'VERTICAL_SOFTWARE_PROVIDER'; type WidgetInitResponse = { bankName?: null | string; /** * Whether the user has accepted the version currently in force. False for a user who accepted an * earlier version, which is what makes publishing a new one prompt them again, and false when * there is no user yet. Prompt on this rather than on `status`, which cannot answer it: an * already-active user can owe a re-acceptance while never being invited again. */ disclosuresAccepted?: boolean; /** * Whether embedded banking requires this widget session's user to accept disclosures. * Resolved through the organization hierarchy, nearest owner first: the organization asked about, * then its VSP, then its parent platform, then the bank, defaulting to NOT_REQUIRED. * Resolved for the user when there is one, which is the rung the acceptance writes against. * It falls back to the organization owning the widget application in the two cases where the user * cannot answer: before the user exists, which is what an onboarding widget needs, and when their * organization's settings chain resolves nothing at all. In that second case the acceptance * refuses rather than reporting the user clear, so a prompt shown here is never one the widget * can silently fail to record. */ disclosuresRequired?: DisclosureRequirement; organizationId?: null | string; organizationTypes?: null | Array; scopes: Array; status?: WidgetUserStatus; userId?: null | string; vspName?: null | string; }; type WidgetUserStatus = 'ACTIVE' | 'INACTIVE' | 'INVITED' | 'NOT_FOUND'; type EmbeddedClient = Client; type ExtractLiterals = T extends string ? string extends T ? never : T : never; type BaseUrl = ExtractLiterals; /** * Returns a new {@link EmbeddedClient} that is a shallow clone of `source`: * same config, and all existing interceptors copied in their original order. * * Use this inside a `configClient` callback when you want to add interceptors * without mutating the client instance that was passed in. * * @example * ```ts * const addLogging = useCallback((client: EmbeddedClient) => { * const cloned = cloneEmbeddedClient(client); * cloned.interceptors.request.use((req) => { * console.log('[widget]', req.method, req.url); * return req; * }); * return cloned; * }, []); * ``` */ declare function cloneEmbeddedClient(source: EmbeddedClient): EmbeddedClient; type LinkComponentProps = AnchorHTMLAttributes & { children?: ReactNode; }; type LinkComponent = ComponentType; /** * The UI frameworks a widget's UI layer can render with. * * - `shadcn` — the shadcn/Tailwind implementation. This is the default and the * implicit fallback, so existing consumers that select nothing keep rendering * shadcn. * - `tecton` — the Tecton implementation. * * Declared as an `as const` object (not a TypeScript `enum`) per repo * convention. */ declare const UIFramework: { readonly Shadcn: "shadcn"; readonly Tecton: "tecton"; }; type UIFramework = (typeof UIFramework)[keyof typeof UIFramework]; /** * A renderer is just a component that accepts the widget's public props. The * registry is keyed by a stable widget id (e.g. `'help-widget'`), so a single * extension can register implementations for many widgets at once. */ type AnyRenderer = ComponentType; type RendererMap = Record; /** A framework's design-system bootstrap (idempotent, SSR-safe). */ type DesignSystemEnsurer = () => Promise; /** * Registers UI renderers for a framework. Called by an extension package (never * by core) to make its implementations resolvable by the widget switches. * * Idempotent and additive: later calls merge into any existing map for the * framework, so multiple extensions (or repeated calls) compose rather than * clobber. Notifies mounted switches via `useSyncExternalStore`. * * @param framework - The framework these renderers implement (e.g. `'tecton'`). * @param map - Widget-id → component for that framework's surface. */ declare function registerUIRenderers(framework: UIFramework, map: RendererMap): void; /** * Registers a framework's design-system bootstrap (e.g. Tecton's * `ensureTectonDesignSystem`). Called by an extension; core invokes the * registered ensurer from its provider cascade when the resolved framework * matches. No-op resolution (undefined) means the extension is absent — core * simply does not bootstrap any non-shadcn design system. * * @param framework - The framework this ensurer bootstraps. * @param ensurer - Idempotent, SSR-safe bootstrap returning a `Promise`. */ declare function registerDesignSystemEnsurer(framework: UIFramework, ensurer: DesignSystemEnsurer): void; declare const ERROR_STATE_ID = "error-state"; /** * The implementation a widget renders with. * * - `native` — the Tesouro-native implementation. This is the default and the * implicit fallback, so consumers that select nothing keep rendering native. * - `monite` — the Monite SDK implementation. * * Declared as an `as const` object (not a TypeScript `enum`) per repo * convention. */ declare const Implementation: { readonly Native: "native"; readonly Monite: "monite"; }; type Implementation = (typeof Implementation)[keyof typeof Implementation]; /** * The settable fields of the widget config cascade. * * This is the type accepted by {@link setGlobalWidgetConfig} and all provider props. * It intentionally excludes `initResponse`, which is populated automatically by the * provider after a successful fetch and must never be set manually. * * The `null` vs `undefined` distinction on `widgetToken` and `organizationId` is intentional: * - `undefined` — not set at this level; inherit from the nearest ancestor or global store. * - `null` — explicitly cleared; downstream sees "no value" even if an ancestor had one * (e.g. after logout or deliberate de-scoping). * * @see {@link WidgetConfig} for the resolved output type (includes `initResponse`) * @see {@link RootWidgetProvider} * @see {@link WidgetProvider} * @see {@link setGlobalWidgetConfig} */ interface WidgetConfigInput { /** * Base URL of the Tesouro embedded API (e.g. `"https://api.tesouro.com"`). * * When omitted the nearest ancestor's `baseUrl` or the global store value is used. * Changing this recreates the underlying HTTP client so all subsequent requests * go to the new host. */ baseUrl?: BaseUrl; /** * Bearer token used to authenticate widget requests. * * Injected as `Authorization: Bearer ` on every outgoing request via an * interceptor on the scoped HTTP client. Token updates are picked up immediately * without recreating the client. * * - `string` — send this token on all requests from this level downward. * - `null` — explicitly cleared; no auth header is sent and fetching is suppressed. * - `undefined` — not set at this level; inherit from the nearest ancestor or global store. */ widgetToken?: string | null; /** * Organization ID forwarded as the `x-organization-id` request header. * * Passed through {@link EmbedApiProvider} context rather than the auth interceptor, * so individual data-access hooks can opt in per-request. * * - `string` — use this organization for downstream data requests. * - `null` — explicitly cleared; queries that require an org ID will be disabled. * - `undefined` — not set at this level; inherit from the nearest ancestor or global store. * * When `undefined` across the **whole** cascade (no prop, no ancestor, no global * value), the resolved org defaults to the loaded `initResponse.organizationId` * (see {@link WidgetConfig.initResponse}) once the widget-init fetch settles. This * is the lowest-priority fallback — any explicit `string` or `null` at any cascade * level wins, and an explicit `null` is preserved and never falls back. * * Only an **explicit** ancestor org is inherited. An ancestor's *init-derived* * default does not propagate into a descendant that owns its own fetch (its own * `baseUrl`/`widgetToken`); such a descendant defaults to its own * `initResponse.organizationId` instead, so it never sends an ancestor's org with * its own token. */ organizationId?: string | null; /** * Optional post-creation hook for the scoped HTTP client. * * Called once after the provider creates its scoped {@link EmbeddedClient} and * applies the built-in `Authorization: Bearer` interceptor. Receives the * fully-configured client and must return the client to be used for the lifetime of * this provider level — either the same instance (with additional interceptors * attached) or a new client entirely. * * **Order:** The built-in auth interceptor is always applied first. `configClient` * is called on top of it, so any interceptors you add here run after auth is set. * * **Any prop triggers a scoped client.** A {@link WidgetProvider} creates its own * scoped client whenever any prop is set — including `configClient` alone, without * `baseUrl` or `widgetToken`. Only a fully props-free pass-through provider skips * client creation and never calls this function. * * **Stability:** The function reference is included in the client creation memo's * dependency array. Passing an unstable (inline) function recreates the client on * every render. Stabilize with `useCallback` or define the function outside the * component. * * **Cascade:** Inherits from the nearest ancestor when `undefined`. A child * {@link WidgetProvider} that creates its own scoped client will use the resolved * `configClient` from the cascade unless it provides its own override. * * @example * ```tsx * const addLogging = useCallback( * (client: EmbeddedClient) => { * client.interceptors.request.use((req) => { * console.log('[widget]', req.method, req.url); * return req; * }); * return client; * }, * [], * ); * * * * * ``` */ configClient?: (client: EmbeddedClient) => EmbeddedClient; /** * Overrides the widget-gateway routing decision for the scoped HTTP client. * * Any caller reaching the Tesouro API with a widget token must route data * requests through the widget gateway: prefix the path with * `/api/widget-gateway/proxy` and carry the token as `X-Widget-Token`. The * provider applies both automatically per request when the request origin is * a known Tesouro API host (`WIDGET_GATEWAY_HOSTS`, derived from the * generated `ClientOptions['baseUrl']`); `/api/widget-gateway/*` paths (the * init round-trip) always pass through untouched. * * - `undefined` — decide from the request origin, as above. Inherits from * the nearest ancestor or global store like every other config field. * - `true` — always apply the rewrite, even for an unlisted base URL (e.g. a * custom domain in front of the gateway). * - `false` — never apply it. For hosts that route widget requests their own * way, such as a same-origin BFF whose `configClient` retargets every * request. * * Independent of {@link configClient}: a host that only adds a header keeps * the built-in routing, and the built-in interceptor runs before any * `configClient` interceptor. */ gatewayRouting?: boolean; /** * Component the embedded widgets should render in place of plain `` tags. * * Pass e.g. Next.js's `Link` to make in-app navigation use the host router. * Cascades like other config: provider prop > nearest ancestor > global store. * When no value is set anywhere, widgets fall back to a plain `` element. */ linkComponent?: LinkComponent; /** * Which UI framework the widget UI layer should render with. * * Lets a consuming context bind widgets to either the shadcn/Tailwind or the * Tecton implementation behind the same outward-facing API. The selection is * a presentation concern only — it cascades through the provider tree exactly * like {@link linkComponent} and is read by UI libraries via `useUIFramework`; * it never appears in any widget's feature-library or component props. * * - `'shadcn'` — the shadcn/Tailwind implementation. * - `'tecton'` — the Tecton implementation. * - `null` / `undefined` — not set at this level; inherit from the nearest * ancestor or global store, falling back to `shadcn` when unset everywhere. * `shadcn` is the implicit default, so existing consumers need no changes. */ uiFramework?: UIFramework | null; /** * Which implementation a widget renders with. * * Lets a consuming context bind widgets to either the Tesouro-native or the * Monite SDK implementation behind the same outward-facing API. It cascades * through the provider tree exactly like {@link linkComponent} and * {@link uiFramework} — provider prop > nearest ancestor > global store — and * is read via `useImplementation`. * * - `'native'` — the Tesouro-native implementation. * - `'monite'` — the Monite SDK implementation. * - `null` / `undefined` — not set at this level; inherit from the nearest * ancestor or global store, falling back to `native` when unset everywhere. * `native` is the implicit default, so existing consumers need no changes. */ implementation?: Implementation | null; } /** * Props shared by every analytics-owner-capable widget provider. * * Combines the full settable cascade ({@link WidgetConfigInput}) with the * analytics opt-out honored by analytics owners. Both {@link RootWidgetProvider} * and {@link WidgetProvider} build their public props on top of this; the latter * adds error-boundary props of its own. * * @see {@link WidgetConfigInput} for per-field cascade and `null` vs omitted semantics */ interface WidgetProviderBaseProps extends WidgetConfigInput { /** * Opt out of all analytics capture and prevent PostHog from loading. Default `true`. * * Honored only by an analytics **owner** — a {@link RootWidgetProvider} or a * standalone {@link WidgetProvider} with no parent provider. When `false`, * owner-bound `track` calls in this subtree become no-ops and the PostHog * installer is never dynamically imported for this owner's environment. * Setting it on a nested {@link WidgetProvider} is ignored in v1 (a one-time * `console.warn` is emitted to make the no-op discoverable). */ analytics?: boolean; } /** * The fully-resolved widget config at a given provider level. * * Extends {@link WidgetConfigInput} with `initResponse`, which is populated automatically * after a successful `GET /api/widget-gateway/init` fetch. This type is returned by * {@link useWidgetConfig} and represents the cascade result — it is never an input type. * * `initResponse` cascades as a **whole object** — it is either present (a fetch succeeded * at some level in the tree) or absent (`undefined`). Fields are never merged across levels. * It is cleared immediately when `widgetToken` or `baseUrl` changes to prevent stale tenant * data from persisting across auth boundaries. * * @see {@link WidgetConfigInput} for the input type accepted by providers and setGlobalWidgetConfig * @see {@link useWidgetConfig} */ interface WidgetConfig extends WidgetConfigInput { /** * The response from `GET /api/widget-gateway/init` for this level of the tree. * * Read-only — populated automatically by the provider. Use {@link useWidgetConfig} * to access it; do not attempt to set this field via {@link setGlobalWidgetConfig} * or provider props (those accept {@link WidgetConfigInput}, which excludes this field). * * Its `organizationId` also seeds the resolved {@link WidgetConfigInput.organizationId} * when the org is unset across the whole cascade. */ initResponse?: WidgetInitResponse; } /** * Replaces the global widget config and notifies all reactive subscribers. * * Designed for non-React entry points — web component hosts, imperative SDKs, or any * code outside the React tree — that need to push configuration into mounted widgets * before or after they render. Any mounted {@link RootWidgetProvider} or component * calling {@link useWidgetConfig} outside a provider re-renders automatically via * `useSyncExternalStore`. * * **Priority**: The global store is the lowest-priority fallback. Any prop passed * directly to a {@link RootWidgetProvider} or {@link WidgetProvider} overrides it. * * @param config - The new global config. **Replaces** the previous value entirely; * fields absent from `config` revert to `undefined` on the next read. * * @example * ```ts * // Web component attribute-change handler — outside the React tree * setGlobalWidgetConfig({ * baseUrl: 'https://api.tesouro.com', * widgetToken: tokenFromHost, * }); * ``` * * @see {@link getGlobalWidgetConfig} for a synchronous non-reactive read * @see {@link RootWidgetProvider} for the React provider that subscribes to this store */ declare function setGlobalWidgetConfig(config: WidgetConfigInput): void; /** * Merges a partial widget config into the global store and notifies subscribers. * * Unlike {@link setGlobalWidgetConfig}, this does **not** wipe untouched fields: * keys absent from `patch` are preserved. Keys explicitly present in `patch` — * including those set to `undefined` or `null` — overwrite. Use this when you * have a single field to update (most commonly a freshly fetched * `widgetToken`) without disturbing the rest of the global config. * * @param patch - The fields to merge into the existing global config. Omitted * keys are preserved; explicitly present keys replace their counterparts. * * @example * ```ts * setGlobalWidgetConfig({ baseUrl: 'https://api.tesouro.com', widgetToken: 'a' }); * updateGlobalWidgetConfig({ widgetToken: 'b' }); * // baseUrl is still 'https://api.tesouro.com' * ``` * * @see {@link setGlobalWidgetConfig} for the replace-all variant */ declare function updateGlobalWidgetConfig(patch: WidgetConfigInput): void; /** * Returns the current global widget config synchronously without subscribing to changes. * * Use this in non-React contexts such as event handlers or imperative callbacks where * you need a one-off read. For reactive reads inside React components use * {@link useWidgetConfig} instead. * * @returns The current {@link WidgetConfig} from the global store. The object is * replaced (not mutated) on each {@link setGlobalWidgetConfig} call — do not * cache the return value across renders or async boundaries. * * @see {@link setGlobalWidgetConfig} to write to the global store * @see {@link useWidgetConfig} for a reactive React hook alternative */ declare function getGlobalWidgetConfig(): WidgetConfigInput; /** * The widget-init state a non-React host observes. * * A discriminated union, so `status` narrows the payload: the `ready` branch * guarantees an `initResponse` and the `error` branch guarantees an `error`. * * - `idle` — no init in flight and none landed. The owner has no usable * `widgetToken` yet, or it was cleared (logout, de-scoping). Also the state * before any provider mounts and after the last one unmounts. A host that * supplies the token asynchronously — minting it before calling * `setGlobalWidgetConfig`, or mounting `RefreshingRootWidgetProvider`, which * passes `widgetToken={null}` while its fetcher runs — therefore sees `idle` * *before* `loading`, so loading chrome should cover both. The channel says * nothing about the mint itself: if it fails, the state stays `idle`, and * surfacing that is the host's job. * - `loading` — **no usable init response yet**, and a * `GET /api/widget-gateway/init` is in flight or about to be. This is the * first-load and token-rotation signal, *not* "a request is in flight": a * background refetch that still has a valid response for the active token * stays `ready`, so a host rendering from this channel never blanks * mid-session. (A host that needs to show a refresh indicator wants a * separate in-flight flag, which this channel does not carry.) * - `ready` — an init response fetched under the currently-resolved token. * - `error` — the last init fetch settled as a failure. `initResponse` rides * along when a previously-successful response is still valid for the active * token and only a later refetch failed, which is the same split * `useWidgetError()` + `useWidgetConfig()` expose together in the tree; a host * can render through a background failure instead of blanking. * * A response is never carried across a token change: while a rotation's * replacement fetch is in flight the status is `loading`, even though the React * tree deliberately keeps the previous response visible for UI continuity. */ type WidgetInitState = { status: 'idle'; } | { status: 'loading'; } | { status: 'ready'; initResponse: WidgetInitResponse; } | { status: 'error'; error: Error; initResponse?: WidgetInitResponse; }; /** * Returns the current widget-init state synchronously, without subscribing. * * The non-React equivalent of reading `useWidgetConfig().initResponse` + * `useWidgetLoading()` + `useWidgetError()` together. Use it for a one-off read * from an event handler or imperative SDK call, and pair it with * {@link subscribeToGlobalWidgetInitState} when you need to react to changes — * reading first closes the window where init settles before your subscription * lands. * * @returns The elected owner's {@link WidgetInitState}, or an `idle` state when * no provider is mounted. The object is replaced (never mutated) on change. * * @example * ```ts * const state = getGlobalWidgetInitState(); * if (state.status === 'ready' && state.initResponse.status === 'INVITED') { * showDisclosureGate(); * } * ``` * * @see {@link subscribeToGlobalWidgetInitState} for change notifications * @see {@link getGlobalWidgetConfig} for the matching read of the config store * @see {@link useWidgetConfig} for the React equivalent */ declare function getGlobalWidgetInitState(): WidgetInitState; /** * Subscribes to widget-init changes from outside the React tree. * * Designed for web-component and drop-in hosts, which have no hooks available * to them: it is the only way for such a host to branch on the user's init * status (`status`, `scopes`, `disclosuresRequired`, …) or to show its own * loading and error chrome around the widget tree. * * The listener fires only on change — not immediately on subscribe. Call * {@link getGlobalWidgetInitState} once alongside subscribing to pick up an * init that has already settled. * * @param listener - Called with the new state on every change. Repeat states * are collapsed, so a provider re-render that changes nothing does not fire. * @returns An unsubscribe function. Call it to stop receiving updates; the * channel holds no reference to the listener afterwards. * * @example * ```ts * const unsubscribe = subscribeToGlobalWidgetInitState((state) => { * // `idle` too, not just `loading`: a host that mints its own token sits at * // `idle` until the token lands. See {@link WidgetInitState}. * host.toggleSpinner(state.status === 'idle' || state.status === 'loading'); * if (state.status === 'ready') { * host.setDisclosureGate( * state.initResponse.disclosuresRequired === 'REQUIRED', * ); * } * }); * * // Cover an init that settled before this subscription: * const current = getGlobalWidgetInitState(); * * // Later, when the host tears down: * unsubscribe(); * ``` * * @see {@link getGlobalWidgetInitState} for a synchronous non-reactive read * @see {@link setGlobalWidgetConfig} for the matching non-React config channel */ declare function subscribeToGlobalWidgetInitState(listener: (state: WidgetInitState) => void): () => void; /** * Props for {@link RootWidgetProvider}. * * All fields are optional and come from {@link WidgetProviderBaseProps}. When a * field is omitted the global store value (set via {@link setGlobalWidgetConfig}) * is used as a reactive fallback. See {@link WidgetConfigInput} for per-field * cascade and `null` vs omitted semantics. */ interface RootWidgetProviderProps extends WidgetProviderBaseProps { /** * Host-supplied replacement for the `GET /api/widget-gateway/init` response. * * For first-party hosts whose users authenticate directly against the * Tesouro issuer: the host already holds a user access token whose claims * carry everything init would return, so the widget-gateway round-trip is * redundant. When this prop is set the provider skips the init fetch * entirely — no `/api/widget-gateway/init` request is made — and the given * object is exposed as `initResponse` to the whole subtree (scope gating, * org default, `useWidgetConfig()`), exactly as a fetched response would be. * * The `widgetToken` (typically the user's bearer access token in this mode) * is still required and still rides every data request as * `Authorization: Bearer `; only the init round-trip is bypassed. * * Embed integrations that mint widget JWEs must leave this unset — the * gateway init response is the source of truth for their scopes and status. */ unstable_initResponseOverride?: WidgetInitResponse; /** * Accept surface shown when an ACTIVE user owes a new disclosure version. * Pass `` (no invite * credentials) so gated widgets have somewhere to accept. Cascades to * nested WidgetProviders. */ disclosuresAcceptance?: ReactNode; } /** * Top-level provider for the widget config cascade. * * Place this **once** near the root of your React tree. It: * - Resolves `baseUrl`, `widgetToken`, and `organizationId` from its own props, * falling back to the global store (see {@link setGlobalWidgetConfig}) for any * prop that is `undefined`. * - Calls `GET /api/widget-gateway/init` whenever both `baseUrl` and `widgetToken` * resolve to a non-null value. The response is stored as `initResponse` and made * available to every descendant via {@link useWidgetConfig}. * - Creates a stable `QueryClient` once on mount and provides it via * `QueryClientProvider` for the entire subtree. * - Creates a scoped `@hey-api` HTTP client configured for `baseUrl`. The * `Authorization: Bearer` header is kept current via a ref-based interceptor so * token rotation never recreates the client. * - Provides `QueryClientProvider`, {@link EmbedApiProvider}, and `WidgetContext` * for the entire subtree. * * Reacts to {@link setGlobalWidgetConfig} calls after mount — any global change * that resolves a previously missing `baseUrl` or `widgetToken` triggers a fetch. * * @param props.baseUrl - API base URL. Falls back to `global.baseUrl` when omitted. * @param props.widgetToken - Auth token. Falls back to `global.widgetToken` when omitted. * @param props.organizationId - Org ID for data requests. Falls back to `global.organizationId`, * then to the init response's `organizationId` when unset everywhere. * @param props.children - The React subtree that will consume the widget context. * * @example * ```tsx * // Standard usage — one fetch for the whole tree * * * * ``` * * @example * ```tsx * // Host sets the URL globally; React tree only needs the token * setGlobalWidgetConfig({ baseUrl: 'https://api.tesouro.com' }); * * * * * ``` * * @see {@link WidgetProvider} for mid-tree token or URL overrides * @see {@link useWidgetConfig} to read the resolved config in descendants * @see {@link setGlobalWidgetConfig} to push config imperatively from outside React */ declare function RootWidgetProvider({ children, baseUrl, widgetToken, organizationId, configClient, gatewayRouting, linkComponent, uiFramework, implementation, analytics, unstable_initResponseOverride, disclosuresAcceptance, }: PropsWithChildren): React.JSX.Element; /** * Props for {@link WidgetProvider}. * * All fields are optional. When **all** are omitted the provider is a transparent * pass-through: no fetch is issued and all resolved values cascade unchanged from * the nearest ancestor. */ interface WidgetProviderProps extends WidgetProviderBaseProps { /** * Fallback rendered when a render-time exception is caught inside this * provider's subtree. Pass either a `ReactNode` (rendered directly) or a * render-prop receiving `{ error, resetErrorBoundary }` from * `react-error-boundary`. Default is a plain `role="alert"` div with * generic copy from `DEFAULT_LABELS.errorBoundaryFallback`. */ errorFallback?: ReactNode | ((props: FallbackProps) => ReactNode); /** * Called once when the boundary catches an error, before the fallback * renders. Use for telemetry / Sentry / partner logging. Exceptions * thrown from `onError` propagate per `react-error-boundary` semantics. */ onError?: (error: unknown, info: ErrorInfo) => void; /** * Accept surface shown when an ACTIVE user owes a new disclosure version. * Pass `` (no invite * credentials). Cascades like `linkComponent`. Omit on INVITED — that * path still uses invite-link `invitationToken`/`userId` on the host * landing page. WidgetProvider cannot import the widget itself (cycle). */ disclosuresAcceptance?: ReactNode; } type WidgetTokenFetcher = () => Promise<{ widgetToken: string; exp?: number; }>; type WidgetTokenState = { status: 'loading'; } | { status: 'ready'; widgetToken: string; exp?: number; isRefreshing: boolean; lastError?: unknown; } | { status: 'error'; error: unknown; }; interface WidgetTokenManager { start(): void; stop(): void; refresh(): Promise; getState(): WidgetTokenState; subscribe(listener: () => void): () => void; } interface WidgetTokenRefreshProviderProps { fetcher: WidgetTokenFetcher; leadSeconds?: number; onToken?: (widgetToken: string) => void; } declare function WidgetTokenRefreshProvider({ fetcher, leadSeconds, onToken, children, }: PropsWithChildren): React.JSX.Element; type RefreshingRootWidgetProviderProps = Omit & WidgetTokenRefreshProviderProps; /** * One-stop provider that bundles {@link WidgetTokenRefreshProvider} and * {@link RootWidgetProvider} so callers don't have to wire `useWidgetToken()` * into the `widgetToken` prop themselves. Takes every `RootWidgetProvider` * prop *except* `widgetToken` (which is managed by the internal token * refresh manager) plus the refresh provider's `fetcher` / `leadSeconds` / * `onToken`. * * While the manager is `loading` or `error`, this passes `widgetToken={null}` * to `RootWidgetProvider`, deferring the init fetch until a valid token is * available. Once `ready`, it passes the live `state.widgetToken` through. * * Children render inside both providers' contexts, so `useWidgetToken()` and * `useWidgetConfig()` both work in descendants — useful for status badges, * retry buttons, etc. * * @example * ```tsx * { * const res = await fetch('/api/widget-token').then((r) => r.json()); * return { widgetToken: res.token, exp: res.exp }; * }} * > * * * ``` */ declare function RefreshingRootWidgetProvider({ fetcher, leadSeconds, onToken, children, ...rootProps }: PropsWithChildren): React.JSX.Element; /** * Returns the fully-resolved {@link WidgetConfig} for the nearest provider level. * * Reads from the nearest `WidgetContext` ancestor (set by {@link RootWidgetProvider} * or {@link WidgetProvider}) and falls back to the global store when called outside * any provider. Subscribes to {@link setGlobalWidgetConfig} calls reactively via * `useSyncExternalStore`. * * **Cascade priority** (highest to lowest): * 1. Nearest `WidgetProvider` / `RootWidgetProvider` own prop * 2. Global store (`setGlobalWidgetConfig`) * * @returns The resolved {@link WidgetConfig} at the nearest provider level. All fields * may be `undefined` if no values have been provided at any level. `initResponse` is * `undefined` until the first successful fetch completes. * * @example * ```tsx * function BankNameBadge() { * const { initResponse } = useWidgetConfig(); * if (!initResponse) return ; * return {initResponse.bankName}; * } * ``` * * @see {@link useWidgetLoading} to check whether a fetch is currently in progress * @see {@link useWidgetError} to check whether the last fetch failed * @see {@link useOwnWidgetConfig} to read only what the *current* level contributed */ declare function useWidgetConfig(): WidgetConfig; /** * Returns only the {@link WidgetConfig} fields explicitly set at the **current** * provider level, without inheriting from ancestors. * * Useful for debugging or conditional logic that needs to distinguish "set here" * from "inherited from parent". Fields not explicitly set at this level are * `undefined` even if a parent has a value. * * Does **not** subscribe to the global store — use {@link useWidgetConfig} if you * need the fully-resolved (cascaded) config. * * @returns The partial {@link WidgetConfig} owned by the nearest provider, or `null` * when called outside any provider context. * * @example * ```tsx * function DebugLayer() { * const own = useOwnWidgetConfig(); * // e.g. { baseUrl: undefined, widgetToken: 'tok_partner', organizationId: undefined } * // — only widgetToken was set at this provider level * console.log('own config at this level:', own); * return null; * } * ``` * * @see {@link useWidgetConfig} to read the fully-resolved cascaded config instead */ declare function useOwnWidgetConfig(): WidgetConfigInput | null; /** * Host-supplied AcceptDisclosuresWidget (or equivalent) for ACTIVE users who * owe a new disclosure version. `undefined` outside a provider or when the * host has not passed `disclosuresAcceptance`. */ declare function useDisclosuresAcceptanceSurface(): ReactNode | undefined; /** * Returns a stable callback that re-triggers the widget-init fetch at the * **nearest provider level that owns a fetch**. * * Pass-through {@link WidgetProvider} instances (no own `baseUrl`/`widgetToken`) * automatically bubble this up the tree, so the returned function always targets * the correct fetch-owning ancestor regardless of nesting depth. * * Re-fetching keeps the current `initResponse` visible while the request is in * flight — the previous data is not cleared until the new response arrives. This * prevents a blank/loading flash during background refreshes. * * **A failed re-fetch keeps it visible too**, and only sets * {@link useWidgetError}. `useWidgetFetch` clears the retained response for a * *client* change, which is an auth boundary; a re-fetch is not one, so the * previous response is still valid for the active token. This line previously * said the opposite, which matters: a consumer branching on `!initResponse` * would conclude a failed refresh drops it back to its pre-init state, when in * fact it keeps rendering the response it already had. Verified against the * running provider (EMBD-4911) — a suite gating on a field of the init response * holds that gate closed after a failed refresh rather than falling open. * * @returns A stable `() => void` function. Calling it increments an internal counter * that re-triggers the fetch effect. Returns a no-op when called outside any provider. * * @example * ```tsx * function RefreshButton() { * const refetch = useRefetchWidget(); * return ; * } * ``` * * @see {@link useWidgetLoading} to show a loading indicator during the re-fetch * @see {@link useWidgetError} to handle fetch failures after a re-fetch */ declare function useRefetchWidget(): () => void; /** * Returns `true` while the nearest fetch-owning provider has a widget-init * request in flight, `false` otherwise. * * Pass-through {@link WidgetProvider} instances (no own `baseUrl`/`widgetToken`) * bubble this up automatically, so the value always reflects the owning ancestor * regardless of nesting depth. * * `loading` transitions to `true` immediately when a fetch starts (including * manual refetches) and back to `false` when the fetch settles — whether it * succeeds or fails. * * @returns `true` during an active fetch, `false` at all other times. * Returns `false` when called outside any provider. * * @example * ```tsx * function WidgetShell() { * const loading = useWidgetLoading(); * const { initResponse } = useWidgetConfig(); * * if (loading && !initResponse) return ; * if (!initResponse) return null; * return ; * } * ``` * * @see {@link useWidgetError} for fetch failure state * @see {@link useRefetchWidget} to manually trigger a re-fetch */ declare function useWidgetLoading(): boolean; /** * Returns the most recent fetch error from the nearest fetch-owning provider, * or `null` when the last fetch succeeded (or no fetch has run yet). * * Pass-through {@link WidgetProvider} instances (no own `baseUrl`/`widgetToken`) * bubble this up automatically, so the value always reflects the owning ancestor * regardless of nesting depth. * * The error is cleared automatically when: * - `widgetToken` or `baseUrl` changes (a new fetch is about to start). * - A subsequent fetch succeeds. * * A first-load failure leaves `initResponse` from {@link useWidgetConfig} * undefined. A failed same-token refetch can keep the previous response visible * because it is still valid for the active token; token/client changes never * carry the old response across the auth boundary. * * API errors thrown by the HTTP client (4xx/5xx responses) are wrapped in a plain * `Error` with `error.cause` set to the raw response body for inspection. * * @returns The `Error` from the last failed fetch, or `null`. Returns `null` when * called outside any provider. * * @example * ```tsx * function WidgetShell() { * const error = useWidgetError(); * const { initResponse } = useWidgetConfig(); * const refetch = useRefetchWidget(); * * if (error) return ; * if (!initResponse) return ; * return ; * } * ``` * * @see {@link useWidgetLoading} for in-flight request status * @see {@link useRefetchWidget} to retry after an error */ declare function useWidgetError(): Error | null; interface UseWidgetTokenResult { state: WidgetTokenState; refresh: () => Promise; /** * Synchronously read the manager's current state without subscribing the * caller to re-renders. Useful for non-React callbacks (e.g. a Monite * `fetchToken` callback) that need the post-`await refresh()` token without * the React render lag of `state`. */ getState: () => WidgetTokenState; } declare function useWidgetToken(): UseWidgetTokenResult; /** * Public {@link WidgetProvider} — the integrator-facing provider. * * The workspace-internal provider additionally accepts a `widgetName` prop that * stamps analytics identity (`widget_name` + a per-mount `widget_instance_id`) * on everything emitted beneath it (EMBD-4190). That identity is set **only** by * widget feature libs, never by integrators: a spoofed `widget_name` or a forced * fresh `widget_instance_id` would corrupt correlation. * * `WidgetProviderProps` deliberately omits `widgetName`, so typed (TS) consumers * cannot pass it. This wrapper additionally strips any stray `widgetName` a * non-typed (JS) host might pass at runtime before delegating, so the internal * identity prop is unreachable from the published surface in every case — the * provider's declaration in the emitted types carries no `widgetName`. */ declare function WidgetProvider(props: PropsWithChildren): ReactNode; export { ERROR_STATE_ID, Implementation, RefreshingRootWidgetProvider, RootWidgetProvider, UIFramework, WidgetProvider, WidgetTokenRefreshProvider, cloneEmbeddedClient, getGlobalWidgetConfig, getGlobalWidgetInitState, registerDesignSystemEnsurer, registerUIRenderers, setGlobalWidgetConfig, subscribeToGlobalWidgetInitState, updateGlobalWidgetConfig, useDisclosuresAcceptanceSurface, useOwnWidgetConfig, useRefetchWidget, useWidgetConfig, useWidgetError, useWidgetLoading, useWidgetToken }; export type { EmbeddedClient, LinkComponent, LinkComponentProps, RefreshingRootWidgetProviderProps, RootWidgetProviderProps, WidgetConfig, WidgetConfigInput, WidgetInitResponse, WidgetInitState, WidgetProviderProps, WidgetTokenFetcher, WidgetTokenManager, WidgetTokenRefreshProviderProps, WidgetTokenState };