import "./file_row.css"; import type * as React from "react"; import { useRender } from "@base-ui/react/use-render"; import { type DisplayFile } from "./file_thumbnail"; import { type FieldAnnotationProps } from "./field_annotations"; import { type StyleProps } from "./style_props"; export interface FileRowProps extends FieldAnnotationProps, StyleProps { /** The file / document name — the primary line. */ name: string; /** * Secondary line: size, status, timestamp — or a NODE, when the second line * is itself carrying a change. * * A document set under review needs it: a file being RECLASSIFIED is the same * bytes with a different filing ("Other" becomes "Certificate of origin"), * and a file being SUPERSEDED wants the scan it displaces struck beneath it. * Both are `DiffValue`s, and a string could only have described them in prose. * A node renders OUTSIDE the muted single-line `Text` — that wrapper would * clip it and its colour would fight the diff's own. */ meta?: React.ReactNode; /** File type → the FileBadge glyph + color. Omit (with `placeholder`) for an * expected-but-not-yet-provided document. */ mimeType?: string; /** * The stored file, so an IMAGE shows the scan itself where the glyph would be. * * A checklist of photographed paperwork — a permit, a certificate, an ID — is * a list of documents that all carry the SAME badge, so the badge stops * telling one row from another and only says "this is a picture". The picture * says which picture. A non-image (a PDF) falls back to the badge, drawn * inside the SAME square slot the picture fills — a mixed list keeps one left * edge and one row height down the column, which is the whole reason the two * marks share a footprint rather than each taking its own. * * It replaces the badge rather than sitting beside it: two marks on one row is * the same fact twice, and `leading` is reserved for a mark ABOUT the row (a * `DiffMark`, a checkbox) which must line up outside the file's own identity. */ file?: DisplayFile; /** * Makes the THUMBNAIL its own press target, separate from the row's. * * A document row often has two different destinations: the row opens what the * row is ABOUT (expand its fields, drill to the record), while the picture * opens the picture. Without this the row's single door swallows both, so the * only way to see the scan is whatever the row happens to do. * * It is a sibling press, not a nested one — the thumbnail sits outside the * row's own `Pressable`, so this never puts a button inside a button. */ onOpenFile?: () => void; /** Ghost badge — an expected document that hasn't been provided yet. */ placeholder?: boolean; /** Marks the badge as a template (TMPL). */ isTemplate?: boolean; /** When set, the WHOLE row is a pressable "door" (e.g. open the file), with a * hover/press wash. Omit for a static line whose only interaction is `trailing`. */ onPress?: () => void; /** Trailing slot — a status `Status`, an action `Button`, a timestamp, a remove * control. An independently-interactive SIBLING: never swallowed by the row * press (a button never nests in the door button). */ trailing?: React.ReactNode; /** * What the row IS — a status `Status`, a verdict. Rides INSIDE the row's own door, * because a status is part of what the row says and pressing it should open * the row. `trailing` is for what you DO to the row and stays outside. */ status?: React.ReactNode; /** * Leading slot, BEFORE the badge — a `DiffMark` saying what happened to this * document, a selection checkbox, a status dot. * * A SIBLING of the row's own door, like `trailing` — not inside it. It used * to render within the `Pressable`, which made the documented checkbox an * interactive control nested in a `button`: invalid ARIA, and two owners for * one press, since ticking the box also opened the file. The cost of the fix * is that the mark itself is no longer part of the door; that is the correct * trade, because a slot the docs tell you to put a control in cannot be * inside the control. * * It sits outside the badge rather than on it because it must line up DOWN * the list: a mark drawn over a 30px badge moves with the badge's size, and * `sm` and `md` rows would stop agreeing. Give every row the same slot, * filled or empty, or the names stop forming a column. */ leading?: React.ReactNode; /** * Row weight. `"sm"` (default) is the compact attachment line — many files * scanned as a list. `"md"` is the DOCUMENT-DESK row: a taller badge and a * `ListItem`-height body, for the few rows that are the surface's subject * rather than an appendix to it — an expected-document checklist, a slot a * button fills. A one-or-two-row section at `sm` reads as an afterthought. */ size?: "sm" | "md"; testID?: string; ref?: React.Ref; render?: useRender.RenderProp; } /** * A horizontal file / document LINE: a `FileBadge` (or a same-footprint * placeholder) + the full name and an optional meta line, with a composable * `trailing` slot. For document checklists, requirement lists, and attachment * rows where the name must be readable. * * `onPress` makes the whole row a pressable door; `trailing` stays a sibling, so * a button/menu in it is pressed independently (the door + sibling a11y pattern — * see `PressableRow`). For square thumbnail tiles use `FileThumbnailGrid`. */ export declare function FileRow(props: FileRowProps): React.ReactElement>; /** * THE MARK'S SQUARE SLOT on the DOCUMENT-DESK row — the picture fills it and the * badge takes the widest width that fits inside it (45 × 55), so a row of scans * and a row of PDFs share one left edge and one height. * * It is this big because a scan is READ rather than recognised: at badge size a * photographed certificate is an indistinct grey rectangle, and the whole reason * to show the picture is to tell one document from another. The badge's type * letters clear the legible floor at this width and nowhere under 43. */ export declare const IMAGE_THUMB_MD = 56;