/** * Post — a card carrying something somebody said, and what everyone did about it. * * Four shapes, because a feed is not one thing. `feed` is the full card: author, * body, media and a row of counts. `vote` puts a score pill beside a headline * and a thumbnail, the way a ranked community reads. `compact` drops the media * and puts the name and handle on one line, for a dense timeline. `media` gives * the image the whole card and lays the author over it. * * What they share is the anatomy — the same `Post.Header`, `Post.Body`, * `Post.Footer` in every one — so moving between them is a prop rather than a * rewrite. The variant decides padding, media shape and where the author sits; * it does not decide which parts exist. * * ```tsx * * * * * * I've been paying off my credit card #FinancialFreedom * * * * * * * * * ``` * * ## Counts change under the finger * * Every control here is a toggle over a number, and the number is the point: a * like that lights up but leaves `215` sitting there has not told you it * counted. So a stat that changes animates the old value out and the new one in * along the direction of the change, and `Post.Votes` does the same with its * arrows. The alternative — repainting the digits in place — is indisting- * uishable from a re-render, which is exactly the doubt the animation exists to * remove. */ import { type ComponentType, type ReactNode } from 'react'; import { View, type ImageSourcePropType, type PressableProps, type ViewProps } from 'react-native'; import { type VariantProps } from 'tailwind-variants'; import { type IconProps } from '../../icons/index.js'; declare const postVariants: import("tailwind-variants").TVReturnType<{ variant: { /** The full card — author, body, media, counts. */ feed: { header: string; body: string; media: string; footer: string; }; /** A headline with a score beside it, the way a ranked community reads. */ vote: { header: string; body: string; media: string; footer: string; }; /** No media, name and handle on one line — for a dense timeline. */ compact: { root: string; header: string; body: string; media: string; footer: string; }; /** The image is the card; the author is laid over it. */ media: { header: string; body: string; media: string; footer: string; }; }; size: { default: {}; sm: { name: string; meta: string; statLabel: string; }; }; }, { root: string; header: string; author: string; authorLine: string; name: string; handle: string; meta: string; action: string; community: string; communityName: string; communityMeta: string; title: string; body: string; media: string; footer: string; stat: string; statLabel: string; votes: string; voteButton: string; voteScore: string; }, undefined, { variant: { /** The full card — author, body, media, counts. */ feed: { header: string; body: string; media: string; footer: string; }; /** A headline with a score beside it, the way a ranked community reads. */ vote: { header: string; body: string; media: string; footer: string; }; /** No media, name and handle on one line — for a dense timeline. */ compact: { root: string; header: string; body: string; media: string; footer: string; }; /** The image is the card; the author is laid over it. */ media: { header: string; body: string; media: string; footer: string; }; }; size: { default: {}; sm: { name: string; meta: string; statLabel: string; }; }; }, { root: string; header: string; author: string; authorLine: string; name: string; handle: string; meta: string; action: string; community: string; communityName: string; communityMeta: string; title: string; body: string; media: string; footer: string; stat: string; statLabel: string; votes: string; voteButton: string; voteScore: string; }, import("tailwind-variants").TVReturnType<{ variant: { /** The full card — author, body, media, counts. */ feed: { header: string; body: string; media: string; footer: string; }; /** A headline with a score beside it, the way a ranked community reads. */ vote: { header: string; body: string; media: string; footer: string; }; /** No media, name and handle on one line — for a dense timeline. */ compact: { root: string; header: string; body: string; media: string; footer: string; }; /** The image is the card; the author is laid over it. */ media: { header: string; body: string; media: string; footer: string; }; }; size: { default: {}; sm: { name: string; meta: string; statLabel: string; }; }; }, { root: string; header: string; author: string; authorLine: string; name: string; handle: string; meta: string; action: string; community: string; communityName: string; communityMeta: string; title: string; body: string; media: string; footer: string; stat: string; statLabel: string; votes: string; voteButton: string; voteScore: string; }, undefined, unknown, unknown, undefined>>; type PostVariant = 'feed' | 'vote' | 'compact' | 'media'; export interface PostProps extends Omit, VariantProps { className?: string; /** Which of the four shapes. */ variant?: PostVariant; /** `sm` tightens the type for a card in a sidebar or a preview. */ size?: 'default' | 'sm'; /** Opening the post itself. The parts inside keep their own presses. */ onPress?: PressableProps['onPress']; children?: ReactNode; } export interface PostHeaderProps extends ViewProps { className?: string; children?: ReactNode; } export interface PostAuthorProps extends Omit { className?: string; /** Display name. */ name: string; /** `@handle`, shown beside the name in `compact` and under it elsewhere. */ handle?: string; avatar?: ImageSourcePropType; /** Initials behind a missing or broken avatar. */ fallback?: string; /** Draws the verification rosette after the name. */ verified?: boolean; /** "Posted 3m ago" — whatever the caller wants to call the time. */ timestamp?: ReactNode; children?: ReactNode; } export interface PostActionProps extends ViewProps { className?: string; children?: ReactNode; } export interface PostCommunityProps extends Omit { className?: string; /** The group's name — "r/reactnative", "#design". */ name: string; avatar?: ImageSourcePropType; /** How long ago, and anything else that belongs on the line. */ meta?: ReactNode; children?: ReactNode; } export interface PostTitleProps extends ViewProps { className?: string; children?: ReactNode; } export interface PostBodyProps extends Omit { className?: string; /** How many lines before it is cut off. Unlimited by default. */ numberOfLines?: number; /** Called with the tag, without its `#`. Makes hashtags pressable. */ onTagPress?: (tag: string) => void; /** Called with the handle, without its `@`. */ onMentionPress?: (handle: string) => void; children?: ReactNode; } export interface PostMediaProps extends Omit { className?: string; source: ImageSourcePropType; /** Width over height. `16 / 10` by default — wide enough not to eat the feed. */ aspectRatio?: number; /** * Darkens an edge of the image so type laid over it stays legible. * * A gradient rather than a panel: a flat rectangle over the top of a * photograph has an edge of its own, and that edge reads as a bar covering * the picture rather than as shading. `media` posts default to `top`, where * the author sits; everything else to `none`. */ scrim?: 'none' | 'top' | 'bottom' | 'both'; /** Laid over the image: an expand affordance, a duration, a gallery count. */ overlay?: ReactNode; /** Described for a screen reader. An image with nothing to say is decorative. */ alt?: string; onPress?: PressableProps['onPress']; children?: ReactNode; } export interface PostFooterProps extends ViewProps { className?: string; children?: ReactNode; } export interface PostStatProps extends Omit { className?: string; /** The icon component itself, not an element — it is re-rendered on toggle. */ icon?: ComponentType; /** The number, or a word where a number would be meaningless ("Save"). */ value?: ReactNode; /** Lit, and filled. */ active?: boolean; /** Which colour "lit" is. */ tone?: 'default' | 'like' | 'save' | 'repost'; /** Pushes this stat and everything after it to the trailing edge. */ align?: 'start' | 'end'; children?: ReactNode; } export type PostVote = 'up' | 'down' | null; export interface PostVotesProps extends Omit { className?: string; /** The score as it stands, with the reader's own vote already in it. */ score: number | string; /** Which way this reader voted, if either. */ vote?: PostVote; /** * Called with the new vote. Pressing the arrow already cast clears it, so * `null` arrives as often as the other two — a vote you cannot take back is * a vote people hesitate over. */ onVote?: (vote: PostVote) => void; /** `vertical` stacks the arrows beside a thumbnail, the way a ranked list reads. */ orientation?: 'horizontal' | 'vertical'; disabled?: boolean; } export declare const Post: import("react").ForwardRefExoticComponent> & { Header: import("react").ForwardRefExoticComponent>; Author: import("react").ForwardRefExoticComponent>; Action: import("react").ForwardRefExoticComponent>; Community: import("react").ForwardRefExoticComponent>; Title: import("react").ForwardRefExoticComponent>; Body: import("react").ForwardRefExoticComponent>; Media: import("react").ForwardRefExoticComponent>; Footer: import("react").ForwardRefExoticComponent>; Stat: import("react").ForwardRefExoticComponent>; Votes: import("react").ForwardRefExoticComponent>; }; export {}; //# sourceMappingURL=index.d.ts.map