import { EventEmitter } from '../../stencil-public-runtime'; import { VehicleLookupDTO } from "../../global/types/generated/vehicle-lookup/vehicle-lookup-dto"; import { SscRepairTraceDTO } from "../../global/types/generated/vehicle-lookup/ssc-repair-trace-dto"; import sscSchema from "../../locales/vehicleLookup/ssc/type"; import { ManufacturerCheckStatus } from './components/SscCampaigns'; import { VehicleInfoLayoutInterface, VerdictState } from "../../features/vehicle-info-layout/index"; import { BlazorInvokable, DotNetObjectReference, BlazorInvokableFunction } from "../../features/blazor-ref/index"; import { RequestHeadersProvider, VehicleLookupComponent, VehicleLookupMock } from "../../features/vehicle-lookup-component/index"; import { ComponentLocale, ErrorKeys, LanguageKeys, MultiLingual } from "../../features/multi-lingual/index"; /** * The Special Service Campaigns (safety recalls) affecting a vehicle, and nothing else: warranty * coverage lives in . Replaces the campaign half of the retired * . * * A vehicle is on exactly one of two paths, and the panel must never mix them (the rule is spelled * out on `panelVerdict` in ./components/SscCampaigns.tsx and in * .shift/repos/adp/web-components/vehicle-lookup-invariants.md): * * - authorized (in the distributor's records): the campaign list is the verdict; * - unauthorized: the distributor has no records, so the only verdict is the manufacturer's * answer to the reCAPTCHA-gated check — a yes/no, no list. Until it arrives the panel says the * vehicle is not in the records and asserts nothing else. The check is always offered where * the stand-in widget is in use (development, `mockRecaptcha`); the real widget needs the * host's site key, and a production host that configured none gets the notice alone. * * A third state is neither: a wrapper that only counts the SSC tab's own request as a campaign * check (`sscQueryString`) tells this panel through `skipLookup` that a vehicle was looked up * without it. The panel then says the check was not run and offers to run it, rather than sitting * blank next to a VIN as if the vehicle had no campaigns. * * With `show-trace`, every campaign row can open the evidence behind its repair status: the labor * codes accepted for the campaign, every warranty claim on the vehicle with how it was judged, and * the service-history lines that matched. The trace is fetched on first use with `?trace=ssc`, so * the ordinary lookup response stays small and the host can gate the detail behind a permission. * * Every state change is a movement (lookup-motion.css): the outgoing content stays rendered while * the body shuts over it, and the incoming content is swapped in only while the body is shut. The * shared lookup helper waits a second before it asks the server, which is what guarantees the body * has settled shut before a response can land. */ export declare class VehicleSsc implements MultiLingual, VehicleInfoLayoutInterface, VehicleLookupComponent, BlazorInvokable { language: LanguageKeys; locale: ComponentLocale; componentWillLoad(): Promise; changeLanguage(newLanguage: LanguageKeys): Promise; coreOnly: boolean; isDev: boolean; today?: string; disableVinValidation: boolean; baseUrl: string; headers: object; queryString: string; /** * Appended to the campaign lookup request only, never to the trace request. A wrapper passes its * `sscQueryString` — typically a lookup-logging flag — here rather than into `queryString`, so * opening a campaign's evidence (a re-read of a lookup that was already logged) is never counted * as another lookup. The host's endpoint must refuse to log traced requests as well. */ lookupQueryString: string; /** Asked for the current headers before every request this component makes itself; lets a host refresh its token on demand. */ requestHeadersProvider?: RequestHeadersProvider; /** Name of a [JSInvokable] method on the Blazor reference that answers with the current headers. */ blazorRequestHeadersProvider: string; lastRequestHeaders?: object; errorCallback?: BlazorInvokableFunction<(errorMessage: ErrorKeys) => void>; loadingStateChange?: BlazorInvokableFunction<(isLoading: boolean) => void>; loadedResponse?: BlazorInvokableFunction<(response: VehicleLookupDTO) => void>; unauthorizedSscLookupResponse?: BlazorInvokableFunction<(sscLookupStatus: number) => void>; isError: boolean; errorMessage?: ErrorKeys; isLoading: boolean; vehicleLookup?: VehicleLookupDTO; el: HTMLElement; mockData: any; abortController: AbortController; networkTimeoutRef: ReturnType; setMockData(newMockData: VehicleLookupMock): Promise; fetchVin(newData: VehicleLookupDTO | string, headers?: any): Promise; setErrorMessage(message: ErrorKeys): Promise; /** Back to "no vehicle": the body shuts over what it holds, then the panel is emptied unseen. */ clearData(): Promise; /** * The other panels were given a vehicle but this one's own lookup was not run for it — a wrapper * with `sscQueryString` only counts the SSC tab's own request as a campaign check. The panel says * so and offers to run the check itself; the VIN is kept for that. */ skipLookup(vin: string): Promise; onLoadingChange(newValue: boolean): void; /** A vehicle was looked up without this panel; set by `skipLookup`, cleared by the next lookup. */ skippedVin?: string; /** The panel is on its way to empty: the sheen is on and the body is shutting over its content. */ leaving: boolean; private leaveGeneration; /** * The body's last non-empty content, kept while the body is shut so the content slides away * with it instead of vanishing the frame the state changes. Dropped once the body has settled. */ private retainedBody; private retainTimer?; /** How long a state change takes to settle: the --settle token plus a margin for the frame it starts on. */ private settleMs; /** * Puts the chip and lead on the sheen, shuts the body over whatever it holds, and resolves once * they have settled — so the caller can swap the content while nothing is on screen. Resolves at * once when there is nothing to leave. A lookup started meanwhile takes over. */ private leave; private emptyPanel; /** * Height changes here are CSS transitions inside this shadow root, which an enclosing * (the wrapper's tab strip) cannot see; it would keep clipping at the old * height. So every render that moved something announces the change to those containers, the way * a nested does, and they stop clipping until it has settled. */ private heightAnnouncer?; private layoutSignature?; componentDidRender(): void; private runSkippedLookup; /** Remembers what the body shows, and forgets it a settle after the body shut. */ private retainBody; blazorRef?: DotNetObjectReference; setBlazorRef(newBlazorRef: DotNetObjectReference): Promise; /** Shows a per-campaign "why this status?" control. The host gates it on its own permission check; the trace lists claim and invoice details. */ showTrace: boolean; /** * The reCAPTCHA site key the real widget is rendered with. Production needs it to offer the * manufacturer check for an unauthorized vehicle; the stand-in widget (`isDev`, `mockRecaptcha`) * never talks to Google and needs no key. */ recaptchaKey: string; /** Renders a click-to-pass stand-in for the reCAPTCHA widget. Implied by `isDev`; the real widget is only ever used in production mode. */ mockRecaptcha: boolean; unauthorizedSscLookupBaseUrl: string; unauthorizedSscLookupQueryString: string; cityId?: string; cityIntegrationId?: string; companyId?: string; companyIntegrationId?: string; companyBranchId?: string; companyBranchIntegrationId?: string; userId?: string; brandIntegrationId: string; customerName?: string; customerPhone?: string; customerEmail?: string; /** The check is offered: the vehicle is unauthorized and the check can be run (`manufacturerCheckAvailable`). */ showRecaptcha: boolean; checkingUnauthorizedSSC: boolean; devRecaptchaChecked: boolean; recaptchaRes: { status: ManufacturerCheckStatus | null; } | null; private recaptchaIntervalRef; private recaptchaHideTimer?; private recaptchaWidgetId; private recaptchaPortalEl?; private recaptchaPlaceholderRef; private recaptchaReady?; private positionRAF?; /** * Development never shows Google's widget. The stand-in is the default whenever `isDev` is on, and * the real widget is created lazily, only when a production-mode lookup actually needs it — so a * host that flips `isDev` after the element mounted (the dev showcase does) still gets the mock, * instead of a real widget rendered at mount time sitting on top of a mock that never polls it. */ private get useMockRecaptchaWidget(); /** * Whether an unauthorized vehicle can be offered the manufacturer check at all. The stand-in * needs nothing — it never talks to Google, and in development the answer is a stand-in too — * so wherever it is in use the check is always offered; a vehicle the distributor has no record * of is never left with the notice alone. The real widget needs the host's site key. A * production host that configured none gets the notice alone: the one honest state left, since * the panel must never fabricate a manufacturer's answer. */ private get manufacturerCheckAvailable(); private mockRecaptchaTrigger?; onRecaptchaModeChange(): void; private handleDevRecaptchaClick; /** Stops the check from answering — polling, the stand-in's trigger, a request in flight — without touching what is on screen. */ private suspendManufacturerCheck; /** Back to "nothing asked yet" — every new lookup, once the previous check has left the screen, and a cleared panel start here. */ private resetManufacturerCheck; /** * Offers the check for an unauthorized vehicle. Not awaited by the lookup: loading Google's script * must not delay the vehicle landing on screen, so the real widget is armed in the background and * checked against the lookup generation before it starts polling. */ private prepareManufacturerCheck; private armRealRecaptcha; /** Loads Google's script and renders the widget into a body-level portal, once per element. */ private ensureRealRecaptcha; private hideRealRecaptcha; /** * The real widget is visible only while a production-mode check is offered and unanswered. It * lives outside the shadow root, so the body cannot clip it as it shuts; instead it follows the * body's opacity (see `getAncestorOpacity`) and is only taken down once the body has settled. */ private syncRealRecaptchaVisibility; onRecaptchaStateChange(): void; private runUnauthorizedSscLookup; disconnectedCallback(): void; /** * Keeps the widget over its placeholder for as long as it is shown: one frame at a time, one loop * at a time. The placeholder is not always on the page while the widget is. A lookup made after * an answered check prepares the next check while the body is shut over nothing — the last * check's block left with the body once the manufacturer had answered — and the placeholder only * returns with the render that lands the vehicle. So the loop must not end when the placeholder * is missing: it keeps the widget out of sight and out of reach until the placeholder is back, * then takes its place. A loop that ended there left the portal shown but stranded, at the * opacity the body had when it faded out: an invisible widget under a prompt to complete it. */ private followPlaceholder; private stopFollowingPlaceholder; private syncRecaptchaPosition; /** * How see-through the widget's place on the page is: the product of every ancestor's opacity, * from the placeholder up through this shadow root (the body fading as it shuts) and on up the * host page (a tab sliding out). The portal copies it, so the real widget leaves with the panel. */ private getAncestorOpacity; openTraceKey?: string; traces: Record; traceLoading: boolean; traceError?: string; private traceAbortController?; /** The VIN the cached traces belong to; a lookup for another vehicle invalidates them. */ private tracesVin?; private resetTraces; private toggleTrace; private loadTraces; /** The row whose drawer the page is following, and the way to let go of it. */ private followedDrawer?; private stopFollowing?; /** * When a row's evidence opens, brings the row to the top of the page and keeps it there while the * drawer slides open beneath it — as an expanded service-history line does — so the reader is * looking at the evidence they asked for and not at the drawer's edge below the fold. Runs after * every render and acts only when the open drawer changes; closing it, or leaving, lets go. */ private followOpenDrawer; private stopFollowingDrawer; /** * Fires whenever the panel's verdict changes — including back to idle when the vehicle is * cleared — so a composite that draws one card for several panels can colour its accent from the * active one. */ verdictChange: EventEmitter; private lastVerdict?; private currentVerdict; private announceVerdict; private panelState; render(): any; }