/**
* Compare — two versions of one picture, with a seam the reader drags across
* it.
*
* ```tsx
*
*
*
*
*
*
*
*
*
* ```
*
* ## What it is for
*
* Showing that two images differ, when they differ in a way a pair of
* thumbnails side by side will not carry. Retouching, a filter, a render at two
* quality settings, a map at two dates: the change is spread across the frame
* rather than gathered in one place, and the eye cannot hold one image well
* enough to spot it in the other.
*
* The seam works because both versions are in the same place on the screen at
* the same scale. Every pixel the reader is comparing is a pixel that was just
* under the one beside it, so the difference arrives as movement rather than as
* something to be remembered.
*
* ## It clips, it does not resize
*
* The revealed side is a window onto a full-size copy of its content, not a
* copy of the content squeezed into the window. That distinction is the whole
* implementation: a view whose width is animated will lay its children out
* again at every new width, so an image inside one is an image being squashed
* and stretched as the seam moves, and the two halves stop lining up — which
* is the one thing this component exists to guarantee.
*
* It follows that the content has to be told how big to be, and the only thing
* that knows is the container once it has been measured. So nothing is drawn
* until the first layout pass has run, and `Compare.Before` sizes its child to
* the measured box rather than to itself.
*
* ## It needs a height
*
* Everything inside is positioned absolutely, so the box has no height of its
* own to take from its content. `height` is what gives it one. An image told to
* fill the box will fill whatever height is set here, and cropping is
* `resizeMode` on the image rather than anything this component does.
*
* ## Dragging, and the two ways round it
*
* The whole frame is the drag target, not just the knob — a knob is a small
* thing to hit on a phone and the reader's finger is already over the picture.
* The gesture only claims horizontal movement, so a Compare inside a scrolling
* page still scrolls.
*
* A drag is not available to everyone, so the seam is also `adjustable`: a
* screen reader moves it a `step` at a time without one, and `value` drives it
* from anywhere else — a button that snaps to the ends, an animation, a slider
* somewhere else on the screen.
*/
import { type ReactNode } from 'react';
import { type ViewProps } from 'react-native';
export type CompareOrientation = 'horizontal' | 'vertical';
export interface CompareProps extends Omit {
className?: string;
/**
* How tall the frame is, in points.
*
* Required in practice rather than in the types: both sides are positioned
* absolutely, so there is no content left to give the box a height of its own.
*/
height?: number;
/** Where the seam sits, `0` to `1`. Leave unset to let the frame track it. */
value?: number;
/** Where it starts when the frame is tracking it itself. */
defaultValue?: number;
/** Fires while the seam moves, with its new position. */
onValueChange?: (value: number) => void;
/** Fires once, when the finger is lifted. The one to persist. */
onValueCommit?: (value: number) => void;
/** Which way the seam runs. */
orientation?: CompareOrientation;
/** Freezes the seam where it is and takes it out of the accessibility tree. */
disabled?: boolean;
/** How far one screen-reader increment moves the seam, `0` to `1`. */
step?: number;
/** A tick when the seam reaches either end. */
haptics?: boolean;
children?: ReactNode;
}
declare function CompareRoot({ className, height, value, defaultValue, onValueChange, onValueCommit, orientation, disabled, step, haptics, children, ...props }: CompareProps): import("react").JSX.Element;
declare namespace CompareRoot {
var displayName: string;
}
export interface CompareAfterProps extends ViewProps {
className?: string;
children?: ReactNode;
}
/**
* The side the seam uncovers as it travels: the whole frame, underneath.
*
* It is drawn at full size and never clipped, so it is the one that decides
* what the frame looks like at either end of the travel.
*/
declare function CompareAfter({ className, children, ...props }: CompareAfterProps): import("react").JSX.Element;
declare namespace CompareAfter {
var displayName: string;
var layer: "base";
}
export interface CompareBeforeProps extends ViewProps {
className?: string;
children?: ReactNode;
}
/**
* The side on the near edge of the seam: a window onto the content, sized to
* the frame.
*
* The child is given the frame's measured size in points rather than a
* percentage. A percentage would be a percentage *of the window*, which shrinks
* as the seam closes — so the image would slide and scale under the seam
* instead of standing still behind it, and the two halves would no longer be
* the same picture in the same place.
*/
declare function CompareBefore({ className, children, ...props }: CompareBeforeProps): import("react").JSX.Element;
declare namespace CompareBefore {
var displayName: string;
var layer: "clip";
}
export interface CompareHandleProps extends ViewProps {
className?: string;
/** Hide the two grip bars inside the knob. */
withGrip?: boolean;
/** Spoken name. */
accessibilityLabel?: string;
/** Replaces the knob. The line behind it is kept. */
children?: ReactNode;
}
/**
* The seam: a line across the frame with a knob on it.
*
* The knob is a marker rather than the target — the drag is on the whole frame,
* and a 36-point circle is not something to ask a thumb to find. What it is
* for is saying where the seam is and that it is the thing that moves, which a
* bare line does not.
*
* It carries the accessibility wiring for the same reason a splitter's handle
* does: it is the one part of this that is a control, so it is the part that is
* `adjustable` and takes the increment and decrement a screen reader sends
* instead of a drag.
*/
declare function CompareHandle({ className, withGrip, accessibilityLabel, children, style, ...props }: CompareHandleProps): import("react").JSX.Element;
declare namespace CompareHandle {
var displayName: string;
var layer: "over";
}
export interface CompareLabelProps extends ViewProps {
className?: string;
/** Which side of the frame it sits on. */
side?: 'start' | 'end';
children?: ReactNode;
}
/**
* A caption pinned to one corner, for saying which side is which.
*
* Worth adding wherever the two versions are not obviously an original and an
* edit — two dates, two settings, two models. Where they are, it is one more
* thing over the picture and the picture is the point.
*/
declare function CompareLabel({ className, side, children, ...props }: CompareLabelProps): import("react").JSX.Element;
declare namespace CompareLabel {
var displayName: string;
var layer: "over";
}
export declare const Compare: typeof CompareRoot & {
Before: typeof CompareBefore;
After: typeof CompareAfter;
Handle: typeof CompareHandle;
Label: typeof CompareLabel;
};
export {};
//# sourceMappingURL=index.d.ts.map