import { type ComponentType, type ReactNode } from "react"; import { type ColorTokens, type LayoutStyle, type ViewStyle, type TextStyle } from "../../style/index.js"; import { type AvatarProps } from "../../atoms/avatar/avatar.shared.js"; import { type IconName } from "../../atoms/icon/icon.js"; export type AvatarComponent = ComponentType; /** One event in the feed. */ export interface FeedItem { /** * Stable identity for this event, used as the row's React key. Supply it for * mutable or reordered feeds (the common timeline case is prepending the * newest event): without it the rows fall back to their array index, which * desyncs per-row state and press feedback when items are inserted at the * front or reordered. */ id?: string | number; /** Actor who performed the action, rendered bold (e.g. "Rachel Chen"). */ actor?: string; /** The action text, muted (e.g. "approved the request"). */ action?: string; /** Rich event content, used by the activity and trace rows. */ content?: ReactNode; /** Trace category, rendered as an inline eyebrow. */ kind?: string; /** Trace marker and optional halo colors. */ color?: string; halo?: string; /** Optional target of the action, muted and trailing the action. */ target?: string; /** Relative timestamp, muted and small (e.g. "2 hours ago"). */ time?: string; /** Photo URL for the avatar lead; falls back to initials from the actor. */ avatar?: string; /** * Leading Canvas glyph for the CONNECTOR node, named from the kit icon set * (e.g. `"shieldCheck"`, `"gitMerge"`, `"keyRound"`). Rendered through the * `Icon` atom, muted and decorative (the row's own text carries the meaning), * and it takes precedence over the actor's initials and the actor-less dot. * Reach for it on system or automation events, where a glyph names the kind of * event better than a pair of letters. The avatar lead ignores it: that row * leads with the person's photo or initials. */ icon?: IconName; } export interface FeedProps { /** Events to render, top to bottom. */ items?: FeedItem[]; activity?: boolean; trace?: boolean; connector?: boolean; avatar?: boolean; compact?: boolean; /** When set, each event row is pressable, reporting the row index. */ onItemPress?: (index: number) => void; /** * The feed's accessible name (e.g. "Recent activity"): a screen reader announces it * with the list of events. A `virtualized` feed needs one: on the web its scroller * is a keyboard stop while the events overflow, and Chromium names an unnamed stop * from the text of every event it has rendered. */ label?: string; /** * 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. On the web, while the rows * overflow, the windowed list is a keyboard tab stop the keyboard can scroll, and * the feed's card draws the focus ring while it has keyboard focus. */ virtualized?: boolean; /** E2E hook forwarded to the root element. */ testID?: string; /** Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds. */ style?: LayoutStyle; } export type Lead = "activity" | "trace" | "connector" | "avatar"; export interface FeedSkin { /** The card surface framing the feed (shape, border, fill, max-width). */ cardSurface: (t: ColorTokens) => ViewStyle; /** Connector surface padding by density (compact vs default). */ connectorPad: (compact: boolean) => ViewStyle; /** Inter-row vertical rhythm by density for the connector lead (dropped on last). */ connectorRowGap: (compact: boolean) => ViewStyle; /** The leading connector node that carries an item's glyph (a disc). */ node: (t: ColorTokens) => ViewStyle; /** The node of an event with no glyph: a dot, the first one in the accent. */ dot: (t: ColorTokens, first: boolean) => ViewStyle; /** The vertical connector line under the node center. */ connectorLine: (t: ColorTokens) => ViewStyle; /** The outer wrapping line (sizing only). */ lineText: TextStyle; /** The actor name (bold, foreground). */ actorLabel: (t: ColorTokens) => TextStyle; /** The action / target text (muted). */ actionLabel: (t: ColorTokens) => TextStyle; /** The relative timestamp (muted, small). */ timeLabel: (t: ColorTokens) => TextStyle; /** iOS/web dim on press of a row; Android uses a ripple instead (null). */ pressedOpacity: number | null; /** Android ripple over pressable rows; null on iOS/web. */ ripple: ((t: ColorTokens) => { color: string; borderless: boolean; }) | null; /** * Minimum effective touch-target height for a pressable row (HIG 44pt on iOS, * Material 48dp on Android). Rows already taller than this are unaffected; it * only floors the short final connector row (~40pt) up to the platform * minimum. 0 on web (pointer input, no finger-target rule; layout unchanged). */ minTarget: number; } export declare function leadOf(p: FeedProps): Lead; export declare function createFeed(skin: FeedSkin, Avatar?: AvatarComponent): (props: FeedProps) => import("react").JSX.Element; //# sourceMappingURL=feeds.shared.d.ts.map