import * as React from 'react'; import { ComponentType, AnchorHTMLAttributes, ReactNode, ErrorInfo } from 'react'; import { SortingState, OnChangeFn } from '@tanstack/react-table'; import { FallbackProps } from 'react-error-boundary'; /** * Co-located user-facing strings for every chart-of-accounts surface: the table, * the create/edit sheet, and the delete confirmation. Each component takes a * `labels?: Partial<…Labels>` prop merged over the matching `*_LABELS_EN` * default. * * This is the single home for the widget's translation surface. Keeping any of * it next to a component instead splits what a translator has to find. * * The copy follows the Chart of accounts design, which calls each row an * "account" rather than a "GL code" or a "category": the GL code is one field on * an account, not the thing itself. */ interface ChartOfAccountsLabels { /** Section heading, and the sentence beneath it explaining what the list is. */ title: string; subtitle: string; columnGlCode: string; columnName: string; columnDescription: string; columnActions: string; actionEdit: string; actionDelete: string; /** Accessible name for the icon-only sort control in the name column. */ sortByName: string; openActionsMenu: string; /** Toolbar and empty-state call to action. */ addAccount: string; emptyTitle: string; emptyDescription: string; /** * Shown instead of {@link ChartOfAccountsLabels.emptyTitle} when a later page * comes back empty, which happens when the rows it held were deleted. The * organization still has accounts, so the copy must not claim otherwise. */ emptyPageTitle: string; emptyPageDescription: string; errorTitle: string; errorDescription: string; paginationPrev: string; paginationNext: string; } declare const CHART_OF_ACCOUNTS_LABELS_EN: ChartOfAccountsLabels; /** * Copy for the create/edit sheet. * * Four of these are resolved by the **owner** rather than by `AccountFormSheet`: * `createTitle`, `createDescription`, `editDescription`, and `descriptionCounter`. * The sheet takes an already-assembled `title`, `description`, and * `descriptionCounterText`, because choosing between create and edit copy is form * policy and filling `{count}`/`{max}` is formatting, neither of which belongs in * a presentational component. They stay in this file anyway: it is the single * home for the widget's translation surface, and splitting it by which layer * happens to read a key would make a translator hunt in two places. * * There is no `editTitle`. The design titles the edit sheet with the account's * own name, verbatim, so there is no template to translate. */ interface AccountFormSheetLabels { /** Create-mode heading. Owner-resolved. */ createTitle: string; /** Screen-reader description of the edit sheet's purpose. Owner-resolved. */ editDescription: string; /** Screen-reader description of the create sheet's purpose. Owner-resolved. */ createDescription: string; glCodeLabel: string; glCodePlaceholder: string; nameLabel: string; namePlaceholder: string; descriptionLabel: string; descriptionPlaceholder: string; /** * `{count}` and `{max}` are replaced with the current and maximum length. * Owner-resolved; the sheet renders the finished `descriptionCounterText`. */ descriptionCounter: string; cancelButton: string; saveButton: string; /** Tooltip on a disabled save, explaining why it cannot be pressed yet. */ saveDisabledHint: string; openAccountMenu: string; deleteAction: string; /** * Accessible name for the sheet's close control. The built-in `SheetContent` * close is switched off in favour of one this widget owns, so the copy stays * inside the label contract instead of the primitive's hardcoded "Close". */ closeSheet: string; } declare const ACCOUNT_FORM_SHEET_LABELS_EN: AccountFormSheetLabels; interface AccountDeleteDialogLabels { /** * `{name}` is replaced with the account name. Owner-resolved, for the same * reason as the sheet's titles above: the dialog takes a finished `title` * rather than a domain value plus a template. */ title: string; /** Used when the owner passes no `message`, which is the normal case. */ message: string; confirmButton: string; cancelButton: string; } declare const ACCOUNT_DELETE_DIALOG_LABELS_EN: AccountDeleteDialogLabels; type LedgerAccountRow = { id: string; name: string; nominal_code: string; description: string; /** * True when the account came from an external accounting system. The API * refuses to update or delete these (403), so row actions are withheld. */ is_external?: boolean; }; interface ChartOfAccountsTableProps { data: LedgerAccountRow[]; isLoading?: boolean; isError?: boolean; sorting: SortingState; onSortingChange: OnChangeFn; pageSize: number; onPageSizeChange: (pageSize: number) => void; pageSizeOptions: number[]; hasNextPage?: boolean; hasPrevPage?: boolean; onNextPage: () => void; onPrevPage: () => void; /** Merged with CHART_OF_ACCOUNTS_LABELS_EN; only override what you need. */ labels?: Partial; onEdit?: (row: LedgerAccountRow) => void; onDelete?: (row: LedgerAccountRow) => void; /** * Enables the add action. Rendered as a toolbar button above the table, or as * the centred call to action when the first page comes back with no rows. * Omit it (for example when the user lacks write permission) to withhold the * affordance entirely. */ onAdd?: () => void; /** Optional section heading rendered above the table. Omit when the host * already provides its own title. */ title?: string; /** Applied to the empty state's root element. Supplied by the caller, not decided here. */ emptyStateTestId?: string; } declare function ChartOfAccountsTable({ data, isLoading, isError, sorting, onSortingChange, pageSize, onPageSizeChange, pageSizeOptions, hasNextPage, hasPrevPage, onNextPage, onPrevPage, labels, title, emptyStateTestId, onEdit, onDelete, onAdd, }: ChartOfAccountsTableProps): React.JSX.Element; /** * Which form the owner has open. Deliberately *not* a prop on * {@link AccountFormSheet}: the sheet renders whatever `title` and `description` * it is handed, so create-versus-edit is the owner's state rather than something * the sheet interprets. Lives here because it belongs to this widget's shared * vocabulary and is part of the published package surface; * `useChartOfAccountsCrud` is the consumer. */ type AccountFormMode = 'create' | 'edit'; interface AccountFormValues { name: string; nominal_code: string; description: string; } interface AccountFormErrors { name?: string; nominal_code?: string; description?: string; /** Form-level error (e.g. an API failure not tied to a single field). */ form?: string; } interface AccountFormSheetProps { open: boolean; onOpenChange: (open: boolean) => void; /** * Heading, already assembled. The owner decides whether that is the create * copy or the edited account's own name; the sheet does not interpolate a * domain value into a template or branch on a form mode to pick one. */ title: string; /** Screen-reader description of the sheet's purpose, already assembled. */ description: string; values: AccountFormValues; errors?: AccountFormErrors; /** Disables every action while a mutation is in flight. */ inProgress?: boolean; /** * Whether the form is not yet complete enough to submit. The owner decides, * so the rule stays with the validation that enforces it; the sheet only * reflects the answer and shows {@link AccountFormSheetLabels.saveDisabledHint}. */ submitDisabled?: boolean; /** Already-formatted character counter for the description, e.g. "53/280 characters". */ descriptionCounterText: string; onNameChange: (name: string) => void; onGlCodeChange: (nominalCode: string) => void; onDescriptionChange: (description: string) => void; onSubmit: () => void; onCancel: () => void; /** * Shows the header menu when supplied. The owner withholds it for a form that * has nothing to delete yet, so its presence is the whole condition here. */ onDelete?: () => void; /** Merged with {@link ACCOUNT_FORM_SHEET_LABELS_EN}. */ labels?: Partial; } /** * Presentational create/edit form for a ledger account, rendered in a side * sheet. Fully controlled: the owner holds `values` and validation `errors` and * reacts to the field-change and submit/cancel/delete gestures. * * Three fields (GL code, account name, description), in the order the design * lists them. An **Account type** select is also in the design and deliberately * absent here: the API exposes `type` on the response only, so the control would * silently discard whatever was chosen. It arrives with EMBD-4603. */ declare function AccountFormSheet({ open, onOpenChange, title, description, values, errors, inProgress, submitDisabled, descriptionCounterText, onNameChange, onGlCodeChange, onDescriptionChange, onSubmit, onCancel, onDelete, labels, }: AccountFormSheetProps): React.JSX.Element; interface AccountDeleteDialogProps { open: boolean; onOpenChange: (open: boolean) => void; /** * Confirmation heading, already assembled. The owner names the account, so the * dialog never interpolates a domain value into a template. */ title: string; /** * Body copy. Falls back to * {@link AccountDeleteDialogLabels.message} when omitted, since nothing about * this sentence depends on which account is being deleted. */ message?: string; /** Disables the buttons while the delete mutation is in flight. */ isDeleting?: boolean; /** Failure message from the delete attempt; keeps the dialog open. */ error?: string; onConfirm: () => void; onCancel: () => void; /** Merged with {@link ACCOUNT_DELETE_DIALOG_LABELS_EN}. */ labels?: Partial; } /** * Destructive confirmation dialog for deleting a GL code. Controlled by the * owner; composes the shared `AlertDialog` primitive with a destructive confirm * button. */ declare function AccountDeleteDialog({ open, onOpenChange, title, message, isDeleting, error, onConfirm, onCancel, labels, }: AccountDeleteDialogProps): React.JSX.Element; 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 EmbeddedClient = Client; type ExtractLiterals = T extends string ? string extends T ? never : T : never; type BaseUrl = ExtractLiterals; 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]; /** * 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; } /** * 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; } /** * Feature-layer copy for the widget's built-in create/edit/delete flow. * * The table, form sheet, and delete dialog each carry their own label sets in * the `ui` library; these are only the strings the orchestration produces * itself, which is validation messages, API failure fallbacks, and the * confirmation toasts. Consumers override them through the widget's * `messageLabels` prop, merged over {@link CHART_OF_ACCOUNTS_MESSAGE_LABELS_EN}. */ interface ChartOfAccountsMessageLabels { nameRequired: string; glCodeRequired: string; /** `{max}` is replaced with the field's character limit. */ nameTooLong: string; /** `{max}` is replaced with the field's character limit. */ glCodeTooLong: string; /** `{max}` is replaced with the field's character limit. */ descriptionTooLong: string; saveError: string; deleteError: string; /** `{name}` is replaced with the account's name. */ accountCreated: string; /** `{name}` is replaced with the account's name. */ accountUpdated: string; /** `{name}` is replaced with the account's name. */ accountDeleted: string; } declare const CHART_OF_ACCOUNTS_MESSAGE_LABELS_EN: ChartOfAccountsMessageLabels; /** * Props that the feature layer owns and wires internally. Consumers cannot * override these because they are driven by the query and pagination state. * Everything else on `ChartOfAccountsTableProps` (including `title`) passes through * this `Omit` untouched via the `...tableProps` spread below, so no explicit * feature-layer wiring needed when a new pass-through UI prop is added there. */ type TableProps = Omit; /** * Label override channels, one per surface the widget mounts. * * The widget renders more than the table, so a single `labels` prop would leave * the built-in create/edit/delete flow stuck on English while the table around * it localized. Split per surface rather than nested under one object, which is * the shape `tags-widget`, `products-widget`, and `counterparts-widget` all use. */ interface ChartOfAccountsWidgetLabelProps { /** Table copy: headings, column headers, row actions, empty and error states. */ screenLabels?: Partial; /** Create/edit sheet copy: titles, field labels, placeholders, buttons. */ formLabels?: Partial; /** Delete confirmation copy. */ deleteLabels?: Partial; /** Validation messages, save/delete failure fallbacks, and success toasts. */ messageLabels?: Partial; } /** * Public props for {@link ChartOfAccountsWidget}. * * Merges {@link WidgetProviderProps} (auth/base-URL scope) with the subset of * {@link ChartOfAccountsTableProps} that consumers are allowed to control (row * action callbacks, empty-state CTAs, etc.) plus a label channel per surface. */ type ChartOfAccountsWidgetProps = WidgetProviderProps & TableProps & ChartOfAccountsWidgetLabelProps; /** * Self-contained GL code table widget. * * Composes a {@link WidgetProvider} scope with the table's query and pagination * logic. The two-component split (`ChartOfAccountsWidget` → `ChartOfAccountsWidgetInner`) * ensures that `useGetLedgerAccountsQuery` runs *inside* the provider tree and * can therefore resolve the correct API base URL and auth token from context. * * @example * ```tsx * openEditDialog(row)} * onDelete={(row) => confirmDelete(row)} * /> * ``` */ declare function ChartOfAccountsWidget({ baseUrl, widgetToken, organizationId, configClient, gatewayRouting, linkComponent, implementation, uiFramework, analytics, disclosuresAcceptance, errorFallback, onError, ...tableProps }: ChartOfAccountsWidgetProps): React.JSX.Element; export { ACCOUNT_DELETE_DIALOG_LABELS_EN, ACCOUNT_FORM_SHEET_LABELS_EN, AccountDeleteDialog, AccountFormSheet, CHART_OF_ACCOUNTS_LABELS_EN, CHART_OF_ACCOUNTS_MESSAGE_LABELS_EN, ChartOfAccountsTable, ChartOfAccountsWidget }; export type { AccountDeleteDialogLabels, AccountDeleteDialogProps, AccountFormErrors, AccountFormMode, AccountFormSheetLabels, AccountFormSheetProps, AccountFormValues, ChartOfAccountsLabels, ChartOfAccountsMessageLabels, ChartOfAccountsTableProps, ChartOfAccountsWidgetLabelProps, ChartOfAccountsWidgetProps, LedgerAccountRow };