@isoline-ui/react-native 0.0.0-stage → 1.0.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 (167) hide show
  1. package/LICENSE +22 -0
  2. package/NOTICE.md +12 -0
  3. package/README.md +104 -3
  4. package/dist/amount.d.ts +3 -0
  5. package/dist/calendar.d.ts +7 -0
  6. package/dist/components/action-chip.d.ts +9 -0
  7. package/dist/components/amount-field.d.ts +12 -0
  8. package/dist/components/avatar.d.ts +17 -0
  9. package/dist/components/back-button.d.ts +12 -0
  10. package/dist/components/back-icon.d.ts +3 -0
  11. package/dist/components/badge.d.ts +13 -0
  12. package/dist/components/banner.d.ts +14 -0
  13. package/dist/components/bottom-sheet-native.d.ts +11 -0
  14. package/dist/components/bottom-sheet-web.d.ts +18 -0
  15. package/dist/components/bottom-sheet.d.ts +3 -0
  16. package/dist/components/button-group.d.ts +26 -0
  17. package/dist/components/button.d.ts +48 -0
  18. package/dist/components/checkbox.d.ts +12 -0
  19. package/dist/components/color-picker.d.ts +21 -0
  20. package/dist/components/context-menu.d.ts +26 -0
  21. package/dist/components/date-picker.d.ts +64 -0
  22. package/dist/components/dialog-context.d.ts +2 -0
  23. package/dist/components/dialog.d.ts +20 -0
  24. package/dist/components/empty-state.d.ts +15 -0
  25. package/dist/components/expand-indicator.d.ts +27 -0
  26. package/dist/components/expressive-shape.d.ts +18 -0
  27. package/dist/components/fab-menu-legacy.d.ts +31 -0
  28. package/dist/components/fab-menu.d.ts +21 -0
  29. package/dist/components/filter-chip.d.ts +69 -0
  30. package/dist/components/floating-action-button.d.ts +15 -0
  31. package/dist/components/icon-button.d.ts +40 -0
  32. package/dist/components/icons.d.ts +18 -0
  33. package/dist/components/input.d.ts +9 -0
  34. package/dist/components/keyboard-inset-view.d.ts +15 -0
  35. package/dist/components/list-controls.d.ts +38 -0
  36. package/dist/components/loading-indicator.d.ts +9 -0
  37. package/dist/components/menu-sheet.d.ts +36 -0
  38. package/dist/components/panel-sheet.d.ts +8 -0
  39. package/dist/components/password-visibility.d.ts +5 -0
  40. package/dist/components/popover-layout.d.ts +25 -0
  41. package/dist/components/popover.d.ts +20 -0
  42. package/dist/components/pressable.d.ts +12 -0
  43. package/dist/components/radio-navigation.d.ts +11 -0
  44. package/dist/components/refresh-control.d.ts +16 -0
  45. package/dist/components/row-gap.d.ts +9 -0
  46. package/dist/components/search-field.d.ts +22 -0
  47. package/dist/components/select-field.d.ts +16 -0
  48. package/dist/components/settings-list.d.ts +98 -0
  49. package/dist/components/settings-row.d.ts +13 -0
  50. package/dist/components/sheet-frame.d.ts +27 -0
  51. package/dist/components/sheet-lifecycle.d.ts +36 -0
  52. package/dist/components/sheet-transition.d.ts +36 -0
  53. package/dist/components/slider.d.ts +21 -0
  54. package/dist/components/snackbar.d.ts +10 -0
  55. package/dist/components/split-button.d.ts +38 -0
  56. package/dist/components/squish.d.ts +20 -0
  57. package/dist/components/swipeable-row.d.ts +20 -0
  58. package/dist/components/switch.d.ts +8 -0
  59. package/dist/components/tab-bar.d.ts +20 -0
  60. package/dist/components/text-field.d.ts +31 -0
  61. package/dist/components/text.d.ts +9 -0
  62. package/dist/components/time-picker.d.ts +40 -0
  63. package/dist/components/toolbar.d.ts +77 -0
  64. package/dist/components/top-bar.d.ts +27 -0
  65. package/dist/components/undo-bar.d.ts +23 -0
  66. package/dist/components/wavy-progress.d.ts +21 -0
  67. package/dist/components/zoomable-image.d.ts +18 -0
  68. package/dist/expressive-shapes.d.ts +8 -0
  69. package/dist/index.d.ts +62 -0
  70. package/dist/keyboard.d.ts +2 -0
  71. package/dist/material.d.ts +11 -0
  72. package/dist/media.d.ts +11 -0
  73. package/dist/motion.d.ts +96 -0
  74. package/dist/platform.d.ts +3 -0
  75. package/dist/preset-tokens.d.ts +264 -0
  76. package/dist/provider.d.ts +59 -0
  77. package/dist/reduced-motion.d.ts +45 -0
  78. package/dist/selection.d.ts +2 -0
  79. package/dist/shape.d.ts +99 -0
  80. package/dist/sheet-physics.d.ts +37 -0
  81. package/dist/theme.d.ts +103 -0
  82. package/dist/tokens.d.ts +2 -0
  83. package/dist/use-keyboard-height.d.ts +10 -0
  84. package/dist/utils.d.ts +3 -0
  85. package/nativewind.cjs +68 -0
  86. package/package.json +63 -6
  87. package/src/amount.ts +53 -0
  88. package/src/calendar.ts +42 -0
  89. package/src/components/action-chip.tsx +64 -0
  90. package/src/components/amount-field.tsx +49 -0
  91. package/src/components/avatar.tsx +91 -0
  92. package/src/components/back-button.tsx +39 -0
  93. package/src/components/back-icon.tsx +25 -0
  94. package/src/components/badge.tsx +41 -0
  95. package/src/components/banner.tsx +63 -0
  96. package/src/components/bottom-sheet-native.tsx +52 -0
  97. package/src/components/bottom-sheet-web.tsx +193 -0
  98. package/src/components/bottom-sheet.tsx +5 -0
  99. package/src/components/button-group.tsx +326 -0
  100. package/src/components/button.tsx +337 -0
  101. package/src/components/checkbox.tsx +71 -0
  102. package/src/components/color-picker.tsx +115 -0
  103. package/src/components/context-menu.tsx +149 -0
  104. package/src/components/date-picker.tsx +466 -0
  105. package/src/components/dialog-context.ts +3 -0
  106. package/src/components/dialog.tsx +210 -0
  107. package/src/components/empty-state.tsx +49 -0
  108. package/src/components/expand-indicator.tsx +60 -0
  109. package/src/components/expressive-shape.tsx +37 -0
  110. package/src/components/fab-menu-legacy.tsx +181 -0
  111. package/src/components/fab-menu.tsx +90 -0
  112. package/src/components/filter-chip.tsx +136 -0
  113. package/src/components/floating-action-button.tsx +79 -0
  114. package/src/components/icon-button.tsx +127 -0
  115. package/src/components/icons.tsx +43 -0
  116. package/src/components/input.tsx +80 -0
  117. package/src/components/keyboard-inset-view.tsx +28 -0
  118. package/src/components/list-controls.tsx +134 -0
  119. package/src/components/loading-indicator.tsx +183 -0
  120. package/src/components/menu-sheet.tsx +133 -0
  121. package/src/components/panel-sheet.tsx +90 -0
  122. package/src/components/password-visibility.tsx +39 -0
  123. package/src/components/popover-layout.ts +47 -0
  124. package/src/components/popover.tsx +139 -0
  125. package/src/components/pressable.tsx +108 -0
  126. package/src/components/radio-navigation.ts +52 -0
  127. package/src/components/refresh-control.tsx +39 -0
  128. package/src/components/row-gap.tsx +13 -0
  129. package/src/components/search-field.tsx +92 -0
  130. package/src/components/select-field.tsx +105 -0
  131. package/src/components/settings-list.tsx +302 -0
  132. package/src/components/settings-row.tsx +61 -0
  133. package/src/components/sheet-frame.tsx +250 -0
  134. package/src/components/sheet-lifecycle.ts +233 -0
  135. package/src/components/sheet-transition.ts +105 -0
  136. package/src/components/slider.tsx +185 -0
  137. package/src/components/snackbar.tsx +97 -0
  138. package/src/components/split-button.tsx +212 -0
  139. package/src/components/squish.ts +41 -0
  140. package/src/components/swipeable-row.tsx +109 -0
  141. package/src/components/switch.tsx +77 -0
  142. package/src/components/tab-bar.tsx +195 -0
  143. package/src/components/text-field.tsx +264 -0
  144. package/src/components/text.tsx +58 -0
  145. package/src/components/time-picker.tsx +277 -0
  146. package/src/components/toolbar.tsx +406 -0
  147. package/src/components/top-bar.tsx +91 -0
  148. package/src/components/undo-bar.tsx +137 -0
  149. package/src/components/wavy-progress.tsx +150 -0
  150. package/src/components/zoomable-image.tsx +240 -0
  151. package/src/expressive-shapes.ts +25 -0
  152. package/src/index.ts +62 -0
  153. package/src/keyboard.ts +5 -0
  154. package/src/material.ts +16 -0
  155. package/src/media.ts +51 -0
  156. package/src/motion.ts +96 -0
  157. package/src/platform.ts +13 -0
  158. package/src/preset-tokens.ts +265 -0
  159. package/src/provider.tsx +201 -0
  160. package/src/reduced-motion.ts +50 -0
  161. package/src/selection.ts +11 -0
  162. package/src/shape.ts +217 -0
  163. package/src/sheet-physics.ts +73 -0
  164. package/src/theme.ts +180 -0
  165. package/src/tokens.ts +2 -0
  166. package/src/use-keyboard-height.ts +64 -0
  167. package/src/utils.ts +7 -0
@@ -0,0 +1,69 @@
1
+ import * as React from 'react';
2
+ import { type IconProps } from './icons.tsx';
3
+ /**
4
+ * Material 3 filter chip — the app's one selectable pill.
5
+ *
6
+ * Unselected it reads as an offer, selected it fills with the primary
7
+ * container. Both states are drawn from the same set of style properties;
8
+ * only the colour values change. That is load-bearing on Android, and it is
9
+ * why an unselected chip paints an opaque fill in its own surface's tone
10
+ * rather than simply leaving the background unset:
11
+ *
12
+ * React Native builds a view's background out of layers — fill, border,
13
+ * ripple — held in a single drawable. Adding a *layer* that wasn't there
14
+ * before (a fill appearing on select, a border appearing on deselect)
15
+ * replaces that drawable with a freshly constructed one, and a fresh drawable
16
+ * starts with empty bounds. A view with `overflow: hidden` clips its children
17
+ * to those bounds, so for as long as they stay empty the chip paints its fill
18
+ * and nothing else: the icon and the label are laid out at full size but
19
+ * never drawn. That is the bug this shape avoids — and `overflow: hidden` is
20
+ * not optional here, since a contained ripple has to be clipped to the pill
21
+ * (see `pressable.tsx`).
22
+ *
23
+ * So: a fill and a border in *both* states, and selection expressed as
24
+ * colour. `surface` is what an unselected chip fills with, which has to match
25
+ * whatever the chip is sitting on for "off" to read as unfilled.
26
+ *
27
+ * The same reasoning rules out swapping the leading icon for a checkmark on
28
+ * select: everything about the chip's structure stays put across a toggle,
29
+ * and only colour moves. Selection stays legible without colour from the
30
+ * filled silhouette, the same way it does in `button-group.tsx` — the one
31
+ * selectable control in the app that never lost its label, and the shape this
32
+ * chip is now built to match.
33
+ *
34
+ * The radius is a real dp value rather than `rounded-full`: Tailwind's full
35
+ * radius is 9999, and `button-group.tsx` likewise morphs between numbers from
36
+ * the corner scale.
37
+ */
38
+ /** The tones a chip can sit on, as the fill an unselected chip paints. */
39
+ declare const SURFACE_FILL: {
40
+ readonly background: "bg-background";
41
+ readonly surfaceContainerHigh: "bg-surfaceContainerHigh";
42
+ /** Bottom sheets and dialogs. */
43
+ readonly popover: "bg-popover";
44
+ };
45
+ export interface FilterChipProps {
46
+ label: string;
47
+ selected: boolean;
48
+ onPress: () => void;
49
+ /**
50
+ * A second, deliberate action on the same chip — removing a saved search,
51
+ * say. Optional: a chip that only filters has nothing to hide behind a hold.
52
+ */
53
+ onLongPress?: () => void;
54
+ /** Optional leading icon. Drawn in both states, or in neither. */
55
+ icon?: React.ComponentType<IconProps>;
56
+ /**
57
+ * Optional trailing icon — a chevron on a chip that opens a choice rather
58
+ * than toggling. Drawn in both states, like `icon`.
59
+ */
60
+ trailingIcon?: React.ComponentType<IconProps>;
61
+ /**
62
+ * The tone the chip is drawn on. An unselected chip fills with it rather
63
+ * than staying transparent, so its fill is a colour change away from the
64
+ * selected one rather than a new drawable layer.
65
+ */
66
+ surface?: keyof typeof SURFACE_FILL;
67
+ }
68
+ export declare function FilterChip({ label, selected, onPress, onLongPress, icon: Icon, trailingIcon: Trailing, surface, }: FilterChipProps): React.JSX.Element;
69
+ export {};
@@ -0,0 +1,15 @@
1
+ import * as React from 'react';
2
+ import { type StyleProp, type ViewStyle } from 'react-native';
3
+ import { type MaterialOptions } from '../provider.tsx';
4
+ import type { IconProps } from './icons.tsx';
5
+ export interface FloatingActionButtonProps extends MaterialOptions {
6
+ icon: React.ComponentType<IconProps>;
7
+ accessibilityLabel: string;
8
+ onPress: () => void;
9
+ label?: string;
10
+ disabled?: boolean;
11
+ size?: 56 | 64;
12
+ style?: StyleProp<ViewStyle>;
13
+ }
14
+ /** A reusable floating action; screen placement and navigation remain consumer-owned. */
15
+ export declare function FloatingActionButton({ icon: Icon, accessibilityLabel, onPress, label, disabled, size, style, material, glassStyle, tintColor, fallbackColor, interactive, }: FloatingActionButtonProps): React.JSX.Element;
@@ -0,0 +1,40 @@
1
+ import * as React from 'react';
2
+ import { type GestureResponderEvent, type PressableProps, type StyleProp, type ViewStyle } from 'react-native';
3
+ import { type MaterialOptions } from '../provider.tsx';
4
+ export interface IconButtonProps extends MaterialOptions {
5
+ icon: React.ComponentType<{
6
+ size?: number;
7
+ color?: string;
8
+ fill?: string;
9
+ }>;
10
+ /**
11
+ * Receives the press event, for a button nested inside a pressable row that
12
+ * has to stop the row from seeing the same tap.
13
+ */
14
+ onPress: (event: GestureResponderEvent) => void;
15
+ /** Touch target diameter in dp; also sets the ripple's radius. */
16
+ size?: number;
17
+ iconSize?: number;
18
+ /** Defaults to `onSurfaceVariant`. */
19
+ color?: string;
20
+ fill?: string;
21
+ accessibilityLabel?: string;
22
+ hitSlop?: PressableProps['hitSlop'];
23
+ className?: string;
24
+ /** For a filled/elevated variant — plain RN styles, since `elevation` can't be a class. */
25
+ style?: StyleProp<ViewStyle>;
26
+ disabled?: boolean;
27
+ }
28
+ /**
29
+ * The one size every icon button in a screen's header uses: a full 48dp
30
+ * target around a 22dp glyph, so a back arrow, a star and a sync toggle read
31
+ * as the same kind of control from one screen to the next. Spread it in —
32
+ * `<IconButton {...HEADER_ICON_BUTTON} … />` — rather than repeating the
33
+ * numbers, which is how they drifted apart before.
34
+ */
35
+ export declare const HEADER_ICON_BUTTON: {
36
+ readonly size: 48;
37
+ readonly iconSize: 22;
38
+ };
39
+ /** A circular icon-only pressable with the app's standard borderless ripple. */
40
+ export declare function IconButton({ icon: Icon, onPress, size, iconSize, color, fill, accessibilityLabel, hitSlop, className, style, disabled, material, glassStyle, tintColor, fallbackColor, interactive, }: IconButtonProps): React.JSX.Element;
@@ -0,0 +1,18 @@
1
+ import type { StyleProp, ViewStyle } from 'react-native';
2
+ export interface IconProps {
3
+ size?: number;
4
+ color?: string;
5
+ fill?: string;
6
+ ruleColor?: string;
7
+ style?: StyleProp<ViewStyle>;
8
+ }
9
+ export declare const ArrowLeft: ({ size, color, style }: IconProps) => import("react").JSX.Element;
10
+ export declare const Check: ({ size, color, style }: IconProps) => import("react").JSX.Element;
11
+ export declare const ChevronDown: ({ size, color, style }: IconProps) => import("react").JSX.Element;
12
+ export declare const Search: ({ size, color, style }: IconProps) => import("react").JSX.Element;
13
+ export declare const X: ({ size, color, style }: IconProps) => import("react").JSX.Element;
14
+ export declare const ChevronUp: ({ size, color, style }: IconProps) => import("react").JSX.Element;
15
+ export declare const ChevronRight: ({ size, color, style }: IconProps) => import("react").JSX.Element;
16
+ export declare const Eye: ({ size, color, style }: IconProps) => import("react").JSX.Element;
17
+ export declare const EyeOff: ({ size, color, style }: IconProps) => import("react").JSX.Element;
18
+ export declare const Plus: ({ size, color, style }: IconProps) => import("react").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import * as React from 'react';
2
+ import { TextInput } from 'react-native';
3
+ export type InputProps = React.ComponentProps<typeof TextInput> & {
4
+ label?: string;
5
+ /** Shown below the field in destructive color. */
6
+ error?: string | null;
7
+ hint?: string;
8
+ };
9
+ export declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<React.ElementRef<typeof TextInput>>>;
@@ -0,0 +1,15 @@
1
+ import * as React from 'react';
2
+ import { type ViewProps } from 'react-native';
3
+ /**
4
+ * A view that gives up the part of the screen the on-screen keyboard covers.
5
+ *
6
+ * Edge-to-edge (the default since Expo SDK 54) stops Android's `adjustResize`
7
+ * from shrinking the window, and `KeyboardAvoidingView` cannot be relied on to
8
+ * take over: its `height` mode measures the keyboard against a frame that no
9
+ * longer ends where the keyboard begins, and leaves the layout full height.
10
+ * A scroll view inside it then ends behind the keyboard, so its lower fields
11
+ * can neither be seen nor scrolled to. Padding by the measured keyboard height
12
+ * shrinks the scroll view's viewport instead, which also lets Android scroll a
13
+ * focused field into view.
14
+ */
15
+ export declare function KeyboardInsetView({ style, ...props }: ViewProps): React.JSX.Element;
@@ -0,0 +1,38 @@
1
+ import * as React from 'react';
2
+ import { type ScrollViewProps } from 'react-native';
3
+ import type { MaterialOptions } from '../provider.tsx';
4
+ export interface SelectionHeaderProps {
5
+ count: number;
6
+ countLabel: string;
7
+ allSelected: boolean;
8
+ onClear: () => void;
9
+ onToggleAll: () => void;
10
+ clearLabel: string;
11
+ selectAllLabel: string;
12
+ deselectAllLabel: string;
13
+ }
14
+ export declare function SelectionHeader({ count, countLabel, allSelected, onClear, onToggleAll, clearLabel, selectAllLabel, deselectAllLabel, }: SelectionHeaderProps): React.JSX.Element;
15
+ export interface ListSectionHeaderProps {
16
+ title: string;
17
+ first?: boolean;
18
+ trailing?: React.ReactNode;
19
+ }
20
+ export declare function ListSectionHeader({ title, first, trailing }: ListSectionHeaderProps): React.JSX.Element;
21
+ export interface JumpToTopPillProps extends MaterialOptions {
22
+ label: string;
23
+ onPress: () => void;
24
+ count?: number;
25
+ accessibilityLabel?: string;
26
+ }
27
+ export declare function JumpToTopPill({ label, onPress, count, accessibilityLabel, ...materialOptions }: JumpToTopPillProps): React.JSX.Element;
28
+ export interface SettingsScreenLayoutProps {
29
+ title: string;
30
+ caption?: string;
31
+ onBack: () => void;
32
+ backLabel: string;
33
+ children: React.ReactNode;
34
+ overlay?: React.ReactNode;
35
+ scrollProps?: Omit<ScrollViewProps, 'children'>;
36
+ }
37
+ /** Screen geometry without a router dependency. Overlays stay outside the scrolling content. */
38
+ export declare function SettingsScreenLayout({ title, caption, onBack, backLabel, children, overlay, scrollProps, }: SettingsScreenLayoutProps): React.JSX.Element;
@@ -0,0 +1,9 @@
1
+ import * as React from 'react';
2
+ export interface LoadingIndicatorProps {
3
+ size?: number;
4
+ color?: string;
5
+ /** Draws the M3 "contained" variant — the shape inside a tonal circle. */
6
+ contained?: boolean;
7
+ className?: string;
8
+ }
9
+ export declare function LoadingIndicator({ size, color, contained, className, }: LoadingIndicatorProps): React.JSX.Element;
@@ -0,0 +1,36 @@
1
+ import * as React from 'react';
2
+ import type { IconProps } from './icons.tsx';
3
+ import { type MaterialOptions } from '../provider.tsx';
4
+ export interface MenuSheetItem {
5
+ id: string;
6
+ icon: React.ComponentType<IconProps>;
7
+ label: string;
8
+ onPress: () => void;
9
+ /** Overrides the icon colour, for a state like "starred". */
10
+ color?: string;
11
+ /** Filled icons read as "on" for toggles. */
12
+ fill?: string;
13
+ }
14
+ export interface MenuSheetProps extends MaterialOptions {
15
+ visible: boolean;
16
+ onClose: () => void;
17
+ title: string;
18
+ /** A line under the title saying what the actions would act on. */
19
+ subject?: string;
20
+ items: MenuSheetItem[];
21
+ }
22
+ /**
23
+ * A sheet of actions, each with its symbol and its name.
24
+ *
25
+ * The overflow half of a toolbar: what does not fit on the pill — or what an
26
+ * icon on its own would not explain — is listed here instead, where there is
27
+ * room for the word that says what it does. Rows are the same size and shape
28
+ * as the pickers' (`SnoozeSheet`, `MoveSheet`), so an action list and a value
29
+ * list do not read as two different kinds of sheet.
30
+ */
31
+ export declare function MenuSheet({ visible, onClose, title, subject, items, ...materialOptions }: MenuSheetProps): React.JSX.Element;
32
+ /** A menu sheet's rows on their own, for a sheet that shows more above its actions. */
33
+ export declare function MenuSheetRows({ items, onClose, }: {
34
+ items: MenuSheetItem[];
35
+ onClose: () => void;
36
+ }): React.JSX.Element;
@@ -0,0 +1,8 @@
1
+ import * as React from 'react';
2
+ import { type MaterialOptions } from '../provider.tsx';
3
+ export interface PanelSheetProps extends MaterialOptions {
4
+ visible: boolean;
5
+ onClose: () => void;
6
+ children: React.ReactNode;
7
+ }
8
+ export declare function PanelSheet(props: PanelSheetProps): React.JSX.Element;
@@ -0,0 +1,5 @@
1
+ /** Shared affordance for both input styles; credential policy remains caller-owned. */
2
+ export declare function PasswordVisibility({ revealed, onPress, }: {
3
+ revealed: boolean;
4
+ onPress: () => void;
5
+ }): import("react").JSX.Element;
@@ -0,0 +1,25 @@
1
+ export interface AnchorRect {
2
+ x: number;
3
+ y: number;
4
+ width: number;
5
+ height: number;
6
+ }
7
+ export interface PopoverViewport {
8
+ width: number;
9
+ height: number;
10
+ top?: number;
11
+ right?: number;
12
+ bottom?: number;
13
+ left?: number;
14
+ }
15
+ /** Clamp and flip an anchored surface without drawing actions outside the usable window. */
16
+ export declare function placePopover(anchor: AnchorRect, size: {
17
+ width: number;
18
+ height: number;
19
+ }, viewport: PopoverViewport, placement?: 'top' | 'bottom', gap?: number): {
20
+ left: number;
21
+ top: number;
22
+ width: number;
23
+ maxHeight: number;
24
+ placement: string;
25
+ };
@@ -0,0 +1,20 @@
1
+ import * as React from 'react';
2
+ import { View, type StyleProp, type ViewStyle } from 'react-native';
3
+ import { type MaterialOptions } from '../provider.tsx';
4
+ import { type AnchorRect } from './popover-layout.ts';
5
+ export type { AnchorRect } from './popover-layout.ts';
6
+ export type PopoverAnchorRef = React.RefObject<React.ComponentRef<typeof View> | null>;
7
+ export interface PopoverProps extends MaterialOptions {
8
+ visible: boolean;
9
+ onClose: () => void;
10
+ anchorRef?: PopoverAnchorRef;
11
+ anchor?: AnchorRect;
12
+ placement?: 'top' | 'bottom';
13
+ width?: number;
14
+ accessibilityLabel: string;
15
+ children: React.ReactNode;
16
+ style?: StyleProp<ViewStyle>;
17
+ onShow?: () => void;
18
+ }
19
+ /** Controlled anchored surface. Native Modal provides back dismissal; web adds focus trapping/Escape. */
20
+ export declare function Popover({ visible, onClose, anchorRef, anchor, placement, width, accessibilityLabel, children, style, onShow, material, glassStyle, tintColor, fallbackColor, interactive, }: PopoverProps): React.JSX.Element;
@@ -0,0 +1,12 @@
1
+ import * as React from 'react';
2
+ import { Pressable as RNPressable, type PressableProps } from 'react-native';
3
+ import { type AnimatedProps } from 'react-native-reanimated';
4
+ /**
5
+ * Shared touch feedback: contained ripples on Android, a pressed opacity on
6
+ * iOS. Preserve the caller's style callback, handlers and animated styles.
7
+ */
8
+ type PressableRef = React.ElementRef<typeof RNPressable>;
9
+ export declare const Pressable: React.ForwardRefExoticComponent<PressableProps & React.RefAttributes<PressableRef>>;
10
+ /** For a Pressable whose shape or radius is driven by a Reanimated style. */
11
+ export declare const AnimatedPressable: React.ComponentType<Omit<AnimatedProps<PressableProps>, 'ref'> & React.RefAttributes<PressableRef>>;
12
+ export {};
@@ -0,0 +1,11 @@
1
+ import * as React from 'react';
2
+ import { Pressable } from './pressable.tsx';
3
+ /** Native accessibility supplies radio actions; web adds roving focus and selection. */
4
+ export declare function useRadioNavigation(items: {
5
+ id: string;
6
+ disabled?: boolean;
7
+ }[], value: string | null, onChange: (id: string) => void): (id: string) => {
8
+ onKeyDown?: ((event: Parameters<NonNullable<React.ComponentProps<typeof Pressable>["onKeyDown"]>>[0]) => void) | undefined;
9
+ ref: (node: React.ComponentRef<typeof Pressable> | null) => void;
10
+ tabIndex: 0 | -1;
11
+ };
@@ -0,0 +1,16 @@
1
+ import { type RefreshControlProps as RNRefreshControlProps } from 'react-native';
2
+ export type RefreshControlProps = RNRefreshControlProps;
3
+ /**
4
+ * RN's `RefreshControl`, pre-colored with the app's role tokens for the
5
+ * current scheme.
6
+ *
7
+ * Every other prop is forwarded, and that is load-bearing rather than
8
+ * politeness. On Android a `ScrollView` does not render its `refreshControl`
9
+ * beside the list: it clones the element with the scroll view itself as
10
+ * `children` and the list's layout style, and renders that clone as the
11
+ * outer view. A wrapper that accepts only `refreshing` and `onRefresh` drops
12
+ * both — which takes the entire list, empty state and footer included, out of
13
+ * the tree and leaves a blank screen under the header. Keep this a
14
+ * pass-through; anything it swallows, the list loses.
15
+ */
16
+ export declare function RefreshControl({ tintColor, colors, progressBackgroundColor, ...rest }: RefreshControlProps): import("react").JSX.Element;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The space a card list leaves between two rows.
3
+ *
4
+ * Every list that renders rows as separate rounded cards passes this as its
5
+ * `ItemSeparatorComponent`, so the rhythm is one value rather than a number
6
+ * repeated per screen. Taller cards that need to breathe more — the
7
+ * Screener's — space themselves.
8
+ */
9
+ export declare function RowGap(): import("react").JSX.Element;
@@ -0,0 +1,22 @@
1
+ import * as React from 'react';
2
+ import { type MaterialOptions } from '../provider.tsx';
3
+ export interface SearchFieldProps extends MaterialOptions {
4
+ value: string;
5
+ onChangeText: (value: string) => void;
6
+ placeholder: string;
7
+ accessibilityLabel: string;
8
+ /** Label for the clear button, which only appears once something is typed. */
9
+ clearAccessibilityLabel: string;
10
+ /** Opens the keyboard on mount — for a screen whose only job is this field. */
11
+ autoFocus?: boolean;
12
+ className?: string;
13
+ }
14
+ /**
15
+ * The app's filter-as-you-type field: a pill with a leading magnifier and a
16
+ * clear button that appears only once there is something to clear.
17
+ *
18
+ * Deliberately not built on `Input`, which is the form control — a labelled
19
+ * box with room underneath for an error. A filter box has no label, no
20
+ * validation and no submit; it just narrows the list under it.
21
+ */
22
+ export declare function SearchField({ value, onChangeText, placeholder, accessibilityLabel, clearAccessibilityLabel, autoFocus, className, material, glassStyle, tintColor, fallbackColor, interactive, }: SearchFieldProps): React.JSX.Element;
@@ -0,0 +1,16 @@
1
+ import * as React from 'react';
2
+ import { type MaterialOptions } from '../provider.tsx';
3
+ export interface SelectOption<T extends string> {
4
+ id: T;
5
+ label: string;
6
+ disabled?: boolean;
7
+ }
8
+ export interface SelectFieldProps<T extends string> extends MaterialOptions {
9
+ value: T;
10
+ options: SelectOption<T>[];
11
+ onChange: (value: T) => void;
12
+ accessibilityLabel: string;
13
+ menuMaterial?: MaterialOptions['material'];
14
+ disabled?: boolean;
15
+ }
16
+ export declare function SelectField<T extends string>({ value, options, onChange, accessibilityLabel, disabled, material, menuMaterial, glassStyle, tintColor, fallbackColor, interactive, }: SelectFieldProps<T>): React.JSX.Element;
@@ -0,0 +1,98 @@
1
+ import * as React from 'react';
2
+ import { type IconProps } from './icons.tsx';
3
+ import { type SelectOption } from './select-field.tsx';
4
+ import { type MaterialOptions } from '../provider.tsx';
5
+ /**
6
+ * The pieces every settings screen is built from.
7
+ *
8
+ * Settings used to be one screen that spelled out each card, row, switch and
9
+ * chevron inline, which is why the same twelve lines of markup appeared a
10
+ * dozen times over and drifted apart as they were edited. Splitting settings
11
+ * across several screens would have multiplied that, so the row shapes live
12
+ * here instead and a screen only says what its settings *are*.
13
+ */
14
+ export type SettingsIcon = React.ComponentType<IconProps>;
15
+ /**
16
+ * Corner radii for one row of a connected group.
17
+ *
18
+ * M3 Expressive draws a settings group as separate cards that still read as
19
+ * one object: the group's outer corners stay large, and every corner facing a
20
+ * neighbour tightens to the small step.
21
+ */
22
+ export declare function groupRounding(index: number, count: number): string;
23
+ export declare function SettingsSection({ title, children, }: {
24
+ title?: string;
25
+ children: React.ReactNode;
26
+ }): React.JSX.Element;
27
+ /**
28
+ * A run of rows drawn as one connected card group.
29
+ *
30
+ * Takes the rows as children rather than as data so a screen can drop one on a
31
+ * condition (`{Platform.OS === 'android' ? <Row/> : null}`) and still get the
32
+ * rounding right — a falsy child is discarded here, before the corners are
33
+ * worked out, so a hidden row never leaves a flattened corner behind.
34
+ */
35
+ export declare function SettingsGroup({ children }: {
36
+ children: React.ReactNode;
37
+ }): React.JSX.Element;
38
+ export interface SettingsNavRowProps {
39
+ icon?: SettingsIcon;
40
+ /** Custom leading content in the icon's place — an account's color dot. */
41
+ leading?: React.ReactNode;
42
+ label: string;
43
+ description?: string;
44
+ /** The current choice, shown at the row's trailing edge. */
45
+ value?: string;
46
+ onPress: () => void;
47
+ accessibilityLabel?: string;
48
+ /** For a row that removes something: red label, and no chevron to follow. */
49
+ destructive?: boolean;
50
+ }
51
+ /** A row that opens something else — another screen, or a picker sheet. */
52
+ export declare function SettingsNavRow({ icon, leading, label, description, value, onPress, accessibilityLabel, destructive, }: SettingsNavRowProps): React.JSX.Element;
53
+ export interface SettingsChoiceRowProps {
54
+ /** Custom leading content — a calendar's color dot. */
55
+ leading?: React.ReactNode;
56
+ label: string;
57
+ description?: string;
58
+ selected: boolean;
59
+ onPress: () => void;
60
+ accessibilityLabel?: string;
61
+ }
62
+ /**
63
+ * One option of a choice spelled out as rows rather than a menu, for options
64
+ * that need a second line to tell apart: two calendars both called "Personal".
65
+ */
66
+ export declare function SettingsChoiceRow({ leading, label, description, selected, onPress, accessibilityLabel, }: SettingsChoiceRowProps): React.JSX.Element;
67
+ export interface SettingsSwitchRowProps {
68
+ icon?: SettingsIcon;
69
+ /** Custom leading content in the icon's place — a calendar's color dot. */
70
+ leading?: React.ReactNode;
71
+ label: string;
72
+ description?: string;
73
+ value: boolean;
74
+ onValueChange: (value: boolean) => void;
75
+ disabled?: boolean;
76
+ accessibilityLabel?: string;
77
+ }
78
+ export declare function SettingsSwitchRow({ icon, leading, label, description, value, onValueChange, disabled, accessibilityLabel, }: SettingsSwitchRowProps): React.JSX.Element;
79
+ export interface SettingsSelectRowProps<T extends string> extends MaterialOptions {
80
+ menuMaterial?: MaterialOptions['material'];
81
+ disabled?: boolean;
82
+ icon?: SettingsIcon;
83
+ label: string;
84
+ description?: string;
85
+ value: T;
86
+ options: SelectOption<T>[];
87
+ onChange: (value: T) => void;
88
+ accessibilityLabel?: string;
89
+ }
90
+ export declare function SettingsSelectRow<T extends string>({ icon, label, description, value, options, onChange, accessibilityLabel, ...materialOptions }: SettingsSelectRowProps<T>): React.JSX.Element;
91
+ /**
92
+ * A card holding something that is not a row — the theme picker's button
93
+ * group, the accent swatches. Matches a group of one so custom content sits on
94
+ * the same surface at the same inset as the rows above and below it.
95
+ */
96
+ export declare function SettingsCard({ children }: {
97
+ children: React.ReactNode;
98
+ }): React.JSX.Element;
@@ -0,0 +1,13 @@
1
+ import * as React from 'react';
2
+ import { type IconProps } from './icons.tsx';
3
+ /** A row in a settings card: a symbol in its own tinted circle, a label and what it is set to. */
4
+ export declare function SettingsRow({ icon: Icon, label, description, onPress, value, onValueChange, first, }: {
5
+ icon?: React.ComponentType<IconProps>;
6
+ label: string;
7
+ description?: string;
8
+ onPress?: () => void;
9
+ /** A switch instead of a chevron. */
10
+ value?: boolean;
11
+ onValueChange?: (value: boolean) => void;
12
+ first?: boolean;
13
+ }): React.JSX.Element;
@@ -0,0 +1,27 @@
1
+ import * as React from 'react';
2
+ import { type ScrollViewProps, type StyleProp, type ViewStyle } from 'react-native';
3
+ import { type AnimatedStyle } from 'react-native-reanimated';
4
+ import type { Sheet } from './sheet-transition.ts';
5
+ import { type MaterialOptions } from '../provider.tsx';
6
+ /**
7
+ * The scrim, the panel and its handle — everything `BottomSheet` and
8
+ * `PanelSheet` share, so the two look and move as one kind of sheet. Each
9
+ * places it differently: one in a `Modal`, one inside the screen, lifted by
10
+ * the keyboard (`lift`).
11
+ */
12
+ export declare function SheetFrame({ sheet, visible, onClose, lift, panelStyle, children, dragFrom, material, glassStyle, tintColor, fallbackColor, interactive, }: {
13
+ dragFrom?: 'handle' | 'panel';
14
+ sheet: Sheet;
15
+ visible: boolean;
16
+ onClose: () => void;
17
+ lift?: StyleProp<AnimatedStyle<ViewStyle>>;
18
+ panelStyle?: StyleProp<AnimatedStyle<ViewStyle>>;
19
+ children: React.ReactNode;
20
+ } & MaterialOptions): React.JSX.Element;
21
+ /**
22
+ * A vertical list inside a sheet. It scrolls first and lets the sheet's pull
23
+ * take over at its top, as Android's own sheets do; a plain `ScrollView`
24
+ * would fight the pull for every vertical swipe. Sideways rows of chips can
25
+ * stay plain `ScrollView`s: the pull gives way to a sideways swipe.
26
+ */
27
+ export declare function SheetScrollView({ onScroll, onLayout, onContentSizeChange, ...props }: ScrollViewProps): React.JSX.Element;
@@ -0,0 +1,36 @@
1
+ import { type ViewStyle, type LayoutChangeEvent } from 'react-native';
2
+ import { Gesture } from 'react-native-gesture-handler';
3
+ import { type SharedValue, type AnimatedStyle } from 'react-native-reanimated';
4
+ import { type SheetScroll } from '../sheet-physics.ts';
5
+ /** What a `SheetScrollView` needs from the sheet it scrolls in. */
6
+ export interface SheetScrollContextValue {
7
+ pull: ReturnType<typeof Gesture.Pan>;
8
+ scrolls: SharedValue<Record<string, SheetScroll>>;
9
+ }
10
+ /**
11
+ * A bottom sheet's whole life: in, under the finger, and out again.
12
+ *
13
+ * Driven by shared values rather than Reanimated's `entering` layout
14
+ * animations, and that is the point. On Android a layout animation on a view
15
+ * inside a `Modal` leaves the view's *layout* where the animation started even
16
+ * though it is drawn where the animation ended, so presses inside the panel
17
+ * are hit-tested against whatever is behind it — here the scrim, whose one job
18
+ * is to close the panel. A picker built that way looks like it snaps back the
19
+ * instant an option is tapped (software-mansion/react-native-reanimated#4422).
20
+ * An animated transform moves the native view, and Android hit-tests against
21
+ * where the view actually is.
22
+ *
23
+ * The sheet stays `mounted` after `visible` turns false, until the panel has
24
+ * slid out: however it was closed — the scrim, back, a row that acts, a pull —
25
+ * it leaves the way it came. The scrim is not on a clock of its own; it is
26
+ * worked out from where the panel is, so the two always move as one.
27
+ */
28
+ export interface Sheet {
29
+ mounted: boolean;
30
+ scrimStyle: AnimatedStyle<ViewStyle>;
31
+ panelStyle: AnimatedStyle<ViewStyle>;
32
+ onPanelLayout: (event: LayoutChangeEvent) => void;
33
+ pull: ReturnType<typeof Gesture.Pan>;
34
+ scrollContext: SheetScrollContextValue;
35
+ }
36
+ export declare function useSheet(visible: boolean, onClose: () => void): Sheet;
@@ -0,0 +1,36 @@
1
+ import { type LayoutChangeEvent } from 'react-native';
2
+ import { type AnimatedStyle, type SharedValue } from 'react-native-reanimated';
3
+ /**
4
+ * The open transition for a panel presented inside a `Modal`: the scrim dims,
5
+ * and the panel springs up from the edge it is anchored to.
6
+ *
7
+ * Driven by shared values rather than Reanimated's `entering` layout
8
+ * animations, and that is the entire point of this hook. On Android a layout
9
+ * animation on a view inside a `Modal` leaves the view's *layout* where the
10
+ * animation started even though the view is drawn where the animation ended,
11
+ * so presses inside the panel are hit-tested against whatever is behind it —
12
+ * here the scrim, whose one job is to close the panel. A picker built that way
13
+ * looks like it snaps back the instant an option is tapped: the tap closed the
14
+ * sheet and never reached the row it landed on. Only Android is affected, and
15
+ * only inside a `Modal`, which is why it survived review twice
16
+ * (software-mansion/react-native-reanimated#4422).
17
+ *
18
+ * An animated transform has no such problem: it moves the native view, and
19
+ * Android hit-tests against where the view actually is.
20
+ */
21
+ export interface SheetTransition {
22
+ scrimStyle: AnimatedStyle<{
23
+ opacity: number;
24
+ }>;
25
+ panelStyle: AnimatedStyle<{
26
+ transform: {
27
+ translateY: number;
28
+ }[];
29
+ }>;
30
+ onPanelLayout: (event: LayoutChangeEvent) => void;
31
+ drag: SharedValue<number>;
32
+ height: SharedValue<number>;
33
+ reducedMotion: boolean;
34
+ }
35
+ export declare function useSheetTransition(visible: boolean): SheetTransition;
36
+ export { useSheet, type Sheet, type SheetScrollContextValue } from './sheet-lifecycle.ts';