import 'rollup-plugin-inject-process-env'; /** * Shape of the `externalWidget` block on a booking-handoff form step. * * This mirrors `FormStepExternalWidget["externalWidget"]` from * `stentor-models@1.75.0`. See the local type-extension note in * `FormStepDisplay.tsx` for why it is redeclared here instead of imported. */ export interface ExternalWidgetConfig { anchorId: string; scriptSrc: string; configGlobal: string; config: Record; successCallbackKey?: string; cacheBust?: boolean; renderTimeoutMs?: number; fallbackStep?: string; } export type ExternalWidgetOutcome = "pending" | "rendered" | "no_render" | "error"; export interface UseExternalWidgetOptions { /** * Fired once the anchor renders a bookable `#step-*` (any step other than a * no-match or loading step, e.g. `step-schedule` or the returning-visitor * `step-review`). */ onRendered?: (provider: string) => void; /** * Fired when the anchor renders a no-match step (no coverage), or stays empty * with no `#step-loading` past the backstop `renderTimeoutMs`. */ onNoRender?: (provider: string) => void; /** * Fired at most once per mounted handoff, the first time the partner script invokes * the configured success callback. Later invocations within the same handoff are * suppressed, reported to the console and counted (see `suppressedScheduledCount`) * -- CostGuide confirmed (2026-08-13) that it fires "whenever an appointment gets * scheduled", so a single handoff can produce more than one fire and a duplicate * dispatch double-counts the booking downstream. * * Suppression is deliberately NOT its own analytics event: a new eventType needs a * matching server-side eventName mapping in stentor-api, which is out of scope here. * The console error is the signal that works today in a visitor's browser, and * `suppressedScheduledCount` is there for a caller that wants to act on it. * * `payload` is whatever (if anything) the partner passes to it. CostGuide passes * nothing today -- it is a bare trigger with no appointment id, time or contractor -- * but the parameter is kept tolerant in case that changes. */ onScheduled?: (provider: string, payload?: unknown) => void; /** * Fired when the script fails to load, or the scriptSrc is rejected. */ onError?: (provider: string) => void; /** * Fired alongside onNoRender/onError when `externalWidget.fallbackStep` is set, * so the caller can navigate there. Not fired when fallbackStep is unset -- * the caller is expected to render an inline fallback message instead. */ onFallback?: (fallbackStep: string) => void; } type AnchorState = "rendered" | "no_coverage" | "loading" | "empty"; /** * Classifies the current state of the anchor from the partner step id it shows. * * - a no-match step id -> "no_coverage" (a real screen, but no bookable coverage) * - `step-loading` -> "loading" (still working; do not fail yet) * - any other `step-*` -> "rendered" (e.g. `step-schedule`, or the * returning-visitor `step-review` -- do NOT assume one) * - no `step-*` present -> "empty" (not rendered yet) */ export declare function classifyAnchor(anchor: HTMLElement): AnchorState; /** * Derives the analytics `provider` string from the partner script's hostname. */ export declare function getExternalWidgetProvider(scriptSrc: string | undefined): string; /** * Drives the mount sequence for a third-party booking-widget handoff step: * assigns the merged config to `window[configGlobal]` (including the wired-up * success callback), appends the partner's embed script, and watches the * anchor for a render-timeout outcome. * * The mount sequence runs at most once per component lifetime (guarded by a * ref) the first time `externalWidget` is defined. If the config object is * later replaced with a new reference (e.g. a slower FORM_SUBMIT response * merging server values in after the step already rendered), the global is * re-assigned with the latest values but the script is not re-appended and * the timer is not restarted. */ export declare function useExternalWidget(externalWidget: ExternalWidgetConfig | undefined, options?: UseExternalWidgetOptions): { outcome: ExternalWidgetOutcome; suppressedScheduledCount: number; }; export {};