@sincpro/mobile-ui 0.2.0 → 0.3.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 (234) hide show
  1. package/README.md +76 -19
  2. package/dist/Dialog/BottomSheet/BottomSheet.Root.d.ts +11 -7
  3. package/dist/Dialog/BottomSheet/BottomSheet.Root.js +4 -0
  4. package/dist/Dialog/Confirmation.context.d.ts +1 -1
  5. package/dist/Dialog/Dialog.ActionSheet.d.ts +17 -0
  6. package/dist/Dialog/Dialog.ActionSheet.js +16 -0
  7. package/dist/Dialog/Dialog.EditValue.d.ts +1 -1
  8. package/dist/Dialog/Dialog.Sheet.d.ts +26 -0
  9. package/dist/Dialog/Dialog.Sheet.js +55 -0
  10. package/dist/Dialog/index.d.ts +9 -7
  11. package/dist/Dialog/index.js +2 -0
  12. package/dist/Display/Display.Accordion.d.ts +18 -0
  13. package/dist/Display/Display.Accordion.js +22 -0
  14. package/dist/Display/Display.AvatarGroup.d.ts +12 -0
  15. package/dist/Display/Display.AvatarGroup.js +23 -0
  16. package/dist/Display/Display.Badge.d.ts +1 -1
  17. package/dist/Display/Display.Card.d.ts +46 -0
  18. package/dist/Display/Display.Card.js +36 -0
  19. package/dist/Display/Display.Carousel.d.ts +13 -0
  20. package/dist/Display/Display.Carousel.js +19 -0
  21. package/dist/Display/Display.Chip.d.ts +105 -0
  22. package/dist/Display/Display.Chip.js +45 -0
  23. package/dist/Display/Display.CopyableText.d.ts +1 -1
  24. package/dist/Display/Display.CountRecords.d.ts +1 -1
  25. package/dist/Display/Display.DataTable.d.ts +19 -0
  26. package/dist/Display/Display.DataTable.js +22 -0
  27. package/dist/Display/Display.Date.d.ts +15 -2
  28. package/dist/Display/Display.Date.js +34 -4
  29. package/dist/Display/Display.Divider.d.ts +1 -1
  30. package/dist/Display/Display.IconBadge.d.ts +13 -0
  31. package/dist/Display/Display.IconBadge.js +30 -0
  32. package/dist/Display/Display.Image.d.ts +15 -0
  33. package/dist/Display/Display.Image.js +17 -0
  34. package/dist/Display/Display.KeyValue.d.ts +10 -0
  35. package/dist/Display/Display.KeyValue.js +9 -0
  36. package/dist/Display/Display.ListItem.d.ts +13 -0
  37. package/dist/Display/Display.ListItem.js +14 -0
  38. package/dist/Display/Display.Logo.js +3 -1
  39. package/dist/Display/Display.MediaCard.d.ts +17 -0
  40. package/dist/Display/Display.MediaCard.js +12 -0
  41. package/dist/Display/Display.MediaEmbed.d.ts +19 -0
  42. package/dist/Display/Display.MediaEmbed.js +39 -0
  43. package/dist/Display/Display.MenuButton.d.ts +1 -1
  44. package/dist/Display/Display.Monetary.d.ts +1 -1
  45. package/dist/Display/Display.PriceTag.d.ts +10 -0
  46. package/dist/Display/Display.PriceTag.js +23 -0
  47. package/dist/Display/Display.ProductCard.d.ts +17 -0
  48. package/dist/Display/Display.ProductCard.js +13 -0
  49. package/dist/Display/Display.Rating.d.ts +11 -0
  50. package/dist/Display/Display.Rating.js +16 -0
  51. package/dist/Display/Display.SearchHistory.d.ts +12 -0
  52. package/dist/Display/Display.SearchHistory.js +13 -0
  53. package/dist/Display/Display.SectionHeader.d.ts +13 -0
  54. package/dist/Display/Display.SectionHeader.js +9 -0
  55. package/dist/Display/Display.Stat.d.ts +10 -0
  56. package/dist/Display/Display.Stat.js +9 -0
  57. package/dist/Display/Display.StatCard.d.ts +14 -0
  58. package/dist/Display/Display.StatCard.js +13 -0
  59. package/dist/Display/Display.StatusDot.d.ts +11 -0
  60. package/dist/Display/Display.StatusDot.js +28 -0
  61. package/dist/Display/Display.Story.d.ts +15 -0
  62. package/dist/Display/Display.Story.js +43 -0
  63. package/dist/Display/Display.StoryTray.d.ts +26 -0
  64. package/dist/Display/Display.StoryTray.js +43 -0
  65. package/dist/Display/Display.StoryViewer.d.ts +26 -0
  66. package/dist/Display/Display.StoryViewer.js +79 -0
  67. package/dist/Display/Display.SwipeableRow.d.ts +15 -0
  68. package/dist/Display/Display.SwipeableRow.js +28 -0
  69. package/dist/Display/Display.Tag.d.ts +11 -0
  70. package/dist/Display/Display.Tag.js +9 -0
  71. package/dist/Display/Display.Timeline.d.ts +13 -0
  72. package/dist/Display/Display.Timeline.js +19 -0
  73. package/dist/Display/Display.Tooltip.d.ts +10 -0
  74. package/dist/Display/Display.Tooltip.js +24 -0
  75. package/dist/Display/index.d.ts +66 -0
  76. package/dist/Display/index.js +54 -0
  77. package/dist/Feedback/ErrorBoundary.d.ts +1 -1
  78. package/dist/Feedback/Feedback.Banner.d.ts +82 -0
  79. package/dist/Feedback/Feedback.Banner.js +35 -0
  80. package/dist/Feedback/Feedback.DomainSplashScreen.d.ts +2 -1
  81. package/dist/Feedback/Feedback.DomainSplashScreen.js +1 -1
  82. package/dist/Feedback/Feedback.Empty.d.ts +1 -1
  83. package/dist/Feedback/Feedback.EmptyState.d.ts +15 -0
  84. package/dist/Feedback/Feedback.EmptyState.js +11 -0
  85. package/dist/Feedback/Feedback.Error.d.ts +1 -1
  86. package/dist/Feedback/Feedback.Loading.d.ts +2 -1
  87. package/dist/Feedback/Feedback.PermissionCard.d.ts +15 -0
  88. package/dist/Feedback/Feedback.PermissionCard.js +11 -0
  89. package/dist/Feedback/Feedback.Progress.d.ts +9 -0
  90. package/dist/Feedback/Feedback.Progress.js +35 -0
  91. package/dist/Feedback/Feedback.ProgressCircle.d.ts +12 -0
  92. package/dist/Feedback/Feedback.ProgressCircle.js +15 -0
  93. package/dist/Feedback/Feedback.Skeleton.d.ts +11 -0
  94. package/dist/Feedback/Feedback.Skeleton.js +29 -0
  95. package/dist/Feedback/Feedback.Splash.d.ts +1 -1
  96. package/dist/Feedback/Toast.context.d.ts +35 -0
  97. package/dist/Feedback/Toast.context.js +119 -0
  98. package/dist/Feedback/index.d.ts +15 -0
  99. package/dist/Feedback/index.js +15 -0
  100. package/dist/Form/Form.Button.d.ts +6 -0
  101. package/dist/Form/Form.Button.js +12 -1
  102. package/dist/Form/Form.Checkbox.d.ts +1 -1
  103. package/dist/Form/Form.ControlledCheckbox.d.ts +1 -1
  104. package/dist/Form/Form.ControlledInput.d.ts +1 -1
  105. package/dist/Form/Form.ControlledMonetaryInput.d.ts +1 -1
  106. package/dist/Form/Form.ControlledRadioButton.d.ts +1 -1
  107. package/dist/Form/Form.DatePicker.d.ts +20 -0
  108. package/dist/Form/Form.DatePicker.js +38 -0
  109. package/dist/Form/Form.Dropdown.d.ts +1 -1
  110. package/dist/Form/Form.FAB.d.ts +10 -0
  111. package/dist/Form/Form.FAB.js +17 -0
  112. package/dist/Form/Form.FilterButton.d.ts +1 -1
  113. package/dist/Form/Form.FractionalQuantityInput.d.ts +1 -1
  114. package/dist/Form/Form.IconButton.d.ts +1 -1
  115. package/dist/Form/Form.Input.d.ts +2 -1
  116. package/dist/Form/Form.MonetaryInput.d.ts +1 -1
  117. package/dist/Form/Form.PinInput.d.ts +12 -0
  118. package/dist/Form/Form.PinInput.js +23 -0
  119. package/dist/Form/Form.QuantitySelector.d.ts +2 -1
  120. package/dist/Form/Form.QuantitySelector.js +1 -1
  121. package/dist/Form/Form.RadioButton.d.ts +1 -1
  122. package/dist/Form/Form.SearchBar.d.ts +6 -1
  123. package/dist/Form/Form.SearchBar.js +4 -0
  124. package/dist/Form/Form.Select.d.ts +17 -0
  125. package/dist/Form/Form.Select.js +26 -0
  126. package/dist/Form/Form.Slider.d.ts +20 -0
  127. package/dist/Form/Form.Slider.js +16 -0
  128. package/dist/Form/Form.Switch.d.ts +10 -0
  129. package/dist/Form/Form.Switch.js +9 -0
  130. package/dist/Form/index.d.ts +12 -0
  131. package/dist/Form/index.js +12 -0
  132. package/dist/Navigation/Navigation.AppBar.d.ts +41 -0
  133. package/dist/Navigation/Navigation.AppBar.js +33 -0
  134. package/dist/Navigation/Navigation.BottomNav.d.ts +29 -0
  135. package/dist/Navigation/Navigation.BottomNav.js +35 -0
  136. package/dist/Navigation/Navigation.CollapsingHeader.d.ts +34 -0
  137. package/dist/Navigation/Navigation.CollapsingHeader.js +47 -0
  138. package/dist/Navigation/Navigation.FloatingBar.d.ts +15 -0
  139. package/dist/Navigation/Navigation.FloatingBar.js +21 -0
  140. package/dist/Navigation/Navigation.Header.d.ts +6 -2
  141. package/dist/Navigation/Navigation.Header.js +4 -0
  142. package/dist/Navigation/Navigation.HeaderToolbar.d.ts +1 -1
  143. package/dist/Navigation/Navigation.Menu.d.ts +21 -0
  144. package/dist/Navigation/Navigation.Menu.js +42 -0
  145. package/dist/Navigation/Navigation.RowItem.d.ts +1 -1
  146. package/dist/Navigation/Navigation.SearchBar.d.ts +18 -0
  147. package/dist/Navigation/Navigation.SearchBar.js +22 -0
  148. package/dist/Navigation/Navigation.SegmentedControl.d.ts +14 -0
  149. package/dist/Navigation/Navigation.SegmentedControl.js +13 -0
  150. package/dist/Navigation/Navigation.Steps.d.ts +8 -0
  151. package/dist/Navigation/Navigation.Steps.js +17 -0
  152. package/dist/Navigation/Navigation.TabIcon.d.ts +1 -1
  153. package/dist/Navigation/Navigation.Tabs.d.ts +28 -0
  154. package/dist/Navigation/Navigation.Tabs.js +45 -0
  155. package/dist/Navigation/index.d.ts +32 -1
  156. package/dist/Navigation/index.js +18 -0
  157. package/dist/Typography/Typography.Text.d.ts +2 -1
  158. package/dist/branding.d.ts +6 -0
  159. package/dist/branding.js +7 -0
  160. package/dist/icons/ArrowDownIcon.d.ts +2 -1
  161. package/dist/icons/ArrowUpIcon.d.ts +2 -1
  162. package/dist/icons/CreditIcon.d.ts +1 -1
  163. package/dist/icons/OdooIcon.d.ts +1 -1
  164. package/dist/index.d.ts +1 -0
  165. package/dist/index.js +2 -0
  166. package/dist/layouts/AuthContainer.d.ts +1 -1
  167. package/dist/layouts/Container.d.ts +1 -0
  168. package/dist/layouts/Container.js +2 -3
  169. package/dist/layouts/GradientContainer.d.ts +1 -1
  170. package/dist/layouts/PlainLayout.d.ts +1 -1
  171. package/dist/layouts/ScrollContainer.d.ts +2 -2
  172. package/dist/layouts/ScrollContainer.js +1 -1
  173. package/dist/layouts/TabNavigatorLayout.d.ts +2 -2
  174. package/dist/layouts/TabNavigatorLayout.js +4 -0
  175. package/dist/primitives/AspectRatio.d.ts +10 -0
  176. package/dist/primitives/AspectRatio.js +8 -0
  177. package/dist/primitives/Box.d.ts +1 -1
  178. package/dist/primitives/Pressable.d.ts +10 -0
  179. package/dist/primitives/Pressable.js +9 -0
  180. package/dist/primitives/Row.d.ts +1 -1
  181. package/dist/primitives/Spacer.d.ts +8 -0
  182. package/dist/primitives/Spacer.js +9 -0
  183. package/dist/primitives/Stack.d.ts +1 -1
  184. package/dist/primitives/index.d.ts +3 -0
  185. package/dist/primitives/index.js +3 -0
  186. package/dist/theme/active.d.ts +2 -0
  187. package/dist/theme/active.js +13 -0
  188. package/dist/theme/components/ThemedActivityIndicator.d.ts +1 -1
  189. package/dist/theme/components/index.d.ts +1 -1
  190. package/dist/theme/components/index.js +1 -1
  191. package/dist/theme/dark.d.ts +7 -0
  192. package/dist/theme/dark.js +84 -0
  193. package/dist/theme/define.d.ts +5 -5
  194. package/dist/theme/define.js +5 -5
  195. package/dist/theme/index.d.ts +3 -1
  196. package/dist/theme/index.js +3 -1
  197. package/dist/theme/theme.d.ts +1 -1
  198. package/dist/theme/theme.js +1 -1
  199. package/dist/theme/types.d.ts +14 -14
  200. package/dist/theme/types.js +2 -2
  201. package/dist/theme/useTheme.d.ts +3 -1
  202. package/dist/theme/useTheme.js +6 -1
  203. package/dist/tokens/index.d.ts +2 -0
  204. package/dist/tokens/index.js +2 -0
  205. package/dist/tokens/motion.d.ts +71 -0
  206. package/dist/tokens/motion.js +25 -0
  207. package/dist/utils/date.d.ts +33 -33
  208. package/dist/utils/date.js +39 -39
  209. package/dist/views/AuthFormView.d.ts +1 -1
  210. package/dist/views/FormViewV2.context.d.ts +1 -1
  211. package/dist/views/FormViewV2.d.ts +10 -10
  212. package/dist/views/FormViewV2.js +2 -2
  213. package/dist/views/ListViewV2.context.d.ts +1 -1
  214. package/dist/views/ListViewV2.d.ts +20 -20
  215. package/dist/views/ListViewV2.js +2 -2
  216. package/dist/views/Wizard/Wizard.context.d.ts +1 -1
  217. package/dist/widgets/CircleButton.d.ts +6 -2
  218. package/dist/widgets/CircleButton.js +4 -0
  219. package/dist/widgets/GeoPermissionCard.d.ts +1 -1
  220. package/dist/widgets/HomeHeader.d.ts +4 -0
  221. package/dist/widgets/HomeHeader.js +4 -0
  222. package/dist/widgets/JSONViewer.d.ts +2 -1
  223. package/dist/widgets/JSONViewer.js +6 -6
  224. package/dist/widgets/MenuCard.d.ts +1 -1
  225. package/dist/widgets/ScreenHeader.d.ts +6 -2
  226. package/dist/widgets/ScreenHeader.js +15 -4
  227. package/dist/widgets/TimeZoneSelector.d.ts +1 -1
  228. package/dist/widgets/TimeZoneSelectorModal.d.ts +1 -1
  229. package/package.json +38 -25
  230. package/tailwind.preset.js +14 -0
  231. package/dist/notifications/index.d.ts +0 -1
  232. package/dist/notifications/index.js +0 -1
  233. package/dist/providers/index.d.ts +0 -1
  234. package/dist/providers/index.js +0 -2
package/README.md CHANGED
@@ -1,10 +1,12 @@
1
1
  # @sincpro/mobile-ui
2
2
 
3
- Sincpro Mobile design system: generic, presentational React Native components.
3
+ Sincpro Mobile design system — generic, presentational React Native components (Expo SDK 56).
4
4
 
5
- - **Presentational only** — receives data via props/callbacks. No domain logic, no services, no state stores.
6
- - **Standalone** — does not depend on `@sincpro/mobile` (the core). The core depends on this package.
7
- - Built with NativeWind + tailwind-variants.
5
+ - **Presentational only** — driven by props/callbacks. No domain logic, services, or state stores.
6
+ - **Standalone** — does not depend on `@sincpro/mobile` (the core depends on this package).
7
+ - **Mobile-first** — built with NativeWind 4 + tailwind-variants, design tokens via CSS variables.
8
+
9
+ > 🤖 **AI agents:** read [`AGENTS.md`](AGENTS.md) (ecosystem & patterns) and [`docs/GOTCHAS.md`](docs/GOTCHAS.md) (known traps) first.
8
10
 
9
11
  ## Install
10
12
 
@@ -12,11 +14,18 @@ Sincpro Mobile design system: generic, presentational React Native components.
12
14
  npx expo install @sincpro/mobile-ui
13
15
  ```
14
16
 
15
- Peer dependencies (provided by the host app): `react`, `react-native`, `nativewind`, `react-native-reanimated`, `react-native-svg`, `react-native-safe-area-context`, `react-native-keyboard-controller`, `react-native-worklets`, `react-hook-form`, `react-native-currency-input`, `@expo/vector-icons`, `@expo-google-fonts/montserrat`, and the expo modules listed in `package.json`.
17
+ Peer dependencies are provided by the host app: `react`, `react-native`, `nativewind`,
18
+ `react-native-reanimated`, `react-native-svg`, `react-native-safe-area-context`,
19
+ `react-native-keyboard-controller`, `react-native-worklets`, `react-hook-form`,
20
+ `react-native-currency-input`, `@expo/vector-icons`, `@expo-google-fonts/montserrat`, plus the
21
+ expo modules listed in `package.json`. A few components need **optional** peers (install only if
22
+ you use them): `@react-native-community/slider` (`Form/Slider`), `@react-native-community/datetimepicker`
23
+ (`Form/DatePicker`), `@expo/ui` (future native primitives).
16
24
 
17
25
  ## Tailwind preset (required)
18
26
 
19
- The components use design tokens exposed as Tailwind classes (`bg-primary`, `text-text-secondary`, …) backed by CSS variables. The consumer app wires them via the shipped preset and content globs:
27
+ Components use design tokens exposed as Tailwind classes (`bg-primary`, `text-text-secondary`, …)
28
+ backed by CSS variables. Wire them via the shipped preset and content globs:
20
29
 
21
30
  ```js
22
31
  // tailwind.config.js
@@ -27,31 +36,79 @@ module.exports = {
27
36
  };
28
37
  ```
29
38
 
30
- The token values are CSS variables; override them (a custom theme) in your global CSS `:root`, or inject at runtime with `vars()`. The framework's `createAppShell({ theme })` does this automatically.
39
+ Token values are CSS variables; override them (a custom theme) in your global CSS `:root`, or inject
40
+ at runtime with `vars()`. The framework's `createAppShell({ theme })` does this automatically.
41
+
42
+ ## Usage & import patterns
43
+
44
+ Import by **category subpath** (recommended — better tree-shaking) or from the root:
45
+
46
+ ```tsx
47
+ import { Form } from "@sincpro/mobile-ui/Form"; // inputs + actions
48
+ import { Display } from "@sincpro/mobile-ui/Display"; // data display
49
+ import { Feedback } from "@sincpro/mobile-ui/Feedback"; // app state (Toast, Skeleton…)
50
+ import { Navigation } from "@sincpro/mobile-ui/Navigation"; // AppBar, BottomNav, SearchBar…
51
+ import { Dialog } from "@sincpro/mobile-ui/Dialog"; // overlays (Sheet, ActionSheet…)
52
+ import { theme, useTheme } from "@sincpro/mobile-ui/theme";
53
+ import { motion } from "@sincpro/mobile-ui/tokens";
54
+ ```
55
+
56
+ Full component catalog by category: [`docs/CATALOG.md`](docs/CATALOG.md).
57
+
58
+ ### Dark mode
59
+
60
+ Ships `DEFAULT_THEME` (light) and `DEFAULT_DARK_THEME`. Set the active theme with `setActiveTheme`
61
+ (or `createAppShell({ theme })` in the core) and inject the CSS vars with `vars(themeToVars(tokens))`
62
+ on the subtree. `useTheme()` is a reactive hook to read the theme in components.
63
+
64
+ ### Branding (logo by context)
65
+
66
+ Configure the logo once; headers/login take it as a fallback:
67
+
68
+ ```tsx
69
+ import { setBranding } from "@sincpro/mobile-ui";
70
+ setBranding({ logo: require("../assets/logo.png") }); // Display.Logo uses it when no `source` is passed
71
+ ```
72
+
73
+ ### Toast (queued feedback)
31
74
 
32
- ## Usage
75
+ ```tsx
76
+ import { ToastProvider, useToast } from "@sincpro/mobile-ui/Feedback";
77
+ // wrap the app in <ToastProvider>; then:
78
+ const toast = useToast();
79
+ toast.promise(save(), { loading: "Saving…", success: "Done", error: "Failed" });
80
+ ```
81
+
82
+ ### Bottom sheet
33
83
 
34
84
  ```tsx
35
- import { Form } from "@sincpro/mobile-ui/Form";
36
- import { Display } from "@sincpro/mobile-ui/Display";
37
- import { theme } from "@sincpro/mobile-ui/theme";
85
+ import Sheet from "@sincpro/mobile-ui/Dialog/Dialog.Sheet";
86
+ // controlled by visible/onClose; closes via the top handle (swipe-down) or your own button.
87
+ // Built on RN Modal — no provider or native deps required.
38
88
  ```
39
89
 
90
+ ## Conventions
91
+
92
+ - **Language:** code, comments, and JSDoc are in **English**. Docs in `docs/` are English.
93
+ - **Styling:** NativeWind-first (`className` + tokens). Native/JS escape hatch only where `className`
94
+ can't reach (gradients, native props, Modal surfaces). See [`docs/PHILOSOPHY.md`](docs/PHILOSOPHY.md).
95
+ - **Backwards compatible:** changes are additive by default; superseded components are kept and marked
96
+ `@deprecated` (see `Legacy/*` in Storybook). See [`docs/STRUCTURE.md`](docs/STRUCTURE.md).
97
+
40
98
  ## Storybook (on-device, Expo)
41
99
 
42
- Visualiza los componentes en simulador/dispositivo con Storybook React Native (dev-only, no se publica):
100
+ Preview components on simulator/device with Storybook React Native (dev-only, not published):
43
101
 
44
102
  ```bash
45
103
  make storybook # expo start (Expo Go / dev build)
46
104
  make storybook-android # expo run:android
47
105
  ```
48
106
 
49
- Las stories viven en `.rnstorybook/stories/**/*.stories.tsx` e importan desde `@sincpro/mobile-ui/*`. El harness (`App.tsx`, `metro.config.js`, `.rnstorybook/`) está excluido del paquete publicado (`files: ["dist", ...]`).
107
+ Stories live in `.rnstorybook/stories/**/*.stories.tsx`, grouped as **Foundations / Components /
108
+ Patterns / Legacy**. The harness (`App.tsx`, `.rnstorybook/`) is excluded from the published package
109
+ (`files: ["dist", …]`).
50
110
 
51
- ## Structure
111
+ ## Build & release
52
112
 
53
- - `Form`, `Display`, `Dialog`, `Feedback`, `Typography`, `Navigation`, `primitives` — component categories
54
- - `views` — compound views (ListViewV2, FormViewV2, Wizard)
55
- - `widgets` — generic composed widgets (HomeHeader, MenuGrid, GeoPermissionCard, TimeZoneSelector)
56
- - `theme` — design tokens + tailwind-variants helpers (`defineTheme`, `extendTheme`, `themeToVars`)
57
- - `utils` — generic utilities (date, monetary, quantity, serializer, icon, timezone)
113
+ `make build` compiles `tsc + tsc-alias → dist/` (JS + types). The `exports` map publishes category
114
+ subpaths (`./Display`, `./Form`, …) plus a catch-all `./*`. See [`CHANGELOG.md`](CHANGELOG.md).
@@ -93,7 +93,11 @@ export interface RootProps {
93
93
  * </BottomSheet.Root>
94
94
  * ```
95
95
  */
96
- declare function Root({ visible, onClose, size, dismissible, children }: RootProps): import("react/jsx-runtime").JSX.Element;
96
+ /**
97
+ * @deprecated Custom PanResponder implementation (limited gestures/scroll). The modern
98
+ * replacement is `Dialog.Sheet` (on RN Modal, no provider). Kept for backwards compatibility.
99
+ */
100
+ declare function Root({ visible, onClose, size, dismissible, children }: RootProps): import("react").JSX.Element;
97
101
  export interface HandleProps {
98
102
  children?: ReactNode;
99
103
  }
@@ -116,7 +120,7 @@ export interface HandleProps {
116
120
  * </BottomSheet.Root>
117
121
  * ```
118
122
  */
119
- declare function Handle({ children }: HandleProps): import("react/jsx-runtime").JSX.Element;
123
+ declare function Handle({ children }: HandleProps): import("react").JSX.Element;
120
124
  export interface HeaderProps {
121
125
  children: ReactNode;
122
126
  }
@@ -149,7 +153,7 @@ export interface HeaderProps {
149
153
  * </BottomSheet.Header>
150
154
  * ```
151
155
  */
152
- declare function Header({ children }: HeaderProps): import("react/jsx-runtime").JSX.Element;
156
+ declare function Header({ children }: HeaderProps): import("react").JSX.Element;
153
157
  export interface TitleProps {
154
158
  children: ReactNode;
155
159
  subtitle?: string;
@@ -173,7 +177,7 @@ export interface TitleProps {
173
177
  * </BottomSheet.Title>
174
178
  * ```
175
179
  */
176
- declare function Title({ children, subtitle }: TitleProps): import("react/jsx-runtime").JSX.Element;
180
+ declare function Title({ children, subtitle }: TitleProps): import("react").JSX.Element;
177
181
  export interface ContentProps {
178
182
  children: ReactNode;
179
183
  scrollable?: boolean;
@@ -205,7 +209,7 @@ export interface ContentProps {
205
209
  * </BottomSheet.Content>
206
210
  * ```
207
211
  */
208
- declare function Content({ children, scrollable }: ContentProps): import("react/jsx-runtime").JSX.Element;
212
+ declare function Content({ children, scrollable }: ContentProps): import("react").JSX.Element;
209
213
  export interface ActionsProps {
210
214
  children: ReactNode;
211
215
  layout?: "auto" | "horizontal" | "vertical";
@@ -234,7 +238,7 @@ export interface ActionsProps {
234
238
  * </BottomSheet.Actions>
235
239
  * ```
236
240
  */
237
- declare function Actions({ children, layout }: ActionsProps): import("react/jsx-runtime").JSX.Element;
241
+ declare function Actions({ children, layout }: ActionsProps): import("react").JSX.Element;
238
242
  export interface FooterProps {
239
243
  children: ReactNode;
240
244
  }
@@ -263,7 +267,7 @@ export interface FooterProps {
263
267
  * </BottomSheet.Footer>
264
268
  * ```
265
269
  */
266
- declare function Footer({ children }: FooterProps): import("react/jsx-runtime").JSX.Element;
270
+ declare function Footer({ children }: FooterProps): import("react").JSX.Element;
267
271
  /**
268
272
  * BottomSheet Compound Components
269
273
  *
@@ -90,6 +90,10 @@ const SIZE_MAP = {
90
90
  * </BottomSheet.Root>
91
91
  * ```
92
92
  */
93
+ /**
94
+ * @deprecated Custom PanResponder implementation (limited gestures/scroll). The modern
95
+ * replacement is `Dialog.Sheet` (on RN Modal, no provider). Kept for backwards compatibility.
96
+ */
93
97
  function Root({ visible, onClose, size = "auto", dismissible = true, children }) {
94
98
  const insets = useSafeAreaInsets();
95
99
  const screenHeight = Dimensions.get("window").height;
@@ -16,6 +16,6 @@ type ConfirmationContextValue = {
16
16
  };
17
17
  export declare function ConfirmationProvider({ children }: {
18
18
  children: ReactNode;
19
- }): import("react/jsx-runtime").JSX.Element;
19
+ }): import("react").JSX.Element;
20
20
  export declare function useConfirmationContext(): ConfirmationContextValue;
21
21
  export {};
@@ -0,0 +1,17 @@
1
+ export interface ActionSheetAction {
2
+ label: string;
3
+ icon?: string;
4
+ destructive?: boolean;
5
+ disabled?: boolean;
6
+ onPress: () => void;
7
+ }
8
+ export interface ActionSheetProps {
9
+ visible: boolean;
10
+ onClose: () => void;
11
+ actions: ActionSheetAction[];
12
+ title?: string;
13
+ message?: string;
14
+ cancelLabel?: string;
15
+ }
16
+ declare function ActionSheet({ visible, onClose, actions, title, message, cancelLabel, }: ActionSheetProps): import("react").JSX.Element;
17
+ export default ActionSheet;
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
2
+ import Icon from "../Display/Display.Icon";
3
+ import Pressable from "../primitives/Pressable";
4
+ import { theme } from "../theme";
5
+ import { cn } from "../theme/tw";
6
+ import { Typography } from "../Typography";
7
+ import { Modal, Pressable as RNPressable, View } from "react-native";
8
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
9
+ function ActionSheet({ visible, onClose, actions, title, message, cancelLabel = "Cancelar", }) {
10
+ const insets = useSafeAreaInsets();
11
+ return (_jsx(Modal, { animationType: "slide", onRequestClose: onClose, transparent: true, visible: visible, children: _jsx(RNPressable, { className: "flex-1 justify-end bg-black/50", onPress: onClose, children: _jsxs(RNPressable, { style: { paddingHorizontal: 12, paddingBottom: insets.bottom + 12 }, children: [title || message ? (_jsxs(View, { className: "rounded-xl mb-2 px-4 py-3 items-center", style: { backgroundColor: theme.bg.card }, children: [title ? (_jsx(Typography.Text, { className: "text-text-primary", semibold: true, children: title })) : null, message ? (_jsx(Typography.Text, { className: "text-text-secondary text-sm", variant: "bodySmall", children: message })) : null] })) : null, _jsx(View, { className: "rounded-xl overflow-hidden mb-2", style: { backgroundColor: theme.bg.card }, children: actions.map((action, index) => (_jsxs(Pressable, { accessibilityRole: "button", accessibilityState: { disabled: action.disabled }, className: cn("flex-row items-center justify-center gap-2 px-4 py-4", index < actions.length - 1 && "border-b border-border-light"), disabled: action.disabled, onPress: () => {
12
+ onClose();
13
+ action.onPress();
14
+ }, children: [action.icon ? (_jsx(Icon, { color: action.destructive ? theme.danger : theme.icon.primary, name: action.icon, size: 20 })) : null, _jsx(Typography.Text, { className: cn(action.destructive ? "text-danger" : "text-text-primary"), semibold: true, children: action.label })] }, action.label))) }), _jsx(Pressable, { accessibilityRole: "button", className: "rounded-xl px-4 py-4 items-center", onPress: onClose, style: { backgroundColor: theme.bg.card }, children: _jsx(Typography.Text, { className: "text-primary", semibold: true, children: cancelLabel }) })] }) }) }));
15
+ }
16
+ export default ActionSheet;
@@ -21,5 +21,5 @@ export interface EditableValueModalProps {
21
21
  autoFocus?: boolean;
22
22
  testID?: string;
23
23
  }
24
- declare function EditableValueModal({ visible, title, value, onChangeValue, onConfirm, onCancel, placeholder, helperText, chips, keyboardType, rightAdornment, confirmLabel, cancelLabel, autoFocus, testID, }: EditableValueModalProps): import("react/jsx-runtime").JSX.Element;
24
+ declare function EditableValueModal({ visible, title, value, onChangeValue, onConfirm, onCancel, placeholder, helperText, chips, keyboardType, rightAdornment, confirmLabel, cancelLabel, autoFocus, testID, }: EditableValueModalProps): React.JSX.Element;
25
25
  export default EditableValueModal;
@@ -0,0 +1,26 @@
1
+ import { type ReactNode } from "react";
2
+ /**
3
+ * @deprecated A provider is no longer required. `SheetProvider` is a no-op passthrough
4
+ * kept to avoid breaking prior wiring. Remove it when you can.
5
+ */
6
+ export declare function SheetProvider({ children }: {
7
+ children: ReactNode;
8
+ }): import("react").JSX.Element;
9
+ export interface SheetProps {
10
+ visible: boolean;
11
+ onClose: () => void;
12
+ children: ReactNode;
13
+ title?: string;
14
+ /** Max sheet height (fraction of the screen). Default 0.9. */
15
+ maxHeightRatio?: number;
16
+ /** Allow closing by tapping the dim backdrop. Default `false` (handle/button only). */
17
+ dismissOnBackdrop?: boolean;
18
+ testID?: string;
19
+ }
20
+ /**
21
+ * Bottom sheet on RN's native `Modal`: bottom-anchored, dim backdrop, handle with
22
+ * **swipe-down to close** (handle only). By default it does NOT close on backdrop tap
23
+ * (`dismissOnBackdrop`). No provider or native deps. Import via subpath `Dialog/Sheet`.
24
+ */
25
+ declare function Sheet({ visible, onClose, children, title, maxHeightRatio, dismissOnBackdrop, testID, }: SheetProps): import("react").JSX.Element;
26
+ export default Sheet;
@@ -0,0 +1,55 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
2
+ import { theme } from "../theme";
3
+ import { Typography } from "../Typography";
4
+ import { useEffect, useRef } from "react";
5
+ import { Animated, Modal, PanResponder, ScrollView, View } from "react-native";
6
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
7
+ /**
8
+ * @deprecated A provider is no longer required. `SheetProvider` is a no-op passthrough
9
+ * kept to avoid breaking prior wiring. Remove it when you can.
10
+ */
11
+ export function SheetProvider({ children }) {
12
+ return _jsx(_Fragment, { children: children });
13
+ }
14
+ /**
15
+ * Bottom sheet on RN's native `Modal`: bottom-anchored, dim backdrop, handle with
16
+ * **swipe-down to close** (handle only). By default it does NOT close on backdrop tap
17
+ * (`dismissOnBackdrop`). No provider or native deps. Import via subpath `Dialog/Sheet`.
18
+ */
19
+ function Sheet({ visible, onClose, children, title, maxHeightRatio = 0.9, dismissOnBackdrop = false, testID, }) {
20
+ const insets = useSafeAreaInsets();
21
+ const translateY = useRef(new Animated.Value(0)).current;
22
+ const onCloseRef = useRef(onClose);
23
+ onCloseRef.current = onClose;
24
+ useEffect(() => {
25
+ if (visible)
26
+ translateY.setValue(0);
27
+ }, [visible, translateY]);
28
+ const pan = useRef(PanResponder.create({
29
+ onStartShouldSetPanResponder: () => true,
30
+ onMoveShouldSetPanResponder: (_, g) => g.dy > 2,
31
+ onPanResponderMove: (_, g) => {
32
+ if (g.dy > 0)
33
+ translateY.setValue(g.dy);
34
+ },
35
+ onPanResponderRelease: (_, g) => {
36
+ if (g.dy > 100 || g.vy > 0.5) {
37
+ Animated.timing(translateY, {
38
+ toValue: 800,
39
+ duration: 200,
40
+ useNativeDriver: true,
41
+ }).start(() => onCloseRef.current());
42
+ }
43
+ else {
44
+ Animated.spring(translateY, { toValue: 0, useNativeDriver: true }).start();
45
+ }
46
+ },
47
+ })).current;
48
+ return (_jsx(Modal, { animationType: "slide", onRequestClose: onClose, transparent: true, visible: visible, children: _jsxs(View, { className: "flex-1 justify-end", testID: testID, children: [_jsx(View, { className: "absolute inset-0 bg-black/50", onResponderRelease: dismissOnBackdrop ? onClose : undefined, onStartShouldSetResponder: () => dismissOnBackdrop }), _jsxs(Animated.View, { className: "rounded-t-3xl", style: {
49
+ backgroundColor: theme.bg.card,
50
+ paddingBottom: insets.bottom + 12,
51
+ maxHeight: `${Math.round(maxHeightRatio * 100)}%`,
52
+ transform: [{ translateY }],
53
+ }, children: [_jsx(View, { className: "items-center pt-3 pb-2", ...pan.panHandlers, children: _jsx(View, { className: "w-12 h-1.5 rounded-full bg-border-strong" }) }), title ? (_jsx(Typography.Text, { className: "text-text-primary px-4 pb-1", semibold: true, variant: "subtitle", children: title })) : null, _jsx(ScrollView, { contentContainerStyle: { paddingHorizontal: 16, paddingTop: 4 }, children: children })] })] }) }));
54
+ }
55
+ export default Sheet;
@@ -1,19 +1,21 @@
1
1
  import { BottomSheet } from "../Dialog/BottomSheet";
2
2
  import { ConfirmationProvider, useConfirmationContext } from "../Dialog/Confirmation.context";
3
+ import ActionSheet from "../Dialog/Dialog.ActionSheet";
3
4
  import EditValue, { type EditableValueModalChip, type EditableValueModalProps } from "../Dialog/Dialog.EditValue";
4
5
  export declare const Dialog: {
5
6
  Confirmation: import("react").FC<import("../Dialog/Dialog.Confirmation").Props>;
6
7
  BottomSheet: {
7
- Root: ({ visible, onClose, size, dismissible, children }: import("./BottomSheet/BottomSheet.Root").RootProps) => import("react/jsx-runtime").JSX.Element;
8
- Handle: ({ children }: import("./BottomSheet/BottomSheet.Root").HandleProps) => import("react/jsx-runtime").JSX.Element;
9
- Header: ({ children }: import("./BottomSheet/BottomSheet.Root").HeaderProps) => import("react/jsx-runtime").JSX.Element;
10
- Title: ({ children, subtitle }: import("./BottomSheet/BottomSheet.Root").TitleProps) => import("react/jsx-runtime").JSX.Element;
11
- Content: ({ children, scrollable }: import("./BottomSheet/BottomSheet.Root").ContentProps) => import("react/jsx-runtime").JSX.Element;
12
- Actions: ({ children, layout }: import("./BottomSheet/BottomSheet.Root").ActionsProps) => import("react/jsx-runtime").JSX.Element;
13
- Footer: ({ children }: import("./BottomSheet/BottomSheet.Root").FooterProps) => import("react/jsx-runtime").JSX.Element;
8
+ Root: ({ visible, onClose, size, dismissible, children }: import("./BottomSheet/BottomSheet.Root").RootProps) => import("react").JSX.Element;
9
+ Handle: ({ children }: import("./BottomSheet/BottomSheet.Root").HandleProps) => import("react").JSX.Element;
10
+ Header: ({ children }: import("./BottomSheet/BottomSheet.Root").HeaderProps) => import("react").JSX.Element;
11
+ Title: ({ children, subtitle }: import("./BottomSheet/BottomSheet.Root").TitleProps) => import("react").JSX.Element;
12
+ Content: ({ children, scrollable }: import("./BottomSheet/BottomSheet.Root").ContentProps) => import("react").JSX.Element;
13
+ Actions: ({ children, layout }: import("./BottomSheet/BottomSheet.Root").ActionsProps) => import("react").JSX.Element;
14
+ Footer: ({ children }: import("./BottomSheet/BottomSheet.Root").FooterProps) => import("react").JSX.Element;
14
15
  useBottomSheet: () => import("./BottomSheet/BottomSheet.Root").BottomSheetContextValue;
15
16
  };
16
17
  EditValue: typeof EditValue;
18
+ ActionSheet: typeof ActionSheet;
17
19
  };
18
20
  export { BottomSheet, ConfirmationProvider, type EditableValueModalChip, type EditableValueModalProps, useConfirmationContext, };
19
21
  export default Dialog;
@@ -1,11 +1,13 @@
1
1
  import { BottomSheet } from "../Dialog/BottomSheet";
2
2
  import { ConfirmationProvider, useConfirmationContext, } from "../Dialog/Confirmation.context";
3
+ import ActionSheet from "../Dialog/Dialog.ActionSheet";
3
4
  import Confirmation from "../Dialog/Dialog.Confirmation";
4
5
  import EditValue from "../Dialog/Dialog.EditValue";
5
6
  export const Dialog = {
6
7
  Confirmation,
7
8
  BottomSheet,
8
9
  EditValue,
10
+ ActionSheet,
9
11
  };
10
12
  export { BottomSheet, ConfirmationProvider, useConfirmationContext, };
11
13
  export default Dialog;
@@ -0,0 +1,18 @@
1
+ import { type ReactNode } from "react";
2
+ export interface AccordionItemProps {
3
+ title: string;
4
+ children: ReactNode;
5
+ defaultOpen?: boolean;
6
+ className?: string;
7
+ testID?: string;
8
+ }
9
+ declare function AccordionItem({ title, children, defaultOpen, className, testID, }: AccordionItemProps): import("react").JSX.Element;
10
+ declare function AccordionRoot({ children, className }: {
11
+ children: ReactNode;
12
+ className?: string;
13
+ }): import("react").JSX.Element;
14
+ declare const Accordion: typeof AccordionRoot & {
15
+ Item: typeof AccordionItem;
16
+ };
17
+ export default Accordion;
18
+ export { Accordion };
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
2
+ import Icon from "../Display/Display.Icon";
3
+ import Pressable from "../primitives/Pressable";
4
+ import { theme } from "../theme";
5
+ import { cn } from "../theme/tw";
6
+ import { Typography } from "../Typography";
7
+ import { useState } from "react";
8
+ import { LayoutAnimation, View } from "react-native";
9
+ function AccordionItem({ title, children, defaultOpen = false, className, testID, }) {
10
+ const [open, setOpen] = useState(defaultOpen);
11
+ const toggle = () => {
12
+ LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
13
+ setOpen((prev) => !prev);
14
+ };
15
+ return (_jsxs(View, { className: cn("border-b border-border-default", className), testID: testID, children: [_jsxs(Pressable, { accessibilityRole: "button", accessibilityState: { expanded: open }, className: "flex-row items-center justify-between py-3", onPress: toggle, children: [_jsx(Typography.Text, { className: "flex-1 text-text-primary", semibold: true, children: title }), _jsx(View, { style: { transform: [{ rotate: open ? "180deg" : "0deg" }] }, children: _jsx(Icon, { color: theme.icon.secondary, name: "chevron-down", size: 18 }) })] }), open ? _jsx(View, { className: "pb-3", children: children }) : null] }));
16
+ }
17
+ function AccordionRoot({ children, className }) {
18
+ return _jsx(View, { className: cn("bg-bg-card rounded-lg", className), children: children });
19
+ }
20
+ const Accordion = Object.assign(AccordionRoot, { Item: AccordionItem });
21
+ export default Accordion;
22
+ export { Accordion };
@@ -0,0 +1,12 @@
1
+ export interface AvatarGroupItem {
2
+ initials: string;
3
+ }
4
+ export interface AvatarGroupProps {
5
+ items: AvatarGroupItem[];
6
+ max?: number;
7
+ size?: number;
8
+ className?: string;
9
+ testID?: string;
10
+ }
11
+ declare function AvatarGroup({ items, max, size, className, testID }: AvatarGroupProps): import("react").JSX.Element;
12
+ export default AvatarGroup;
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
2
+ import Avatar from "../Display/Display.Avatar";
3
+ import { theme } from "../theme";
4
+ import { Typography } from "../Typography";
5
+ import { View } from "react-native";
6
+ function AvatarGroup({ items, max = 4, size = 36, className, testID }) {
7
+ const visible = items.slice(0, max);
8
+ const overflow = items.length - visible.length;
9
+ const overlap = Math.round(size / 3);
10
+ return (_jsxs(View, { className: className, style: { flexDirection: "row" }, testID: testID, children: [visible.map((item, index) => (_jsx(View, { style: {
11
+ marginLeft: index === 0 ? 0 : -overlap,
12
+ borderRadius: size,
13
+ borderWidth: 2,
14
+ borderColor: theme.bg.card,
15
+ }, children: _jsx(Avatar, { initials: item.initials, size: size }) }, `${item.initials}-${index}`))), overflow > 0 ? (_jsx(View, { className: "items-center justify-center rounded-full bg-bg-muted", style: {
16
+ width: size,
17
+ height: size,
18
+ marginLeft: -overlap,
19
+ borderWidth: 2,
20
+ borderColor: theme.bg.card,
21
+ }, children: _jsxs(Typography.Text, { className: "text-text-secondary font-semibold text-xs", children: ["+", overflow] }) })) : null] }));
22
+ }
23
+ export default AvatarGroup;
@@ -104,5 +104,5 @@ export type BadgeProps = {
104
104
  variant: BadgeVariants | BadgeVariant | string;
105
105
  className?: string;
106
106
  };
107
- declare function Badge({ label, variant, className }: BadgeProps): import("react/jsx-runtime").JSX.Element;
107
+ declare function Badge({ label, variant, className }: BadgeProps): import("react").JSX.Element;
108
108
  export default Badge;
@@ -0,0 +1,46 @@
1
+ import { type VariantProps } from "../theme/tw";
2
+ import type { ReactNode } from "react";
3
+ declare const card: import("tailwind-variants").TVReturnType<{
4
+ padding: {
5
+ none: string;
6
+ sm: string;
7
+ md: string;
8
+ lg: string;
9
+ };
10
+ }, undefined, "bg-bg-card rounded-lg border border-border-light", {
11
+ padding: {
12
+ none: string;
13
+ sm: string;
14
+ md: string;
15
+ lg: string;
16
+ };
17
+ }, undefined, import("tailwind-variants").TVReturnType<{
18
+ padding: {
19
+ none: string;
20
+ sm: string;
21
+ md: string;
22
+ lg: string;
23
+ };
24
+ }, undefined, "bg-bg-card rounded-lg border border-border-light", unknown, unknown, undefined>>;
25
+ export interface CardProps extends VariantProps<typeof card> {
26
+ elevation?: "none" | "sm" | "md" | "lg";
27
+ onPress?: () => void;
28
+ className?: string;
29
+ children?: ReactNode;
30
+ testID?: string;
31
+ }
32
+ declare function Card({ padding, elevation, onPress, className, children, testID, }: CardProps): import("react").JSX.Element;
33
+ declare function CardTitle({ children, className }: {
34
+ children: ReactNode;
35
+ className?: string;
36
+ }): import("react").JSX.Element;
37
+ declare function CardFooter({ children, className }: {
38
+ children: ReactNode;
39
+ className?: string;
40
+ }): import("react").JSX.Element;
41
+ declare const CardWithSlots: typeof Card & {
42
+ Title: typeof CardTitle;
43
+ Footer: typeof CardFooter;
44
+ };
45
+ export default CardWithSlots;
46
+ export { CardWithSlots as Card };
@@ -0,0 +1,36 @@
1
+ import { jsx as _jsx } from "nativewind/jsx-runtime";
2
+ import Pressable from "../primitives/Pressable";
3
+ import { theme } from "../theme";
4
+ import { cn, tv } from "../theme/tw";
5
+ import { Typography } from "../Typography";
6
+ import { View } from "react-native";
7
+ const card = tv({
8
+ base: "bg-bg-card rounded-lg border border-border-light",
9
+ variants: {
10
+ padding: {
11
+ none: "p-0",
12
+ sm: "p-3",
13
+ md: "p-4",
14
+ lg: "p-6",
15
+ },
16
+ },
17
+ defaultVariants: {
18
+ padding: "md",
19
+ },
20
+ });
21
+ function Card({ padding = "md", elevation = "sm", onPress, className, children, testID, }) {
22
+ const shadow = elevation === "none" ? undefined : theme.shadow[elevation];
23
+ if (onPress) {
24
+ return (_jsx(Pressable, { className: card({ padding, className }), onPress: onPress, style: shadow, testID: testID, children: children }));
25
+ }
26
+ return (_jsx(View, { className: card({ padding, className }), style: shadow, testID: testID, children: children }));
27
+ }
28
+ function CardTitle({ children, className }) {
29
+ return (_jsx(Typography.Text, { className: cn("text-text-primary mb-1", className), semibold: true, variant: "h4", children: children }));
30
+ }
31
+ function CardFooter({ children, className }) {
32
+ return (_jsx(View, { className: cn("flex-row items-center justify-end gap-2 mt-3", className), children: children }));
33
+ }
34
+ const CardWithSlots = Object.assign(Card, { Title: CardTitle, Footer: CardFooter });
35
+ export default CardWithSlots;
36
+ export { CardWithSlots as Card };
@@ -0,0 +1,13 @@
1
+ import { type ReactNode } from "react";
2
+ export interface CarouselProps<T> {
3
+ data: T[];
4
+ renderItem: (item: T, index: number) => ReactNode;
5
+ keyExtractor: (item: T, index: number) => string;
6
+ itemWidth: number;
7
+ gap?: number;
8
+ showDots?: boolean;
9
+ className?: string;
10
+ testID?: string;
11
+ }
12
+ declare function Carousel<T>({ data, renderItem, keyExtractor, itemWidth, gap, showDots, className, testID, }: CarouselProps<T>): import("react").JSX.Element;
13
+ export default Carousel;
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
2
+ import { theme } from "../theme";
3
+ import { cn } from "../theme/tw";
4
+ import { useState } from "react";
5
+ import { ScrollView, View, } from "react-native";
6
+ function Carousel({ data, renderItem, keyExtractor, itemWidth, gap = 12, showDots = true, className, testID, }) {
7
+ const [active, setActive] = useState(0);
8
+ const snap = itemWidth + gap;
9
+ const onScroll = (e) => {
10
+ const index = Math.round(e.nativeEvent.contentOffset.x / snap);
11
+ if (index !== active)
12
+ setActive(index);
13
+ };
14
+ return (_jsxs(View, { className: className, testID: testID, children: [_jsx(ScrollView, { decelerationRate: "fast", horizontal: true, onMomentumScrollEnd: onScroll, showsHorizontalScrollIndicator: false, snapToInterval: snap, children: data.map((item, index) => (_jsx(View, { style: { width: itemWidth, marginRight: index < data.length - 1 ? gap : 0 }, children: renderItem(item, index) }, keyExtractor(item, index)))) }), showDots && data.length > 1 ? (_jsx(View, { className: "flex-row justify-center gap-1.5 mt-3", children: data.map((item, index) => (_jsx(View, { className: cn("h-1.5 rounded-full"), style: {
15
+ width: index === active ? 16 : 6,
16
+ backgroundColor: index === active ? theme.primary : theme.border.strong,
17
+ } }, keyExtractor(item, index)))) })) : null] }));
18
+ }
19
+ export default Carousel;