/** * ProgressButton — press and hold to confirm, with the wait drawn on the button. * * ```tsx * * Hold to erase * * ``` * * For the action a confirmation dialog exists to slow down. A dialog asks the * question somewhere else and takes the answer as a tap — which is two taps, * and two taps in a row is a rhythm a hand falls into. A hold cannot be * completed by accident and cannot be completed by habit: it has to be * sustained, and the fill says for how much longer. * * ## The fill is the promise * * Nothing fires until the fill reaches the end. There is no tolerance near the * top, because a tolerance means the button sometimes commits after the reader * has deliberately let go — which is the one failure a confirmation control * cannot have. Released early, the fill drains back, in proportion to how far * it got. * * ## How it is drawn * * The fill is a clipped copy of the button in inverted colours, growing from * the leading edge. That is what keeps the label legible across the boundary: * a single label under a translucent wash goes muddy in the middle of the * wipe, exactly where the eye is. Two labels, each at full contrast on its own * ground, never do. * * The clip is a view under `overflow: 'hidden'`, and its width is animated. * Animating a width is normally a layout pass per frame; this view is * absolutely positioned over the button and its copy of the label is pinned to * the button's own width, so nothing it contains reflows as it grows. * * ## Reduced motion * * The wipe is replaced by a stepped fill that advances in fifths. The hold * still has to be legible — a control that asks you to wait and shows nothing * is a broken button — so this is a coarser indicator, not the absence of one. */ import { type ReactNode } from 'react'; import { View, type PressableProps, type ViewProps } from 'react-native'; import { type SharedValue } from 'react-native-reanimated'; import { type VariantProps } from 'tailwind-variants'; declare const progressButtonVariants: import("tailwind-variants").TVReturnType<{ variant: { primary: { label: string; fill: string; fillLabel: string; }; secondary: { label: string; fill: string; fillLabel: string; }; destructive: { label: string; fill: string; fillLabel: string; }; success: { label: string; fill: string; fillLabel: string; }; }; size: { sm: { root: string; content: string; label: string; fillLabel: string; }; md: { root: string; content: string; label: string; fillLabel: string; }; lg: { root: string; content: string; label: string; fillLabel: string; }; }; shape: { pill: { root: string; }; rounded: { root: string; }; }; fullWidth: { true: { root: string; }; }; disabled: { true: { root: string; }; }; }, { root: string; content: string; label: string; /** The inverted copy, drawn on the filled ground. */ fill: string; fillLabel: string; }, undefined, { variant: { primary: { label: string; fill: string; fillLabel: string; }; secondary: { label: string; fill: string; fillLabel: string; }; destructive: { label: string; fill: string; fillLabel: string; }; success: { label: string; fill: string; fillLabel: string; }; }; size: { sm: { root: string; content: string; label: string; fillLabel: string; }; md: { root: string; content: string; label: string; fillLabel: string; }; lg: { root: string; content: string; label: string; fillLabel: string; }; }; shape: { pill: { root: string; }; rounded: { root: string; }; }; fullWidth: { true: { root: string; }; }; disabled: { true: { root: string; }; }; }, { root: string; content: string; label: string; /** The inverted copy, drawn on the filled ground. */ fill: string; fillLabel: string; }, import("tailwind-variants").TVReturnType<{ variant: { primary: { label: string; fill: string; fillLabel: string; }; secondary: { label: string; fill: string; fillLabel: string; }; destructive: { label: string; fill: string; fillLabel: string; }; success: { label: string; fill: string; fillLabel: string; }; }; size: { sm: { root: string; content: string; label: string; fillLabel: string; }; md: { root: string; content: string; label: string; fillLabel: string; }; lg: { root: string; content: string; label: string; fillLabel: string; }; }; shape: { pill: { root: string; }; rounded: { root: string; }; }; fullWidth: { true: { root: string; }; }; disabled: { true: { root: string; }; }; }, { root: string; content: string; label: string; /** The inverted copy, drawn on the filled ground. */ fill: string; fillLabel: string; }, undefined, unknown, unknown, undefined>>; type ProgressButtonVariantProps = VariantProps; /** How a progress button looks. */ export type ProgressButtonVariant = NonNullable; /** How big a progress button is. */ export type ProgressButtonSize = NonNullable; /** What corner a progress button has. */ export type ProgressButtonShape = NonNullable; /** How far through the hold this button is, for something rendered inside it. */ export declare function useProgressButton(): { progress: SharedValue; completed: boolean; }; export interface ProgressButtonProps extends Omit, Omit { className?: string; /** * Milliseconds the button has to be held. Defaults to `2000`, and is floored * at `200` — a hold that completes on touch-down is a button with extra steps. */ holdDuration?: number; /** Fires once the hold has been sustained to the end. */ onComplete?: () => void; /** Fires whenever the completed state changes, including on a reset. */ onCompletedChange?: (completed: boolean) => void; /** Controlled completion. Leave unset to let the button own it. */ completed?: boolean; /** Return to the unfilled state after `autoResetDelay`. */ autoReset?: boolean; /** Milliseconds to stay completed before resetting. Defaults to `1000`. */ autoResetDelay?: number; /** * Dim the button and refuse the hold outright. The fill never starts, so * there is no half-finished state to explain. */ disabled?: boolean; /** * A tick as the hold takes, and a knock when it completes. Off by default: * whether an action is worth feeling is the caller's call, not the control's. */ haptics?: boolean; /** * The corner. `pill` by default — the fill is clipped by it, so a half-circle * sends the wipe's leading edge out as a curve and the button reads as * filling up. * * `rounded` gives it [Button](/docs/components/button)'s box exactly: the * same radius, side padding and minimum width, at heights that already * matched. Use it where the hold stands in a row of ordinary buttons — a * form's footer, a toolbar, a card's actions — and a lone pill would read as * a different kind of control rather than as the one that has to be held. */ shape?: ProgressButtonShape; children?: ReactNode; } export interface ProgressButtonLabelProps extends ViewProps { className?: string; children?: ReactNode; } /** * What the button says, drawn twice. * * The second copy is the one inside the fill, in the inverted colour, pinned to * the button's own width and clipped to however far the hold has got. Both are * the same text at the same position, so the boundary between them falls in the * middle of a glyph rather than between two differently laid-out lines. */ declare function ProgressButtonLabel({ className, children, ...props }: ProgressButtonLabelProps): import("react").JSX.Element; declare namespace ProgressButtonLabel { var displayName: string; } export interface ProgressButtonDoneProps extends ViewProps { className?: string; /** * What the button shows once the hold has landed. A tick on its own by * default; children replace it, so a word beside one is * `Paid`. */ children?: ReactNode; } /** * The drawing the button lands on. * * It sits over the finished fill rather than beside the label, so the button * does not change width at the moment it completes — a control that resizes as * it succeeds moves everything under it, and the reader's eye is on the button. * * One is added for you unless you write your own, because a hold that lands and * shows nothing leaves the reader checking whether it worked. */ declare function ProgressButtonDone({ className, children, ...props }: ProgressButtonDoneProps): import("react").JSX.Element; declare namespace ProgressButtonDone { var displayName: string; } export declare const ProgressButton: import("react").ForwardRefExoticComponent> & { Label: typeof ProgressButtonLabel; Done: typeof ProgressButtonDone; }; export { DEFAULT_AUTO_RESET_DELAY, DEFAULT_HOLD_DURATION, DEFAULT_RELEASE_DURATION, fillDuration, isComplete, releaseDuration, resolveHoldDuration, } from './progress-button-hold.js'; //# sourceMappingURL=index.d.ts.map