export interface PinCeremonyOptions { /** The app being pinned — its in-thread card is the ghost's source. */ appId: string; /** The slot it lands in. Omitted, the ceremony aims at the only mounted * VendoSlot; with several mounted and no id there is no way to know, so the * panel still dismisses and nothing flies. */ slot?: string; /** What confirms the pin actually happened — Vendo's placement write, or the * host's own. The ring is a claim that the pin LANDED, so it waits on this and * never fires unless it resolves; the flight itself is unconditional. Omitted, * nothing confirms the pin and there is no ring: a caller cannot get the claim * without supplying what backs it. */ confirmed?: Promise; /** Dismiss the surface the card is in. Called ONCE, after the ghost is clear * and before anything is measured — so a pin dismisses the panel even when * there is no animation to play. */ dismiss?(): void; } /** Play the pin ceremony. Reduced motion keeps the dismiss and the settle pulse * and skips the flight — the pulse is the whole movement. Safe to call anywhere: * without a DOM (SSR) or the Web Animations API it just dismisses. */ export declare function playPinCeremony({ appId, slot, confirmed, dismiss }: PinCeremonyOptions): void; /** * The pin affordance's nudge state (mockup 2026-08-04): a settled build whose * pin has not been taken INVITES it with a quiet infinite pulse, and the moment * it is taken the affordance resolves to a settled accent state. `undefined` is * the quiet default. * * "Not taken yet" is the pin bus, NOT a placements read: placements live on the * app document, which no pin affordance holds, so knowing it for certain costs a * list fetch per card — a request to render one boolean. The honest cost of that * choice is that a pin made in an earlier session invites once more. * * `invited` is the CALLER's — whether this surface's build just landed (the * in-thread card is `restored === false`) — because only the caller knows. */ export declare function usePinNudge(appId: string, invited: boolean): "invite" | "pinned" | undefined; /** * Every pin affordance's one path: ceremony, THEN the placement write, then * the announcement that lets every mounted slot show the result without * waiting for a poll, then the host's optional `onPin`. * * The write is Vendo's now (2026-08-05): a pin is `apps.place`, awaited, so * "the app is in the slot" is true before anything is announced. `onPin` * survives as a side-effect seam for hosts that mirror the pin into their own * product state — it is no longer what makes a pin happen. * * `slot` is the CALLER's, and it comes from the slot registry rather than any * provider config (2026-08-20): a mounted `` is the only thing that * knows a slot exists, so the affordance that reads the registry is the one * that can name the destination (`PlacementAction`, add-to-picker.tsx). A host * that mounts one slot gets the whole feature with no server code and no props * at all. * * Returns undefined when there is NEITHER a destination nor an `onPin` — which * is what hides the affordances in the first place. */ export declare function usePinAction(slot?: string): ((app: { appId: string; payload: unknown; }) => void) | undefined;