@retray-dev/ui-kit 6.2.0 → 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 +997 -20
- package/EXAMPLES.md +250 -2
- package/README.md +21 -14
- package/dist/Accordion.d.mts +28 -0
- package/dist/Accordion.d.ts +28 -0
- package/dist/Accordion.js +392 -0
- package/dist/Accordion.mjs +7 -0
- package/dist/AlertBanner.d.mts +16 -0
- package/dist/AlertBanner.d.ts +16 -0
- package/dist/AlertBanner.js +250 -0
- package/dist/AlertBanner.mjs +6 -0
- 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.d.mts +20 -0
- package/dist/Avatar.d.ts +20 -0
- package/dist/Avatar.js +244 -0
- package/dist/Avatar.mjs +4 -0
- package/dist/Badge.d.mts +26 -0
- package/dist/Badge.d.ts +26 -0
- package/dist/Badge.js +257 -0
- package/dist/Badge.mjs +5 -0
- package/dist/Button.d.mts +30 -0
- package/dist/Button.d.ts +30 -0
- package/dist/Button.js +432 -0
- package/dist/Button.mjs +9 -0
- package/dist/ButtonGroup.d.mts +26 -0
- package/dist/ButtonGroup.d.ts +26 -0
- package/dist/ButtonGroup.js +52 -0
- package/dist/ButtonGroup.mjs +3 -0
- package/dist/Card.d.mts +39 -0
- package/dist/Card.d.ts +39 -0
- package/dist/Card.js +349 -0
- package/dist/Card.mjs +8 -0
- package/dist/CategoryStrip.d.mts +26 -0
- package/dist/CategoryStrip.d.ts +26 -0
- package/dist/CategoryStrip.js +453 -0
- package/dist/CategoryStrip.mjs +9 -0
- package/dist/Checkbox.d.mts +14 -0
- package/dist/Checkbox.d.ts +14 -0
- package/dist/Checkbox.js +336 -0
- package/dist/Checkbox.mjs +7 -0
- package/dist/Chip.d.mts +31 -0
- package/dist/Chip.d.ts +31 -0
- package/dist/Chip.js +403 -0
- package/dist/Chip.mjs +8 -0
- package/dist/ConfirmDialog.d.mts +15 -0
- package/dist/ConfirmDialog.d.ts +15 -0
- package/dist/ConfirmDialog.js +560 -0
- package/dist/ConfirmDialog.mjs +10 -0
- package/dist/CurrencyDisplay.d.mts +24 -0
- package/dist/CurrencyDisplay.d.ts +24 -0
- package/dist/CurrencyDisplay.js +189 -0
- package/dist/CurrencyDisplay.mjs +4 -0
- package/dist/CurrencyInput.d.mts +26 -0
- package/dist/CurrencyInput.d.ts +26 -0
- package/dist/CurrencyInput.js +408 -0
- package/dist/CurrencyInput.mjs +8 -0
- package/dist/DetailRow.d.mts +32 -0
- package/dist/DetailRow.d.ts +32 -0
- package/dist/DetailRow.js +275 -0
- package/dist/DetailRow.mjs +5 -0
- package/dist/EmptyState.d.mts +27 -0
- package/dist/EmptyState.d.ts +27 -0
- package/dist/EmptyState.js +523 -0
- package/dist/EmptyState.mjs +10 -0
- 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.d.mts +52 -0
- package/dist/Form.d.ts +52 -0
- package/dist/Form.js +204 -0
- package/dist/Form.mjs +4 -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 +27 -0
- package/dist/IconButton.d.ts +27 -0
- package/dist/IconButton.js +400 -0
- package/dist/IconButton.mjs +8 -0
- 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.d.mts +23 -0
- package/dist/Input.d.ts +23 -0
- package/dist/Input.js +351 -0
- package/dist/Input.mjs +7 -0
- package/dist/LabelValue.d.mts +16 -0
- package/dist/LabelValue.d.ts +16 -0
- package/dist/LabelValue.js +225 -0
- package/dist/LabelValue.mjs +5 -0
- package/dist/ListGroup.d.mts +34 -0
- package/dist/ListGroup.d.ts +34 -0
- package/dist/ListGroup.js +217 -0
- package/dist/ListGroup.mjs +5 -0
- package/dist/ListItem.d.mts +64 -0
- package/dist/ListItem.d.ts +64 -0
- package/dist/ListItem.js +444 -0
- package/dist/ListItem.mjs +9 -0
- package/dist/MediaCard.d.mts +39 -0
- package/dist/MediaCard.d.ts +39 -0
- package/dist/MediaCard.js +475 -0
- package/dist/MediaCard.mjs +9 -0
- package/dist/MenuGroup.d.mts +34 -0
- package/dist/MenuGroup.d.ts +34 -0
- package/dist/MenuGroup.js +217 -0
- package/dist/MenuGroup.mjs +5 -0
- package/dist/MenuItem.d.mts +48 -0
- package/dist/MenuItem.d.ts +48 -0
- package/dist/MenuItem.js +415 -0
- package/dist/MenuItem.mjs +9 -0
- package/dist/MonthPicker.d.mts +28 -0
- package/dist/MonthPicker.d.ts +28 -0
- package/dist/MonthPicker.js +297 -0
- package/dist/MonthPicker.mjs +5 -0
- 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 +34 -0
- package/dist/Pressable.d.ts +34 -0
- package/dist/Pressable.js +143 -0
- package/dist/Pressable.mjs +5 -0
- 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.d.mts +14 -0
- package/dist/Progress.d.ts +14 -0
- package/dist/Progress.js +191 -0
- package/dist/Progress.mjs +5 -0
- package/dist/RadioGroup.d.mts +19 -0
- package/dist/RadioGroup.d.ts +19 -0
- package/dist/RadioGroup.js +392 -0
- package/dist/RadioGroup.mjs +7 -0
- 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.d.mts +22 -0
- package/dist/Select.d.ts +22 -0
- package/dist/Select.js +488 -0
- package/dist/Select.mjs +7 -0
- 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.d.mts +10 -0
- package/dist/Separator.d.ts +10 -0
- package/dist/Separator.js +156 -0
- package/dist/Separator.mjs +3 -0
- package/dist/Sheet.d.mts +93 -0
- package/dist/Sheet.d.ts +93 -0
- package/dist/Sheet.js +450 -0
- package/dist/Sheet.mjs +6 -0
- package/dist/Skeleton.d.mts +67 -0
- package/dist/Skeleton.d.ts +67 -0
- package/dist/Skeleton.js +266 -0
- package/dist/Skeleton.mjs +6 -0
- package/dist/Slider.d.mts +20 -0
- package/dist/Slider.d.ts +20 -0
- package/dist/Slider.js +279 -0
- package/dist/Slider.mjs +5 -0
- package/dist/Spinner.d.mts +12 -0
- package/dist/Spinner.d.ts +12 -0
- package/dist/Spinner.js +193 -0
- package/dist/Spinner.mjs +4 -0
- package/dist/Switch.d.mts +13 -0
- package/dist/Switch.d.ts +13 -0
- package/dist/Switch.js +311 -0
- package/dist/Switch.mjs +6 -0
- 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.d.mts +27 -0
- package/dist/Tabs.d.ts +27 -0
- package/dist/Tabs.js +419 -0
- package/dist/Tabs.mjs +7 -0
- package/dist/Text.d.mts +12 -0
- package/dist/Text.d.ts +12 -0
- package/dist/Text.js +327 -0
- package/dist/Text.mjs +5 -0
- package/dist/Textarea.d.mts +16 -0
- package/dist/Textarea.d.ts +16 -0
- package/dist/Textarea.js +333 -0
- package/dist/Textarea.mjs +7 -0
- package/dist/Toast.d.mts +47 -0
- package/dist/Toast.d.ts +47 -0
- package/dist/Toast.js +185 -0
- package/dist/Toast.mjs +4 -0
- package/dist/Toggle.d.mts +36 -0
- package/dist/Toggle.d.ts +36 -0
- package/dist/Toggle.js +412 -0
- package/dist/Toggle.mjs +8 -0
- package/dist/VirtualList.d.mts +19 -0
- package/dist/VirtualList.d.ts +19 -0
- package/dist/VirtualList.js +38 -0
- package/dist/VirtualList.mjs +2 -0
- package/dist/chunk-26BCI223.mjs +14 -0
- package/dist/chunk-2CE3TQVY.mjs +11 -0
- package/dist/chunk-2TFTAWVJ.mjs +131 -0
- package/dist/chunk-2UYENBLV.mjs +49 -0
- package/dist/chunk-3BBOZ3OQ.mjs +41 -0
- package/dist/chunk-3DKJ2GIC.mjs +30 -0
- package/dist/chunk-3U4SSNWP.mjs +120 -0
- package/dist/chunk-4I7D47FH.mjs +139 -0
- package/dist/chunk-4K625MVM.mjs +142 -0
- package/dist/chunk-6OAZJ577.mjs +98 -0
- package/dist/chunk-6Q64UFIA.mjs +71 -0
- package/dist/chunk-756RAKE4.mjs +145 -0
- package/dist/chunk-7QHVVCB3.mjs +115 -0
- package/dist/chunk-A3A6KNQN.mjs +245 -0
- package/dist/chunk-A4MDAP7G.mjs +42 -0
- package/dist/chunk-AJ7ZDNBT.mjs +120 -0
- package/dist/chunk-AV4EMIRH.mjs +94 -0
- package/dist/chunk-AZJF2BLK.mjs +115 -0
- package/dist/chunk-BNP626TY.mjs +159 -0
- package/dist/chunk-BRKYVJVV.mjs +60 -0
- package/dist/chunk-DVK4G2GT.mjs +59 -0
- package/dist/chunk-EH745HE5.mjs +127 -0
- package/dist/chunk-EJ7ZPXOH.mjs +163 -0
- package/dist/chunk-GD6KXMG5.mjs +106 -0
- package/dist/chunk-GQYFLP3D.mjs +187 -0
- package/dist/chunk-ID72TK46.mjs +111 -0
- package/dist/chunk-IRRY3CRZ.mjs +82 -0
- package/dist/chunk-JB67UOB5.mjs +92 -0
- package/dist/chunk-JMOZEC77.mjs +90 -0
- package/dist/chunk-JT7HKXRB.mjs +114 -0
- package/dist/chunk-KIHCWCWL.mjs +124 -0
- package/dist/chunk-LXJIIOYQ.mjs +104 -0
- package/dist/chunk-M6ZXVBTK.mjs +64 -0
- package/dist/chunk-MAC465BB.mjs +61 -0
- package/dist/chunk-MBMXYJJV.mjs +36 -0
- package/dist/chunk-MLF3EZFW.mjs +119 -0
- package/dist/chunk-MX6HRKMI.mjs +29 -0
- package/dist/chunk-NA7PARID.mjs +147 -0
- package/dist/chunk-NC5ZTR2Y.mjs +32 -0
- package/dist/chunk-O3HA6TYM.mjs +139 -0
- package/dist/chunk-OB4JUQ3O.mjs +51 -0
- package/dist/chunk-PFZTM6D5.mjs +238 -0
- package/dist/chunk-QKH5ZOD5.mjs +97 -0
- package/dist/chunk-QY3X2UYR.mjs +191 -0
- package/dist/chunk-SOA2Z4RB.mjs +82 -0
- package/dist/chunk-SOYNZDVY.mjs +151 -0
- package/dist/chunk-T7XZ7H7Y.mjs +57 -0
- package/dist/chunk-TERDKCLE.mjs +74 -0
- package/dist/chunk-UREA2GYY.mjs +113 -0
- package/dist/chunk-VGTDN7SW.mjs +164 -0
- package/dist/chunk-VQ57HWPL.mjs +144 -0
- package/dist/chunk-WBOOUHSS.mjs +62 -0
- package/dist/chunk-WJLKJMKR.mjs +78 -0
- package/dist/chunk-X4G6APW6.mjs +134 -0
- package/dist/chunk-Y6FXYEAI.mjs +8 -0
- package/dist/chunk-YFZ3ELX5.mjs +16 -0
- package/dist/chunk-YNROWHQJ.mjs +46 -0
- package/dist/chunk-Z4BVUWW6.mjs +196 -0
- package/dist/chunk-ZJKGQMYH.mjs +131 -0
- package/dist/index-wt-orHUi.d.mts +85 -0
- package/dist/index-wt-orHUi.d.ts +85 -0
- package/dist/index.d.mts +149 -920
- package/dist/index.d.ts +149 -920
- package/dist/index.js +2560 -970
- package/dist/index.mjs +60 -3895
- package/package.json +55 -16
- package/src/assets/fonts/Sohne-Bold.otf +0 -0
- package/src/assets/fonts/Sohne-BoldItalic.otf +0 -0
- package/src/assets/fonts/Sohne-ExtraBold.otf +0 -0
- package/src/assets/fonts/Sohne-ExtraBoldItalic.otf +0 -0
- package/src/assets/fonts/Sohne-ExtraLight.otf +0 -0
- package/src/assets/fonts/Sohne-ExtraLightItalic.otf +0 -0
- package/src/assets/fonts/Sohne-Italic.otf +0 -0
- package/src/assets/fonts/Sohne-Light.otf +0 -0
- package/src/assets/fonts/Sohne-LightItalic.otf +0 -0
- package/src/assets/fonts/Sohne-Medium.otf +0 -0
- package/src/assets/fonts/Sohne-MediumItalic.otf +0 -0
- package/src/assets/fonts/Sohne-Regular.otf +0 -0
- package/src/assets/fonts/Sohne-SemiBold.otf +0 -0
- package/src/assets/fonts/Sohne-SemiBoldItalic.otf +0 -0
- package/src/assets/fonts/SohneMono-Bold.otf +0 -0
- package/src/assets/fonts/SohneMono-BoldItalic.otf +0 -0
- package/src/assets/fonts/SohneMono-ExtraBold.otf +0 -0
- package/src/assets/fonts/SohneMono-ExtraBoldItalic.otf +0 -0
- package/src/assets/fonts/SohneMono-ExtraLight.otf +0 -0
- package/src/assets/fonts/SohneMono-ExtraLightItalic.otf +0 -0
- package/src/assets/fonts/SohneMono-Italic.otf +0 -0
- package/src/assets/fonts/SohneMono-Light.otf +0 -0
- package/src/assets/fonts/SohneMono-LightItalic.otf +0 -0
- package/src/assets/fonts/SohneMono-Medium.otf +0 -0
- package/src/assets/fonts/SohneMono-MediumItalic.otf +0 -0
- package/src/assets/fonts/SohneMono-Regular.otf +0 -0
- package/src/assets/fonts/SohneMono-SemiBold.otf +0 -0
- package/src/assets/fonts/SohneMono-SemiBoldItalic.otf +0 -0
- package/src/components/Accordion/Accordion.tsx +15 -4
- package/src/components/AlertBanner/AlertBanner.tsx +38 -12
- package/src/components/AppHeader/AppHeader.tsx +172 -0
- package/src/components/AppHeader/index.ts +1 -0
- package/src/components/Avatar/Avatar.tsx +14 -4
- package/src/components/Badge/Badge.tsx +12 -3
- package/src/components/Button/Button.tsx +30 -38
- package/src/components/ButtonGroup/ButtonGroup.tsx +13 -10
- package/src/components/Card/Card.tsx +29 -57
- package/src/components/CategoryStrip/CategoryStrip.tsx +41 -42
- package/src/components/Checkbox/Checkbox.tsx +36 -45
- package/src/components/Chip/Chip.tsx +41 -48
- package/src/components/ConfirmDialog/ConfirmDialog.tsx +2 -2
- package/src/components/CurrencyDisplay/CurrencyDisplay.tsx +4 -2
- package/src/components/CurrencyInput/CurrencyInput.tsx +12 -10
- package/src/components/DetailRow/DetailRow.tsx +9 -7
- package/src/components/EmptyState/EmptyState.tsx +4 -3
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +153 -0
- package/src/components/ErrorBoundary/index.ts +1 -0
- package/src/components/Form/Form.tsx +149 -0
- package/src/components/Form/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 +23 -29
- package/src/components/ImageViewer/ImageViewer.tsx +290 -0
- package/src/components/ImageViewer/index.ts +1 -0
- package/src/components/Input/Input.tsx +27 -31
- package/src/components/LabelValue/LabelValue.tsx +6 -4
- package/src/components/ListGroup/ListGroup.tsx +145 -0
- package/src/components/ListGroup/index.ts +1 -0
- package/src/components/ListItem/ListItem.tsx +78 -76
- package/src/components/MediaCard/MediaCard.tsx +15 -7
- package/src/components/MenuGroup/MenuGroup.tsx +145 -0
- package/src/components/MenuGroup/index.ts +1 -0
- package/src/components/MenuItem/MenuItem.tsx +16 -33
- package/src/components/MonthPicker/MonthPicker.tsx +41 -15
- 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 +23 -39
- package/src/components/RetrayProvider/RetrayProvider.tsx +59 -0
- package/src/components/RetrayProvider/index.ts +1 -0
- package/src/components/Select/Select.tsx +6 -6
- package/src/components/SelectableGrid/SelectableGrid.tsx +205 -0
- package/src/components/SelectableGrid/index.ts +1 -0
- package/src/components/Separator/Separator.tsx +1 -3
- package/src/components/Sheet/Sheet.tsx +146 -18
- package/src/components/Skeleton/Skeleton.tsx +143 -2
- package/src/components/Slider/Slider.tsx +2 -2
- package/src/components/Spinner/Spinner.tsx +18 -3
- package/src/components/Switch/Switch.tsx +44 -49
- package/src/components/TabBar/TabBar.tsx +169 -0
- package/src/components/TabBar/index.ts +1 -0
- package/src/components/Tabs/Tabs.tsx +45 -44
- package/src/components/Text/Text.tsx +5 -1
- package/src/components/Textarea/Textarea.tsx +18 -14
- package/src/components/Toast/Toast.tsx +6 -6
- package/src/components/Toggle/Toggle.tsx +80 -72
- package/src/components/VirtualList/VirtualList.tsx +60 -0
- package/src/components/VirtualList/index.ts +1 -0
- package/src/fonts.ts +41 -20
- package/src/index.ts +28 -3
- package/src/theme/colors.ts +53 -39
- package/src/theme/types.ts +3 -0
- package/src/tokens.ts +49 -39
- package/src/utils/animations.ts +29 -1
- package/src/utils/fontGuard.ts +34 -0
- package/src/utils/haptics.ts +211 -9
- package/src/utils/icons.ts +47 -20
- package/src/utils/pressable.ts +66 -0
- package/src/utils/usePressScale.ts +2 -0
- package/src/assets/fonts/Poppins-Black.ttf +0 -0
- package/src/assets/fonts/Poppins-BlackItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-Bold.ttf +0 -0
- package/src/assets/fonts/Poppins-BoldItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-ExtraBold.ttf +0 -0
- package/src/assets/fonts/Poppins-ExtraBoldItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-ExtraLight.ttf +0 -0
- package/src/assets/fonts/Poppins-ExtraLightItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-Italic.ttf +0 -0
- package/src/assets/fonts/Poppins-Light.ttf +0 -0
- package/src/assets/fonts/Poppins-LightItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-Medium.ttf +0 -0
- package/src/assets/fonts/Poppins-MediumItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-Regular.ttf +0 -0
- package/src/assets/fonts/Poppins-SemiBold.ttf +0 -0
- package/src/assets/fonts/Poppins-SemiBoldItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-Thin.ttf +0 -0
- package/src/assets/fonts/Poppins-ThinItalic.ttf +0 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ViewStyle } from 'react-native';
|
|
3
|
+
|
|
4
|
+
interface AppHeaderProps {
|
|
5
|
+
/** Primary title. */
|
|
6
|
+
title?: string;
|
|
7
|
+
/** Secondary text below the title. */
|
|
8
|
+
subtitle?: string;
|
|
9
|
+
/** Show a back button on the left and call this when pressed. */
|
|
10
|
+
onBack?: () => void;
|
|
11
|
+
/** Icon name for the back button. Defaults to `'chevron-left'`. */
|
|
12
|
+
backIconName?: string;
|
|
13
|
+
/** Custom left content — overrides the back button. */
|
|
14
|
+
left?: React.ReactNode;
|
|
15
|
+
/** Custom right content (actions). */
|
|
16
|
+
right?: React.ReactNode;
|
|
17
|
+
/**
|
|
18
|
+
* Title alignment.
|
|
19
|
+
* - `'auto'` (default): left on narrow screens, centered when width ≥ `BREAKPOINTS.wide`.
|
|
20
|
+
* - `'left'` / `'center'`: force alignment.
|
|
21
|
+
*/
|
|
22
|
+
titleAlign?: 'auto' | 'left' | 'center';
|
|
23
|
+
/** Render a hairline border under the header. Defaults to true. */
|
|
24
|
+
bordered?: boolean;
|
|
25
|
+
/** Apply the top safe-area inset as padding. Defaults to true. */
|
|
26
|
+
withSafeArea?: boolean;
|
|
27
|
+
/** Background color. Defaults to theme `background`. */
|
|
28
|
+
backgroundColor?: string;
|
|
29
|
+
style?: ViewStyle;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Top app bar / screen chrome — back button, title/subtitle, and a right action
|
|
33
|
+
* slot. Responsive: the title left-aligns on phones and centers on wide layouts.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* <AppHeader title="Settings" onBack={navigation.goBack} right={<IconButton iconName="more-horizontal" variant="text" />} />
|
|
37
|
+
*/
|
|
38
|
+
declare function AppHeader({ title, subtitle, onBack, backIconName, left, right, titleAlign, bordered, withSafeArea, backgroundColor, style, }: AppHeaderProps): React.JSX.Element;
|
|
39
|
+
|
|
40
|
+
export { AppHeader, type AppHeaderProps };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ViewStyle } from 'react-native';
|
|
3
|
+
|
|
4
|
+
interface AppHeaderProps {
|
|
5
|
+
/** Primary title. */
|
|
6
|
+
title?: string;
|
|
7
|
+
/** Secondary text below the title. */
|
|
8
|
+
subtitle?: string;
|
|
9
|
+
/** Show a back button on the left and call this when pressed. */
|
|
10
|
+
onBack?: () => void;
|
|
11
|
+
/** Icon name for the back button. Defaults to `'chevron-left'`. */
|
|
12
|
+
backIconName?: string;
|
|
13
|
+
/** Custom left content — overrides the back button. */
|
|
14
|
+
left?: React.ReactNode;
|
|
15
|
+
/** Custom right content (actions). */
|
|
16
|
+
right?: React.ReactNode;
|
|
17
|
+
/**
|
|
18
|
+
* Title alignment.
|
|
19
|
+
* - `'auto'` (default): left on narrow screens, centered when width ≥ `BREAKPOINTS.wide`.
|
|
20
|
+
* - `'left'` / `'center'`: force alignment.
|
|
21
|
+
*/
|
|
22
|
+
titleAlign?: 'auto' | 'left' | 'center';
|
|
23
|
+
/** Render a hairline border under the header. Defaults to true. */
|
|
24
|
+
bordered?: boolean;
|
|
25
|
+
/** Apply the top safe-area inset as padding. Defaults to true. */
|
|
26
|
+
withSafeArea?: boolean;
|
|
27
|
+
/** Background color. Defaults to theme `background`. */
|
|
28
|
+
backgroundColor?: string;
|
|
29
|
+
style?: ViewStyle;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Top app bar / screen chrome — back button, title/subtitle, and a right action
|
|
33
|
+
* slot. Responsive: the title left-aligns on phones and centers on wide layouts.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* <AppHeader title="Settings" onBack={navigation.goBack} right={<IconButton iconName="more-horizontal" variant="text" />} />
|
|
37
|
+
*/
|
|
38
|
+
declare function AppHeader({ title, subtitle, onBack, backIconName, left, right, titleAlign, bordered, withSafeArea, backgroundColor, style, }: AppHeaderProps): React.JSX.Element;
|
|
39
|
+
|
|
40
|
+
export { AppHeader, type AppHeaderProps };
|
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React4 = require('react');
|
|
4
|
+
var reactNative = require('react-native');
|
|
5
|
+
var reactNativeSafeAreaContext = require('react-native-safe-area-context');
|
|
6
|
+
var reactNativeSizeMatters = require('react-native-size-matters');
|
|
7
|
+
var AntDesign = require('@expo/vector-icons/AntDesign');
|
|
8
|
+
var Entypo = require('@expo/vector-icons/Entypo');
|
|
9
|
+
var Feather = require('@expo/vector-icons/Feather');
|
|
10
|
+
var FontAwesome5 = require('@expo/vector-icons/FontAwesome5');
|
|
11
|
+
var MaterialIcons = require('@expo/vector-icons/MaterialIcons');
|
|
12
|
+
var Ionicons = require('@expo/vector-icons/Ionicons');
|
|
13
|
+
var pressto = require('pressto');
|
|
14
|
+
var reactNativeReanimated = require('react-native-reanimated');
|
|
15
|
+
|
|
16
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
17
|
+
|
|
18
|
+
var React4__default = /*#__PURE__*/_interopDefault(React4);
|
|
19
|
+
var AntDesign__default = /*#__PURE__*/_interopDefault(AntDesign);
|
|
20
|
+
var Entypo__default = /*#__PURE__*/_interopDefault(Entypo);
|
|
21
|
+
var Feather__default = /*#__PURE__*/_interopDefault(Feather);
|
|
22
|
+
var FontAwesome5__default = /*#__PURE__*/_interopDefault(FontAwesome5);
|
|
23
|
+
var MaterialIcons__default = /*#__PURE__*/_interopDefault(MaterialIcons);
|
|
24
|
+
var Ionicons__default = /*#__PURE__*/_interopDefault(Ionicons);
|
|
25
|
+
|
|
26
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
27
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
28
|
+
}) : x)(function(x) {
|
|
29
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
30
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// src/theme/colorUtils.ts
|
|
34
|
+
function hexToRgb(hex) {
|
|
35
|
+
const clean = hex.replace("#", "");
|
|
36
|
+
const full = clean.length === 3 ? clean.split("").map((c) => c + c).join("") : clean;
|
|
37
|
+
if (full.length !== 6) return null;
|
|
38
|
+
return {
|
|
39
|
+
r: parseInt(full.slice(0, 2), 16),
|
|
40
|
+
g: parseInt(full.slice(2, 4), 16),
|
|
41
|
+
b: parseInt(full.slice(4, 6), 16)
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function componentToHex(c) {
|
|
45
|
+
return Math.round(Math.max(0, Math.min(255, c))).toString(16).padStart(2, "0");
|
|
46
|
+
}
|
|
47
|
+
function rgbToHex(r, g, b) {
|
|
48
|
+
return `#${componentToHex(r)}${componentToHex(g)}${componentToHex(b)}`;
|
|
49
|
+
}
|
|
50
|
+
function withAlphaOnWhite(hex, alpha) {
|
|
51
|
+
const rgb = hexToRgb(hex);
|
|
52
|
+
if (!rgb) return hex;
|
|
53
|
+
const r = rgb.r * alpha + 255 * (1 - alpha);
|
|
54
|
+
const g = rgb.g * alpha + 255 * (1 - alpha);
|
|
55
|
+
const b = rgb.b * alpha + 255 * (1 - alpha);
|
|
56
|
+
return rgbToHex(r, g, b);
|
|
57
|
+
}
|
|
58
|
+
function withAlphaOnDark(hex, alpha, bgHex = "#0f0f0f") {
|
|
59
|
+
const rgb = hexToRgb(hex);
|
|
60
|
+
const bg = hexToRgb(bgHex);
|
|
61
|
+
if (!rgb || !bg) return hex;
|
|
62
|
+
const r = rgb.r * alpha + bg.r * (1 - alpha);
|
|
63
|
+
const g = rgb.g * alpha + bg.g * (1 - alpha);
|
|
64
|
+
const b = rgb.b * alpha + bg.b * (1 - alpha);
|
|
65
|
+
return rgbToHex(r, g, b);
|
|
66
|
+
}
|
|
67
|
+
function mixWithBackground(fgHex, bgHex, opacity) {
|
|
68
|
+
const fg = hexToRgb(fgHex);
|
|
69
|
+
const bg = hexToRgb(bgHex);
|
|
70
|
+
if (!fg || !bg) return fgHex;
|
|
71
|
+
const r = fg.r * opacity + bg.r * (1 - opacity);
|
|
72
|
+
const g = fg.g * opacity + bg.g * (1 - opacity);
|
|
73
|
+
const b = fg.b * opacity + bg.b * (1 - opacity);
|
|
74
|
+
return rgbToHex(r, g, b);
|
|
75
|
+
}
|
|
76
|
+
function lighten(hex, amount) {
|
|
77
|
+
return withAlphaOnWhite(hex, 1 - amount);
|
|
78
|
+
}
|
|
79
|
+
function darken(hex, amount) {
|
|
80
|
+
const rgb = hexToRgb(hex);
|
|
81
|
+
if (!rgb) return hex;
|
|
82
|
+
return rgbToHex(rgb.r * (1 - amount), rgb.g * (1 - amount), rgb.b * (1 - amount));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// src/theme/colors.ts
|
|
86
|
+
var defaultLight = {
|
|
87
|
+
background: "#ffffff",
|
|
88
|
+
foreground: "#1a1a1a",
|
|
89
|
+
card: "#ffffff",
|
|
90
|
+
primary: "#1a1a1a",
|
|
91
|
+
primaryForeground: "#ffffff",
|
|
92
|
+
// AUDIT FIX: brand accent — was undefined; falls back to primary when omitted
|
|
93
|
+
accent: "#d4561d",
|
|
94
|
+
accentForeground: "#ffffff",
|
|
95
|
+
border: "#dddddd",
|
|
96
|
+
// AUDIT FIX: was #e53935 (4.22:1 on white — fails AA); #c72828 = 5.59:1 ✓
|
|
97
|
+
destructive: "#c72828",
|
|
98
|
+
destructiveForeground: "#ffffff",
|
|
99
|
+
success: "#1a7a45",
|
|
100
|
+
successForeground: "#ffffff",
|
|
101
|
+
// AUDIT FIX: was #e67e00 (2.86:1 — severe fail); #9a5200 = 5.86:1 ✓ AAA-near
|
|
102
|
+
warning: "#9a5200",
|
|
103
|
+
warningForeground: "#ffffff"
|
|
104
|
+
};
|
|
105
|
+
function deriveColors(t, scheme) {
|
|
106
|
+
const dark = scheme === "dark";
|
|
107
|
+
const bg = t.background;
|
|
108
|
+
const foregroundSubtle = mixWithBackground(t.foreground, bg, 0.7);
|
|
109
|
+
const foregroundMuted = mixWithBackground(t.foreground, bg, 0.62);
|
|
110
|
+
const surface = dark ? lighten(bg, -0.06) : darken(bg, 0.04);
|
|
111
|
+
const surfaceStrong = dark ? lighten(bg, -0.12) : darken(bg, 0.08);
|
|
112
|
+
const destructiveTint = dark ? withAlphaOnDark(t.destructive, 0.15, bg) : withAlphaOnWhite(t.destructive, 0.08);
|
|
113
|
+
const destructiveBorder = dark ? withAlphaOnDark(t.destructive, 0.45, bg) : withAlphaOnWhite(t.destructive, 0.3);
|
|
114
|
+
const successTint = dark ? withAlphaOnDark(t.success, 0.15, bg) : withAlphaOnWhite(t.success, 0.08);
|
|
115
|
+
const successBorder = dark ? withAlphaOnDark(t.success, 0.45, bg) : withAlphaOnWhite(t.success, 0.3);
|
|
116
|
+
const warningTint = dark ? withAlphaOnDark(t.warning, 0.15, bg) : withAlphaOnWhite(t.warning, 0.08);
|
|
117
|
+
const warningBorder = dark ? withAlphaOnDark(t.warning, 0.45, bg) : withAlphaOnWhite(t.warning, 0.3);
|
|
118
|
+
return {
|
|
119
|
+
...t,
|
|
120
|
+
foregroundSubtle,
|
|
121
|
+
foregroundMuted,
|
|
122
|
+
surface,
|
|
123
|
+
surfaceStrong,
|
|
124
|
+
destructiveTint,
|
|
125
|
+
destructiveBorder,
|
|
126
|
+
successTint,
|
|
127
|
+
successBorder,
|
|
128
|
+
warningTint,
|
|
129
|
+
warningBorder,
|
|
130
|
+
overlay: t.overlay ?? "rgba(0,0,0,0.45)",
|
|
131
|
+
accentResolved: t.accent ?? t.primary,
|
|
132
|
+
accentForegroundResolved: t.accentForeground ?? t.primaryForeground,
|
|
133
|
+
ring: t.accent ?? t.primary,
|
|
134
|
+
input: t.border,
|
|
135
|
+
separator: dark ? lighten(t.border, 0.22) : darken(t.border, 0.16)
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/theme/ThemeProvider.tsx
|
|
140
|
+
var ThemeContext = React4.createContext({
|
|
141
|
+
colors: deriveColors(defaultLight, "light"),
|
|
142
|
+
colorScheme: "light"
|
|
143
|
+
});
|
|
144
|
+
function useTheme() {
|
|
145
|
+
const context = React4.useContext(ThemeContext);
|
|
146
|
+
if (!context) {
|
|
147
|
+
throw new Error("useTheme must be used within a ThemeProvider");
|
|
148
|
+
}
|
|
149
|
+
return context;
|
|
150
|
+
}
|
|
151
|
+
var _haptics = null;
|
|
152
|
+
var _hapticsLoaded = false;
|
|
153
|
+
async function getHaptics() {
|
|
154
|
+
if (reactNative.Platform.OS === "web") return null;
|
|
155
|
+
if (!_hapticsLoaded) {
|
|
156
|
+
_hapticsLoaded = true;
|
|
157
|
+
try {
|
|
158
|
+
_haptics = await import('expo-haptics');
|
|
159
|
+
} catch {
|
|
160
|
+
_haptics = null;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return _haptics;
|
|
164
|
+
}
|
|
165
|
+
var _pulsar = null;
|
|
166
|
+
var _pulsarChecked = false;
|
|
167
|
+
var _pulsarAvailable = false;
|
|
168
|
+
function isPulsarNativeRegistered() {
|
|
169
|
+
try {
|
|
170
|
+
const g = globalThis;
|
|
171
|
+
if (typeof g.__turboModuleProxy === "function") {
|
|
172
|
+
return g.__turboModuleProxy("RNPulsar") != null;
|
|
173
|
+
}
|
|
174
|
+
return reactNative.NativeModules?.RNPulsar != null;
|
|
175
|
+
} catch {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function getPulsar() {
|
|
180
|
+
if (reactNative.Platform.OS === "web") return null;
|
|
181
|
+
if (!_pulsarChecked) {
|
|
182
|
+
_pulsarChecked = true;
|
|
183
|
+
try {
|
|
184
|
+
if (isPulsarNativeRegistered()) {
|
|
185
|
+
_pulsar = __require("react-native-pulsar");
|
|
186
|
+
_pulsarAvailable = true;
|
|
187
|
+
}
|
|
188
|
+
} catch {
|
|
189
|
+
_pulsar = null;
|
|
190
|
+
_pulsarAvailable = false;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return _pulsarAvailable ? _pulsar : null;
|
|
194
|
+
}
|
|
195
|
+
function impactLight() {
|
|
196
|
+
if (reactNative.Platform.OS === "web") return;
|
|
197
|
+
getHaptics().then((h) => {
|
|
198
|
+
if (h) {
|
|
199
|
+
h.impactAsync(h.ImpactFeedbackStyle.Light);
|
|
200
|
+
} else {
|
|
201
|
+
getPulsar()?.Presets.System.impactLight();
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
var isWeb = reactNative.Platform.OS === "web";
|
|
206
|
+
var s = isWeb ? (n) => n : reactNativeSizeMatters.scale;
|
|
207
|
+
var vs = isWeb ? (n) => n : reactNativeSizeMatters.verticalScale;
|
|
208
|
+
var ms = isWeb ? (n, _factor) => n : reactNativeSizeMatters.moderateScale;
|
|
209
|
+
var mvs = isWeb ? (n, _factor) => n : reactNativeSizeMatters.moderateVerticalScale;
|
|
210
|
+
var glyphMapOf = (mod) => mod.glyphMap ?? {};
|
|
211
|
+
var ALL_FAMILIES = [
|
|
212
|
+
{ name: "Ionicons", component: Ionicons__default.default, getGlyphMap: () => glyphMapOf(Ionicons__default.default) },
|
|
213
|
+
{ name: "MaterialIcons", component: MaterialIcons__default.default, getGlyphMap: () => glyphMapOf(MaterialIcons__default.default) },
|
|
214
|
+
{ name: "FontAwesome5", component: FontAwesome5__default.default, getGlyphMap: () => glyphMapOf(FontAwesome5__default.default) },
|
|
215
|
+
{ name: "Entypo", component: Entypo__default.default, getGlyphMap: () => glyphMapOf(Entypo__default.default) },
|
|
216
|
+
{ name: "AntDesign", component: AntDesign__default.default, getGlyphMap: () => glyphMapOf(AntDesign__default.default) },
|
|
217
|
+
{ name: "Feather", component: Feather__default.default, getGlyphMap: () => glyphMapOf(Feather__default.default) }
|
|
218
|
+
];
|
|
219
|
+
var activeFamilies = ALL_FAMILIES;
|
|
220
|
+
var resolvedCache = null;
|
|
221
|
+
function buildCache() {
|
|
222
|
+
const cache = /* @__PURE__ */ new Map();
|
|
223
|
+
for (const family of activeFamilies) {
|
|
224
|
+
const glyphMap = family.getGlyphMap();
|
|
225
|
+
for (const iconName of Object.keys(glyphMap)) {
|
|
226
|
+
cache.set(iconName, family);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return cache;
|
|
230
|
+
}
|
|
231
|
+
function resolveFamily(name) {
|
|
232
|
+
if (!resolvedCache) {
|
|
233
|
+
resolvedCache = buildCache();
|
|
234
|
+
}
|
|
235
|
+
return resolvedCache.get(name) ?? null;
|
|
236
|
+
}
|
|
237
|
+
function Icon({ name, size, color, family }) {
|
|
238
|
+
let resolved = null;
|
|
239
|
+
if (family) {
|
|
240
|
+
resolved = ALL_FAMILIES.find((f) => f.name === family) ?? null;
|
|
241
|
+
} else {
|
|
242
|
+
resolved = resolveFamily(name);
|
|
243
|
+
}
|
|
244
|
+
if (!resolved) return null;
|
|
245
|
+
const Component = resolved.component;
|
|
246
|
+
return React4__default.default.createElement(Component, { name, size, color });
|
|
247
|
+
}
|
|
248
|
+
function renderIcon(name, size, color) {
|
|
249
|
+
return React4__default.default.createElement(Icon, { name, size, color });
|
|
250
|
+
}
|
|
251
|
+
({
|
|
252
|
+
/** Material-style ease-out — natural deceleration for state changes. */
|
|
253
|
+
standard: reactNativeReanimated.Easing.bezier(0.2, 0, 0, 1),
|
|
254
|
+
/** Strong ease-out for expanding surfaces (Accordion open). */
|
|
255
|
+
expand: reactNativeReanimated.Easing.bezier(0.23, 1, 0.32, 1),
|
|
256
|
+
/** Quick ease-in for collapsing. */
|
|
257
|
+
collapse: reactNativeReanimated.Easing.in(reactNativeReanimated.Easing.ease)
|
|
258
|
+
});
|
|
259
|
+
var PRESS_SCALE = {
|
|
260
|
+
button: 0.95,
|
|
261
|
+
card: 0.98,
|
|
262
|
+
row: 0.97,
|
|
263
|
+
chip: 0.94
|
|
264
|
+
};
|
|
265
|
+
var PressableButton = pressto.createAnimatedPressable((progress) => {
|
|
266
|
+
"worklet";
|
|
267
|
+
const scale2 = 1 - (1 - PRESS_SCALE.button) * progress;
|
|
268
|
+
return { transform: [{ scale: scale2 }] };
|
|
269
|
+
});
|
|
270
|
+
pressto.createAnimatedPressable((progress) => {
|
|
271
|
+
"worklet";
|
|
272
|
+
const scale2 = 1 - (1 - PRESS_SCALE.card) * progress;
|
|
273
|
+
return { transform: [{ scale: scale2 }] };
|
|
274
|
+
});
|
|
275
|
+
pressto.createAnimatedPressable((progress) => {
|
|
276
|
+
"worklet";
|
|
277
|
+
const scale2 = 1 - (1 - PRESS_SCALE.row) * progress;
|
|
278
|
+
return { transform: [{ scale: scale2 }] };
|
|
279
|
+
});
|
|
280
|
+
pressto.createAnimatedPressable((progress) => {
|
|
281
|
+
"worklet";
|
|
282
|
+
const scale2 = 1 - (1 - PRESS_SCALE.chip) * progress;
|
|
283
|
+
return { transform: [{ scale: scale2 }] };
|
|
284
|
+
});
|
|
285
|
+
pressto.createAnimatedPressable((progress) => {
|
|
286
|
+
"worklet";
|
|
287
|
+
const scale2 = 1 - (1 - PRESS_SCALE.button) * progress;
|
|
288
|
+
return { transform: [{ scale: scale2 }] };
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
// src/components/IconButton/IconButton.tsx
|
|
292
|
+
var sizeMap = {
|
|
293
|
+
// AUDIT FIX: sm was 32pt — below Apple HIG 44pt minimum touch target.
|
|
294
|
+
sm: { container: s(44), icon: 18 },
|
|
295
|
+
md: { container: s(44), icon: 20 },
|
|
296
|
+
lg: { container: s(52), icon: 24 }
|
|
297
|
+
};
|
|
298
|
+
function IconButtonBase({
|
|
299
|
+
iconName,
|
|
300
|
+
icon,
|
|
301
|
+
iconColor,
|
|
302
|
+
variant = "primary",
|
|
303
|
+
size = "md",
|
|
304
|
+
loading = false,
|
|
305
|
+
badge,
|
|
306
|
+
disabled,
|
|
307
|
+
style,
|
|
308
|
+
onPress,
|
|
309
|
+
accessibilityLabel,
|
|
310
|
+
accessibilityHint
|
|
311
|
+
}) {
|
|
312
|
+
const { colors } = useTheme();
|
|
313
|
+
const isDisabled = disabled || loading;
|
|
314
|
+
const handlePress = () => {
|
|
315
|
+
impactLight();
|
|
316
|
+
onPress?.();
|
|
317
|
+
};
|
|
318
|
+
const containerVariantStyle = {
|
|
319
|
+
primary: { backgroundColor: colors.primary },
|
|
320
|
+
secondary: { backgroundColor: colors.surface },
|
|
321
|
+
outline: { backgroundColor: "transparent", borderWidth: 1.5, borderColor: colors.border },
|
|
322
|
+
text: { backgroundColor: "transparent" },
|
|
323
|
+
destructive: { backgroundColor: colors.destructive }
|
|
324
|
+
}[variant];
|
|
325
|
+
const defaultIconColor = {
|
|
326
|
+
primary: colors.primaryForeground,
|
|
327
|
+
secondary: colors.foreground,
|
|
328
|
+
outline: colors.foreground,
|
|
329
|
+
text: colors.foreground,
|
|
330
|
+
destructive: colors.destructiveForeground
|
|
331
|
+
}[variant];
|
|
332
|
+
const spinnerColor = variant === "destructive" ? colors.destructiveForeground : variant === "primary" ? colors.primaryForeground : colors.foreground;
|
|
333
|
+
const { container: containerSize, icon: iconSize } = sizeMap[size];
|
|
334
|
+
const resolvedIcon = iconName ? renderIcon(iconName, iconSize, iconColor ?? defaultIconColor) : icon;
|
|
335
|
+
const showBadge = badge !== void 0 && badge !== false && badge !== 0;
|
|
336
|
+
const badgeCount = typeof badge === "number" ? Math.min(badge, 99) : null;
|
|
337
|
+
const showCount = typeof badge === "number" && badge > 0;
|
|
338
|
+
return /* @__PURE__ */ React4__default.default.createElement(reactNative.View, { style: styles.wrapper }, /* @__PURE__ */ React4__default.default.createElement(
|
|
339
|
+
PressableButton,
|
|
340
|
+
{
|
|
341
|
+
style: [
|
|
342
|
+
styles.base,
|
|
343
|
+
containerVariantStyle,
|
|
344
|
+
{ width: containerSize, height: containerSize },
|
|
345
|
+
isDisabled && styles.disabled,
|
|
346
|
+
style
|
|
347
|
+
],
|
|
348
|
+
enabled: !isDisabled,
|
|
349
|
+
onPress: handlePress,
|
|
350
|
+
rippleColor: "transparent",
|
|
351
|
+
touchSoundDisabled: true,
|
|
352
|
+
activateOnHover: true,
|
|
353
|
+
accessibilityRole: "button",
|
|
354
|
+
accessibilityLabel: accessibilityLabel ?? iconName ?? "icon button",
|
|
355
|
+
accessibilityHint,
|
|
356
|
+
accessibilityState: { disabled: isDisabled, busy: loading }
|
|
357
|
+
},
|
|
358
|
+
loading ? /* @__PURE__ */ React4__default.default.createElement(reactNative.ActivityIndicator, { size: "small", color: spinnerColor }) : resolvedIcon
|
|
359
|
+
), showBadge && /* @__PURE__ */ React4__default.default.createElement(reactNative.View, { style: [
|
|
360
|
+
styles.badge,
|
|
361
|
+
{ backgroundColor: colors.primary },
|
|
362
|
+
showCount ? styles.badgeCount : styles.badgeDot
|
|
363
|
+
] }, showCount && /* @__PURE__ */ React4__default.default.createElement(reactNative.Text, { style: [styles.badgeText, { color: colors.primaryForeground }] }, badgeCount)));
|
|
364
|
+
}
|
|
365
|
+
var IconButton = React4__default.default.memo(IconButtonBase);
|
|
366
|
+
var styles = reactNative.StyleSheet.create({
|
|
367
|
+
wrapper: {
|
|
368
|
+
alignSelf: "flex-start"
|
|
369
|
+
},
|
|
370
|
+
base: {
|
|
371
|
+
borderRadius: 9999,
|
|
372
|
+
alignItems: "center",
|
|
373
|
+
justifyContent: "center"
|
|
374
|
+
},
|
|
375
|
+
disabled: {
|
|
376
|
+
opacity: 0.45
|
|
377
|
+
},
|
|
378
|
+
badge: {
|
|
379
|
+
position: "absolute",
|
|
380
|
+
top: -2,
|
|
381
|
+
right: -2,
|
|
382
|
+
alignItems: "center",
|
|
383
|
+
justifyContent: "center"
|
|
384
|
+
},
|
|
385
|
+
badgeDot: {
|
|
386
|
+
width: 8,
|
|
387
|
+
height: 8,
|
|
388
|
+
borderRadius: 9999
|
|
389
|
+
},
|
|
390
|
+
badgeCount: {
|
|
391
|
+
minWidth: 16,
|
|
392
|
+
height: 16,
|
|
393
|
+
borderRadius: 9999,
|
|
394
|
+
paddingHorizontal: 3
|
|
395
|
+
},
|
|
396
|
+
badgeText: {
|
|
397
|
+
fontFamily: "Sohne-Bold",
|
|
398
|
+
fontSize: ms(9),
|
|
399
|
+
lineHeight: 14
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
// src/tokens.ts
|
|
404
|
+
var BREAKPOINTS = {
|
|
405
|
+
wide: 700
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
// src/components/AppHeader/AppHeader.tsx
|
|
409
|
+
function AppHeader({
|
|
410
|
+
title,
|
|
411
|
+
subtitle,
|
|
412
|
+
onBack,
|
|
413
|
+
backIconName = "chevron-left",
|
|
414
|
+
left,
|
|
415
|
+
right,
|
|
416
|
+
titleAlign = "auto",
|
|
417
|
+
bordered = true,
|
|
418
|
+
withSafeArea = true,
|
|
419
|
+
backgroundColor,
|
|
420
|
+
style
|
|
421
|
+
}) {
|
|
422
|
+
const { colors } = useTheme();
|
|
423
|
+
const insets = reactNativeSafeAreaContext.useSafeAreaInsets();
|
|
424
|
+
const { width } = reactNative.useWindowDimensions();
|
|
425
|
+
const isWide = width >= BREAKPOINTS.wide;
|
|
426
|
+
const centered = titleAlign === "center" || titleAlign === "auto" && isWide;
|
|
427
|
+
const leftNode = left ?? (onBack ? /* @__PURE__ */ React4__default.default.createElement(
|
|
428
|
+
IconButton,
|
|
429
|
+
{
|
|
430
|
+
iconName: backIconName,
|
|
431
|
+
variant: "text",
|
|
432
|
+
size: "md",
|
|
433
|
+
onPress: onBack,
|
|
434
|
+
accessibilityLabel: "Go back"
|
|
435
|
+
}
|
|
436
|
+
) : null);
|
|
437
|
+
const titleBlock = /* @__PURE__ */ React4__default.default.createElement(reactNative.View, { style: [styles2.titleBlock, centered && styles2.titleBlockCentered], pointerEvents: "none" }, title ? /* @__PURE__ */ React4__default.default.createElement(
|
|
438
|
+
reactNative.Text,
|
|
439
|
+
{
|
|
440
|
+
style: [styles2.title, { color: colors.foreground }, centered && styles2.textCentered],
|
|
441
|
+
numberOfLines: 1,
|
|
442
|
+
allowFontScaling: true,
|
|
443
|
+
accessibilityRole: "header"
|
|
444
|
+
},
|
|
445
|
+
title
|
|
446
|
+
) : null, subtitle ? /* @__PURE__ */ React4__default.default.createElement(
|
|
447
|
+
reactNative.Text,
|
|
448
|
+
{
|
|
449
|
+
style: [styles2.subtitle, { color: colors.foregroundMuted }, centered && styles2.textCentered],
|
|
450
|
+
numberOfLines: 1,
|
|
451
|
+
allowFontScaling: true
|
|
452
|
+
},
|
|
453
|
+
subtitle
|
|
454
|
+
) : null);
|
|
455
|
+
return /* @__PURE__ */ React4__default.default.createElement(
|
|
456
|
+
reactNative.View,
|
|
457
|
+
{
|
|
458
|
+
style: [
|
|
459
|
+
styles2.container,
|
|
460
|
+
{
|
|
461
|
+
backgroundColor: backgroundColor ?? colors.background,
|
|
462
|
+
paddingTop: withSafeArea ? insets.top : 0,
|
|
463
|
+
borderBottomWidth: bordered ? reactNative.StyleSheet.hairlineWidth : 0,
|
|
464
|
+
borderBottomColor: colors.border
|
|
465
|
+
},
|
|
466
|
+
style
|
|
467
|
+
]
|
|
468
|
+
},
|
|
469
|
+
/* @__PURE__ */ React4__default.default.createElement(reactNative.View, { style: styles2.bar }, centered ? /* @__PURE__ */ React4__default.default.createElement(React4__default.default.Fragment, null, /* @__PURE__ */ React4__default.default.createElement(reactNative.View, { style: reactNative.StyleSheet.absoluteFill }, titleBlock), /* @__PURE__ */ React4__default.default.createElement(reactNative.View, { style: styles2.side }, leftNode), /* @__PURE__ */ React4__default.default.createElement(reactNative.View, { style: [styles2.side, styles2.sideRight] }, right)) : /* @__PURE__ */ React4__default.default.createElement(React4__default.default.Fragment, null, /* @__PURE__ */ React4__default.default.createElement(reactNative.View, { style: styles2.side }, leftNode), titleBlock, /* @__PURE__ */ React4__default.default.createElement(reactNative.View, { style: [styles2.side, styles2.sideRight] }, right)))
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
var styles2 = reactNative.StyleSheet.create({
|
|
473
|
+
container: {
|
|
474
|
+
width: "100%"
|
|
475
|
+
},
|
|
476
|
+
bar: {
|
|
477
|
+
minHeight: vs(48),
|
|
478
|
+
flexDirection: "row",
|
|
479
|
+
alignItems: "center",
|
|
480
|
+
paddingHorizontal: s(8)
|
|
481
|
+
},
|
|
482
|
+
side: {
|
|
483
|
+
minWidth: s(44),
|
|
484
|
+
flexDirection: "row",
|
|
485
|
+
alignItems: "center",
|
|
486
|
+
justifyContent: "flex-start"
|
|
487
|
+
},
|
|
488
|
+
sideRight: {
|
|
489
|
+
justifyContent: "flex-end"
|
|
490
|
+
},
|
|
491
|
+
titleBlock: {
|
|
492
|
+
flex: 1,
|
|
493
|
+
justifyContent: "center",
|
|
494
|
+
paddingHorizontal: s(8),
|
|
495
|
+
gap: vs(1)
|
|
496
|
+
},
|
|
497
|
+
titleBlockCentered: {
|
|
498
|
+
alignItems: "center"
|
|
499
|
+
},
|
|
500
|
+
title: {
|
|
501
|
+
fontFamily: "Sohne-SemiBold",
|
|
502
|
+
fontSize: ms(18),
|
|
503
|
+
lineHeight: mvs(24)
|
|
504
|
+
},
|
|
505
|
+
subtitle: {
|
|
506
|
+
fontFamily: "Sohne-Regular",
|
|
507
|
+
fontSize: ms(13),
|
|
508
|
+
lineHeight: mvs(16)
|
|
509
|
+
},
|
|
510
|
+
textCentered: {
|
|
511
|
+
textAlign: "center"
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
exports.AppHeader = AppHeader;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { AppHeader } from './chunk-AZJF2BLK.mjs';
|
|
2
|
+
import './chunk-3U4SSNWP.mjs';
|
|
3
|
+
import './chunk-3DKJ2GIC.mjs';
|
|
4
|
+
import './chunk-EJ7ZPXOH.mjs';
|
|
5
|
+
import './chunk-DVK4G2GT.mjs';
|
|
6
|
+
import './chunk-QY3X2UYR.mjs';
|
|
7
|
+
import './chunk-T7XZ7H7Y.mjs';
|
|
8
|
+
import './chunk-SOYNZDVY.mjs';
|
|
9
|
+
import './chunk-2CE3TQVY.mjs';
|
|
10
|
+
import './chunk-Y6FXYEAI.mjs';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ViewStyle } from 'react-native';
|
|
3
|
+
|
|
4
|
+
type AvatarSize = 'sm' | 'md' | 'lg' | 'xl';
|
|
5
|
+
type AvatarStatus = 'online' | 'offline' | 'busy' | 'away';
|
|
6
|
+
interface AvatarProps {
|
|
7
|
+
src?: string | null;
|
|
8
|
+
/** Manual initials (max 2 chars). */
|
|
9
|
+
fallback?: string;
|
|
10
|
+
/** Full name — extracts up to 2 initials (e.g. "Julian Cruz" → "JC"). */
|
|
11
|
+
fallbackText?: string;
|
|
12
|
+
size?: AvatarSize | number;
|
|
13
|
+
/** Optional status indicator dot — bottom-right corner. */
|
|
14
|
+
status?: AvatarStatus;
|
|
15
|
+
style?: ViewStyle;
|
|
16
|
+
}
|
|
17
|
+
declare function AvatarBase({ src, fallback, fallbackText, size, status, style }: AvatarProps): React.JSX.Element;
|
|
18
|
+
declare const Avatar: React.MemoExoticComponent<typeof AvatarBase>;
|
|
19
|
+
|
|
20
|
+
export { Avatar, type AvatarProps, type AvatarSize };
|
package/dist/Avatar.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ViewStyle } from 'react-native';
|
|
3
|
+
|
|
4
|
+
type AvatarSize = 'sm' | 'md' | 'lg' | 'xl';
|
|
5
|
+
type AvatarStatus = 'online' | 'offline' | 'busy' | 'away';
|
|
6
|
+
interface AvatarProps {
|
|
7
|
+
src?: string | null;
|
|
8
|
+
/** Manual initials (max 2 chars). */
|
|
9
|
+
fallback?: string;
|
|
10
|
+
/** Full name — extracts up to 2 initials (e.g. "Julian Cruz" → "JC"). */
|
|
11
|
+
fallbackText?: string;
|
|
12
|
+
size?: AvatarSize | number;
|
|
13
|
+
/** Optional status indicator dot — bottom-right corner. */
|
|
14
|
+
status?: AvatarStatus;
|
|
15
|
+
style?: ViewStyle;
|
|
16
|
+
}
|
|
17
|
+
declare function AvatarBase({ src, fallback, fallbackText, size, status, style }: AvatarProps): React.JSX.Element;
|
|
18
|
+
declare const Avatar: React.MemoExoticComponent<typeof AvatarBase>;
|
|
19
|
+
|
|
20
|
+
export { Avatar, type AvatarProps, type AvatarSize };
|