@retray-dev/ui-kit 7.0.1 → 9.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.
- package/COMPONENTS.md +554 -11
- package/EXAMPLES.md +2 -2
- package/README.md +14 -8
- package/dist/Accordion.js +57 -5
- package/dist/Accordion.mjs +4 -3
- package/dist/AlertBanner.js +4 -1
- package/dist/AlertBanner.mjs +3 -2
- package/dist/AppHeader.d.mts +40 -0
- package/dist/AppHeader.d.ts +40 -0
- package/dist/AppHeader.js +515 -0
- package/dist/AppHeader.mjs +10 -0
- package/dist/Avatar.js +39 -29
- package/dist/Avatar.mjs +2 -1
- package/dist/Badge.js +11 -1
- package/dist/Badge.mjs +2 -1
- package/dist/Button.d.mts +8 -3
- package/dist/Button.d.ts +8 -3
- package/dist/Button.js +126 -108
- package/dist/Button.mjs +6 -5
- package/dist/ButtonGroup.mjs +1 -0
- package/dist/Card.js +90 -70
- package/dist/Card.mjs +5 -4
- package/dist/CategoryStrip.js +79 -22
- package/dist/CategoryStrip.mjs +6 -6
- package/dist/Checkbox.js +118 -86
- package/dist/Checkbox.mjs +5 -5
- package/dist/Chip.js +113 -80
- package/dist/Chip.mjs +5 -5
- package/dist/ConfirmDialog.js +140 -110
- package/dist/ConfirmDialog.mjs +7 -6
- package/dist/CurrencyDisplay.mjs +1 -0
- package/dist/CurrencyInput.d.mts +1 -1
- package/dist/CurrencyInput.d.ts +1 -1
- package/dist/CurrencyInput.js +9 -5
- package/dist/CurrencyInput.mjs +5 -4
- package/dist/DetailRow.mjs +1 -0
- package/dist/EmptyState.js +131 -111
- package/dist/EmptyState.mjs +7 -6
- package/dist/ErrorBoundary.d.mts +42 -0
- package/dist/ErrorBoundary.d.ts +42 -0
- package/dist/ErrorBoundary.js +351 -0
- package/dist/ErrorBoundary.mjs +7 -0
- package/dist/Form.mjs +1 -0
- package/dist/HolographicCard.d.mts +55 -0
- package/dist/HolographicCard.d.ts +55 -0
- package/dist/HolographicCard.js +316 -0
- package/dist/HolographicCard.mjs +191 -0
- package/dist/IconButton.d.mts +8 -3
- package/dist/IconButton.d.ts +8 -3
- package/dist/IconButton.js +115 -98
- package/dist/IconButton.mjs +5 -4
- package/dist/ImageViewer.d.mts +23 -0
- package/dist/ImageViewer.d.ts +23 -0
- package/dist/ImageViewer.js +582 -0
- package/dist/ImageViewer.mjs +8 -0
- package/dist/Input.mjs +4 -3
- package/dist/LabelValue.mjs +1 -0
- package/dist/ListGroup.mjs +1 -0
- package/dist/ListItem.js +131 -117
- package/dist/ListItem.mjs +6 -5
- package/dist/MediaCard.js +54 -6
- package/dist/MediaCard.mjs +6 -5
- package/dist/MenuGroup.mjs +1 -0
- package/dist/MenuItem.js +91 -79
- package/dist/MenuItem.mjs +6 -5
- package/dist/MonthPicker.d.mts +10 -2
- package/dist/MonthPicker.d.ts +10 -2
- package/dist/MonthPicker.js +80 -17
- package/dist/MonthPicker.mjs +3 -2
- package/dist/PagerDots.d.mts +35 -0
- package/dist/PagerDots.d.ts +35 -0
- package/dist/PagerDots.js +392 -0
- package/dist/PagerDots.mjs +7 -0
- package/dist/Pressable.d.mts +5 -5
- package/dist/Pressable.d.ts +5 -5
- package/dist/Pressable.js +97 -86
- package/dist/Pressable.mjs +5 -4
- package/dist/PricingCard.d.mts +50 -0
- package/dist/PricingCard.d.ts +50 -0
- package/dist/PricingCard.js +636 -0
- package/dist/PricingCard.mjs +11 -0
- package/dist/Progress.mjs +3 -2
- package/dist/RadioGroup.js +81 -30
- package/dist/RadioGroup.mjs +5 -5
- package/dist/RetrayProvider.d.mts +2 -0
- package/dist/RetrayProvider.d.ts +2 -0
- package/dist/RetrayProvider.js +214 -0
- package/dist/RetrayProvider.mjs +5 -0
- package/dist/Select.js +51 -4
- package/dist/Select.mjs +5 -4
- package/dist/SelectableGrid.d.mts +44 -0
- package/dist/SelectableGrid.d.ts +44 -0
- package/dist/SelectableGrid.js +448 -0
- package/dist/SelectableGrid.mjs +9 -0
- package/dist/Separator.mjs +1 -0
- package/dist/Sheet.d.mts +13 -1
- package/dist/Sheet.d.ts +13 -1
- package/dist/Sheet.js +115 -5
- package/dist/Sheet.mjs +4 -2
- package/dist/Skeleton.d.mts +50 -0
- package/dist/Skeleton.d.ts +50 -0
- package/dist/Skeleton.js +61 -0
- package/dist/Skeleton.mjs +4 -2
- package/dist/Slider.js +51 -4
- package/dist/Slider.mjs +3 -2
- package/dist/Spinner.js +28 -7
- package/dist/Spinner.mjs +2 -1
- package/dist/Switch.js +98 -48
- package/dist/Switch.mjs +4 -3
- package/dist/TabBar.d.mts +42 -0
- package/dist/TabBar.d.ts +42 -0
- package/dist/TabBar.js +361 -0
- package/dist/TabBar.mjs +6 -0
- package/dist/Tabs.js +92 -62
- package/dist/Tabs.mjs +5 -4
- package/dist/Text.js +16 -0
- package/dist/Text.mjs +2 -1
- package/dist/Textarea.mjs +4 -3
- package/dist/Toast.d.mts +7 -7
- package/dist/Toast.d.ts +7 -7
- package/dist/Toast.mjs +1 -0
- package/dist/Toggle.d.mts +6 -3
- package/dist/Toggle.d.ts +6 -3
- package/dist/Toggle.js +135 -120
- package/dist/Toggle.mjs +5 -5
- package/dist/VirtualList.mjs +1 -0
- package/dist/{chunk-7H2OR44A.mjs → chunk-26BCI223.mjs} +1 -1
- package/dist/{chunk-CRYBX2CM.mjs → chunk-2TFTAWVJ.mjs} +44 -59
- package/dist/chunk-3DKJ2GIC.mjs +30 -0
- package/dist/{chunk-KWCPOM6W.mjs → chunk-3U4SSNWP.mjs} +32 -48
- package/dist/chunk-4I7D47FH.mjs +139 -0
- package/dist/chunk-4K625MVM.mjs +142 -0
- package/dist/{chunk-MN7OG7IY.mjs → chunk-6OAZJ577.mjs} +6 -4
- package/dist/{chunk-L7E7TVEZ.mjs → chunk-756RAKE4.mjs} +2 -2
- package/dist/{chunk-HSPSMN6U.mjs → chunk-7QHVVCB3.mjs} +2 -2
- package/dist/{chunk-URLL5JBR.mjs → chunk-A3A6KNQN.mjs} +3 -3
- package/dist/chunk-AJ7ZDNBT.mjs +120 -0
- package/dist/{chunk-FTLJOUOQ.mjs → chunk-AV4EMIRH.mjs} +25 -28
- package/dist/chunk-AZJF2BLK.mjs +115 -0
- package/dist/chunk-BNP626TY.mjs +159 -0
- package/dist/{chunk-5IKW3VNC.mjs → chunk-DVK4G2GT.mjs} +17 -1
- package/dist/{chunk-6LQYY7HC.mjs → chunk-EH745HE5.mjs} +2 -2
- package/dist/chunk-EJ7ZPXOH.mjs +163 -0
- package/dist/{chunk-RKLHUDZS.mjs → chunk-GD6KXMG5.mjs} +29 -15
- package/dist/{chunk-RR2VQLKE.mjs → chunk-GQYFLP3D.mjs} +14 -17
- package/dist/{chunk-Y6MXOREN.mjs → chunk-ID72TK46.mjs} +8 -17
- package/dist/{chunk-NQGVLMWG.mjs → chunk-JMOZEC77.mjs} +1 -1
- package/dist/{chunk-GCWOGZYL.mjs → chunk-JT7HKXRB.mjs} +39 -29
- package/dist/{chunk-LWG526VX.mjs → chunk-KIHCWCWL.mjs} +47 -62
- package/dist/chunk-LXJIIOYQ.mjs +104 -0
- package/dist/{chunk-SBZYEV4S.mjs → chunk-M6ZXVBTK.mjs} +5 -2
- package/dist/{chunk-XDMN67KV.mjs → chunk-MAC465BB.mjs} +10 -8
- package/dist/chunk-MBMXYJJV.mjs +36 -0
- package/dist/chunk-MLF3EZFW.mjs +119 -0
- package/dist/chunk-NA7PARID.mjs +147 -0
- package/dist/{chunk-QXGYKWI7.mjs → chunk-O3HA6TYM.mjs} +9 -4
- package/dist/{chunk-63357L2X.mjs → chunk-OB4JUQ3O.mjs} +1 -1
- package/dist/{chunk-AU2VDY4P.mjs → chunk-PFZTM6D5.mjs} +52 -4
- package/dist/chunk-QKH5ZOD5.mjs +97 -0
- package/dist/{chunk-KZJRQOIU.mjs → chunk-TERDKCLE.mjs} +11 -1
- package/dist/{chunk-U4N7WF4Z.mjs → chunk-UREA2GYY.mjs} +28 -23
- package/dist/{chunk-TAJ2PQ2O.mjs → chunk-VGTDN7SW.mjs} +7 -6
- package/dist/{chunk-URDE3EUU.mjs → chunk-VQ57HWPL.mjs} +27 -15
- package/dist/chunk-WBOOUHSS.mjs +62 -0
- package/dist/{chunk-GNGLDL6Z.mjs → chunk-WJLKJMKR.mjs} +18 -0
- package/dist/{chunk-YZJAFS4P.mjs → chunk-X4G6APW6.mjs} +22 -19
- package/dist/chunk-Y6FXYEAI.mjs +8 -0
- package/dist/chunk-YFZ3ELX5.mjs +16 -0
- package/dist/{chunk-QCNARS3X.mjs → chunk-YNROWHQJ.mjs} +1 -1
- package/dist/chunk-Z4BVUWW6.mjs +196 -0
- package/dist/{chunk-GPOUINK5.mjs → chunk-ZJKGQMYH.mjs} +10 -27
- package/dist/index-wt-orHUi.d.mts +85 -0
- package/dist/index-wt-orHUi.d.ts +85 -0
- package/dist/index.d.mts +59 -51
- package/dist/index.d.ts +59 -51
- package/dist/index.js +1940 -744
- package/dist/index.mjs +49 -39
- package/package.json +35 -5
- package/src/components/Accordion/Accordion.tsx +12 -1
- package/src/components/AlertBanner/AlertBanner.tsx +5 -0
- package/src/components/AppHeader/AppHeader.tsx +172 -0
- package/src/components/AppHeader/index.ts +1 -0
- package/src/components/Avatar/Avatar.tsx +10 -2
- package/src/components/Badge/Badge.tsx +8 -1
- package/src/components/Button/Button.tsx +20 -27
- package/src/components/Card/Card.tsx +12 -23
- package/src/components/CategoryStrip/CategoryStrip.tsx +17 -21
- package/src/components/Checkbox/Checkbox.tsx +26 -40
- package/src/components/Chip/Chip.tsx +24 -33
- package/src/components/CurrencyInput/CurrencyInput.tsx +10 -8
- package/src/components/EmptyState/EmptyState.tsx +2 -1
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +153 -0
- package/src/components/ErrorBoundary/index.ts +1 -0
- package/src/components/HolographicCard/HolographicCard.tsx +315 -0
- package/src/components/HolographicCard/index.ts +1 -0
- package/src/components/IconButton/IconButton.tsx +19 -27
- package/src/components/ImageViewer/ImageViewer.tsx +290 -0
- package/src/components/ImageViewer/index.ts +1 -0
- package/src/components/ListItem/ListItem.tsx +70 -67
- package/src/components/MediaCard/MediaCard.tsx +8 -2
- package/src/components/MenuItem/MenuItem.tsx +10 -25
- package/src/components/MonthPicker/MonthPicker.tsx +39 -13
- package/src/components/MonthPicker/index.ts +1 -1
- package/src/components/PagerDots/PagerDots.tsx +200 -0
- package/src/components/PagerDots/index.ts +1 -0
- package/src/components/Pressable/Pressable.tsx +19 -35
- package/src/components/PricingCard/PricingCard.tsx +220 -0
- package/src/components/PricingCard/index.ts +1 -0
- package/src/components/RadioGroup/RadioGroup.tsx +14 -27
- package/src/components/RetrayProvider/RetrayProvider.tsx +59 -0
- package/src/components/RetrayProvider/index.ts +1 -0
- package/src/components/SelectableGrid/SelectableGrid.tsx +205 -0
- package/src/components/SelectableGrid/index.ts +1 -0
- package/src/components/Sheet/Sheet.tsx +65 -1
- package/src/components/Skeleton/Skeleton.tsx +142 -1
- package/src/components/Spinner/Spinner.tsx +17 -2
- package/src/components/Switch/Switch.tsx +30 -58
- package/src/components/TabBar/TabBar.tsx +169 -0
- package/src/components/TabBar/index.ts +1 -0
- package/src/components/Tabs/Tabs.tsx +23 -26
- package/src/components/Text/Text.tsx +2 -0
- package/src/components/Toggle/Toggle.tsx +35 -51
- package/src/fonts.ts +4 -1
- package/src/index.ts +23 -2
- package/src/utils/animations.ts +29 -1
- package/src/utils/fontGuard.ts +34 -0
- package/src/utils/haptics.ts +211 -9
- package/src/utils/pressable.ts +66 -0
- package/dist/chunk-76PFOSM2.mjs +0 -41
- package/dist/chunk-DITNP6PL.mjs +0 -106
- package/dist/chunk-JBLL7U3U.mjs +0 -64
- package/dist/chunk-LG4DO3DK.mjs +0 -174
- package/dist/chunk-RMMK64W5.mjs +0 -54
- package/dist/chunk-RTC3CFXF.mjs +0 -29
package/dist/index.mjs
CHANGED
|
@@ -1,52 +1,62 @@
|
|
|
1
|
-
export { Toggle } from './chunk-
|
|
1
|
+
export { Toggle } from './chunk-KIHCWCWL.mjs';
|
|
2
2
|
export { VirtualList } from './chunk-NC5ZTR2Y.mjs';
|
|
3
|
-
export { Skeleton } from './chunk-
|
|
4
|
-
export { Slider } from './chunk-
|
|
5
|
-
export { Spinner } from './chunk-
|
|
6
|
-
export { Switch } from './chunk-
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
9
|
-
export {
|
|
3
|
+
export { Skeleton } from './chunk-AJ7ZDNBT.mjs';
|
|
4
|
+
export { Slider } from './chunk-JMOZEC77.mjs';
|
|
5
|
+
export { Spinner } from './chunk-WBOOUHSS.mjs';
|
|
6
|
+
export { Switch } from './chunk-QKH5ZOD5.mjs';
|
|
7
|
+
export { TabBar } from './chunk-MLF3EZFW.mjs';
|
|
8
|
+
export { Tabs, TabsContent } from './chunk-GQYFLP3D.mjs';
|
|
9
|
+
export { Text } from './chunk-WJLKJMKR.mjs';
|
|
10
|
+
export { Textarea } from './chunk-EH745HE5.mjs';
|
|
11
|
+
export { PricingCard } from './chunk-4I7D47FH.mjs';
|
|
12
|
+
export { Progress } from './chunk-OB4JUQ3O.mjs';
|
|
13
|
+
export { RadioGroup } from './chunk-X4G6APW6.mjs';
|
|
14
|
+
export { RetrayProvider } from './chunk-YFZ3ELX5.mjs';
|
|
10
15
|
export { ToastProvider, sonnerToast as toast, useToast } from './chunk-2UYENBLV.mjs';
|
|
11
|
-
export {
|
|
12
|
-
export {
|
|
13
|
-
export { Pressable } from './chunk-RMMK64W5.mjs';
|
|
14
|
-
export { Progress } from './chunk-63357L2X.mjs';
|
|
15
|
-
export { RadioGroup } from './chunk-YZJAFS4P.mjs';
|
|
16
|
-
export { Select } from './chunk-URLL5JBR.mjs';
|
|
16
|
+
export { Select } from './chunk-A3A6KNQN.mjs';
|
|
17
|
+
export { SelectableGrid } from './chunk-NA7PARID.mjs';
|
|
17
18
|
export { Separator } from './chunk-MX6HRKMI.mjs';
|
|
18
|
-
export { BottomSheetModalProvider, Sheet, BottomSheetTextInput as SheetTextInput } from './chunk-
|
|
19
|
-
export { Form, FormField, FormFooter, FormSection } from './chunk-6Q64UFIA.mjs';
|
|
20
|
-
export { IconButton } from './chunk-KWCPOM6W.mjs';
|
|
21
|
-
export { LabelValue } from './chunk-A4MDAP7G.mjs';
|
|
19
|
+
export { BottomSheetModalProvider, Sheet, BottomSheetTextInput as SheetTextInput } from './chunk-PFZTM6D5.mjs';
|
|
22
20
|
export { ListGroup, ListGroupFooter, ListGroupHeader } from './chunk-SOA2Z4RB.mjs';
|
|
23
|
-
export { ListItem } from './chunk-
|
|
24
|
-
export { MediaCard } from './chunk-
|
|
21
|
+
export { ListItem } from './chunk-BNP626TY.mjs';
|
|
22
|
+
export { MediaCard } from './chunk-VGTDN7SW.mjs';
|
|
25
23
|
export { MenuGroup, MenuGroupFooter, MenuGroupHeader } from './chunk-IRRY3CRZ.mjs';
|
|
26
|
-
export {
|
|
27
|
-
export {
|
|
28
|
-
export {
|
|
29
|
-
export {
|
|
24
|
+
export { MenuItem } from './chunk-ZJKGQMYH.mjs';
|
|
25
|
+
export { MonthPicker, dateToMonthPickerValue, monthPickerValueToDate } from './chunk-GD6KXMG5.mjs';
|
|
26
|
+
export { Pressable } from './chunk-MBMXYJJV.mjs';
|
|
27
|
+
export { EmptyState } from './chunk-6OAZJ577.mjs';
|
|
28
|
+
export { ErrorBoundary } from './chunk-LXJIIOYQ.mjs';
|
|
29
|
+
export { Form, FormField, FormFooter, FormSection } from './chunk-6Q64UFIA.mjs';
|
|
30
|
+
export { ImageViewer } from './chunk-Z4BVUWW6.mjs';
|
|
31
|
+
export { PagerDots } from './chunk-4K625MVM.mjs';
|
|
32
|
+
export { LabelValue } from './chunk-A4MDAP7G.mjs';
|
|
33
|
+
export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from './chunk-ID72TK46.mjs';
|
|
34
|
+
export { CategoryStrip } from './chunk-VQ57HWPL.mjs';
|
|
35
|
+
import './chunk-YNROWHQJ.mjs';
|
|
36
|
+
export { Checkbox } from './chunk-AV4EMIRH.mjs';
|
|
37
|
+
export { Chip, ChipGroup } from './chunk-UREA2GYY.mjs';
|
|
38
|
+
export { ConfirmDialog } from './chunk-7QHVVCB3.mjs';
|
|
30
39
|
export { CurrencyDisplay } from './chunk-BRKYVJVV.mjs';
|
|
31
|
-
export { CurrencyInput
|
|
32
|
-
export { Input } from './chunk-
|
|
33
|
-
import './chunk-
|
|
40
|
+
export { CurrencyInput } from './chunk-MAC465BB.mjs';
|
|
41
|
+
export { Input } from './chunk-756RAKE4.mjs';
|
|
42
|
+
import './chunk-26BCI223.mjs';
|
|
34
43
|
export { DetailRow } from './chunk-JB67UOB5.mjs';
|
|
35
|
-
export {
|
|
36
|
-
export {
|
|
37
|
-
export {
|
|
38
|
-
export {
|
|
39
|
-
export {
|
|
40
|
-
export {
|
|
41
|
-
export {
|
|
42
|
-
|
|
43
|
-
export {
|
|
44
|
-
import './chunk-
|
|
45
|
-
import './chunk-RTC3CFXF.mjs';
|
|
46
|
-
import './chunk-5IKW3VNC.mjs';
|
|
44
|
+
export { Accordion } from './chunk-O3HA6TYM.mjs';
|
|
45
|
+
export { AlertBanner } from './chunk-M6ZXVBTK.mjs';
|
|
46
|
+
export { AppHeader } from './chunk-AZJF2BLK.mjs';
|
|
47
|
+
export { IconButton } from './chunk-3U4SSNWP.mjs';
|
|
48
|
+
export { Avatar } from './chunk-JT7HKXRB.mjs';
|
|
49
|
+
export { Badge } from './chunk-TERDKCLE.mjs';
|
|
50
|
+
export { Button } from './chunk-2TFTAWVJ.mjs';
|
|
51
|
+
import './chunk-3DKJ2GIC.mjs';
|
|
52
|
+
export { impactHeavy, impactLight, impactMedium, notificationError, notificationSuccess, notificationWarning, richHaptics, selectionAsync } from './chunk-EJ7ZPXOH.mjs';
|
|
53
|
+
import './chunk-DVK4G2GT.mjs';
|
|
47
54
|
export { BREAKPOINTS, ICON_SIZES, RADIUS, SHADOWS, SPACING, TYPOGRAPHY } from './chunk-QY3X2UYR.mjs';
|
|
55
|
+
export { Icon, configureIconFamilies, renderIcon } from './chunk-T7XZ7H7Y.mjs';
|
|
48
56
|
export { ThemeProvider, defaultDark, defaultLight, deriveColors, useTheme } from './chunk-SOYNZDVY.mjs';
|
|
57
|
+
export { ButtonGroup } from './chunk-3BBOZ3OQ.mjs';
|
|
49
58
|
import './chunk-2CE3TQVY.mjs';
|
|
59
|
+
import './chunk-Y6FXYEAI.mjs';
|
|
50
60
|
|
|
51
61
|
// src/utils/typography.ts
|
|
52
62
|
function getResponsiveFontSize(text, maxSize, steps = [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@retray-dev/ui-kit",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0",
|
|
4
4
|
"description": "Personal UI Kit for React Native / Expo",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -28,13 +28,16 @@
|
|
|
28
28
|
"build": "tsup",
|
|
29
29
|
"dev": "tsup --watch",
|
|
30
30
|
"typecheck": "tsc --noEmit",
|
|
31
|
+
"test": "jest",
|
|
32
|
+
"test:watch": "jest --watch",
|
|
33
|
+
"test:coverage": "jest --coverage",
|
|
31
34
|
"lint": "eslint src",
|
|
32
35
|
"lint:fix": "eslint src --fix",
|
|
33
36
|
"format": "prettier --write src",
|
|
34
37
|
"format:check": "prettier --check src",
|
|
35
38
|
"lint:all": "pnpm lint && pnpm --filter retray-ui-kit-example lint",
|
|
36
39
|
"format:all": "pnpm format && pnpm --filter retray-ui-kit-example format",
|
|
37
|
-
"verify": "pnpm typecheck && pnpm lint && pnpm build",
|
|
40
|
+
"verify": "pnpm typecheck && pnpm lint && pnpm test && pnpm build",
|
|
38
41
|
"deploy": "pnpm typecheck && pnpm build && npm publish --access public"
|
|
39
42
|
},
|
|
40
43
|
"keywords": [
|
|
@@ -46,21 +49,38 @@
|
|
|
46
49
|
"license": "MIT",
|
|
47
50
|
"peerDependencies": {
|
|
48
51
|
"@expo/vector-icons": ">=14.0.0",
|
|
49
|
-
"@gorhom/bottom-sheet": ">=5.
|
|
52
|
+
"@gorhom/bottom-sheet": ">=5.2.0",
|
|
50
53
|
"@react-native-community/slider": ">=4.0.0",
|
|
51
54
|
"@react-native-picker/picker": ">=2.0.0",
|
|
55
|
+
"@shopify/react-native-skia": ">=1.0.0",
|
|
52
56
|
"expo-font": ">=14.0.0",
|
|
53
57
|
"expo-haptics": ">=14.0.0",
|
|
54
58
|
"expo-linear-gradient": ">=13.0.0",
|
|
59
|
+
"expo-sensors": ">=13.0.0",
|
|
60
|
+
"pressto": ">=0.6.0",
|
|
55
61
|
"react": ">=17",
|
|
56
|
-
"react-native": ">=0.
|
|
62
|
+
"react-native": ">=0.76",
|
|
63
|
+
"react-native-ease": ">=0.7.0",
|
|
57
64
|
"react-native-gesture-handler": ">=2.0.0",
|
|
65
|
+
"react-native-pulsar": ">=1.6.0",
|
|
58
66
|
"react-native-reanimated": ">=4.0.0",
|
|
59
67
|
"react-native-safe-area-context": ">=4.0.0",
|
|
60
68
|
"react-native-screens": ">=3.0.0",
|
|
61
69
|
"react-native-size-matters": ">=0.4.0",
|
|
62
70
|
"react-native-svg": ">=15.0.0",
|
|
63
|
-
"react-native-worklets": ">=0.5.0"
|
|
71
|
+
"react-native-worklets": ">=0.5.0",
|
|
72
|
+
"sonner-native": ">=0.20.0"
|
|
73
|
+
},
|
|
74
|
+
"peerDependenciesMeta": {
|
|
75
|
+
"@shopify/react-native-skia": {
|
|
76
|
+
"optional": true
|
|
77
|
+
},
|
|
78
|
+
"expo-sensors": {
|
|
79
|
+
"optional": true
|
|
80
|
+
},
|
|
81
|
+
"react-native-pulsar": {
|
|
82
|
+
"optional": true
|
|
83
|
+
}
|
|
64
84
|
},
|
|
65
85
|
"pnpm": {
|
|
66
86
|
"overrides": {
|
|
@@ -82,7 +102,11 @@
|
|
|
82
102
|
"@gorhom/bottom-sheet": "5.2.8",
|
|
83
103
|
"@react-native-community/slider": "5.0.1",
|
|
84
104
|
"@react-native-picker/picker": "2.11.1",
|
|
105
|
+
"@shopify/react-native-skia": "2.2.12",
|
|
106
|
+
"@testing-library/react-native": "^14.0.0",
|
|
107
|
+
"@types/jest": "^30.0.0",
|
|
85
108
|
"@types/react": "19.1.17",
|
|
109
|
+
"babel-preset-expo": "~54.0.11",
|
|
86
110
|
"eslint": "^9.0.0",
|
|
87
111
|
"eslint-config-prettier": "^10.0.0",
|
|
88
112
|
"eslint-plugin-react": "^7.37.0",
|
|
@@ -90,10 +114,15 @@
|
|
|
90
114
|
"expo-font": "~14.0.11",
|
|
91
115
|
"expo-haptics": "~15.0.8",
|
|
92
116
|
"expo-linear-gradient": "~15.0.8",
|
|
117
|
+
"expo-sensors": "~15.0.7",
|
|
118
|
+
"jest-expo": "~54.0.17",
|
|
119
|
+
"pressto": "^0.6.1",
|
|
93
120
|
"prettier": "^3.8.3",
|
|
94
121
|
"react": "19.1.0",
|
|
95
122
|
"react-native": "0.81.5",
|
|
123
|
+
"react-native-ease": "^0.7.2",
|
|
96
124
|
"react-native-gesture-handler": "~2.28.0",
|
|
125
|
+
"react-native-pulsar": "^1.6.1",
|
|
97
126
|
"react-native-reanimated": "~4.1.1",
|
|
98
127
|
"react-native-safe-area-context": "5.6.2",
|
|
99
128
|
"react-native-screens": "4.16.0",
|
|
@@ -101,6 +130,7 @@
|
|
|
101
130
|
"react-native-svg": "15.12.1",
|
|
102
131
|
"react-native-worklets": "~0.5.1",
|
|
103
132
|
"sonner-native": "0.23.1",
|
|
133
|
+
"test-renderer": "^1.2.0",
|
|
104
134
|
"tsup": "^8.0.0",
|
|
105
135
|
"typescript": "^5.4.0",
|
|
106
136
|
"typescript-eslint": "^8.60.0"
|
|
@@ -126,7 +126,13 @@ function AccordionItemComponent({
|
|
|
126
126
|
height.value = e.nativeEvent.layout.height
|
|
127
127
|
}}
|
|
128
128
|
>
|
|
129
|
-
{item.content
|
|
129
|
+
{typeof item.content === 'string' || typeof item.content === 'number' ? (
|
|
130
|
+
<Text style={[styles.contentText, { color: colors.foregroundMuted }]} allowFontScaling={true}>
|
|
131
|
+
{item.content}
|
|
132
|
+
</Text>
|
|
133
|
+
) : (
|
|
134
|
+
item.content
|
|
135
|
+
)}
|
|
130
136
|
</View>
|
|
131
137
|
</Animated.View>
|
|
132
138
|
</View>
|
|
@@ -204,4 +210,9 @@ const styles = StyleSheet.create({
|
|
|
204
210
|
position: 'absolute',
|
|
205
211
|
width: '100%',
|
|
206
212
|
},
|
|
213
|
+
contentText: {
|
|
214
|
+
fontFamily: 'Sohne-Regular',
|
|
215
|
+
fontSize: ms(14),
|
|
216
|
+
lineHeight: ms(20),
|
|
217
|
+
},
|
|
207
218
|
})
|
|
@@ -61,6 +61,9 @@ export function AlertBanner({ title, description, variant = 'default', icon, ico
|
|
|
61
61
|
? renderIcon(iconName, ms(16), iconColor ?? accentColor)
|
|
62
62
|
: icon ?? defaultIcon
|
|
63
63
|
|
|
64
|
+
// Accessibility: AlertBanner is a notification — "alert" role announces it.
|
|
65
|
+
const a11yLabel = description ? `${title}. ${description}` : title
|
|
66
|
+
|
|
64
67
|
return (
|
|
65
68
|
<View
|
|
66
69
|
style={[
|
|
@@ -68,6 +71,8 @@ export function AlertBanner({ title, description, variant = 'default', icon, ico
|
|
|
68
71
|
{ backgroundColor: bgColor, borderWidth: 1, borderColor },
|
|
69
72
|
style,
|
|
70
73
|
]}
|
|
74
|
+
accessibilityRole="alert"
|
|
75
|
+
accessibilityLabel={a11yLabel}
|
|
71
76
|
>
|
|
72
77
|
<View style={styles.iconSlot}>{effectiveIcon}</View>
|
|
73
78
|
<View style={styles.content}>
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { View, Text, StyleSheet, ViewStyle, useWindowDimensions } from 'react-native'
|
|
3
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
4
|
+
import { useTheme } from '../../theme'
|
|
5
|
+
import { IconButton } from '../IconButton'
|
|
6
|
+
import { s, vs, ms, mvs } from '../../utils/scaling'
|
|
7
|
+
import { BREAKPOINTS } from '../../tokens'
|
|
8
|
+
|
|
9
|
+
export interface AppHeaderProps {
|
|
10
|
+
/** Primary title. */
|
|
11
|
+
title?: string
|
|
12
|
+
/** Secondary text below the title. */
|
|
13
|
+
subtitle?: string
|
|
14
|
+
/** Show a back button on the left and call this when pressed. */
|
|
15
|
+
onBack?: () => void
|
|
16
|
+
/** Icon name for the back button. Defaults to `'chevron-left'`. */
|
|
17
|
+
backIconName?: string
|
|
18
|
+
/** Custom left content — overrides the back button. */
|
|
19
|
+
left?: React.ReactNode
|
|
20
|
+
/** Custom right content (actions). */
|
|
21
|
+
right?: React.ReactNode
|
|
22
|
+
/**
|
|
23
|
+
* Title alignment.
|
|
24
|
+
* - `'auto'` (default): left on narrow screens, centered when width ≥ `BREAKPOINTS.wide`.
|
|
25
|
+
* - `'left'` / `'center'`: force alignment.
|
|
26
|
+
*/
|
|
27
|
+
titleAlign?: 'auto' | 'left' | 'center'
|
|
28
|
+
/** Render a hairline border under the header. Defaults to true. */
|
|
29
|
+
bordered?: boolean
|
|
30
|
+
/** Apply the top safe-area inset as padding. Defaults to true. */
|
|
31
|
+
withSafeArea?: boolean
|
|
32
|
+
/** Background color. Defaults to theme `background`. */
|
|
33
|
+
backgroundColor?: string
|
|
34
|
+
style?: ViewStyle
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Top app bar / screen chrome — back button, title/subtitle, and a right action
|
|
39
|
+
* slot. Responsive: the title left-aligns on phones and centers on wide layouts.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* <AppHeader title="Settings" onBack={navigation.goBack} right={<IconButton iconName="more-horizontal" variant="text" />} />
|
|
43
|
+
*/
|
|
44
|
+
export function AppHeader({
|
|
45
|
+
title,
|
|
46
|
+
subtitle,
|
|
47
|
+
onBack,
|
|
48
|
+
backIconName = 'chevron-left',
|
|
49
|
+
left,
|
|
50
|
+
right,
|
|
51
|
+
titleAlign = 'auto',
|
|
52
|
+
bordered = true,
|
|
53
|
+
withSafeArea = true,
|
|
54
|
+
backgroundColor,
|
|
55
|
+
style,
|
|
56
|
+
}: AppHeaderProps) {
|
|
57
|
+
const { colors } = useTheme()
|
|
58
|
+
const insets = useSafeAreaInsets()
|
|
59
|
+
const { width } = useWindowDimensions()
|
|
60
|
+
|
|
61
|
+
const isWide = width >= BREAKPOINTS.wide
|
|
62
|
+
const centered = titleAlign === 'center' || (titleAlign === 'auto' && isWide)
|
|
63
|
+
|
|
64
|
+
const leftNode = left ?? (onBack ? (
|
|
65
|
+
<IconButton
|
|
66
|
+
iconName={backIconName}
|
|
67
|
+
variant="text"
|
|
68
|
+
size="md"
|
|
69
|
+
onPress={onBack}
|
|
70
|
+
accessibilityLabel="Go back"
|
|
71
|
+
/>
|
|
72
|
+
) : null)
|
|
73
|
+
|
|
74
|
+
const titleBlock = (
|
|
75
|
+
<View style={[styles.titleBlock, centered && styles.titleBlockCentered]} pointerEvents="none">
|
|
76
|
+
{title ? (
|
|
77
|
+
<Text
|
|
78
|
+
style={[styles.title, { color: colors.foreground }, centered && styles.textCentered]}
|
|
79
|
+
numberOfLines={1}
|
|
80
|
+
allowFontScaling={true}
|
|
81
|
+
accessibilityRole="header"
|
|
82
|
+
>
|
|
83
|
+
{title}
|
|
84
|
+
</Text>
|
|
85
|
+
) : null}
|
|
86
|
+
{subtitle ? (
|
|
87
|
+
<Text
|
|
88
|
+
style={[styles.subtitle, { color: colors.foregroundMuted }, centered && styles.textCentered]}
|
|
89
|
+
numberOfLines={1}
|
|
90
|
+
allowFontScaling={true}
|
|
91
|
+
>
|
|
92
|
+
{subtitle}
|
|
93
|
+
</Text>
|
|
94
|
+
) : null}
|
|
95
|
+
</View>
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<View
|
|
100
|
+
style={[
|
|
101
|
+
styles.container,
|
|
102
|
+
{
|
|
103
|
+
backgroundColor: backgroundColor ?? colors.background,
|
|
104
|
+
paddingTop: withSafeArea ? insets.top : 0,
|
|
105
|
+
borderBottomWidth: bordered ? StyleSheet.hairlineWidth : 0,
|
|
106
|
+
borderBottomColor: colors.border,
|
|
107
|
+
},
|
|
108
|
+
style,
|
|
109
|
+
]}
|
|
110
|
+
>
|
|
111
|
+
<View style={styles.bar}>
|
|
112
|
+
{/* Centered layout: absolutely-positioned title so it stays centered regardless of slot widths. */}
|
|
113
|
+
{centered ? (
|
|
114
|
+
<>
|
|
115
|
+
<View style={StyleSheet.absoluteFill}>{titleBlock}</View>
|
|
116
|
+
<View style={styles.side}>{leftNode}</View>
|
|
117
|
+
<View style={[styles.side, styles.sideRight]}>{right}</View>
|
|
118
|
+
</>
|
|
119
|
+
) : (
|
|
120
|
+
<>
|
|
121
|
+
<View style={styles.side}>{leftNode}</View>
|
|
122
|
+
{titleBlock}
|
|
123
|
+
<View style={[styles.side, styles.sideRight]}>{right}</View>
|
|
124
|
+
</>
|
|
125
|
+
)}
|
|
126
|
+
</View>
|
|
127
|
+
</View>
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const styles = StyleSheet.create({
|
|
132
|
+
container: {
|
|
133
|
+
width: '100%',
|
|
134
|
+
},
|
|
135
|
+
bar: {
|
|
136
|
+
minHeight: vs(48),
|
|
137
|
+
flexDirection: 'row',
|
|
138
|
+
alignItems: 'center',
|
|
139
|
+
paddingHorizontal: s(8),
|
|
140
|
+
},
|
|
141
|
+
side: {
|
|
142
|
+
minWidth: s(44),
|
|
143
|
+
flexDirection: 'row',
|
|
144
|
+
alignItems: 'center',
|
|
145
|
+
justifyContent: 'flex-start',
|
|
146
|
+
},
|
|
147
|
+
sideRight: {
|
|
148
|
+
justifyContent: 'flex-end',
|
|
149
|
+
},
|
|
150
|
+
titleBlock: {
|
|
151
|
+
flex: 1,
|
|
152
|
+
justifyContent: 'center',
|
|
153
|
+
paddingHorizontal: s(8),
|
|
154
|
+
gap: vs(1),
|
|
155
|
+
},
|
|
156
|
+
titleBlockCentered: {
|
|
157
|
+
alignItems: 'center',
|
|
158
|
+
},
|
|
159
|
+
title: {
|
|
160
|
+
fontFamily: 'Sohne-SemiBold',
|
|
161
|
+
fontSize: ms(18),
|
|
162
|
+
lineHeight: mvs(24),
|
|
163
|
+
},
|
|
164
|
+
subtitle: {
|
|
165
|
+
fontFamily: 'Sohne-Regular',
|
|
166
|
+
fontSize: ms(13),
|
|
167
|
+
lineHeight: mvs(16),
|
|
168
|
+
},
|
|
169
|
+
textCentered: {
|
|
170
|
+
textAlign: 'center',
|
|
171
|
+
},
|
|
172
|
+
})
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './AppHeader'
|
|
@@ -59,8 +59,9 @@ function AvatarBase({ src, fallback, fallbackText, size = 'md', status, style }:
|
|
|
59
59
|
|
|
60
60
|
const statusSize = typeof size === 'number' ? size * 0.25 : statusSizeMap[size as AvatarSize]
|
|
61
61
|
|
|
62
|
+
// AUDIT FIX: online was hardcoded '#22c55e' — now uses theme token.
|
|
62
63
|
const statusColor: Record<AvatarStatus, string> = {
|
|
63
|
-
online:
|
|
64
|
+
online: colors.success,
|
|
64
65
|
offline: 'transparent',
|
|
65
66
|
busy: colors.destructive,
|
|
66
67
|
away: colors.warning,
|
|
@@ -74,8 +75,15 @@ function AvatarBase({ src, fallback, fallbackText, size = 'md', status, style }:
|
|
|
74
75
|
overflow: 'hidden',
|
|
75
76
|
}
|
|
76
77
|
|
|
78
|
+
// Compute accessible label: prefer explicit fallback text, then initials.
|
|
79
|
+
const a11yLabel = fallbackText || fallback || 'Avatar'
|
|
80
|
+
|
|
77
81
|
return (
|
|
78
|
-
<View
|
|
82
|
+
<View
|
|
83
|
+
style={[styles.wrapper, style]}
|
|
84
|
+
accessibilityRole="image"
|
|
85
|
+
accessibilityLabel={a11yLabel}
|
|
86
|
+
>
|
|
79
87
|
<View style={[styles.base, containerStyle]}>
|
|
80
88
|
{!showFallback ? (
|
|
81
89
|
<Image
|
|
@@ -78,8 +78,15 @@ function BadgeBase({ label, children, variant = 'default', size = 'md', icon, ic
|
|
|
78
78
|
|
|
79
79
|
const content = children ?? label
|
|
80
80
|
|
|
81
|
+
// Accessibility: badges are status indicators — role helps screen readers.
|
|
82
|
+
const a11yLabel = typeof content === 'string' ? content : label
|
|
83
|
+
|
|
81
84
|
return (
|
|
82
|
-
<View
|
|
85
|
+
<View
|
|
86
|
+
style={[styles.container, containerStyle, sizePadding[size], { gap: sizeIconGap[size] }, style]}
|
|
87
|
+
accessibilityRole="text"
|
|
88
|
+
accessibilityLabel={a11yLabel}
|
|
89
|
+
>
|
|
83
90
|
{effectiveIcon}
|
|
84
91
|
{typeof content === 'string' ? (
|
|
85
92
|
<Text style={[styles.label, { color: textColor }, sizeFontSize[size]]} allowFontScaling={true}>
|
|
@@ -1,26 +1,23 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
View,
|
|
4
4
|
Text,
|
|
5
5
|
ActivityIndicator,
|
|
6
6
|
StyleSheet,
|
|
7
|
-
TouchableOpacityProps,
|
|
8
7
|
ViewStyle,
|
|
9
8
|
TextStyle,
|
|
10
9
|
} from 'react-native'
|
|
11
|
-
import Animated from 'react-native-reanimated'
|
|
12
10
|
import { impactMedium } from '../../utils/haptics'
|
|
13
11
|
import { useTheme } from '../../theme'
|
|
14
12
|
import { s, vs, ms, mvs } from '../../utils/scaling'
|
|
15
13
|
import { renderIcon } from '../../utils/icons'
|
|
16
14
|
import { RADIUS, TYPOGRAPHY } from '../../tokens'
|
|
17
|
-
import {
|
|
18
|
-
import { PRESS_SCALE } from '../../utils/animations'
|
|
15
|
+
import { PressableButton } from '../../utils/pressable'
|
|
19
16
|
|
|
20
17
|
export type ButtonVariant = 'primary' | 'secondary' | 'text' | 'destructive'
|
|
21
18
|
export type ButtonSize = 'sm' | 'md' | 'lg'
|
|
22
19
|
|
|
23
|
-
export interface ButtonProps
|
|
20
|
+
export interface ButtonProps {
|
|
24
21
|
label: string
|
|
25
22
|
variant?: ButtonVariant
|
|
26
23
|
size?: ButtonSize
|
|
@@ -30,10 +27,16 @@ export interface ButtonProps extends TouchableOpacityProps {
|
|
|
30
27
|
iconName?: string
|
|
31
28
|
iconColor?: string
|
|
32
29
|
iconPosition?: 'left' | 'right'
|
|
30
|
+
disabled?: boolean
|
|
31
|
+
style?: ViewStyle
|
|
32
|
+
onPress?: () => void
|
|
33
|
+
accessibilityLabel?: string
|
|
34
|
+
accessibilityHint?: string
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
const containerSizeStyles: Record<ButtonSize, ViewStyle> = {
|
|
36
|
-
|
|
38
|
+
// AUDIT FIX: sm was 40pt — below Apple HIG 44pt minimum touch target.
|
|
39
|
+
sm: { paddingHorizontal: s(16), paddingVertical: vs(12), minHeight: 44 },
|
|
37
40
|
md: { paddingHorizontal: s(24), paddingVertical: vs(14), minHeight: 48 },
|
|
38
41
|
lg: { paddingHorizontal: s(28), paddingVertical: vs(16), minHeight: 56 },
|
|
39
42
|
}
|
|
@@ -61,18 +64,13 @@ function ButtonBase({
|
|
|
61
64
|
onPress,
|
|
62
65
|
accessibilityLabel,
|
|
63
66
|
accessibilityHint,
|
|
64
|
-
...props
|
|
65
67
|
}: ButtonProps) {
|
|
66
68
|
const { colors } = useTheme()
|
|
67
69
|
const isDisabled = disabled || loading
|
|
68
|
-
const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
69
|
-
pressScale: PRESS_SCALE.button,
|
|
70
|
-
disabled: isDisabled,
|
|
71
|
-
})
|
|
72
70
|
|
|
73
|
-
const handlePress
|
|
71
|
+
const handlePress = () => {
|
|
74
72
|
impactMedium()
|
|
75
|
-
onPress?.(
|
|
73
|
+
onPress?.()
|
|
76
74
|
}
|
|
77
75
|
|
|
78
76
|
const containerVariantStyle: ViewStyle = {
|
|
@@ -108,11 +106,8 @@ function ButtonBase({
|
|
|
108
106
|
const { flex, ...restStyle } = flatStyle || {}
|
|
109
107
|
|
|
110
108
|
return (
|
|
111
|
-
<
|
|
112
|
-
|
|
113
|
-
{...hoverHandlers}
|
|
114
|
-
>
|
|
115
|
-
<TouchableOpacity
|
|
109
|
+
<View style={[fullWidth && styles.fullWidth, flex !== undefined && { flex }]}>
|
|
110
|
+
<PressableButton
|
|
116
111
|
style={[
|
|
117
112
|
styles.base,
|
|
118
113
|
containerVariantStyle,
|
|
@@ -121,17 +116,15 @@ function ButtonBase({
|
|
|
121
116
|
isDisabled && styles.disabled,
|
|
122
117
|
restStyle,
|
|
123
118
|
]}
|
|
124
|
-
|
|
125
|
-
activeOpacity={1}
|
|
126
|
-
touchSoundDisabled={true}
|
|
119
|
+
enabled={!isDisabled}
|
|
127
120
|
onPress={handlePress}
|
|
128
|
-
|
|
129
|
-
|
|
121
|
+
rippleColor="transparent"
|
|
122
|
+
touchSoundDisabled
|
|
123
|
+
activateOnHover
|
|
130
124
|
accessibilityRole="button"
|
|
131
125
|
accessibilityLabel={accessibilityLabel ?? label}
|
|
132
126
|
accessibilityHint={accessibilityHint}
|
|
133
127
|
accessibilityState={{ disabled: isDisabled, busy: loading }}
|
|
134
|
-
{...props}
|
|
135
128
|
>
|
|
136
129
|
{loading ? (
|
|
137
130
|
<>
|
|
@@ -157,8 +150,8 @@ function ButtonBase({
|
|
|
157
150
|
{effectiveIcon && iconPosition === 'right' && <>{effectiveIcon}</>}
|
|
158
151
|
</>
|
|
159
152
|
)}
|
|
160
|
-
</
|
|
161
|
-
</
|
|
153
|
+
</PressableButton>
|
|
154
|
+
</View>
|
|
162
155
|
)
|
|
163
156
|
}
|
|
164
157
|
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { View, Text,
|
|
3
|
-
import Animated from 'react-native-reanimated'
|
|
2
|
+
import { View, Text, StyleSheet, ViewStyle, TextStyle } from 'react-native'
|
|
4
3
|
import { impactLight } from '../../utils/haptics'
|
|
5
4
|
import { useTheme } from '../../theme'
|
|
6
5
|
import { s, vs, ms, mvs } from '../../utils/scaling'
|
|
7
6
|
import { RADIUS } from '../../tokens'
|
|
8
|
-
import {
|
|
9
|
-
import { SPRINGS, PRESS_SCALE } from '../../utils/animations'
|
|
7
|
+
import { PressableCard } from '../../utils/pressable'
|
|
10
8
|
|
|
11
9
|
export type CardVariant = 'elevated' | 'outlined' | 'filled'
|
|
12
10
|
|
|
@@ -26,12 +24,6 @@ export interface CardFooterProps { children: React.ReactNode; style?: ViewStyle
|
|
|
26
24
|
|
|
27
25
|
export function Card({ children, variant = 'elevated', onPress, style, accessibilityLabel }: CardProps) {
|
|
28
26
|
const { colors } = useTheme()
|
|
29
|
-
const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
30
|
-
pressScale: PRESS_SCALE.card,
|
|
31
|
-
pressInSpring: SPRINGS.surfacePressIn,
|
|
32
|
-
pressOutSpring: SPRINGS.surfacePressOut,
|
|
33
|
-
disabled: !onPress,
|
|
34
|
-
})
|
|
35
27
|
|
|
36
28
|
const handlePress = () => {
|
|
37
29
|
if (!onPress) return
|
|
@@ -74,19 +66,16 @@ export function Card({ children, variant = 'elevated', onPress, style, accessibi
|
|
|
74
66
|
|
|
75
67
|
if (onPress) {
|
|
76
68
|
return (
|
|
77
|
-
<
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
{cardContent}
|
|
88
|
-
</TouchableOpacity>
|
|
89
|
-
</Animated.View>
|
|
69
|
+
<PressableCard
|
|
70
|
+
onPress={handlePress}
|
|
71
|
+
rippleColor="transparent"
|
|
72
|
+
touchSoundDisabled
|
|
73
|
+
activateOnHover
|
|
74
|
+
accessibilityRole="button"
|
|
75
|
+
accessibilityLabel={accessibilityLabel}
|
|
76
|
+
>
|
|
77
|
+
{cardContent}
|
|
78
|
+
</PressableCard>
|
|
90
79
|
)
|
|
91
80
|
}
|
|
92
81
|
|