panelui-native 0.97.0 → 0.99.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +1 -0
  2. package/lib/module/components/image-viewer/image-viewer-geometry.js +203 -0
  3. package/lib/module/components/image-viewer/image-viewer-geometry.js.map +1 -0
  4. package/lib/module/components/image-viewer/index.js +1100 -0
  5. package/lib/module/components/image-viewer/index.js.map +1 -0
  6. package/lib/module/components/stack-card/index.js +1204 -0
  7. package/lib/module/components/stack-card/index.js.map +1 -0
  8. package/lib/module/components/stack-card/stack-card-geometry.js +261 -0
  9. package/lib/module/components/stack-card/stack-card-geometry.js.map +1 -0
  10. package/lib/module/index.js +2 -0
  11. package/lib/module/index.js.map +1 -1
  12. package/lib/module/primitives/scrim.js +65 -1
  13. package/lib/module/primitives/scrim.js.map +1 -1
  14. package/lib/typescript/src/components/image-viewer/image-viewer-geometry.d.ts +83 -0
  15. package/lib/typescript/src/components/image-viewer/image-viewer-geometry.d.ts.map +1 -0
  16. package/lib/typescript/src/components/image-viewer/index.d.ts +148 -0
  17. package/lib/typescript/src/components/image-viewer/index.d.ts.map +1 -0
  18. package/lib/typescript/src/components/stack-card/index.d.ts +472 -0
  19. package/lib/typescript/src/components/stack-card/index.d.ts.map +1 -0
  20. package/lib/typescript/src/components/stack-card/stack-card-geometry.d.ts +126 -0
  21. package/lib/typescript/src/components/stack-card/stack-card-geometry.d.ts.map +1 -0
  22. package/lib/typescript/src/index.d.ts +2 -0
  23. package/lib/typescript/src/index.d.ts.map +1 -1
  24. package/lib/typescript/src/primitives/scrim.d.ts +11 -1
  25. package/lib/typescript/src/primitives/scrim.d.ts.map +1 -1
  26. package/package.json +8 -1
  27. package/src/components/image-viewer/image-viewer-geometry.ts +205 -0
  28. package/src/components/image-viewer/index.tsx +1329 -0
  29. package/src/components/stack-card/index.tsx +1423 -0
  30. package/src/components/stack-card/stack-card-geometry.ts +279 -0
  31. package/src/index.ts +19 -0
  32. package/src/primitives/scrim.tsx +96 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-viewer-geometry.d.ts","sourceRoot":"","sources":["../../../../../src/components/image-viewer/image-viewer-geometry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,IAAI;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,IAAK,SAAQ,IAAI;IAChC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,kEAAkE;AAClE,eAAO,MAAM,WAAW,OAAO,CAAC;AAEhC,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGrE;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAGhE;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAQ9D;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,GAAG,IAAI,CASvD;AAED,oEAAoE;AACpE,wBAAgB,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,GAAG,IAAI,CAItD;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,GAAG,IAAI,CAOxD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAK7F;AAED,yFAAyF;AACzF,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,CAOR;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGhF;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,MAAM,CAIR;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,GAChB,MAAM,CAMR;AAED,sFAAsF;AACtF,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAK5E;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAInE;AAED,iFAAiF;AACjF,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIpE;AAED,uFAAuF;AACvF,wBAAgB,QAAQ,CACtB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,GACT,OAAO,CAQT"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * ImageViewer — a picture that opens out of the page to fill the screen.
3
+ *
4
+ * Pressing a trigger lifts its image from where it sits, grows it to the whole
5
+ * picture in the middle of the screen, and blurs the page behind it. From there
6
+ * it can be pinched and double-tapped to zoom, swiped sideways to the next
7
+ * image under the same root, and dragged away to put it back.
8
+ *
9
+ * ```tsx
10
+ * <ImageViewer>
11
+ * {photos.map((photo) => (
12
+ * <ImageViewer.Trigger
13
+ * key={photo.id}
14
+ * source={photo.source}
15
+ * alt={photo.alt}
16
+ * radius={12}
17
+ * className="h-40 flex-1 rounded-xl"
18
+ * />
19
+ * ))}
20
+ * </ImageViewer>
21
+ * ```
22
+ *
23
+ * ## The image travels; nothing appears
24
+ *
25
+ * The viewer never fades a second copy of the picture in over the first. The
26
+ * thumbnail is hidden and the same image is drawn in a frame that starts at the
27
+ * thumbnail's exact rectangle and corner radius and ends at the fitted one. The
28
+ * picture inside that frame is always drawn at the size that *covers* it, so the
29
+ * crop a thumbnail shows opens out into the whole image as the frame grows — and
30
+ * closes back into the crop on the way home. That continuity is the point: the
31
+ * picture on screen is the one that was pressed, not a picture of it.
32
+ *
33
+ * The frame animates its bounds rather than a transform, because a transform
34
+ * cannot change a crop. It is one view with one child, so the layout pass it
35
+ * costs per frame is small.
36
+ *
37
+ * ## Every trigger under one root is a page
38
+ *
39
+ * Triggers register themselves with the root as they mount, in render order or
40
+ * by an explicit `index`. Opening one opens the gallery at its page, and the
41
+ * thumbnail hidden underneath follows the page — close on the third image and it
42
+ * flies back into the third thumbnail.
43
+ *
44
+ * ## One gesture surface, decided at the start
45
+ *
46
+ * Pinching, panning a zoomed image, turning the page and dragging to dismiss all
47
+ * begin as a one- or two-finger drag, and which one it is gets decided the
48
+ * moment it starts: two fingers zoom, one finger on a zoomed image pans it, one
49
+ * finger moving sideways across a gallery turns the page, and anything else
50
+ * drags the image away. Deciding once keeps a drag from changing its mind
51
+ * halfway, which is what makes a viewer feel loose.
52
+ */
53
+ import { type ReactNode } from 'react';
54
+ import { type ImageSourcePropType, type PressableProps } from 'react-native';
55
+ export interface ImageViewerProps {
56
+ children?: ReactNode;
57
+ /** Controlled open state. */
58
+ open?: boolean;
59
+ /** Initial open state when uncontrolled. */
60
+ defaultOpen?: boolean;
61
+ onOpenChange?: (open: boolean) => void;
62
+ /** Controlled page — which trigger's image is showing, in page order. */
63
+ index?: number;
64
+ /** Initial page when uncontrolled. */
65
+ defaultIndex?: number;
66
+ onIndexChange?: (index: number) => void;
67
+ /**
68
+ * Blur the page behind the picture. Needs the optional `expo-blur`, and dims
69
+ * instead without it. Reduce Transparency draws an opaque backdrop.
70
+ */
71
+ blur?: boolean;
72
+ /** How far a pinch can zoom in, as a multiple of the fitted size. */
73
+ maxScale?: number;
74
+ /** Where a double tap zooms to, as a multiple of the fitted size. */
75
+ doubleTapScale?: number;
76
+ /** Tick as a drag to dismiss begins. Needs the optional `expo-haptics`. */
77
+ haptics?: boolean;
78
+ /** Draw the close button. Tapping outside the picture and dragging it away still close it. */
79
+ showClose?: boolean;
80
+ /** Read out for the close button. */
81
+ closeLabel?: string;
82
+ /**
83
+ * Space kept between the open picture and the edges of the screen, in points.
84
+ * Measured from the safe area at the top and bottom, and the larger of the
85
+ * two is used for both, so the picture stays centred. `0` fills the screen.
86
+ */
87
+ inset?: number;
88
+ /**
89
+ * Corner radius of the open picture, in points. The corners stay this size on
90
+ * screen while the picture is zoomed or dragged. `0` squares them.
91
+ */
92
+ cornerRadius?: number;
93
+ }
94
+ declare function ImageViewerRoot({ children, open, defaultOpen, onOpenChange, index, defaultIndex, onIndexChange, blur, maxScale, doubleTapScale, haptics, showClose, closeLabel, inset, cornerRadius, }: ImageViewerProps): import("react").JSX.Element;
95
+ export interface ImageViewerTriggerProps extends Omit<PressableProps, 'children' | 'style' | 'disabled'> {
96
+ /**
97
+ * Classes on the pressable. Without `children` the image fills it, so give it
98
+ * a size — `h-48 w-full`, `aspect-square flex-1`.
99
+ */
100
+ className?: string;
101
+ /** The picture. Shown in the page and, until `fullSource` loads, in the viewer. */
102
+ source: ImageSourcePropType;
103
+ /**
104
+ * A larger copy to show once the viewer is open. It loads when the viewer
105
+ * opens and replaces `source` when it arrives, so a feed can carry thumbnails.
106
+ */
107
+ fullSource?: ImageSourcePropType;
108
+ /** Described for a screen reader, on the trigger and in the viewer. */
109
+ alt?: string;
110
+ /** Shown under the picture while it is open. A string is set as text. */
111
+ caption?: ReactNode;
112
+ /** Page order within the root. Render order when left out. */
113
+ index?: number;
114
+ /**
115
+ * The corner radius the picture has in the page, in points, so the flight
116
+ * starts from the same shape. Match it to the `rounded-*` class you gave the
117
+ * trigger — a class cannot be read back.
118
+ */
119
+ radius?: number;
120
+ /**
121
+ * The image's own width and height, when known. Saves looking it up, and is
122
+ * the only way the viewer knows the proportions before a remote image loads.
123
+ */
124
+ width?: number;
125
+ height?: number;
126
+ /** Nothing opens, and the press is not reported. */
127
+ disabled?: boolean;
128
+ /**
129
+ * Draw the picture yourself — a `Post.Media`, a card. It should show `source`
130
+ * cropped to fill, the way the viewer's own flight starts. Left out, the
131
+ * trigger draws `source` to fill its box.
132
+ */
133
+ children?: ReactNode;
134
+ }
135
+ /**
136
+ * The thing pressed to open the viewer.
137
+ *
138
+ * It registers its picture with the root, so the gallery is simply every
139
+ * trigger under that root. While its picture is out on the screen it is drawn
140
+ * transparent — not removed, so the page does not reflow under the blur and the
141
+ * flight home has somewhere to land.
142
+ */
143
+ declare function ImageViewerTrigger({ className, source, fullSource, alt, caption, index, radius, width, height, disabled, children, onPress, onLayout, ...props }: ImageViewerTriggerProps): import("react").JSX.Element;
144
+ export declare const ImageViewer: typeof ImageViewerRoot & {
145
+ Trigger: typeof ImageViewerTrigger;
146
+ };
147
+ export {};
148
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/image-viewer/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,OAAO,EAWL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAOL,KAAK,mBAAmB,EAExB,KAAK,cAAc,EACpB,MAAM,cAAc,CAAC;AAyKtB,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,6BAA6B;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,4CAA4C;IAC5C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8FAA8F;IAC9F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,iBAAS,eAAe,CAAC,EACvB,QAAQ,EACR,IAAI,EACJ,WAAmB,EACnB,YAAY,EACZ,KAAK,EACL,YAAgB,EAChB,aAAa,EACb,IAAW,EACX,QAAY,EACZ,cAAoB,EACpB,OAAc,EACd,SAAgB,EAChB,UAAoB,EACpB,KAAqB,EACrB,YAAoC,GACrC,EAAE,gBAAgB,+BAuElB;AAMD,MAAM,WAAW,uBACf,SAAQ,IAAI,CAAC,cAAc,EAAE,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;IAC/D;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,MAAM,EAAE,mBAAmB,CAAC;IAC5B;;;OAGG;IACH,UAAU,CAAC,EAAE,mBAAmB,CAAC;IACjC,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAmBD;;;;;;;GAOG;AACH,iBAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,MAAM,EACN,UAAU,EACV,GAAG,EACH,OAAO,EACP,KAAK,EACL,MAAU,EACV,KAAK,EACL,MAAM,EACN,QAAgB,EAChB,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,uBAAuB,+BAyGzB;AA0vBD,eAAO,MAAM,WAAW;;CAEtB,CAAC"}
@@ -0,0 +1,472 @@
1
+ /**
2
+ * StackCard — a pile of cards, taken one at a time by throwing the top one off.
3
+ *
4
+ * ```tsx
5
+ * <StackCard className="h-[460px]" onSwipe={(direction, index) => decide(people[index], direction)}>
6
+ * <StackCard.Stamp direction="right" color="success">Yes</StackCard.Stamp>
7
+ * <StackCard.Stamp direction="left" color="destructive">No</StackCard.Stamp>
8
+ * {people.map((person) => (
9
+ * <StackCard.Card key={person.id}>
10
+ * <Text>{person.name}</Text>
11
+ * </StackCard.Card>
12
+ * ))}
13
+ * <StackCard.Empty>
14
+ * <Text muted>Nobody left</Text>
15
+ * </StackCard.Empty>
16
+ * </StackCard>
17
+ * ```
18
+ *
19
+ * For a queue of things each answered with one decision and then gone: a
20
+ * review queue, a set of flashcards, an inbox of suggestions. The gesture is
21
+ * the answer, which is what makes it quicker than a list of rows with buttons
22
+ * on them — and what makes it wrong for anything the reader has to compare,
23
+ * skim or come back to. A deck shows one card and hides the rest.
24
+ *
25
+ * For a run of slides the reader browses rather than disposes of, use
26
+ * [Carousel](../carousel); for one row's actions in a list, [Swipe](../swipe).
27
+ *
28
+ * ## The pile is one drag, read by everything
29
+ *
30
+ * The top card's `x` and `y` are the only values a gesture writes, and every
31
+ * other moving part is derived from them: each stamp fades in on how far the
32
+ * drag has carried the card toward its own direction, and the cards behind
33
+ * climb toward the top position on the furthest of those.
34
+ *
35
+ * That derivation is also what makes a dismissal seamless. By the time the top
36
+ * card has been carried far enough to leave, the second card is already
37
+ * exactly where the top card sits — so when the deck advances there is nothing
38
+ * left for it to move, and no frame in which the pile re-arranges itself.
39
+ *
40
+ * ## The deck moves on the UI thread, and React catches up
41
+ *
42
+ * Which card is on top is held twice: as React state, for what is mounted and
43
+ * for the callbacks, and as a shared value, for what is drawn. A throw is
44
+ * handled entirely on the UI thread — the card leaves on the frame the finger
45
+ * lets go, and once it is off the screen the top card, the offset and the fade
46
+ * all move in one step — and only then is the new index requested from React.
47
+ *
48
+ * Nothing on the screen waits for a render, so a busy JavaScript thread cannot
49
+ * stall a throw or leave a frame where the two halves disagree. What React
50
+ * renders afterwards is kept from showing before the UI thread agrees with it:
51
+ * a stamp is only drawn on the card the UI thread has on top.
52
+ *
53
+ * A controlled deck is still the owner's to decide. An owner that declines the
54
+ * new index gets the card back, flown in from the way it went; one that
55
+ * accepts it sees nothing move at all, because it already has.
56
+ *
57
+ * One card behind the pile's stated depth stays mounted so it can fade in as
58
+ * it takes the last visible place, and one card ahead of the top stays mounted
59
+ * so `undo` has something to fly back in. The rest are unmounted, which is
60
+ * what makes a deck of five hundred cost what a deck of five costs.
61
+ *
62
+ * ## A deck is not reachable by a gesture alone
63
+ *
64
+ * A throw is not available to a screen reader, and neither is a card that can
65
+ * only be answered by throwing it. So the top card publishes an accessibility
66
+ * action for every direction the deck accepts, and `StackCard.Action` renders
67
+ * the same decisions as ordinary buttons — which sighted people reach for too,
68
+ * on the card they are not sure about.
69
+ */
70
+ import { type ReactNode } from 'react';
71
+ import { View, type ViewProps } from 'react-native';
72
+ import { type SharedValue } from 'react-native-reanimated';
73
+ import { type VariantProps } from 'tailwind-variants';
74
+ import { type StackCardDirection } from './stack-card-geometry.js';
75
+ export type { StackCardDirection } from './stack-card-geometry.js';
76
+ /**
77
+ * The deck's state, for a control that lives outside the pile — a counter, a
78
+ * progress bar, a button in a toolbar.
79
+ *
80
+ * `release` is a shared value running 0 to 1 as the top card is carried toward
81
+ * leaving, so something beside the deck can move with the drag rather than
82
+ * starting a second animation next to it.
83
+ */
84
+ export declare function useStackCard(): {
85
+ /** How many cards have been answered, which is also the top card's index. */
86
+ index: number;
87
+ /** How many cards the deck was given. */
88
+ count: number;
89
+ /** How many are left, the top one included. */
90
+ remaining: number;
91
+ /** Whether there is a card to bring back. */
92
+ canUndo: boolean;
93
+ release: SharedValue<number>;
94
+ send: (direction: StackCardDirection) => void;
95
+ undo: () => void;
96
+ reset: () => void;
97
+ };
98
+ /** How the cards behind the top one are arranged. */
99
+ export type StackCardLayout = 'stack' | 'fan' | 'flat';
100
+ export interface StackCardHandle {
101
+ /** Send the top card away as though it had been thrown that way. */
102
+ swipe: (direction: StackCardDirection) => void;
103
+ /** Bring the last card back, and with it the decision that removed it. */
104
+ undo: () => void;
105
+ /** Put every card back. */
106
+ reset: () => void;
107
+ }
108
+ export interface StackCardProps extends Omit<ViewProps, 'children'> {
109
+ /**
110
+ * A `StackCard.Card` for each card, plus any of `StackCard.Stamp`,
111
+ * `StackCard.Empty` and `StackCard.Actions`, in any order. Anything else is
112
+ * laid out under the pile.
113
+ */
114
+ children?: ReactNode;
115
+ /**
116
+ * Which card is on top, when the caller holds it. Leave unset to let the
117
+ * deck keep its own. A controlled deck that declines a request stays where
118
+ * it is and the thrown card comes back, so this is also how a decision is
119
+ * confirmed before it is taken.
120
+ */
121
+ index?: number;
122
+ /** Which card an uncontrolled deck starts on. */
123
+ defaultIndex?: number;
124
+ /** Fires whenever the deck asks to move, with the index it is asking for. */
125
+ onIndexChange?: (index: number) => void;
126
+ /**
127
+ * Fires when a card leaves, with the way it went and the index it was at.
128
+ * It fires before `onIndexChange` asks for the next index. Not called by
129
+ * `undo` — the index going back is what reports that.
130
+ */
131
+ onSwipe?: (direction: StackCardDirection, index: number) => void;
132
+ /** Fires once when the last card leaves. */
133
+ onEmpty?: () => void;
134
+ /**
135
+ * Which ways a card may be thrown. Left and right by default.
136
+ *
137
+ * A direction left out still follows the finger a little and then comes
138
+ * back, rather than refusing to move at all — a card that does not budge
139
+ * reads as a frozen screen.
140
+ */
141
+ directions?: readonly StackCardDirection[];
142
+ /**
143
+ * How the cards behind the top one are arranged. `stack` steps them down and
144
+ * back; `fan` turns them alternately, like a hand of cards; `flat` hides them
145
+ * entirely, for full-bleed cards where a peeking edge is only clutter.
146
+ */
147
+ layout?: StackCardLayout;
148
+ /** How many cards are drawn behind the top one. Two is a pile; five is a mess. */
149
+ depth?: number;
150
+ /**
151
+ * How far a card has to be taken for a release to send it away, as a
152
+ * fraction of the card. Momentum counts toward it, so a flick clears it
153
+ * without travelling.
154
+ */
155
+ threshold?: number;
156
+ /** Stop the deck taking a gesture, without changing how it looks. */
157
+ disabled?: boolean;
158
+ /** A tick when a drag first reaches the point of no return, and a knock as the card goes. */
159
+ haptics?: boolean;
160
+ /**
161
+ * What a screen reader is offered for each direction, in place of "Swipe
162
+ * left". Name the decision — `{ left: 'Skip', right: 'Save' }`.
163
+ */
164
+ directionLabels?: Partial<Record<StackCardDirection, string>>;
165
+ /** Classes for the whole control. Give it a height; the pile fills what is left. */
166
+ className?: string;
167
+ /** Classes for the box the cards are laid out in. */
168
+ pileClassName?: string;
169
+ }
170
+ export interface StackCardCardProps extends ViewProps {
171
+ className?: string;
172
+ children?: ReactNode;
173
+ }
174
+ /**
175
+ * A stamp is a filled block of colour with a word on it, turned a few degrees
176
+ * so it reads as pressed onto the card rather than laid out on it.
177
+ *
178
+ * The fill is the status colour at full strength rather than a tint of it: a
179
+ * stamp exists only for the moment it appears, and a six-per-cent wash of the
180
+ * card's own surface is a smudge rather than an answer. The word is carried in
181
+ * white, which is what the status colours are chosen to take — a status's
182
+ * `-foreground` token is its darker text form, meant for a neutral surface,
183
+ * and over the fill it is the same hue twice.
184
+ *
185
+ * It sits in the corner the card is being pulled away from, which is also the
186
+ * corner the thumb is not over.
187
+ */
188
+ declare const stampVariants: import("tailwind-variants").TVReturnType<{
189
+ color: {
190
+ default: {
191
+ pill: string;
192
+ label: string;
193
+ };
194
+ primary: {
195
+ pill: string;
196
+ label: string;
197
+ };
198
+ success: {
199
+ pill: string;
200
+ label: string;
201
+ };
202
+ warning: {
203
+ pill: string;
204
+ label: string;
205
+ };
206
+ info: {
207
+ pill: string;
208
+ label: string;
209
+ };
210
+ destructive: {
211
+ pill: string;
212
+ label: string;
213
+ };
214
+ };
215
+ direction: {
216
+ left: {
217
+ root: string;
218
+ pill: string;
219
+ };
220
+ right: {
221
+ root: string;
222
+ pill: string;
223
+ };
224
+ up: {
225
+ root: string;
226
+ };
227
+ down: {
228
+ root: string;
229
+ };
230
+ };
231
+ }, {
232
+ root: string;
233
+ pill: string;
234
+ label: string;
235
+ }, undefined, {
236
+ color: {
237
+ default: {
238
+ pill: string;
239
+ label: string;
240
+ };
241
+ primary: {
242
+ pill: string;
243
+ label: string;
244
+ };
245
+ success: {
246
+ pill: string;
247
+ label: string;
248
+ };
249
+ warning: {
250
+ pill: string;
251
+ label: string;
252
+ };
253
+ info: {
254
+ pill: string;
255
+ label: string;
256
+ };
257
+ destructive: {
258
+ pill: string;
259
+ label: string;
260
+ };
261
+ };
262
+ direction: {
263
+ left: {
264
+ root: string;
265
+ pill: string;
266
+ };
267
+ right: {
268
+ root: string;
269
+ pill: string;
270
+ };
271
+ up: {
272
+ root: string;
273
+ };
274
+ down: {
275
+ root: string;
276
+ };
277
+ };
278
+ }, {
279
+ root: string;
280
+ pill: string;
281
+ label: string;
282
+ }, import("tailwind-variants").TVReturnType<{
283
+ color: {
284
+ default: {
285
+ pill: string;
286
+ label: string;
287
+ };
288
+ primary: {
289
+ pill: string;
290
+ label: string;
291
+ };
292
+ success: {
293
+ pill: string;
294
+ label: string;
295
+ };
296
+ warning: {
297
+ pill: string;
298
+ label: string;
299
+ };
300
+ info: {
301
+ pill: string;
302
+ label: string;
303
+ };
304
+ destructive: {
305
+ pill: string;
306
+ label: string;
307
+ };
308
+ };
309
+ direction: {
310
+ left: {
311
+ root: string;
312
+ pill: string;
313
+ };
314
+ right: {
315
+ root: string;
316
+ pill: string;
317
+ };
318
+ up: {
319
+ root: string;
320
+ };
321
+ down: {
322
+ root: string;
323
+ };
324
+ };
325
+ }, {
326
+ root: string;
327
+ pill: string;
328
+ label: string;
329
+ }, undefined, unknown, unknown, undefined>>;
330
+ export type StackCardStampColor = 'default' | 'primary' | 'success' | 'warning' | 'info' | 'destructive';
331
+ export interface StackCardStampProps extends Omit<ViewProps, 'children'>, VariantProps<typeof stampVariants> {
332
+ className?: string;
333
+ /** The word, or anything else to draw on the stamp. */
334
+ children?: ReactNode;
335
+ /** Which direction the stamp answers for. Also where on the card it goes. */
336
+ direction?: StackCardDirection;
337
+ /** Extra classes for the label, when the stamp is given a string. */
338
+ labelClassName?: string;
339
+ }
340
+ export interface StackCardEmptyProps extends ViewProps {
341
+ className?: string;
342
+ children?: ReactNode;
343
+ }
344
+ export interface StackCardActionsProps extends ViewProps {
345
+ className?: string;
346
+ children?: ReactNode;
347
+ }
348
+ declare const actionVariants: import("tailwind-variants").TVReturnType<{
349
+ color: {
350
+ default: {
351
+ root: string;
352
+ };
353
+ primary: {
354
+ root: string;
355
+ };
356
+ success: {
357
+ root: string;
358
+ };
359
+ warning: {
360
+ root: string;
361
+ };
362
+ info: {
363
+ root: string;
364
+ };
365
+ destructive: {
366
+ root: string;
367
+ };
368
+ };
369
+ size: {
370
+ sm: {
371
+ root: string;
372
+ };
373
+ md: {
374
+ root: string;
375
+ };
376
+ lg: {
377
+ root: string;
378
+ };
379
+ };
380
+ }, {
381
+ root: string;
382
+ }, undefined, {
383
+ color: {
384
+ default: {
385
+ root: string;
386
+ };
387
+ primary: {
388
+ root: string;
389
+ };
390
+ success: {
391
+ root: string;
392
+ };
393
+ warning: {
394
+ root: string;
395
+ };
396
+ info: {
397
+ root: string;
398
+ };
399
+ destructive: {
400
+ root: string;
401
+ };
402
+ };
403
+ size: {
404
+ sm: {
405
+ root: string;
406
+ };
407
+ md: {
408
+ root: string;
409
+ };
410
+ lg: {
411
+ root: string;
412
+ };
413
+ };
414
+ }, {
415
+ root: string;
416
+ }, import("tailwind-variants").TVReturnType<{
417
+ color: {
418
+ default: {
419
+ root: string;
420
+ };
421
+ primary: {
422
+ root: string;
423
+ };
424
+ success: {
425
+ root: string;
426
+ };
427
+ warning: {
428
+ root: string;
429
+ };
430
+ info: {
431
+ root: string;
432
+ };
433
+ destructive: {
434
+ root: string;
435
+ };
436
+ };
437
+ size: {
438
+ sm: {
439
+ root: string;
440
+ };
441
+ md: {
442
+ root: string;
443
+ };
444
+ lg: {
445
+ root: string;
446
+ };
447
+ };
448
+ }, {
449
+ root: string;
450
+ }, undefined, unknown, unknown, undefined>>;
451
+ export interface StackCardActionProps extends Omit<ViewProps, 'children'>, VariantProps<typeof actionVariants> {
452
+ className?: string;
453
+ /** What pressing it does: send the top card that way, or bring the last one back. */
454
+ action: StackCardDirection | 'undo';
455
+ /** The glyph. Sized and tinted by the button — pass neither. */
456
+ icon?: ReactNode;
457
+ /**
458
+ * What a screen reader is offered. Falls back to "Undo", or to the plain
459
+ * name of the direction.
460
+ */
461
+ label?: string;
462
+ /** Run after the deck has been told, for a sound or a log. */
463
+ onPress?: () => void;
464
+ }
465
+ export declare const StackCard: import("react").ForwardRefExoticComponent<StackCardProps & import("react").RefAttributes<StackCardHandle>> & {
466
+ Card: import("react").ForwardRefExoticComponent<StackCardCardProps & import("react").RefAttributes<View>>;
467
+ Stamp: import("react").ForwardRefExoticComponent<StackCardStampProps & import("react").RefAttributes<View>>;
468
+ Empty: import("react").ForwardRefExoticComponent<StackCardEmptyProps & import("react").RefAttributes<View>>;
469
+ Actions: import("react").ForwardRefExoticComponent<StackCardActionsProps & import("react").RefAttributes<View>>;
470
+ Action: import("react").ForwardRefExoticComponent<StackCardActionProps & import("react").RefAttributes<View>>;
471
+ };
472
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/stack-card/index.tsx"],"names":[],"mappings":"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"}