/** * Swipe — a row that slides aside to reveal the things you can do to it. * * It is the one list interaction a phone has that a page does not: the actions * are not on screen taking up room, they are behind the row, and the gesture * that reveals them is the same one everywhere else in the OS. An inbox, a * task list, a settings screen — all of them want it, and all of them * otherwise end up with a trailing button too small to hit. * * ```tsx * * * } label="Delete" color="destructive" onPress={remove} /> * * * Invoice.pdf * * * ``` * * The sides are `start` and `end` rather than left and right, because the * gesture mirrors with the reading direction: in a right-to-left app the row * that opened toward the right has to open toward the left, and a caller * should not have to write that twice. Yoga mirrors where the panels sit; the * drag is measured in raw pixels and cannot be mirrored for us, so it reads * the direction and turns itself around. * * Everything that moves runs on the UI thread. A row being dragged does not * re-render — the only React work in a swipe is the callback at the end of it. * * Rows in a `Swipe.Group` close each other, so only one of them is ever open. * That is the behaviour of every list on the phone that has this gesture, and * a row cannot arrange it alone: it knows when it opens and has no way to hear * that a sibling did. */ import { type ReactNode } from 'react'; import { View, type ViewProps } from 'react-native'; import { type VariantProps } from 'tailwind-variants'; type SwipeSide = 'start' | 'end'; /** The side a row is open on, or `null` while it is closed. */ export type SwipeOpenSide = SwipeSide | null; export interface SwipeHandle { /** Slide the row aside to reveal one side's actions. */ open: (side: SwipeSide) => void; /** Put the row back. */ close: () => void; } export interface SwipeGroupProps extends ViewProps { className?: string; children?: ReactNode; /** * Close the other rows when one opens. On by default — that is the whole * reason to reach for a group. Turning it off keeps the container and the * `useSwipeGroup` handle while letting several rows stand open at once. */ exclusive?: boolean; } /** * Shut every row in the enclosing `Swipe.Group`. * * The one thing a group knows that a single row cannot: a list that scrolls, * navigates away, or has just deleted the row that was open wants all of them * put back, and holding a ref to each row to do it by hand is bookkeeping the * group is already doing. * * ```tsx * const { closeAll } = useSwipeGroup(); * * ``` * * Outside a group it is inert rather than an error, so a row that is sometimes * grouped and sometimes not does not need two versions of its parent. */ export declare function useSwipeGroup(): { closeAll: () => void; }; /** * A tile is a filled block of colour with its content laid over it, which * settles both halves of how it is coloured: * * - The fill is the status colour at full strength, never a tint of it. A tile * only exists while the row is out of the way, so it has to be legible in the * moment it appears; a 6%-alpha wash of the row's own background is not a * tile at all, it is a hole with a glyph floating in it. * - The content is white, because the status colours are chosen to be carried * at full strength with white over them. The `-foreground` token of a status * is the *darker text* form of that hue, meant for a neutral surface — laid * over the fill it is the same hue twice and the label all but disappears. * * `default` and `primary` are the two that cannot take white. `primary` * inverts with the theme and owns a true on-primary token, so it uses it; * `default` is a mid grey in every theme, and takes the background colour, * which is the neutral furthest from it in whichever direction the theme runs. */ declare const actionVariants: import("tailwind-variants").TVReturnType<{ color: { default: { root: string; label: string; }; primary: { root: string; label: string; }; success: { root: string; label: string; }; warning: { root: string; label: string; }; info: { root: string; label: string; }; destructive: { root: string; label: string; }; }; }, { root: string; label: string; }, undefined, { color: { default: { root: string; label: string; }; primary: { root: string; label: string; }; success: { root: string; label: string; }; warning: { root: string; label: string; }; info: { root: string; label: string; }; destructive: { root: string; label: string; }; }; }, { root: string; label: string; }, import("tailwind-variants").TVReturnType<{ color: { default: { root: string; label: string; }; primary: { root: string; label: string; }; success: { root: string; label: string; }; warning: { root: string; label: string; }; info: { root: string; label: string; }; destructive: { root: string; label: string; }; }; }, { root: string; label: string; }, undefined, unknown, unknown, undefined>>; export type SwipeActionColor = 'default' | 'primary' | 'success' | 'warning' | 'info' | 'destructive'; export interface SwipeActionProps extends Omit, VariantProps { className?: string; /** What the action does. Also what a screen reader is offered. */ label: string; /** * Drawn above the label and tinted to match it. Pass the glyph, not a colour * and not a size — a tile sizes it to read at a glance, since it is the part * of an action the eye reaches before the word underneath it. */ icon?: ReactNode; /** Run when the tile is tapped, or when a full swipe reaches it. */ onPress?: () => void; /** * Leave the row open after the action runs. Off by default: an action that * has already happened has nothing left to offer, and a row left standing * open is the most common way a swipe list ends up feeling stuck. */ keepOpen?: boolean; /** Extra classes for the label. */ labelClassName?: string; } export interface SwipePanelProps extends Omit { className?: string; children?: ReactNode; } export interface SwipeProps extends Omit { className?: string; /** * The row itself, plus a `Swipe.Start` and/or `Swipe.End` holding its * actions. Order does not matter — the panels are recognised by type. */ children?: ReactNode; /** * Let a drag carried well past the panel fire its outermost action on * release, without the tile ever being tapped. On by default, and the reason * the far end of a panel is the destructive slot by convention. */ fullSwipe?: boolean; /** Turn the gesture off and leave the row static. The tiles stay tappable. */ disabled?: boolean; /** Tick when a drag crosses the point at which letting go fires an action. */ haptics?: boolean; /** Told which side opened, or `null` when the row closed. */ onOpenChange?: (side: SwipeOpenSide) => void; /** Extra classes for the moving row. */ contentClassName?: string; } export declare const Swipe: import("react").ForwardRefExoticComponent> & { Group: import("react").ForwardRefExoticComponent>; Start: import("react").ForwardRefExoticComponent>; End: import("react").ForwardRefExoticComponent>; Action: import("react").ForwardRefExoticComponent>; }; export {}; //# sourceMappingURL=index.d.ts.map