/** * The Vault browser-extension popup, as a shared component. * * A faithful recreation of `clients/extension` — the real popup's routes, * layout, copy, field labels, sort options and tag/folder structure — running on * sample data that never leaves the device. Interactive: open an item, copy a * field, reveal a TOTP, switch tabs, walk into settings. * * It lives HERE rather than in either consumer because both the marketing site * and the Vault app show it, and two copies of a 1,000-line recreation would * drift the moment the real extension changed. Same reasoning as sharing * `PasswordGenerator` instead of rewriting it per app. * * Two things the website's original did that this deliberately does not: * * * **No `auto` mode.** That drove a synthetic cursor with `querySelector` and * `getBoundingClientRect`, which has no meaning on native. It belongs to that * page's choreography, not to the extension, so the showcase keeps it. * * **No drag-and-drop in the tags tab.** It used `@dnd-kit`, which is DOM-only. * The grip handles remain as affordances because removing them would change * the layout this exists to reproduce, but they do not drag. * * Everything else is the original, moved rather than rewritten. */ import React from "react"; import { ScrollView } from "react-native"; /** * The real popup's frame, in px. * * `HEIGHT` is Chrome's *maximum* for a browser action popup, not a fixed size — * the real popup is as tall as it needs to be, up to this. So a host with less * vertical room may render it shorter (see the `height` prop) without the thing * on screen becoming a lie about what the extension looks like; the item list * scrolls inside, exactly as it does at full height. */ export declare const EXTENSION_POPUP_WIDTH = 380; export declare const EXTENSION_POPUP_HEIGHT = 600; /** Below this the chrome crowds out the list and it stops reading as the popup. */ export declare const EXTENSION_POPUP_MIN_HEIGHT = 320; export declare function useInk(): { fg: string; muted: string; bg: string; border: string; secondary: string; danger: string; star: string; }; export declare function vaultVars(dark: boolean): Record; export interface Account { username: string; password: string; totp_secret?: string; notes?: string; } export interface Tag { name: string; color: string; icon?: "tag" | "circle" | "star"; } export interface Item { id: string; name: string; url: string; favorite: boolean; tags: Tag[]; accounts: Account[]; created: string; updated: string; } export declare const T: { social: Tag; shopping: Tag; finance: Tag; streaming: Tag; gaming: Tag; }; export declare const ITEMS: Item[]; export declare const SORT_OPTIONS: readonly [{ readonly value: "name_asc"; readonly label: "Name (A-Z)"; readonly cmp: (a: Item, b: Item) => number; }, { readonly value: "name_desc"; readonly label: "Name (Z-A)"; readonly cmp: (a: Item, b: Item) => number; }, { readonly value: "updated_newest"; readonly label: "Recently updated"; readonly cmp: (a: Item, b: Item) => number; }, { readonly value: "created_newest"; readonly label: "Newest first"; readonly cmp: (a: Item, b: Item) => number; }, { readonly value: "created_oldest"; readonly label: "Oldest first"; readonly cmp: (a: Item, b: Item) => number; }]; export declare function host(url: string): string; export declare function favicon(url: string): string; export declare function ItemIcon({ url, size, radius, }: { url: string; size?: number; radius?: number; }): React.JSX.Element; export declare function useCopy(): { copied: string | null; copy: (key: string, text: string) => void; }; export declare function totpCode(seed: string, step: number): string; export declare function useTotp(secret?: string): { code: string; remaining: number; }; export declare function RingCountdown({ remaining, size, period, color, }: { remaining: number; size?: number; period?: number; color: string; }): React.JSX.Element; export declare function VaultItemRow({ item, ink, onPress, highlight, }: { item: Item; ink: ReturnType; onPress: () => void; highlight?: boolean; }): React.JSX.Element; export declare function Dropdown({ open, onToggle, label, icon, children, ink, }: { open: boolean; onToggle: () => void; label: string; icon?: React.ReactNode; children: React.ReactNode; ink: ReturnType; }): React.JSX.Element; export declare function VaultList({ ink, onOpen, items, scrollRef, highlightId, }: { ink: ReturnType; onOpen: (id: string) => void; items?: Item[]; scrollRef?: React.Ref; highlightId?: string | null; }): React.JSX.Element; export declare function FieldRow({ label, value, ink, copied, copy, secret, totp, }: { label: string; value: string; ink: ReturnType; copied: string | null; copy: (k: string, t: string) => void; secret?: boolean; totp?: ReturnType; }): React.JSX.Element; export declare function ItemDetail({ item, ink, onBack, onDelete, forceCopiedLabel, scrollRef, }: { item: Item; ink: ReturnType; onBack: () => void; onDelete?: () => void; forceCopiedLabel?: string | null; scrollRef?: React.Ref; }): React.JSX.Element | null; /** * The mark in the popup header. * * Supplied by the caller rather than loaded from a path. The original pointed * at `/products/vault_light.png`, which only resolves on the marketing site — * a shared package cannot reach into one consumer's public directory. Falls * back to the wordmark so the header is never empty. */ export declare function VaultMark({ logo }: { logo?: React.ReactNode; }): React.JSX.Element; export type ExtRoute = { r: "main"; } | { r: "detail"; id: string; } | { r: "settings"; } | { r: "new"; }; /** * A parent-driven view of the popup. * * Lets a scene puppet the popup — scroll the list, highlight a row, open it, * show a field as copied — while the popup keeps owning how any of that looks. * All of it is RN-safe, which is why it survived the move. * * What did NOT survive is the original's self-driving `auto` mode: it steered a * synthetic cursor with `querySelector` and `getBoundingClientRect`, which have * no meaning on native. A scene that wants that keeps its own cursor and drives * this controller instead. */ export interface ExtensionPopupController { route: ExtRoute; highlightId: string | null; autoCopied: string | null; listScrollRef: React.Ref; detailScrollRef: React.Ref; } /** * The browser-extension popup. * * Interactive by default. Pass `external` to have a parent scene drive it. */ export declare function ExtensionPopup({ logo, external, height, }?: { logo?: React.ReactNode; external?: ExtensionPopupController; /** Frame height. Defaults to the full 600; see `EXTENSION_POPUP_HEIGHT`. */ height?: number; }): React.JSX.Element; export default ExtensionPopup; //# sourceMappingURL=extension-popup.d.ts.map