import { type ComponentType, type ReactNode } from "react"; import { type GestureResponderEvent } from "react-native"; import { type StyleProp, type ViewStyle } from "../../style/index.js"; import { type AvatarProps } from "../../atoms/avatar/avatar.shared.js"; import { type BadgeProps } from "../../atoms/badge/badge.shared.js"; import { type ButtonProps } from "../../atoms/button/button.shared.js"; import { type DragDropProviderProps, type DropZoneProps, type DraggableProps, type DragHandleProps } from "../../organisms/drag-drop/drag-drop.shared.js"; import { type StackedListMove } from "./stacked-lists.reorder.js"; import { type StackedListSkin } from "./stacked-lists.styles.js"; /** One row in the list. */ export interface StackedListItem { /** Stable identity for the row's React key, so reorder/insert/delete keeps a * row mapped to the same item (preserving in-progress press/hover/focus state * and avoiding needless avatar remounts). The array index is the fallback, * which is only safe for static, never-reordered lists. */ id?: string | number; /** Primary line, bold (e.g. a person's name). */ name: string; /** Secondary line, smaller and muted (e.g. an email or role). */ detail: string; /** Trailing metadata text (e.g. "2h ago"). Ignored when `badge` is set. */ meta?: string; /** Trailing badge label; rendered as a instead of plain meta text. */ badge?: string; /** Status tone for the trailing `badge`, drawn as the kit's status pill. * * These are the item's only tonal surface, so they are named for the meaning * rather than prefixed: a row reads `{ name: "Kratos", badge: "Healthy", * success: true }`. Mutually exclusive; first match wins in the order listed * here. Without one the badge keeps its neutral `secondary` look, which is * what every existing call site gets. Ignored when `badge` is unset. */ success?: boolean; error?: boolean; warning?: boolean; info?: boolean; neutral?: boolean; /** Photo URL for the avatar; falls back to initials when absent. */ avatar?: string; /** Initials shown when there is no photo; derived from `name` when omitted. */ initials?: string; /** * Right-aligned slot rendered before the badge/meta cluster, for an inline * per-row editor or affordance (a Chip, a small Select, an action button). * Interactive content is fine in every variant: a `clickable` row carrying * this slot moves its press target to the content region (avatar + text), so * a control here never nests inside the row pressable. */ trailing?: ReactNode; } export interface StackedListProps { /** Rows to render. */ items?: StackedListItem[]; /** Optional header title; shown above the rows, separated by a rule. */ title?: ReactNode; /** Trailing header content (e.g. an action button); only shown with a title. * Takes precedence over `addAction` when both are supplied. */ action?: ReactNode; /** Convenience header action: renders a small outlined button with a leading * plus icon and this label (e.g. "Add"). Only shown with a title and when * `action` is not set. Serializable, so the playground can drive it. */ addAction?: string; /** Appends a trailing ghost overflow ("...") action-menu button to every row. * Press is reported through `onPressItemMenu`. */ rowMenu?: boolean; /** Press handler for a row, by index. Only used in the `clickable` variant. */ onPressItem?: (index: number, event: GestureResponderEvent) => void; /** Press handler for a row's overflow menu, by index. Used with `rowMenu`. */ onPressItemMenu?: (index: number, event: GestureResponderEvent) => void; clickable?: boolean; card?: boolean; flush?: boolean; /** * Render the rows through a windowed `FlatList` instead of mounting every row up * front, for large lists. Give the list a bounded height (via `style`, e.g. * `{ maxHeight: 400 }`) so it can scroll; without one it warns and renders eagerly * anyway. Default (omitted) mounts all rows, unchanged. Ignored (with a dev * warning) when `reorderable` is set: windowing unmounts off-screen rows, which * would leave them undraggable and unmeasurable mid-drag. */ virtualized?: boolean; /** * Make the rows reorderable: each row gains a leading drag grip (keyboard- and * screen-reader-operable: Space grabs, the arrow keys move, Space drops, Escape * cancels) and the list becomes one drop zone. The order stays CONTROLLED by the * consumer's `items` array: a drop only reports the move through `onReorder`, * never reorders internally. */ reorderable?: boolean; /** Fired on drop with the computed move (row id, from/to index, new neighbors). */ onReorder?: (move: StackedListMove) => void; /** E2E hook forwarded to the root element. */ testID?: string; /** Outer layout composition only (width/flex within a parent), never a restyle hook. */ style?: StyleProp; } export type AvatarComponent = ComponentType; export type BadgeComponent = ComponentType; export type ButtonComponent = ComponentType; export interface StackedListDnd { DragDropProvider: ComponentType; DropZone: ComponentType; Draggable: ComponentType>; DragHandle: ComponentType; } export type { StackedListMove }; export declare function createStackedList(skin: StackedListSkin, Avatar?: AvatarComponent, Badge?: BadgeComponent, Button?: ButtonComponent, dnd?: StackedListDnd): (props: StackedListProps) => import("react").JSX.Element; //# sourceMappingURL=stacked-lists.shared.d.ts.map