/** Sources are supplied by the host; the SDK never infers a host filesystem path. */ export type PickerSource = 'server' | 'localFile' export type PickerSelectionMode = 'single-file' | 'multi-file' | 'folder' | 'folder+files' /** `list` shows one folder at a time (the default); `tree` adds disclosure triangles. */ export type PickerView = 'list' | 'tree' /** Row order inside each folder; folders always come before files. */ export type PickerSort = 'newest' | 'oldest' | 'name' | 'name-desc' interface PickerNodeBase { path: string name: string parentPath?: string | null parentName?: string bytes?: number | null /** ISO timestamp of the last change, shown in the list and the preview. */ modifiedAt?: string | null /** An explicit adapter failure makes a row inert, including its disclosure. */ unavailableReason?: string } export interface PickerFolder extends PickerNodeBase { kind: 'folder' fileCount?: number | null formats?: Record hasChildren?: boolean } export interface PickerFile extends PickerNodeBase { kind: 'file' format: string /** Present only for browser-selected files. The picker does not read its bytes. */ file?: File } export type PickerNode = PickerFolder | PickerFile export interface PickerRequest { signal?: AbortSignal source?: PickerSource /** * Set only when the user pressed Refresh. Adapters that cache listings (or * ask a server to bypass its own cache) should re-read the location then and * serve cached data otherwise; the picker keeps folder contents while it is * open and re-reads the current location on each open. */ refresh?: true } /** What a search found before a server or walk limit stopped it. */ export interface PickerSearchResult { nodes: PickerNode[] truncated: boolean } export interface PickerAdapter { /** * `listRoot()` returns mount points. FilePicker then shows them as header * sources and opens the first reachable one instead of listing the root. */ mounts?: boolean /** The path of the mount holding `path`, so an initial folder inside a mount can name it. */ mountOf?(path: string): string | undefined /** Discard cached and pending results on close, source changes, or refresh. */ invalidate?(): void listRoot(request?: PickerRequest): Promise listChildren(path: string, request?: PickerRequest): Promise search( query: string, scope: { path: string; recursive: boolean }, request?: PickerRequest, ): Promise } export interface PickerCapability { /** Case-insensitive suffixes, including compound extensions such as mzML.gz. */ formats: string[] maxBytes?: number /** Optional host-owned blank classification; no filename heuristics in the SDK. */ isBlank?: (node: PickerNode) => boolean } export type PickerCapabilities = Partial> export type PickerExclusionReason = 'deselected' | 'unsupported' | 'tooLarge' | 'blank' | 'unreadable' | 'forbidden' export interface PickerExcluded { /** Opaque identity prevents collisions between equal filenames in different folders. */ path: string name: string reason: PickerExclusionReason } export type PickerSelection = | { source: 'server'; folders: string[]; files: PickerFile[]; excluded: PickerExcluded[] } | { source: 'localFile'; files: File[]; relativePaths?: string[] } export interface PickerTreeRow { node: PickerNode depth: number expanded: boolean loading: boolean error?: string }