@sincpro/mobile-ui 0.2.1 → 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.
- package/README.md +75 -20
- package/dist/Dialog/BottomSheet/BottomSheet.Root.d.ts +11 -7
- package/dist/Dialog/BottomSheet/BottomSheet.Root.js +4 -0
- package/dist/Dialog/Confirmation.context.d.ts +1 -1
- package/dist/Dialog/Dialog.ActionSheet.d.ts +17 -0
- package/dist/Dialog/Dialog.ActionSheet.js +16 -0
- package/dist/Dialog/Dialog.EditValue.d.ts +1 -1
- package/dist/Dialog/Dialog.Sheet.d.ts +26 -0
- package/dist/Dialog/Dialog.Sheet.js +55 -0
- package/dist/Dialog/index.d.ts +9 -7
- package/dist/Dialog/index.js +2 -0
- package/dist/Display/Display.Accordion.d.ts +18 -0
- package/dist/Display/Display.Accordion.js +22 -0
- package/dist/Display/Display.AvatarGroup.d.ts +12 -0
- package/dist/Display/Display.AvatarGroup.js +23 -0
- package/dist/Display/Display.Badge.d.ts +1 -1
- package/dist/Display/Display.Card.d.ts +46 -0
- package/dist/Display/Display.Card.js +36 -0
- package/dist/Display/Display.Carousel.d.ts +13 -0
- package/dist/Display/Display.Carousel.js +19 -0
- package/dist/Display/Display.Chip.d.ts +105 -0
- package/dist/Display/Display.Chip.js +45 -0
- package/dist/Display/Display.CopyableText.d.ts +1 -1
- package/dist/Display/Display.CountRecords.d.ts +1 -1
- package/dist/Display/Display.DataTable.d.ts +19 -0
- package/dist/Display/Display.DataTable.js +22 -0
- package/dist/Display/Display.Date.d.ts +15 -2
- package/dist/Display/Display.Date.js +34 -4
- package/dist/Display/Display.Divider.d.ts +1 -1
- package/dist/Display/Display.IconBadge.d.ts +13 -0
- package/dist/Display/Display.IconBadge.js +30 -0
- package/dist/Display/Display.Image.d.ts +15 -0
- package/dist/Display/Display.Image.js +17 -0
- package/dist/Display/Display.KeyValue.d.ts +10 -0
- package/dist/Display/Display.KeyValue.js +9 -0
- package/dist/Display/Display.ListItem.d.ts +13 -0
- package/dist/Display/Display.ListItem.js +14 -0
- package/dist/Display/Display.Logo.js +3 -1
- package/dist/Display/Display.MediaCard.d.ts +17 -0
- package/dist/Display/Display.MediaCard.js +12 -0
- package/dist/Display/Display.MediaEmbed.d.ts +19 -0
- package/dist/Display/Display.MediaEmbed.js +39 -0
- package/dist/Display/Display.MenuButton.d.ts +1 -1
- package/dist/Display/Display.Monetary.d.ts +1 -1
- package/dist/Display/Display.PriceTag.d.ts +10 -0
- package/dist/Display/Display.PriceTag.js +23 -0
- package/dist/Display/Display.ProductCard.d.ts +17 -0
- package/dist/Display/Display.ProductCard.js +13 -0
- package/dist/Display/Display.Rating.d.ts +11 -0
- package/dist/Display/Display.Rating.js +16 -0
- package/dist/Display/Display.SearchHistory.d.ts +12 -0
- package/dist/Display/Display.SearchHistory.js +13 -0
- package/dist/Display/Display.SectionHeader.d.ts +13 -0
- package/dist/Display/Display.SectionHeader.js +9 -0
- package/dist/Display/Display.Stat.d.ts +10 -0
- package/dist/Display/Display.Stat.js +9 -0
- package/dist/Display/Display.StatCard.d.ts +14 -0
- package/dist/Display/Display.StatCard.js +13 -0
- package/dist/Display/Display.StatusDot.d.ts +11 -0
- package/dist/Display/Display.StatusDot.js +28 -0
- package/dist/Display/Display.Story.d.ts +15 -0
- package/dist/Display/Display.Story.js +43 -0
- package/dist/Display/Display.StoryTray.d.ts +26 -0
- package/dist/Display/Display.StoryTray.js +43 -0
- package/dist/Display/Display.StoryViewer.d.ts +26 -0
- package/dist/Display/Display.StoryViewer.js +79 -0
- package/dist/Display/Display.SwipeableRow.d.ts +15 -0
- package/dist/Display/Display.SwipeableRow.js +28 -0
- package/dist/Display/Display.Tag.d.ts +11 -0
- package/dist/Display/Display.Tag.js +9 -0
- package/dist/Display/Display.Timeline.d.ts +13 -0
- package/dist/Display/Display.Timeline.js +19 -0
- package/dist/Display/Display.Tooltip.d.ts +10 -0
- package/dist/Display/Display.Tooltip.js +24 -0
- package/dist/Display/index.d.ts +66 -0
- package/dist/Display/index.js +54 -0
- package/dist/Feedback/ErrorBoundary.d.ts +1 -1
- package/dist/Feedback/Feedback.Banner.d.ts +82 -0
- package/dist/Feedback/Feedback.Banner.js +35 -0
- package/dist/Feedback/Feedback.DomainSplashScreen.d.ts +2 -1
- package/dist/Feedback/Feedback.DomainSplashScreen.js +1 -1
- package/dist/Feedback/Feedback.Empty.d.ts +1 -1
- package/dist/Feedback/Feedback.EmptyState.d.ts +15 -0
- package/dist/Feedback/Feedback.EmptyState.js +11 -0
- package/dist/Feedback/Feedback.Error.d.ts +1 -1
- package/dist/Feedback/Feedback.Loading.d.ts +2 -1
- package/dist/Feedback/Feedback.PermissionCard.d.ts +15 -0
- package/dist/Feedback/Feedback.PermissionCard.js +11 -0
- package/dist/Feedback/Feedback.Progress.d.ts +9 -0
- package/dist/Feedback/Feedback.Progress.js +35 -0
- package/dist/Feedback/Feedback.ProgressCircle.d.ts +12 -0
- package/dist/Feedback/Feedback.ProgressCircle.js +15 -0
- package/dist/Feedback/Feedback.Skeleton.d.ts +11 -0
- package/dist/Feedback/Feedback.Skeleton.js +29 -0
- package/dist/Feedback/Feedback.Splash.d.ts +1 -1
- package/dist/Feedback/Toast.context.d.ts +35 -0
- package/dist/Feedback/Toast.context.js +119 -0
- package/dist/Feedback/index.d.ts +15 -0
- package/dist/Feedback/index.js +15 -0
- package/dist/Form/Form.Button.d.ts +6 -0
- package/dist/Form/Form.Button.js +12 -1
- package/dist/Form/Form.Checkbox.d.ts +1 -1
- package/dist/Form/Form.ControlledCheckbox.d.ts +1 -1
- package/dist/Form/Form.ControlledInput.d.ts +1 -1
- package/dist/Form/Form.ControlledMonetaryInput.d.ts +1 -1
- package/dist/Form/Form.ControlledRadioButton.d.ts +1 -1
- package/dist/Form/Form.DatePicker.d.ts +20 -0
- package/dist/Form/Form.DatePicker.js +38 -0
- package/dist/Form/Form.Dropdown.d.ts +1 -1
- package/dist/Form/Form.FAB.d.ts +10 -0
- package/dist/Form/Form.FAB.js +17 -0
- package/dist/Form/Form.FilterButton.d.ts +1 -1
- package/dist/Form/Form.FractionalQuantityInput.d.ts +1 -1
- package/dist/Form/Form.IconButton.d.ts +1 -1
- package/dist/Form/Form.Input.d.ts +2 -1
- package/dist/Form/Form.MonetaryInput.d.ts +1 -1
- package/dist/Form/Form.PinInput.d.ts +12 -0
- package/dist/Form/Form.PinInput.js +23 -0
- package/dist/Form/Form.QuantitySelector.d.ts +2 -1
- package/dist/Form/Form.QuantitySelector.js +1 -1
- package/dist/Form/Form.RadioButton.d.ts +1 -1
- package/dist/Form/Form.SearchBar.d.ts +6 -1
- package/dist/Form/Form.SearchBar.js +4 -0
- package/dist/Form/Form.Select.d.ts +17 -0
- package/dist/Form/Form.Select.js +26 -0
- package/dist/Form/Form.Slider.d.ts +20 -0
- package/dist/Form/Form.Slider.js +16 -0
- package/dist/Form/Form.Switch.d.ts +10 -0
- package/dist/Form/Form.Switch.js +9 -0
- package/dist/Form/index.d.ts +12 -0
- package/dist/Form/index.js +12 -0
- package/dist/Navigation/Navigation.AppBar.d.ts +41 -0
- package/dist/Navigation/Navigation.AppBar.js +33 -0
- package/dist/Navigation/Navigation.BottomNav.d.ts +29 -0
- package/dist/Navigation/Navigation.BottomNav.js +35 -0
- package/dist/Navigation/Navigation.CollapsingHeader.d.ts +34 -0
- package/dist/Navigation/Navigation.CollapsingHeader.js +47 -0
- package/dist/Navigation/Navigation.FloatingBar.d.ts +15 -0
- package/dist/Navigation/Navigation.FloatingBar.js +21 -0
- package/dist/Navigation/Navigation.Header.d.ts +6 -2
- package/dist/Navigation/Navigation.Header.js +4 -0
- package/dist/Navigation/Navigation.HeaderToolbar.d.ts +1 -1
- package/dist/Navigation/Navigation.Menu.d.ts +21 -0
- package/dist/Navigation/Navigation.Menu.js +42 -0
- package/dist/Navigation/Navigation.RowItem.d.ts +1 -1
- package/dist/Navigation/Navigation.SearchBar.d.ts +18 -0
- package/dist/Navigation/Navigation.SearchBar.js +22 -0
- package/dist/Navigation/Navigation.SegmentedControl.d.ts +14 -0
- package/dist/Navigation/Navigation.SegmentedControl.js +13 -0
- package/dist/Navigation/Navigation.Steps.d.ts +8 -0
- package/dist/Navigation/Navigation.Steps.js +17 -0
- package/dist/Navigation/Navigation.TabIcon.d.ts +1 -1
- package/dist/Navigation/Navigation.Tabs.d.ts +28 -0
- package/dist/Navigation/Navigation.Tabs.js +45 -0
- package/dist/Navigation/index.d.ts +32 -1
- package/dist/Navigation/index.js +18 -0
- package/dist/Typography/Typography.Text.d.ts +2 -1
- package/dist/branding.d.ts +6 -0
- package/dist/branding.js +7 -0
- package/dist/icons/ArrowDownIcon.d.ts +2 -1
- package/dist/icons/ArrowUpIcon.d.ts +2 -1
- package/dist/icons/CreditIcon.d.ts +1 -1
- package/dist/icons/OdooIcon.d.ts +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/layouts/AuthContainer.d.ts +1 -1
- package/dist/layouts/Container.d.ts +1 -0
- package/dist/layouts/Container.js +2 -3
- package/dist/layouts/GradientContainer.d.ts +1 -1
- package/dist/layouts/PlainLayout.d.ts +1 -1
- package/dist/layouts/ScrollContainer.d.ts +2 -2
- package/dist/layouts/ScrollContainer.js +1 -1
- package/dist/layouts/TabNavigatorLayout.d.ts +2 -2
- package/dist/layouts/TabNavigatorLayout.js +4 -0
- package/dist/primitives/AspectRatio.d.ts +10 -0
- package/dist/primitives/AspectRatio.js +8 -0
- package/dist/primitives/Box.d.ts +1 -1
- package/dist/primitives/Pressable.d.ts +10 -0
- package/dist/primitives/Pressable.js +9 -0
- package/dist/primitives/Row.d.ts +1 -1
- package/dist/primitives/Spacer.d.ts +8 -0
- package/dist/primitives/Spacer.js +9 -0
- package/dist/primitives/Stack.d.ts +1 -1
- package/dist/primitives/index.d.ts +3 -0
- package/dist/primitives/index.js +3 -0
- package/dist/theme/active.d.ts +2 -0
- package/dist/theme/active.js +13 -0
- package/dist/theme/components/ThemedActivityIndicator.d.ts +1 -1
- package/dist/theme/components/index.d.ts +1 -1
- package/dist/theme/components/index.js +1 -1
- package/dist/theme/dark.d.ts +7 -0
- package/dist/theme/dark.js +84 -0
- package/dist/theme/define.d.ts +5 -5
- package/dist/theme/define.js +5 -5
- package/dist/theme/index.d.ts +3 -1
- package/dist/theme/index.js +3 -1
- package/dist/theme/theme.d.ts +1 -1
- package/dist/theme/theme.js +1 -1
- package/dist/theme/types.d.ts +14 -14
- package/dist/theme/types.js +2 -2
- package/dist/theme/useTheme.d.ts +3 -1
- package/dist/theme/useTheme.js +6 -1
- package/dist/tokens/index.d.ts +2 -0
- package/dist/tokens/index.js +2 -0
- package/dist/tokens/motion.d.ts +71 -0
- package/dist/tokens/motion.js +25 -0
- package/dist/utils/date.d.ts +33 -33
- package/dist/utils/date.js +39 -39
- package/dist/views/AuthFormView.d.ts +1 -1
- package/dist/views/FormViewV2.context.d.ts +1 -1
- package/dist/views/FormViewV2.d.ts +10 -10
- package/dist/views/ListViewV2.context.d.ts +1 -1
- package/dist/views/ListViewV2.d.ts +20 -20
- package/dist/views/Wizard/Wizard.context.d.ts +1 -1
- package/dist/widgets/CircleButton.d.ts +6 -2
- package/dist/widgets/CircleButton.js +4 -0
- package/dist/widgets/GeoPermissionCard.d.ts +1 -1
- package/dist/widgets/HomeHeader.d.ts +4 -0
- package/dist/widgets/HomeHeader.js +4 -0
- package/dist/widgets/JSONViewer.d.ts +2 -1
- package/dist/widgets/JSONViewer.js +6 -6
- package/dist/widgets/MenuCard.d.ts +1 -1
- package/dist/widgets/ScreenHeader.d.ts +5 -1
- package/dist/widgets/ScreenHeader.js +4 -0
- package/dist/widgets/TimeZoneSelector.d.ts +1 -1
- package/dist/widgets/TimeZoneSelectorModal.d.ts +1 -1
- package/package.json +38 -25
- package/tailwind.preset.js +14 -0
- package/dist/notifications/index.d.ts +0 -1
- package/dist/notifications/index.js +0 -1
- package/dist/providers/index.d.ts +0 -1
- package/dist/providers/index.js +0 -2
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# @sincpro/mobile-ui
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Sincpro Mobile design system — generic, presentational React Native components (Expo SDK 56).
|
|
4
4
|
|
|
5
|
-
|
|
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.
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
- **Standalone** — does not depend on `@sincpro/mobile` (the core). The core depends on this package.
|
|
9
|
-
- Built with NativeWind + tailwind-variants.
|
|
9
|
+
> 🤖 **AI agents:** read [`AGENTS.md`](AGENTS.md) (ecosystem & patterns) and [`docs/GOTCHAS.md`](docs/GOTCHAS.md) (known traps) first.
|
|
10
10
|
|
|
11
11
|
## Install
|
|
12
12
|
|
|
@@ -14,11 +14,18 @@ Sincpro Mobile design system: generic, presentational React Native components.
|
|
|
14
14
|
npx expo install @sincpro/mobile-ui
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
Peer dependencies
|
|
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).
|
|
18
24
|
|
|
19
25
|
## Tailwind preset (required)
|
|
20
26
|
|
|
21
|
-
|
|
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:
|
|
22
29
|
|
|
23
30
|
```js
|
|
24
31
|
// tailwind.config.js
|
|
@@ -29,31 +36,79 @@ module.exports = {
|
|
|
29
36
|
};
|
|
30
37
|
```
|
|
31
38
|
|
|
32
|
-
|
|
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.
|
|
33
41
|
|
|
34
|
-
## Usage
|
|
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:
|
|
35
67
|
|
|
36
68
|
```tsx
|
|
37
|
-
import {
|
|
38
|
-
|
|
39
|
-
import { theme } from "@sincpro/mobile-ui/theme";
|
|
69
|
+
import { setBranding } from "@sincpro/mobile-ui";
|
|
70
|
+
setBranding({ logo: require("../assets/logo.png") }); // Display.Logo uses it when no `source` is passed
|
|
40
71
|
```
|
|
41
72
|
|
|
73
|
+
### Toast (queued feedback)
|
|
74
|
+
|
|
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
|
|
83
|
+
|
|
84
|
+
```tsx
|
|
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.
|
|
88
|
+
```
|
|
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
|
+
|
|
42
98
|
## Storybook (on-device, Expo)
|
|
43
99
|
|
|
44
|
-
|
|
100
|
+
Preview components on simulator/device with Storybook React Native (dev-only, not published):
|
|
45
101
|
|
|
46
102
|
```bash
|
|
47
103
|
make storybook # expo start (Expo Go / dev build)
|
|
48
104
|
make storybook-android # expo run:android
|
|
49
105
|
```
|
|
50
106
|
|
|
51
|
-
|
|
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", …]`).
|
|
52
110
|
|
|
53
|
-
##
|
|
111
|
+
## Build & release
|
|
54
112
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
- `widgets` — generic composed widgets (HomeHeader, MenuGrid, GeoPermissionCard, TimeZoneSelector)
|
|
58
|
-
- `theme` — design tokens + tailwind-variants helpers (`defineTheme`, `extendTheme`, `themeToVars`)
|
|
59
|
-
- `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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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):
|
|
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;
|
package/dist/Dialog/index.d.ts
CHANGED
|
@@ -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
|
|
8
|
-
Handle: ({ children }: import("./BottomSheet/BottomSheet.Root").HandleProps) => import("react
|
|
9
|
-
Header: ({ children }: import("./BottomSheet/BottomSheet.Root").HeaderProps) => import("react
|
|
10
|
-
Title: ({ children, subtitle }: import("./BottomSheet/BottomSheet.Root").TitleProps) => import("react
|
|
11
|
-
Content: ({ children, scrollable }: import("./BottomSheet/BottomSheet.Root").ContentProps) => import("react
|
|
12
|
-
Actions: ({ children, layout }: import("./BottomSheet/BottomSheet.Root").ActionsProps) => import("react
|
|
13
|
-
Footer: ({ children }: import("./BottomSheet/BottomSheet.Root").FooterProps) => import("react
|
|
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;
|
package/dist/Dialog/index.js
CHANGED
|
@@ -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
|
|
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;
|