/**
* 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