diff --git a/app/index.js b/app/index.js index a58bc3754..f34e341e7 100644 --- a/app/index.js +++ b/app/index.js @@ -13,20 +13,18 @@ import 'react-native-get-random-values'; import { Buffer } from 'buffer'; import React from 'react'; import { AppRegistry, LogBox } from 'react-native'; -import { createTamagui, TamaguiProvider } from 'tamagui'; +import { TamaguiProvider } from 'tamagui'; import App from './App'; import { name as appName } from './app.json'; +import tamaguiConfig from './tamagui.config'; import './src/utils/ethers'; import 'react-native-gesture-handler'; -import { config } from '@tamagui/config/v2-native'; // Set global Buffer before any other imports global.Buffer = Buffer; -const tamaguiConfig = createTamagui(config); - LogBox.ignoreLogs([ /bad setState/, 'Warning, duplicate ID for input', diff --git a/app/jest.config.cjs b/app/jest.config.cjs index 7d552df0d..b97823593 100644 --- a/app/jest.config.cjs +++ b/app/jest.config.cjs @@ -6,7 +6,7 @@ module.exports = { preset: 'react-native', moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], transformIgnorePatterns: [ - 'node_modules/(?!(react-native|@react-native|@react-navigation|@react-native-community|@segment/analytics-react-native|@openpassport|react-native-keychain|react-native-check-version|react-native-nfc-manager|react-native-passport-reader|react-native-gesture-handler|uuid|@stablelib|@react-native-google-signin|react-native-cloud-storage|@react-native-clipboard|@react-native-firebase|@selfxyz|@sentry|@anon-aadhaar)/)', + 'node_modules/(?!(react-native|@react-native|@react-navigation|@react-native-community|@segment/analytics-react-native|@openpassport|react-native-keychain|react-native-check-version|react-native-nfc-manager|react-native-passport-reader|react-native-gesture-handler|uuid|@stablelib|@react-native-google-signin|react-native-cloud-storage|@react-native-clipboard|@react-native-firebase|@selfxyz|@sentry|@anon-aadhaar|react-native-svg|react-native-svg-circle-country-flags)/)', ], setupFiles: ['/jest.setup.js'], testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.[jt]sx?$', @@ -17,8 +17,12 @@ module.exports = { '^@$': '/src', '^@tests/(.*)$': '/tests/src/$1', '^@tests$': '/tests/src', + // Map react-native-svg to app's node_modules for all packages + '^react-native-svg$': '/node_modules/react-native-svg', '^@selfxyz/mobile-sdk-alpha$': '/../packages/mobile-sdk-alpha/dist/cjs/index.cjs', + '^@selfxyz/mobile-sdk-alpha/components$': + '/../packages/mobile-sdk-alpha/dist/cjs/components/index.cjs', '^@selfxyz/mobile-sdk-alpha/onboarding/(.*)$': '/../packages/mobile-sdk-alpha/dist/cjs/flows/onboarding/$1.cjs', '^@selfxyz/mobile-sdk-alpha/disclosing/(.*)$': diff --git a/app/jest.setup.js b/app/jest.setup.js index 36d1c068b..2a79522ae 100644 --- a/app/jest.setup.js +++ b/app/jest.setup.js @@ -682,6 +682,50 @@ jest.mock('./src/utils/notifications/notificationService', () => require('./tests/__setup__/notificationServiceMock.js'), ); +// Mock react-native-svg +jest.mock('react-native-svg', () => { + const React = require('react'); + + // Mock SvgXml component that handles XML strings + const SvgXml = React.forwardRef( + ({ xml, width, height, style, ...props }, ref) => { + return React.createElement('div', { + ref, + style: { + width: width || 'auto', + height: height || 'auto', + display: 'inline-block', + ...style, + }, + dangerouslySetInnerHTML: { __html: xml }, + ...props, + }); + }, + ); + SvgXml.displayName = 'SvgXml'; + + return { + __esModule: true, + default: SvgXml, + SvgXml, + Svg: props => React.createElement('Svg', props, props.children), + Circle: props => React.createElement('Circle', props, props.children), + Path: props => React.createElement('Path', props, props.children), + G: props => React.createElement('G', props, props.children), + Rect: props => React.createElement('Rect', props, props.children), + Defs: props => React.createElement('Defs', props, props.children), + LinearGradient: props => + React.createElement('LinearGradient', props, props.children), + Stop: props => React.createElement('Stop', props, props.children), + ClipPath: props => React.createElement('ClipPath', props, props.children), + Polygon: props => React.createElement('Polygon', props, props.children), + Polyline: props => React.createElement('Polyline', props, props.children), + Line: props => React.createElement('Line', props, props.children), + Text: props => React.createElement('Text', props, props.children), + TSpan: props => React.createElement('TSpan', props, props.children), + }; +}); + // Mock React Navigation jest.mock('@react-navigation/native', () => { const actualNav = jest.requireActual('@react-navigation/native'); diff --git a/app/package.json b/app/package.json index 299b4ad0f..70283679e 100644 --- a/app/package.json +++ b/app/package.json @@ -143,7 +143,6 @@ "react-native-screens": "4.15.3", "react-native-sqlite-storage": "^6.0.1", "react-native-svg": "15.12.1", - "react-native-svg-circle-country-flags": "^0.2.2", "react-native-svg-web": "^1.0.9", "react-native-web": "^0.19.0", "react-qr-barcode-scanner": "^2.1.8", diff --git a/app/src/components/Disclosures.tsx b/app/src/components/Disclosures.tsx index a55702119..58809af5c 100644 --- a/app/src/components/Disclosures.tsx +++ b/app/src/components/Disclosures.tsx @@ -8,8 +8,8 @@ import { XStack, YStack } from 'tamagui'; import type { Country3LetterCode } from '@selfxyz/common/constants'; import { countryCodes } from '@selfxyz/common/constants'; import type { SelfAppDisclosureConfig } from '@selfxyz/common/utils'; +import { BodyText } from '@selfxyz/mobile-sdk-alpha/components'; -import { BodyText } from '@/components/typography/BodyText'; import CheckMark from '@/images/icons/checkmark.svg'; import { slate200, slate500 } from '@/utils/colors'; @@ -115,7 +115,7 @@ const DisclosureItem: React.FC = ({ paddingHorizontal={10} > - + {text} diff --git a/app/src/components/FeedbackModal.tsx b/app/src/components/FeedbackModal.tsx index de4c20e77..651050151 100644 --- a/app/src/components/FeedbackModal.tsx +++ b/app/src/components/FeedbackModal.tsx @@ -6,7 +6,8 @@ import React, { useState } from 'react'; import { Alert, Modal, StyleSheet, Text, TextInput, View } from 'react-native'; import { Button, XStack, YStack } from 'tamagui'; -import { Caption } from '@/components/typography/Caption'; +import { Caption } from '@selfxyz/mobile-sdk-alpha/components'; + import { black, slate400, white, zinc800, zinc900 } from '@/utils/colors'; import { advercase, dinot } from '@/utils/fonts'; diff --git a/app/src/components/FeedbackModalScreen.tsx b/app/src/components/FeedbackModalScreen.tsx index 1554ea8e9..1b1c793e8 100644 --- a/app/src/components/FeedbackModalScreen.tsx +++ b/app/src/components/FeedbackModalScreen.tsx @@ -6,10 +6,13 @@ import React, { useCallback } from 'react'; import { Modal, StyleSheet } from 'react-native'; import { styled, View, XStack, YStack } from 'tamagui'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import { SecondaryButton } from '@/components/buttons/SecondaryButton'; -import Description from '@/components/typography/Description'; -import { Title } from '@/components/typography/Title'; +import { + Description, + PrimaryButton, + SecondaryButton, + Title, +} from '@selfxyz/mobile-sdk-alpha/components'; + import ModalClose from '@/images/icons/modal_close.svg'; import LogoInversed from '@/images/logo_inversed.svg'; import { white } from '@/utils/colors'; @@ -112,7 +115,9 @@ const FeedbackModalScreen: React.FC = ({ )} - {modalParams.titleText} + + {modalParams.titleText} + {modalParams.bodyText} diff --git a/app/src/components/NavBar/AadhaarNavBar.tsx b/app/src/components/NavBar/AadhaarNavBar.tsx index 39ea21f60..080b25a2f 100644 --- a/app/src/components/NavBar/AadhaarNavBar.tsx +++ b/app/src/components/NavBar/AadhaarNavBar.tsx @@ -61,10 +61,12 @@ export const AadhaarNavBar = (props: NativeStackHeaderProps) => { /> AADHAAR REGISTRATION diff --git a/app/src/components/NavBar/BaseNavBar.tsx b/app/src/components/NavBar/BaseNavBar.tsx index d345c8ea3..2c3ff10a5 100644 --- a/app/src/components/NavBar/BaseNavBar.tsx +++ b/app/src/components/NavBar/BaseNavBar.tsx @@ -3,13 +3,14 @@ // NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. import React, { useMemo } from 'react'; +import type { TextProps } from 'react-native'; import type { SystemBarStyle } from 'react-native-edge-to-edge'; import { SystemBars } from 'react-native-edge-to-edge'; -import type { TextProps, ViewProps, XStackProps } from 'tamagui'; +import type { ViewProps, XStackProps } from 'tamagui'; import { Button, View, XStack } from 'tamagui'; import { ChevronLeft, X } from '@tamagui/lucide-icons'; -import { Title } from '@/components/typography/Title'; +import { Title } from '@selfxyz/mobile-sdk-alpha/components'; interface NavBarProps extends XStackProps { children: React.ReactNode; diff --git a/app/src/components/NavBar/DocumentFlowNavBar.tsx b/app/src/components/NavBar/DocumentFlowNavBar.tsx index d790902c2..79c8d0633 100644 --- a/app/src/components/NavBar/DocumentFlowNavBar.tsx +++ b/app/src/components/NavBar/DocumentFlowNavBar.tsx @@ -32,7 +32,7 @@ export const DocumentFlowNavBar = ({ justifyContent="space-between" > navigation.goBack()} /> - + {title} { } /> - + {props.options.title} { } /> - + {props.options.title} )} - + {title} {': '} diff --git a/app/src/components/buttons/PrimaryButtonLongHold.web.tsx b/app/src/components/buttons/PrimaryButtonLongHold.web.tsx deleted file mode 100644 index c98138528..000000000 --- a/app/src/components/buttons/PrimaryButtonLongHold.web.tsx +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc. -// SPDX-License-Identifier: BUSL-1.1 -// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. - -import React, { useEffect, useState } from 'react'; -import type { LayoutChangeEvent } from 'react-native'; -// Tamagui imports for web -import { AnimatePresence, YStack } from 'tamagui'; - -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import type { HeldPrimaryButtonProps } from '@/components/buttons/PrimaryButtonLongHold.shared'; -import { - ACTION_TIMER, - COLORS, -} from '@/components/buttons/PrimaryButtonLongHold.shared'; - -export function HeldPrimaryButton({ - children, - onLongPress, - ...props -}: HeldPrimaryButtonProps) { - const [hasTriggered, setHasTriggered] = useState(false); - const [size, setSize] = useState({ width: 0, height: 0 }); - const [isPressed, setIsPressed] = useState(false); - - const onPressIn = () => { - setHasTriggered(false); - setIsPressed(true); - }; - - const onPressOut = () => { - setIsPressed(false); - }; - - const getButtonSize = (e: LayoutChangeEvent) => { - const width = e.nativeEvent.layout.width - 1; - const height = e.nativeEvent.layout.height - 1; - setSize({ width, height }); - }; - - useEffect(() => { - // Web: Use setTimeout to trigger onLongPress - let timeoutId: NodeJS.Timeout; - if (isPressed && !hasTriggered) { - timeoutId = setTimeout(() => { - if (isPressed && !hasTriggered) { - setHasTriggered(true); - onLongPress(); - } - }, ACTION_TIMER); - } - return () => { - if (timeoutId) clearTimeout(timeoutId); - }; - }, [hasTriggered, onLongPress, isPressed]); - - const renderAnimatedComponent = () => { - // Web: Use Tamagui AnimatePresence with CSS transitions - return ( - - {isPressed && ( - - )} - - ); - }; - - return ( - - {children} - - ); -} diff --git a/app/src/components/homeScreen/idCard.tsx b/app/src/components/homeScreen/idCard.tsx index 53b5b9aa2..ff5b27a96 100644 --- a/app/src/components/homeScreen/idCard.tsx +++ b/app/src/components/homeScreen/idCard.tsx @@ -142,7 +142,7 @@ const IdCardLayout: FC = ({ Verified{' '} diff --git a/app/src/components/typography/BodyText.ts b/app/src/components/typography/BodyText.ts deleted file mode 100644 index 0cbc9274e..000000000 --- a/app/src/components/typography/BodyText.ts +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc. -// SPDX-License-Identifier: BUSL-1.1 -// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. - -import { styled, Text } from 'tamagui'; - -import { dinot } from '@/utils/fonts'; - -export const BodyText = styled(Text, { - fontFamily: dinot, -}); diff --git a/app/src/components/typography/Caption.tsx b/app/src/components/typography/Caption.tsx deleted file mode 100644 index 5d3b7149c..000000000 --- a/app/src/components/typography/Caption.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc. -// SPDX-License-Identifier: BUSL-1.1 -// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. - -import { styled } from 'tamagui'; - -import { BodyText } from '@/components/typography/BodyText'; -import { slate400 } from '@/utils/colors'; - -export const Caption = styled(BodyText, { - fontSize: 15, - color: slate400, - variants: { - size: { - small: { - fontSize: 14, - }, - large: { - fontSize: 16, - }, - }, - }, -}); diff --git a/app/src/components/typography/Description.tsx b/app/src/components/typography/Description.tsx deleted file mode 100644 index 924cfe327..000000000 --- a/app/src/components/typography/Description.tsx +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc. -// SPDX-License-Identifier: BUSL-1.1 -// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. - -import React from 'react'; -import { StyleSheet } from 'react-native'; -import type { TextProps } from 'tamagui'; -import { Text } from 'tamagui'; - -import { slate500 } from '@/utils/colors'; -import { dinot } from '@/utils/fonts'; - -type DescriptionProps = TextProps; - -const Description = ({ children, style, ...props }: DescriptionProps) => { - return ( - - {children} - - ); -}; - -export default Description; - -const styles = StyleSheet.create({ - description: { - color: slate500, - fontSize: 18, - lineHeight: 23, - textAlign: 'center', - fontFamily: dinot, - }, -}); diff --git a/app/src/components/typography/SubHeader.tsx b/app/src/components/typography/SubHeader.tsx deleted file mode 100644 index 1d173696d..000000000 --- a/app/src/components/typography/SubHeader.tsx +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc. -// SPDX-License-Identifier: BUSL-1.1 -// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. - -import { styled, Text } from 'tamagui'; - -import { dinot } from '@/utils/fonts'; - -export const SubHeader = styled(Text, { - fontFamily: dinot, - lineHeight: 18, - fontSize: 15, - fontWeight: '500', - letterSpacing: 0.6, - textTransform: 'uppercase', - textAlign: 'center', -}); diff --git a/app/src/components/typography/Title.tsx b/app/src/components/typography/Title.tsx deleted file mode 100644 index e77b5d234..000000000 --- a/app/src/components/typography/Title.tsx +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc. -// SPDX-License-Identifier: BUSL-1.1 -// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. - -import type { StyleProp, TextStyle } from 'react-native'; -import { styled, Text } from 'tamagui'; - -import { advercase } from '@/utils/fonts'; - -export const Title = styled( - Text, - { - fontSize: 28, - lineHeight: 35, - fontFamily: advercase, - variants: { - size: { - large: { - fontSize: 38, - lineHeight: 47, - }, - }, - }, - }, - { - acceptsClassName: true, - style: (props: { style?: StyleProp }) => props.style, - }, -); diff --git a/app/src/layouts/SimpleScrolledTitleLayout.tsx b/app/src/layouts/SimpleScrolledTitleLayout.tsx index ca85f8dbe..2df632d32 100644 --- a/app/src/layouts/SimpleScrolledTitleLayout.tsx +++ b/app/src/layouts/SimpleScrolledTitleLayout.tsx @@ -7,9 +7,12 @@ import React from 'react'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { ScrollView, YStack } from 'tamagui'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import { SecondaryButton } from '@/components/buttons/SecondaryButton'; -import { Title } from '@/components/typography/Title'; +import { + PrimaryButton, + SecondaryButton, + Title, +} from '@selfxyz/mobile-sdk-alpha/components'; + import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; import { white } from '@/utils/colors'; @@ -50,7 +53,10 @@ export default function SimpleScrolledTitleLayout({ )} {secondaryButtonText && onSecondaryButtonPress && ( - + {secondaryButtonText} )} diff --git a/app/src/screens/account/recovery/AccountRecoveryChoiceScreen.tsx b/app/src/screens/account/recovery/AccountRecoveryChoiceScreen.tsx index d39a33253..48de3df54 100644 --- a/app/src/screens/account/recovery/AccountRecoveryChoiceScreen.tsx +++ b/app/src/screens/account/recovery/AccountRecoveryChoiceScreen.tsx @@ -9,13 +9,15 @@ import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { isUserRegisteredWithAlternativeCSCA } from '@selfxyz/common/utils/passports/validate'; import { useSelfClient } from '@selfxyz/mobile-sdk-alpha'; +import { + Caption, + Description, + PrimaryButton, + SecondaryButton, + Title, +} from '@selfxyz/mobile-sdk-alpha/components'; import { BackupEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import { SecondaryButton } from '@/components/buttons/SecondaryButton'; -import { Caption } from '@/components/typography/Caption'; -import Description from '@/components/typography/Description'; -import { Title } from '@/components/typography/Title'; import useHapticNavigation from '@/hooks/useHapticNavigation'; import Keyboard from '@/images/icons/keyboard.svg'; import RestoreAccountSvg from '@/images/icons/restore_account.svg'; diff --git a/app/src/screens/account/recovery/AccountRecoveryScreen.tsx b/app/src/screens/account/recovery/AccountRecoveryScreen.tsx index b151056f2..2e2c31e41 100644 --- a/app/src/screens/account/recovery/AccountRecoveryScreen.tsx +++ b/app/src/screens/account/recovery/AccountRecoveryScreen.tsx @@ -5,12 +5,14 @@ import React from 'react'; import { View, YStack } from 'tamagui'; +import { + Description, + PrimaryButton, + SecondaryButton, + Title, +} from '@selfxyz/mobile-sdk-alpha/components'; import { BackupEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import { SecondaryButton } from '@/components/buttons/SecondaryButton'; -import Description from '@/components/typography/Description'; -import { Title } from '@/components/typography/Title'; import useHapticNavigation from '@/hooks/useHapticNavigation'; import RestoreAccountSvg from '@/images/icons/restore_account.svg'; import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; diff --git a/app/src/screens/account/recovery/DocumentDataNotFoundScreen.tsx b/app/src/screens/account/recovery/DocumentDataNotFoundScreen.tsx index fff7ad5b0..f1fbdf8c4 100644 --- a/app/src/screens/account/recovery/DocumentDataNotFoundScreen.tsx +++ b/app/src/screens/account/recovery/DocumentDataNotFoundScreen.tsx @@ -8,10 +8,12 @@ import { hasAnyValidRegisteredDocument, useSelfClient, } from '@selfxyz/mobile-sdk-alpha'; +import { + Description, + PrimaryButton, + Title, +} from '@selfxyz/mobile-sdk-alpha/components'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import Description from '@/components/typography/Description'; -import { Title } from '@/components/typography/Title'; import useHapticNavigation from '@/hooks/useHapticNavigation'; import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; import analytics from '@/utils/analytics'; @@ -41,13 +43,15 @@ const DocumentDataNotFoundScreen: React.FC = () => { return ( - + <Title style={{ textAlign: 'center', color: white }}> ✨ Are you new here? It seems like you need to go through the registration flow first. diff --git a/app/src/screens/account/recovery/RecoverWithPhraseScreen.tsx b/app/src/screens/account/recovery/RecoverWithPhraseScreen.tsx index de49cc0e5..a7613bfcf 100644 --- a/app/src/screens/account/recovery/RecoverWithPhraseScreen.tsx +++ b/app/src/screens/account/recovery/RecoverWithPhraseScreen.tsx @@ -12,10 +12,12 @@ import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { isUserRegisteredWithAlternativeCSCA } from '@selfxyz/common/utils/passports/validate'; import { useSelfClient } from '@selfxyz/mobile-sdk-alpha'; +import { + Description, + SecondaryButton, +} from '@selfxyz/mobile-sdk-alpha/components'; import { BackupEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; -import { SecondaryButton } from '@/components/buttons/SecondaryButton'; -import Description from '@/components/typography/Description'; import Paste from '@/images/icons/paste.svg'; import type { RootStackParamList } from '@/navigation'; import { useAuth } from '@/providers/authProvider'; @@ -115,7 +117,7 @@ const RecoverWithPhraseScreen: React.FC = () => { paddingBottom="$2.5" style={styles.layout} > - + Your recovery phrase has 24 words. Enter the words in the correct order, separated by spaces. diff --git a/app/src/screens/account/settings/CloudBackupScreen.tsx b/app/src/screens/account/settings/CloudBackupScreen.tsx index d1afbe930..469477ce7 100644 --- a/app/src/screens/account/settings/CloudBackupScreen.tsx +++ b/app/src/screens/account/settings/CloudBackupScreen.tsx @@ -9,14 +9,16 @@ import { useNavigation } from '@react-navigation/native'; import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { useSelfClient } from '@selfxyz/mobile-sdk-alpha'; +import { + Caption, + Description, + PrimaryButton, + SecondaryButton, + Title, +} from '@selfxyz/mobile-sdk-alpha/components'; import { BackupEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; import BackupDocumentationLink from '@/components/BackupDocumentationLink'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import { SecondaryButton } from '@/components/buttons/SecondaryButton'; -import { Caption } from '@/components/typography/Caption'; -import Description from '@/components/typography/Description'; -import { Title } from '@/components/typography/Title'; import { useModal } from '@/hooks/useModal'; import Cloud from '@/images/icons/logo_cloud_backup.svg'; import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; diff --git a/app/src/screens/account/settings/SettingsScreen.tsx b/app/src/screens/account/settings/SettingsScreen.tsx index 3d1b476d1..5e95d56bd 100644 --- a/app/src/screens/account/settings/SettingsScreen.tsx +++ b/app/src/screens/account/settings/SettingsScreen.tsx @@ -13,8 +13,8 @@ import { useNavigation } from '@react-navigation/native'; import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { Bug, FileText } from '@tamagui/lucide-icons'; -import { pressedStyle } from '@/components/buttons/pressedStyle'; -import { BodyText } from '@/components/typography/BodyText'; +import { BodyText, pressedStyle } from '@selfxyz/mobile-sdk-alpha/components'; + import { appStoreUrl, gitHubUrl, @@ -119,7 +119,7 @@ const MenuButton: React.FC = ({ children, Icon, onPress }) => ( hitSlop={4} > - + {children} @@ -262,14 +262,16 @@ ${deviceInfo.map(([k, v]) => `${k}=${v}`).join('; ')} pressStyle={pressedStyle} onPress={goToStore} > - Leave an app store review + + Leave an app store review + {social.map(([Icon, href], i) => ( ))} - + SELF {/* Dont remove if not viewing on ios */} diff --git a/app/src/screens/account/settings/ShowRecoveryPhraseScreen.tsx b/app/src/screens/account/settings/ShowRecoveryPhraseScreen.tsx index 5017709b9..dcfec766d 100644 --- a/app/src/screens/account/settings/ShowRecoveryPhraseScreen.tsx +++ b/app/src/screens/account/settings/ShowRecoveryPhraseScreen.tsx @@ -4,8 +4,9 @@ import React, { useCallback } from 'react'; +import { Description } from '@selfxyz/mobile-sdk-alpha/components'; + import Mnemonic from '@/components/Mnemonic'; -import Description from '@/components/typography/Description'; import useMnemonic from '@/hooks/useMnemonic'; import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; diff --git a/app/src/screens/app/DeferredLinkingInfoScreen.tsx b/app/src/screens/app/DeferredLinkingInfoScreen.tsx index e1db56959..7a2d17f72 100644 --- a/app/src/screens/app/DeferredLinkingInfoScreen.tsx +++ b/app/src/screens/app/DeferredLinkingInfoScreen.tsx @@ -6,9 +6,12 @@ import React from 'react'; import { YStack } from 'tamagui'; import { useNavigation } from '@react-navigation/native'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import Description from '@/components/typography/Description'; -import { Title } from '@/components/typography/Title'; +import { + Description, + PrimaryButton, + Title, +} from '@selfxyz/mobile-sdk-alpha/components'; + import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; import { black, white } from '@/utils/colors'; import { confirmTap } from '@/utils/haptic'; diff --git a/app/src/screens/app/LaunchScreen.tsx b/app/src/screens/app/LaunchScreen.tsx index bbdf72ffe..f2e42ef7f 100644 --- a/app/src/screens/app/LaunchScreen.tsx +++ b/app/src/screens/app/LaunchScreen.tsx @@ -8,11 +8,13 @@ import { Gesture, GestureDetector } from 'react-native-gesture-handler'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { Anchor, Text, YStack } from 'tamagui'; +import { + AbstractButton, + BodyText, + Caption, +} from '@selfxyz/mobile-sdk-alpha/components'; import { AppEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; -import AbstractButton from '@/components/buttons/AbstractButton'; -import { BodyText } from '@/components/typography/BodyText'; -import { Caption } from '@/components/typography/Caption'; import { privacyUrl, termsUrl } from '@/consts/links'; import useConnectionModal from '@/hooks/useConnectionModal'; import useHapticNavigation from '@/hooks/useHapticNavigation'; @@ -64,11 +66,13 @@ const LaunchScreen: React.FC = () => { Take control of your digital identity Self is the easiest way to verify your identity safely wherever you are. diff --git a/app/src/screens/app/ModalScreen.tsx b/app/src/screens/app/ModalScreen.tsx index 2c3a9e7ac..aa2e42f2b 100644 --- a/app/src/screens/app/ModalScreen.tsx +++ b/app/src/screens/app/ModalScreen.tsx @@ -7,10 +7,13 @@ import { styled, View, XStack, YStack } from 'tamagui'; import type { StaticScreenProps } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import { SecondaryButton } from '@/components/buttons/SecondaryButton'; -import Description from '@/components/typography/Description'; -import { Title } from '@/components/typography/Title'; +import { + Description, + PrimaryButton, + SecondaryButton, + Title, +} from '@selfxyz/mobile-sdk-alpha/components'; + import ModalClose from '@/images/icons/modal_close.svg'; import LogoInversed from '@/images/logo_inversed.svg'; import { white } from '@/utils/colors'; @@ -112,9 +115,11 @@ const ModalScreen: React.FC = ({ route: { params } }) => { {params?.preventDismiss ? null : } - {params?.titleText} + + {params?.titleText as React.ReactNode} + - {params?.bodyText} + {params?.bodyText as React.ReactNode} diff --git a/app/src/screens/dev/CreateMockScreen.tsx b/app/src/screens/dev/CreateMockScreen.tsx index a645a3363..2beb2dbce 100644 --- a/app/src/screens/dev/CreateMockScreen.tsx +++ b/app/src/screens/dev/CreateMockScreen.tsx @@ -29,11 +29,10 @@ import { signatureAlgorithmToStrictSignatureAlgorithm, useSelfClient, } from '@selfxyz/mobile-sdk-alpha'; +import { Caption, PrimaryButton } from '@selfxyz/mobile-sdk-alpha/components'; import { MockDataEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; import ButtonsContainer from '@/components/ButtonsContainer'; -import { Caption } from '@/components/typography/Caption'; import { useMockDataForm } from '@/hooks/useMockDataForm'; import SelfDevCard from '@/images/card-dev.svg'; import IdIcon from '@/images/icons/id_icon.svg'; @@ -88,7 +87,7 @@ const MockDocumentTitleCard = () => { Generate mock document data - + Configure data parameters to generate a mock document for testing purposes on the Self Protocol. diff --git a/app/src/screens/dev/CreateMockScreenDeepLink.tsx b/app/src/screens/dev/CreateMockScreenDeepLink.tsx index 8563e344e..5f0cb8c6b 100644 --- a/app/src/screens/dev/CreateMockScreenDeepLink.tsx +++ b/app/src/screens/dev/CreateMockScreenDeepLink.tsx @@ -14,13 +14,15 @@ import { countryCodes } from '@selfxyz/common/constants'; import { getCountryISO2 } from '@selfxyz/common/constants/countries'; import type { IdDocInput } from '@selfxyz/common/utils'; import { genMockIdDocAndInitDataParsing } from '@selfxyz/common/utils/passports'; +import { + BodyText, + Description, + PrimaryButton, + Title, +} from '@selfxyz/mobile-sdk-alpha/components'; import { MockDataEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; import ButtonsContainer from '@/components/ButtonsContainer'; -import { BodyText } from '@/components/typography/BodyText'; -import Description from '@/components/typography/Description'; -import { Title } from '@/components/typography/Title'; import type { RootStackParamList } from '@/navigation'; import { storePassportData } from '@/providers/passportDataProvider'; import useUserStore from '@/stores/userStore'; @@ -196,7 +198,7 @@ const CreateMockScreenDeepLink: React.FC = () => { > - + Onboarding your Developer ID diff --git a/app/src/screens/documents/aadhaar/AadhaarUploadErrorScreen.tsx b/app/src/screens/documents/aadhaar/AadhaarUploadErrorScreen.tsx index c5ef05f47..dd73ce08d 100644 --- a/app/src/screens/documents/aadhaar/AadhaarUploadErrorScreen.tsx +++ b/app/src/screens/documents/aadhaar/AadhaarUploadErrorScreen.tsx @@ -8,12 +8,14 @@ import type { RouteProp } from '@react-navigation/native'; import { useNavigation, useRoute } from '@react-navigation/native'; import { useSelfClient } from '@selfxyz/mobile-sdk-alpha'; +import { + BodyText, + PrimaryButton, + SecondaryButton, +} from '@selfxyz/mobile-sdk-alpha/components'; import { AadhaarEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; import { getErrorMessages } from '@selfxyz/mobile-sdk-alpha/onboarding/import-aadhaar'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import { SecondaryButton } from '@/components/buttons/SecondaryButton'; -import { BodyText } from '@/components/typography/BodyText'; import WarningIcon from '@/images/warning.svg'; import { useSafeAreaInsets } from '@/mocks/react-native-safe-area-context'; import { black, slate100, slate200, slate500, white } from '@/utils/colors'; @@ -58,14 +60,16 @@ const AadhaarUploadErrorScreen: React.FC = () => { borderBlockWidth={1} borderBlockColor={slate200} > - + {title} {description} diff --git a/app/src/screens/documents/aadhaar/AadhaarUploadScreen.tsx b/app/src/screens/documents/aadhaar/AadhaarUploadScreen.tsx index a914e8b19..55705a51e 100644 --- a/app/src/screens/documents/aadhaar/AadhaarUploadScreen.tsx +++ b/app/src/screens/documents/aadhaar/AadhaarUploadScreen.tsx @@ -10,11 +10,10 @@ import { useNavigation } from '@react-navigation/native'; import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { useSelfClient } from '@selfxyz/mobile-sdk-alpha'; +import { BodyText, PrimaryButton } from '@selfxyz/mobile-sdk-alpha/components'; import { AadhaarEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; import { useAadhaar } from '@selfxyz/mobile-sdk-alpha/onboarding/import-aadhaar'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import { BodyText } from '@/components/typography/BodyText'; import { useModal } from '@/hooks/useModal'; import AadhaarImage from '@/images/512w.png'; import { useSafeAreaInsets } from '@/mocks/react-native-safe-area-context'; @@ -170,17 +169,23 @@ const AadhaarUploadScreen: React.FC = () => { borderBlockWidth={1} borderBlockColor={slate200} > - + Generate a QR code from the mAadaar app - + Save the QR code to your photo library and upload it here. SELF DOES NOT STORE THIS INFORMATION. diff --git a/app/src/screens/documents/aadhaar/AadhaarUploadedSuccessScreen.tsx b/app/src/screens/documents/aadhaar/AadhaarUploadedSuccessScreen.tsx index df161f318..2af3e05ba 100644 --- a/app/src/screens/documents/aadhaar/AadhaarUploadedSuccessScreen.tsx +++ b/app/src/screens/documents/aadhaar/AadhaarUploadedSuccessScreen.tsx @@ -8,10 +8,9 @@ import { useNavigation } from '@react-navigation/native'; import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { useSelfClient } from '@selfxyz/mobile-sdk-alpha'; +import { BodyText, PrimaryButton } from '@selfxyz/mobile-sdk-alpha/components'; import { AadhaarEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import { BodyText } from '@/components/typography/BodyText'; import BlueCheckIcon from '@/images/blue_check.svg'; import { useSafeAreaInsets } from '@/mocks/react-native-safe-area-context'; import type { RootStackParamList } from '@/navigation'; @@ -45,14 +44,16 @@ const AadhaarUploadedSuccessScreen: React.FC = () => { borderBlockWidth={1} borderBlockColor={slate200} > - + QR code upload successful You are ready to register your Aadhaar card with Self. diff --git a/app/src/screens/documents/management/DocumentDataInfoScreen.tsx b/app/src/screens/documents/management/DocumentDataInfoScreen.tsx index 5da9abf3c..270427f1f 100644 --- a/app/src/screens/documents/management/DocumentDataInfoScreen.tsx +++ b/app/src/screens/documents/management/DocumentDataInfoScreen.tsx @@ -10,9 +10,9 @@ import { useFocusEffect } from '@react-navigation/native'; import type { PassportMetadata } from '@selfxyz/common/types'; import type { AadhaarData } from '@selfxyz/common/utils/types'; import { useSelfClient } from '@selfxyz/mobile-sdk-alpha'; +import { Caption } from '@selfxyz/mobile-sdk-alpha/components'; import { DocumentEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; -import { Caption } from '@/components/typography/Caption'; import { usePassport } from '@/providers/passportDataProvider'; import { black, slate200, white } from '@/utils/colors'; import { extraYPadding } from '@/utils/constants'; @@ -63,10 +63,8 @@ const InfoRow: React.FC<{ }> = ({ label, value }) => ( - {label} - - {value} - + {label} + {value} diff --git a/app/src/screens/documents/management/ManageDocumentsScreen.tsx b/app/src/screens/documents/management/ManageDocumentsScreen.tsx index f0e030aa7..d14eb9f47 100644 --- a/app/src/screens/documents/management/ManageDocumentsScreen.tsx +++ b/app/src/screens/documents/management/ManageDocumentsScreen.tsx @@ -15,10 +15,12 @@ import type { DocumentMetadata, } from '@selfxyz/common/utils/types'; import { useSelfClient } from '@selfxyz/mobile-sdk-alpha'; +import { + PrimaryButton, + SecondaryButton, +} from '@selfxyz/mobile-sdk-alpha/components'; import { DocumentEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import { SecondaryButton } from '@/components/buttons/SecondaryButton'; import ButtonsContainer from '@/components/ButtonsContainer'; import type { RootStackParamList } from '@/navigation'; import { usePassport } from '@/providers/passportDataProvider'; diff --git a/app/src/screens/documents/scanning/DocumentCameraScreen.tsx b/app/src/screens/documents/scanning/DocumentCameraScreen.tsx index 890091447..0bf74f621 100644 --- a/app/src/screens/documents/scanning/DocumentCameraScreen.tsx +++ b/app/src/screens/documents/scanning/DocumentCameraScreen.tsx @@ -11,6 +11,12 @@ import { hasAnyValidRegisteredDocument, useSelfClient, } from '@selfxyz/mobile-sdk-alpha'; +import { + Additional, + Description, + SecondaryButton, + Title, +} from '@selfxyz/mobile-sdk-alpha/components'; import { PassportEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; import { mrzReadInstructions, @@ -18,12 +24,8 @@ import { } from '@selfxyz/mobile-sdk-alpha/onboarding/read-mrz'; import passportScanAnimation from '@/assets/animations/passport_scan.json'; -import { SecondaryButton } from '@/components/buttons/SecondaryButton'; import { DelayedLottieView } from '@/components/DelayedLottieView'; import { PassportCamera } from '@/components/native/PassportCamera'; -import Additional from '@/components/typography/Additional'; -import Description from '@/components/typography/Description'; -import { Title } from '@/components/typography/Title'; import useHapticNavigation from '@/hooks/useHapticNavigation'; import Scan from '@/images/icons/passport_camera_scan.svg'; import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; diff --git a/app/src/screens/documents/scanning/DocumentCameraTroubleScreen.tsx b/app/src/screens/documents/scanning/DocumentCameraTroubleScreen.tsx index a8d1b4e1f..765d6f1eb 100644 --- a/app/src/screens/documents/scanning/DocumentCameraTroubleScreen.tsx +++ b/app/src/screens/documents/scanning/DocumentCameraTroubleScreen.tsx @@ -4,9 +4,10 @@ import React, { useEffect } from 'react'; +import { Caption } from '@selfxyz/mobile-sdk-alpha/components'; + import type { TipProps } from '@/components/Tips'; import Tips from '@/components/Tips'; -import { Caption } from '@/components/typography/Caption'; import useHapticNavigation from '@/hooks/useHapticNavigation'; import Activity from '@/images/icons/activity.svg'; import PassportCameraBulb from '@/images/icons/passport_camera_bulb.svg'; @@ -60,12 +61,12 @@ const DocumentCameraTroubleScreen: React.FC = () => { title="Having trouble scanning your ID?" onDismiss={go} header={ - + Here are a few tips that might help: } footer={ - + Following these steps should help your phone's camera capture the ID page quickly and clearly! diff --git a/app/src/screens/documents/scanning/DocumentNFCMethodSelectionScreen.tsx b/app/src/screens/documents/scanning/DocumentNFCMethodSelectionScreen.tsx index 092170176..326423bef 100644 --- a/app/src/screens/documents/scanning/DocumentNFCMethodSelectionScreen.tsx +++ b/app/src/screens/documents/scanning/DocumentNFCMethodSelectionScreen.tsx @@ -9,13 +9,15 @@ import { useNavigation } from '@react-navigation/native'; import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { useSelfClient } from '@selfxyz/mobile-sdk-alpha'; +import { + BodyText, + Description, + PrimaryButton, + SecondaryButton, + Title, +} from '@selfxyz/mobile-sdk-alpha/components'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import { SecondaryButton } from '@/components/buttons/SecondaryButton'; import ButtonsContainer from '@/components/ButtonsContainer'; -import { BodyText } from '@/components/typography/BodyText'; -import Description from '@/components/typography/Description'; -import { Title } from '@/components/typography/Title'; import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; import type { RootStackParamList } from '@/navigation'; import { white } from '@/utils/colors'; @@ -173,7 +175,9 @@ const DocumentNFCMethodSelectionScreen: React.FC = () => { maxLength={6} /> {error ? ( - {error} + + {error} + ) : null} )} diff --git a/app/src/screens/documents/scanning/DocumentNFCScanScreen.tsx b/app/src/screens/documents/scanning/DocumentNFCScanScreen.tsx index e3b5b8284..040144bb8 100644 --- a/app/src/screens/documents/scanning/DocumentNFCScanScreen.tsx +++ b/app/src/screens/documents/scanning/DocumentNFCScanScreen.tsx @@ -36,15 +36,17 @@ import { hasAnyValidRegisteredDocument, useSelfClient, } from '@selfxyz/mobile-sdk-alpha'; +import { + BodyText, + PrimaryButton, + SecondaryButton, + Title, +} from '@selfxyz/mobile-sdk-alpha/components'; import { PassportEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; import passportVerifyAnimation from '@/assets/animations/passport_verify.json'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import { SecondaryButton } from '@/components/buttons/SecondaryButton'; import ButtonsContainer from '@/components/ButtonsContainer'; import TextsContainer from '@/components/TextsContainer'; -import { BodyText } from '@/components/typography/BodyText'; -import { Title } from '@/components/typography/Title'; import { useFeedbackAutoHide } from '@/hooks/useFeedbackAutoHide'; import useHapticNavigation from '@/hooks/useHapticNavigation'; import NFC_IMAGE from '@/images/nfc.png'; @@ -546,7 +548,7 @@ const DocumentNFCScanScreen: React.FC = () => { <> - <BodyText textAlign="center"> + <BodyText style={{ textAlign: 'center' }}> {nfcMessage && nfcMessage.trim().length > 0 ? ( nfcMessage ) : ( @@ -588,24 +590,22 @@ const DocumentNFCScanScreen: React.FC = () => { </GestureDetector> {isNfcEnabled ? ( <> - <Title style={styles.title} marginTop="$2"> + <Title style={[styles.title, { marginTop: 8 }]}> Find the RFID chip in your ID Place your phone against the chip and keep it still until the sensor reads it. - + SELF DOES NOT STORE THIS INFORMATION. ) : ( <> - + {dialogMessage} diff --git a/app/src/screens/documents/scanning/DocumentNFCScanScreen.web.tsx b/app/src/screens/documents/scanning/DocumentNFCScanScreen.web.tsx index 1a6afeadb..73608bf5c 100644 --- a/app/src/screens/documents/scanning/DocumentNFCScanScreen.web.tsx +++ b/app/src/screens/documents/scanning/DocumentNFCScanScreen.web.tsx @@ -9,13 +9,15 @@ import { hasAnyValidRegisteredDocument, useSelfClient, } from '@selfxyz/mobile-sdk-alpha'; +import { + BodyText, + SecondaryButton, + Title, +} from '@selfxyz/mobile-sdk-alpha/components'; import { PassportEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; -import { SecondaryButton } from '@/components/buttons/SecondaryButton'; import ButtonsContainer from '@/components/ButtonsContainer'; import TextsContainer from '@/components/TextsContainer'; -import { BodyText } from '@/components/typography/BodyText'; -import { Title } from '@/components/typography/Title'; import useHapticNavigation from '@/hooks/useHapticNavigation'; import NFC_IMAGE from '@/images/nfc.png'; import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; @@ -48,7 +50,7 @@ const DocumentNFCScanScreen: React.FC = () => { <> - <BodyText textAlign="center">TODO implement</BodyText> + <BodyText style={{ textAlign: 'center' }}>TODO implement</BodyText> </TextsContainer> <Image height="$8" diff --git a/app/src/screens/documents/scanning/DocumentNFCTroubleScreen.tsx b/app/src/screens/documents/scanning/DocumentNFCTroubleScreen.tsx index c49b3c655..107ab90b9 100644 --- a/app/src/screens/documents/scanning/DocumentNFCTroubleScreen.tsx +++ b/app/src/screens/documents/scanning/DocumentNFCTroubleScreen.tsx @@ -7,10 +7,10 @@ import { View } from 'react-native'; import { Gesture, GestureDetector } from 'react-native-gesture-handler'; import { YStack } from 'tamagui'; -import { SecondaryButton } from '@/components/buttons/SecondaryButton'; +import { Caption, SecondaryButton } from '@selfxyz/mobile-sdk-alpha/components'; + import type { TipProps } from '@/components/Tips'; import Tips from '@/components/Tips'; -import { Caption } from '@/components/typography/Caption'; import { useFeedbackAutoHide } from '@/hooks/useFeedbackAutoHide'; import useHapticNavigation from '@/hooks/useHapticNavigation'; import SimpleScrolledTitleLayout from '@/layouts/SimpleScrolledTitleLayout'; @@ -80,7 +80,7 @@ const DocumentNFCTroubleScreen: React.FC = () => { origin: 'passport/nfc-trouble', }) } - marginBottom={0} + style={{ marginBottom: 0 }} > Report Issue </SecondaryButton> @@ -95,13 +95,13 @@ const DocumentNFCTroubleScreen: React.FC = () => { > <GestureDetector gesture={devModeTap}> <View collapsable={false}> - <Caption size="large" color={slate500}> + <Caption size="large" style={{ color: slate500 }}> Here are some tips to help you successfully scan the RFID chip: </Caption> </View> </GestureDetector> <Tips items={tips} /> - <Caption size="large" color={slate500}> + <Caption size="large" style={{ color: slate500 }}> These steps should help improve the success rate of reading the RFID chip in your passport. If the issue persists, double-check that your device supports NFC and that your passport's RFID is functioning diff --git a/app/src/screens/documents/selection/ConfirmBelongingScreen.tsx b/app/src/screens/documents/selection/ConfirmBelongingScreen.tsx index bdc9ae4d4..97d4b3eca 100644 --- a/app/src/screens/documents/selection/ConfirmBelongingScreen.tsx +++ b/app/src/screens/documents/selection/ConfirmBelongingScreen.tsx @@ -8,6 +8,11 @@ import { usePreventRemove } from '@react-navigation/native'; import type { DocumentCategory } from '@selfxyz/common/utils/types'; import { loadSelectedDocument, useSelfClient } from '@selfxyz/mobile-sdk-alpha'; +import { + Description, + PrimaryButton, + Title, +} from '@selfxyz/mobile-sdk-alpha/components'; import { PassportEvents, ProofEvents, @@ -15,10 +20,7 @@ import { import { getPreRegistrationDescription } from '@selfxyz/mobile-sdk-alpha/onboarding/confirm-identification'; import successAnimation from '@/assets/animations/loading/success.json'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; import { DelayedLottieView } from '@/components/DelayedLottieView'; -import Description from '@/components/typography/Description'; -import { Title } from '@/components/typography/Title'; import useHapticNavigation from '@/hooks/useHapticNavigation'; import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; import { styles } from '@/screens/verification/ProofRequestStatusScreen'; @@ -144,8 +146,8 @@ const ConfirmBelongingScreen: React.FC<ConfirmBelongingScreenProps> = () => { paddingBottom={20} backgroundColor={white} > - <Title textAlign="center">Confirm your identity - + Confirm your identity + {getPreRegistrationDescription()} - + {countryName} @@ -126,10 +125,10 @@ const CountryPickerScreen: React.FC = () => { - + Select the country that issued your ID - + Self has support for over 300 ID types. You can select the type of ID in the next step @@ -141,11 +140,13 @@ const CountryPickerScreen: React.FC = () => { {showSuggestion && ( SUGGESTION @@ -156,11 +157,13 @@ const CountryPickerScreen: React.FC = () => { onSelect={onPressCountry} /> SELECT AN ISSUING COUNTRY diff --git a/app/src/screens/documents/selection/DocumentOnboardingScreen.tsx b/app/src/screens/documents/selection/DocumentOnboardingScreen.tsx index 5390b63ae..4d3dc4bbd 100644 --- a/app/src/screens/documents/selection/DocumentOnboardingScreen.tsx +++ b/app/src/screens/documents/selection/DocumentOnboardingScreen.tsx @@ -8,16 +8,18 @@ import { StyleSheet } from 'react-native'; import { SystemBars } from 'react-native-edge-to-edge'; import { useNavigation } from '@react-navigation/native'; +import { + Additional, + Description, + PrimaryButton, + SecondaryButton, + Title, +} from '@selfxyz/mobile-sdk-alpha/components'; import { PassportEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; import passportOnboardingAnimation from '@/assets/animations/passport_onboarding.json'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import { SecondaryButton } from '@/components/buttons/SecondaryButton'; import ButtonsContainer from '@/components/ButtonsContainer'; import TextsContainer from '@/components/TextsContainer'; -import Additional from '@/components/typography/Additional'; -import Description from '@/components/typography/Description'; -import { Title } from '@/components/typography/Title'; import useHapticNavigation from '@/hooks/useHapticNavigation'; import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; import { black, slate100, white } from '@/utils/colors'; diff --git a/app/src/screens/documents/selection/IDPickerScreen.tsx b/app/src/screens/documents/selection/IDPickerScreen.tsx index f4bd27112..229eaf6d9 100644 --- a/app/src/screens/documents/selection/IDPickerScreen.tsx +++ b/app/src/screens/documents/selection/IDPickerScreen.tsx @@ -9,14 +9,13 @@ import type { RouteProp } from '@react-navigation/native'; import { useRoute } from '@react-navigation/native'; import { SdkEvents, useSelfClient } from '@selfxyz/mobile-sdk-alpha'; +import { BodyText, RoundFlag } from '@selfxyz/mobile-sdk-alpha/components'; import AadhaarLogo from '@selfxyz/mobile-sdk-alpha/svgs/icons/aadhaar.svg'; import EPassportLogoRounded from '@selfxyz/mobile-sdk-alpha/svgs/icons/epassport_rounded.svg'; import PlusIcon from '@selfxyz/mobile-sdk-alpha/svgs/icons/plus.svg'; import SelfLogo from '@selfxyz/mobile-sdk-alpha/svgs/logo.svg'; -import { RoundFlag } from '@/components/flag/RoundFlag'; import { DocumentFlowNavBar } from '@/components/NavBar/DocumentFlowNavBar'; -import { BodyText } from '@/components/typography/BodyText'; import type { RootStackParamList } from '@/navigation'; import { black, slate100, slate300, slate400, white } from '@/utils/colors'; import { extraYPadding } from '@/utils/constants'; @@ -132,10 +131,12 @@ const IDPickerScreen: React.FC = () => { Select an ID type @@ -156,10 +157,18 @@ const IDPickerScreen: React.FC = () => { {getDocumentLogo(docType)} - + {getDocumentName(docType)} - + {getDocumentDescription(docType)} @@ -167,10 +176,12 @@ const IDPickerScreen: React.FC = () => { ))} Be sure your document is ready to scan diff --git a/app/src/screens/home/ProofHistoryList.tsx b/app/src/screens/home/ProofHistoryList.tsx index 2efb38e7d..47b3ff43e 100644 --- a/app/src/screens/home/ProofHistoryList.tsx +++ b/app/src/screens/home/ProofHistoryList.tsx @@ -14,7 +14,8 @@ import { useNavigation } from '@react-navigation/native'; import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { CheckSquare2, Wallet, XCircle } from '@tamagui/lucide-icons'; -import { BodyText } from '@/components/typography/BodyText'; +import { BodyText } from '@selfxyz/mobile-sdk-alpha/components'; + import type { RootStackParamList } from '@/navigation'; import { useProofHistoryStore } from '@/stores/proofHistoryStore'; import type { ProofHistory } from '@/stores/proofTypes'; @@ -231,14 +232,18 @@ export const ProofHistoryList: React.FC = ({ /> )} - + {item.appName} {formatDate(item.timestamp)} diff --git a/app/src/screens/home/ProofHistoryScreen.tsx b/app/src/screens/home/ProofHistoryScreen.tsx index 7ef9be892..15952c168 100644 --- a/app/src/screens/home/ProofHistoryScreen.tsx +++ b/app/src/screens/home/ProofHistoryScreen.tsx @@ -15,7 +15,8 @@ import { useNavigation } from '@react-navigation/native'; import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { CheckSquare2, Wallet, XCircle } from '@tamagui/lucide-icons'; -import { BodyText } from '@/components/typography/BodyText'; +import { BodyText } from '@selfxyz/mobile-sdk-alpha/components'; + import type { RootStackParamList } from '@/navigation'; import { useProofHistoryStore } from '@/stores/proofHistoryStore'; import type { ProofHistory } from '@/stores/proofTypes'; @@ -238,10 +239,12 @@ const ProofHistoryScreen: React.FC = () => { /> )} - + {item.appName} - + {formatDate(item.timestamp)} diff --git a/app/src/screens/onboarding/AccountVerifiedSuccessScreen.tsx b/app/src/screens/onboarding/AccountVerifiedSuccessScreen.tsx index 9281a703f..1469839d1 100644 --- a/app/src/screens/onboarding/AccountVerifiedSuccessScreen.tsx +++ b/app/src/screens/onboarding/AccountVerifiedSuccessScreen.tsx @@ -7,13 +7,15 @@ import { YStack } from 'tamagui'; import { useNavigation } from '@react-navigation/native'; import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; +import { + Description, + PrimaryButton, + Title, +} from '@selfxyz/mobile-sdk-alpha/components'; import { BackupEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; import proofSuccessAnimation from '@/assets/animations/proof_success.json'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; import { DelayedLottieView } from '@/components/DelayedLottieView'; -import Description from '@/components/typography/Description'; -import { Title } from '@/components/typography/Title'; import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; import type { RootStackParamList } from '@/navigation'; import { styles } from '@/screens/verification/ProofRequestStatusScreen'; diff --git a/app/src/screens/onboarding/DisclaimerScreen.tsx b/app/src/screens/onboarding/DisclaimerScreen.tsx index a428cd938..28a68253e 100644 --- a/app/src/screens/onboarding/DisclaimerScreen.tsx +++ b/app/src/screens/onboarding/DisclaimerScreen.tsx @@ -8,13 +8,15 @@ import { YStack } from 'tamagui'; import { useNavigation } from '@react-navigation/native'; import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; +import { + Caution, + PrimaryButton, + SubHeader, +} from '@selfxyz/mobile-sdk-alpha/components'; import { AppEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; import warningAnimation from '@/assets/animations/warning.json'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; import { DelayedLottieView } from '@/components/DelayedLottieView'; -import Caution from '@/components/typography/Caution'; -import { SubHeader } from '@/components/typography/SubHeader'; import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; import type { RootStackParamList } from '@/navigation'; import { useSettingStore } from '@/stores/settingStore'; diff --git a/app/src/screens/onboarding/SaveRecoveryPhraseScreen.tsx b/app/src/screens/onboarding/SaveRecoveryPhraseScreen.tsx index 1115d014e..4b2b03550 100644 --- a/app/src/screens/onboarding/SaveRecoveryPhraseScreen.tsx +++ b/app/src/screens/onboarding/SaveRecoveryPhraseScreen.tsx @@ -4,12 +4,15 @@ import React, { useCallback, useState } from 'react'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import { SecondaryButton } from '@/components/buttons/SecondaryButton'; +import { + Caption, + Description, + PrimaryButton, + SecondaryButton, + Title, +} from '@selfxyz/mobile-sdk-alpha/components'; + import Mnemonic from '@/components/Mnemonic'; -import { Caption } from '@/components/typography/Caption'; -import Description from '@/components/typography/Description'; -import { Title } from '@/components/typography/Title'; import useHapticNavigation from '@/hooks/useHapticNavigation'; import useMnemonic from '@/hooks/useMnemonic'; import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; @@ -42,10 +45,10 @@ const SaveRecoveryPhraseScreen: React.FC = () => { justifyContent="space-between" gap={10} > - + <Title style={{ paddingTop: 20, textAlign: 'center' }}> Save your recovery phrase - + This phrase is the only way to recover your account. Keep it secret, keep it safe. @@ -56,7 +59,7 @@ const SaveRecoveryPhraseScreen: React.FC = () => { backgroundColor={white} > - + You can reveal your recovery phrase in settings. diff --git a/app/src/screens/shared/ComingSoonScreen.tsx b/app/src/screens/shared/ComingSoonScreen.tsx index 8c5862523..8a480167d 100644 --- a/app/src/screens/shared/ComingSoonScreen.tsx +++ b/app/src/screens/shared/ComingSoonScreen.tsx @@ -12,13 +12,15 @@ import { hasAnyValidRegisteredDocument, useSelfClient, } from '@selfxyz/mobile-sdk-alpha'; +import { + BodyText, + PrimaryButton, + RoundFlag, + SecondaryButton, + Title, +} from '@selfxyz/mobile-sdk-alpha/components'; import { PassportEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import { SecondaryButton } from '@/components/buttons/SecondaryButton'; -import { RoundFlag } from '@/components/flag/RoundFlag'; -import { BodyText } from '@/components/typography/BodyText'; -import { Title } from '@/components/typography/Title'; import useHapticNavigation from '@/hooks/useHapticNavigation'; import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; import analytics from '@/utils/analytics'; @@ -135,30 +137,36 @@ const ComingSoonScreen: React.FC = ({ route }) => { )} Coming Soon {documentTypeText ? `We're working to roll out support for ${documentTypeText} in ${countryName}.` : `We're working to roll out support in ${countryName}.`} Sign up for live updates. diff --git a/app/src/screens/verification/ProofRequestStatusScreen.tsx b/app/src/screens/verification/ProofRequestStatusScreen.tsx index 2271cab7e..11fe31dc8 100644 --- a/app/src/screens/verification/ProofRequestStatusScreen.tsx +++ b/app/src/screens/verification/ProofRequestStatusScreen.tsx @@ -11,16 +11,18 @@ import { ScrollView, Spinner } from 'tamagui'; import { useIsFocused } from '@react-navigation/native'; import { useSelfClient } from '@selfxyz/mobile-sdk-alpha'; +import { + BodyText, + Description, + PrimaryButton, + Title, + typography, +} from '@selfxyz/mobile-sdk-alpha/components'; import { ProofEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; import loadingAnimation from '@/assets/animations/loading/misc.json'; import failAnimation from '@/assets/animations/proof_failed.json'; import succesAnimation from '@/assets/animations/proof_success.json'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import { BodyText } from '@/components/typography/BodyText'; -import Description from '@/components/typography/Description'; -import { typography } from '@/components/typography/styles'; -import { Title } from '@/components/typography/Title'; import useHapticNavigation from '@/hooks/useHapticNavigation'; import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; import { useProofHistoryStore } from '@/stores/proofHistoryStore'; diff --git a/app/src/screens/verification/ProveScreen.tsx b/app/src/screens/verification/ProveScreen.tsx index d73b4c5af..4444dbcbd 100644 --- a/app/src/screens/verification/ProveScreen.tsx +++ b/app/src/screens/verification/ProveScreen.tsx @@ -24,13 +24,15 @@ import { Eye, EyeOff } from '@tamagui/lucide-icons'; import type { SelfAppDisclosureConfig } from '@selfxyz/common/utils/appType'; import { formatEndpoint } from '@selfxyz/common/utils/scope'; import { useSelfClient } from '@selfxyz/mobile-sdk-alpha'; +import { + BodyText, + Caption, + HeldPrimaryButtonProveScreen, +} from '@selfxyz/mobile-sdk-alpha/components'; import { ProofEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; import miscAnimation from '@/assets/animations/loading/misc.json'; -import { HeldPrimaryButtonProveScreen } from '@/components/buttons/HeldPrimaryButtonProveScreen'; import Disclosures from '@/components/Disclosures'; -import { BodyText } from '@/components/typography/BodyText'; -import { Caption } from '@/components/typography/Caption'; import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; import type { RootStackParamList } from '@/navigation'; import { @@ -238,10 +240,14 @@ const ProveScreen: React.FC = () => { objectFit="contain" /> )} - + {url} - + {selectedApp.appName} is requesting that you prove the following information: @@ -267,10 +273,12 @@ const ProveScreen: React.FC = () => { {formattedUserId && ( {selectedApp?.userIdType === 'hex' ? 'Connected Wallet' @@ -294,15 +302,16 @@ const ProveScreen: React.FC = () => { marginRight={selectedApp?.userIdType === 'hex' ? 12 : 0} > {selectedApp?.userIdType === 'hex' && showFullAddress ? selectedApp.userId @@ -321,10 +330,12 @@ const ProveScreen: React.FC = () => { {selectedApp?.userIdType === 'hex' && ( {showFullAddress ? 'Tap to hide address' @@ -340,10 +351,12 @@ const ProveScreen: React.FC = () => { {selectedApp?.userDefinedData && ( Additional Information: @@ -353,7 +366,9 @@ const ProveScreen: React.FC = () => { borderRadius={8} marginBottom={10} > - + {selectedApp.userDefinedData} @@ -362,12 +377,14 @@ const ProveScreen: React.FC = () => { Self will confirm that these details are accurate and none of your confidential info will be revealed to {selectedApp?.appName} diff --git a/app/src/screens/verification/QRCodeTroubleScreen.tsx b/app/src/screens/verification/QRCodeTroubleScreen.tsx index 17094704d..b65266ce2 100644 --- a/app/src/screens/verification/QRCodeTroubleScreen.tsx +++ b/app/src/screens/verification/QRCodeTroubleScreen.tsx @@ -4,9 +4,10 @@ import React, { useEffect } from 'react'; +import { Caption } from '@selfxyz/mobile-sdk-alpha/components'; + import type { TipProps } from '@/components/Tips'; import Tips from '@/components/Tips'; -import { Caption } from '@/components/typography/Caption'; import useHapticNavigation from '@/hooks/useHapticNavigation'; import SimpleScrolledTitleLayout from '@/layouts/SimpleScrolledTitleLayout'; import { flushAllAnalytics } from '@/utils/analytics'; @@ -55,7 +56,7 @@ const QRCodeTrouble: React.FC = () => { title="Having trouble scanning the QR code?" onDismiss={go} > - + Here are some tips to help you successfully scan the QR code: diff --git a/app/src/screens/verification/QRCodeViewFinderScreen.tsx b/app/src/screens/verification/QRCodeViewFinderScreen.tsx index feb2841ae..c8d2b15c2 100644 --- a/app/src/screens/verification/QRCodeViewFinderScreen.tsx +++ b/app/src/screens/verification/QRCodeViewFinderScreen.tsx @@ -14,14 +14,16 @@ import { import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { useSelfClient } from '@selfxyz/mobile-sdk-alpha'; +import { + Additional, + Description, + Title, +} from '@selfxyz/mobile-sdk-alpha/components'; import { ProofEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; import qrScanAnimation from '@/assets/animations/qr_scan.json'; import type { QRCodeScannerViewProps } from '@/components/native/QRCodeScanner'; import { QRCodeScannerView } from '@/components/native/QRCodeScanner'; -import Additional from '@/components/typography/Additional'; -import Description from '@/components/typography/Description'; -import { Title } from '@/components/typography/Title'; import useConnectionModal from '@/hooks/useConnectionModal'; import useHapticNavigation from '@/hooks/useHapticNavigation'; import QRScan from '@/images/icons/qr_code.svg'; diff --git a/packages/mobile-sdk-alpha/README.md b/packages/mobile-sdk-alpha/README.md index 848a98c1c..3804408db 100644 --- a/packages/mobile-sdk-alpha/README.md +++ b/packages/mobile-sdk-alpha/README.md @@ -21,7 +21,70 @@ Alpha SDK for registering and proving. Adapters-first, React Native-first with w - The `browser` build replaces the scanner with `webNFCScannerShim`, which throws for NFC scanning (not supported on web). -## Quick start (local, monorepo) +## Installation & Setup + +### 1. Install the package + +```bash +npm install @selfxyz/mobile-sdk-alpha +# or +yarn add @selfxyz/mobile-sdk-alpha +``` + +### 2. Link native dependencies and assets + +The SDK includes custom fonts that need to be linked to your app: + +#### Automatic Linking (Recommended) + +If your app uses React Native autolinking (RN 0.60+), run: + +```bash +npx react-native-asset +# or +yarn react-native-asset +``` + +This will automatically copy the font files to your iOS and Android projects. + +#### Manual Linking + +If autolinking doesn't work or you need manual control: + +**iOS:** + +1. Add fonts to your Xcode project: + - Open your Xcode workspace + - Drag the font files from `node_modules/@selfxyz/mobile-sdk-alpha/assets/fonts/` to your project + - Ensure "Copy items if needed" is checked + - Add to your app target + +2. Update `Info.plist` to include the fonts: + ```xml + UIAppFonts + + Advercase-Regular.otf + DINOT-Medium.otf + IBMPlexMono-Regular.otf + + ``` + +**Android:** + +1. Copy font files to your Android project: + + ```bash + cp node_modules/@selfxyz/mobile-sdk-alpha/assets/fonts/* android/app/src/main/assets/fonts/ + ``` + +2. If the `fonts` directory doesn't exist, create it: + ```bash + mkdir -p android/app/src/main/assets/fonts + ``` + +The fonts will be automatically available to your app. + +### 3. Initialize the SDK Provide `scanner`, `network`, and `crypto` adapters. `storage`, `clock`, and `logger` default to no-ops. diff --git a/packages/mobile-sdk-alpha/assets/fonts/Advercase-Regular.otf b/packages/mobile-sdk-alpha/assets/fonts/Advercase-Regular.otf new file mode 100644 index 000000000..e8f7f49ee Binary files /dev/null and b/packages/mobile-sdk-alpha/assets/fonts/Advercase-Regular.otf differ diff --git a/packages/mobile-sdk-alpha/assets/fonts/DINOT-Medium.otf b/packages/mobile-sdk-alpha/assets/fonts/DINOT-Medium.otf new file mode 100755 index 000000000..e6bc7f6ed Binary files /dev/null and b/packages/mobile-sdk-alpha/assets/fonts/DINOT-Medium.otf differ diff --git a/packages/mobile-sdk-alpha/assets/fonts/IBMPlexMono-Regular.otf b/packages/mobile-sdk-alpha/assets/fonts/IBMPlexMono-Regular.otf new file mode 100644 index 000000000..e5b6bfed7 Binary files /dev/null and b/packages/mobile-sdk-alpha/assets/fonts/IBMPlexMono-Regular.otf differ diff --git a/packages/mobile-sdk-alpha/package.json b/packages/mobile-sdk-alpha/package.json index efdd55f79..485264d2f 100644 --- a/packages/mobile-sdk-alpha/package.json +++ b/packages/mobile-sdk-alpha/package.json @@ -89,6 +89,7 @@ "android", "ios", "svgs", + "assets", "mobile-sdk-alpha.podspec", "react-native.config.cjs" ], @@ -113,14 +114,15 @@ "dependencies": { "@babel/runtime": "^7.28.3", "@selfxyz/common": "workspace:^", + "@xstate/react": "^5.0.5", "node-forge": "^1.3.1", + "react-native-svg-circle-country-flags": "^0.2.2", "socket.io-client": "^4.8.1", "uuid": "^11.1.0", "xstate": "^5.20.2", "zustand": "^4.5.2" }, "devDependencies": { - "@tamagui/types": "1.126.14", "@testing-library/react": "^14.1.2", "@types/react": "^18.3.4", "@types/react-dom": "^18.3.0", @@ -141,7 +143,6 @@ "react-native": "0.76.9", "react-native-localize": "^3.5.2", "react-native-web": "^0.21.1", - "tamagui": "1.126.14", "tsup": "^8.0.1", "typescript": "^5.9.2", "vitest": "^2.1.8" @@ -150,12 +151,7 @@ "react": "^18.3.1", "react-native": "0.76.9", "react-native-localize": "*", - "tamagui": "1.126.x" - }, - "peerDependenciesMeta": { - "tamagui": { - "optional": false - } + "react-native-svg": "*" }, "packageManager": "yarn@4.6.0", "publishConfig": { diff --git a/packages/mobile-sdk-alpha/react-native.config.cjs b/packages/mobile-sdk-alpha/react-native.config.cjs index f2bec2f10..14f70f89a 100644 --- a/packages/mobile-sdk-alpha/react-native.config.cjs +++ b/packages/mobile-sdk-alpha/react-native.config.cjs @@ -21,4 +21,5 @@ module.exports = { }, }, }, + assets: ['./assets/fonts'], }; diff --git a/app/src/components/buttons/AbstractButton.tsx b/packages/mobile-sdk-alpha/src/components/buttons/AbstractButton.tsx similarity index 74% rename from app/src/components/buttons/AbstractButton.tsx rename to packages/mobile-sdk-alpha/src/components/buttons/AbstractButton.tsx index cfb865d81..d849c433b 100644 --- a/app/src/components/buttons/AbstractButton.tsx +++ b/packages/mobile-sdk-alpha/src/components/buttons/AbstractButton.tsx @@ -2,24 +2,19 @@ // SPDX-License-Identifier: BUSL-1.1 // NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. -import React from 'react'; -import type { - GestureResponderEvent, - LayoutChangeEvent, - ViewStyle, -} from 'react-native'; -import { Platform, StyleSheet } from 'react-native'; -import type { ViewProps } from 'tamagui'; -import { Button, Text } from 'tamagui'; +import type React from 'react'; +import type { GestureResponderEvent, LayoutChangeEvent, PressableProps, ViewStyle } from 'react-native'; +import { Platform, Pressable, StyleSheet, Text } from 'react-native'; -import { pressedStyle } from '@/components/buttons/pressedStyle'; -import analytics from '@/utils/analytics'; -import { dinot } from '@/utils/fonts'; +import { useSelfClient } from '../../context'; +import { dinot } from '../../utils/fonts'; +import { pressedStyle } from './pressedStyle'; -export interface ButtonProps extends ViewProps { +export interface ButtonProps extends PressableProps { children: React.ReactNode; animatedComponent?: React.ReactNode; trackEvent?: string; + borderWidth?: number; onLayout?: (event: LayoutChangeEvent) => void; } @@ -28,11 +23,8 @@ interface AbstractButtonProps extends ButtonProps { borderColor?: string; borderWidth?: number; color: string; - onPress?: ((e: GestureResponderEvent) => void) | null | undefined; } -const { trackEvent: analyticsTrackEvent } = analytics(); - /* Base Button component that can be used to create different types of buttons use PrimaryButton and SecondaryButton instead of this component or create a new button component @@ -51,6 +43,7 @@ export default function AbstractButton({ onPress, ...props }: AbstractButtonProps) { + const selfClient = useSelfClient(); const hasBorder = borderColor ? true : false; const handlePress = (e: GestureResponderEvent) => { @@ -60,7 +53,7 @@ export default function AbstractButton({ if (parsedEvent) { trackEvent = parsedEvent; } - analyticsTrackEvent(`Click: ${trackEvent}`); + selfClient.trackEvent(`Click: ${trackEvent}`); } if (onPress) { onPress(e); @@ -68,11 +61,10 @@ export default function AbstractButton({ }; return ( - + ); } diff --git a/app/src/components/buttons/HeldPrimaryButtonProveScreen.tsx b/packages/mobile-sdk-alpha/src/components/buttons/HeldPrimaryButtonProveScreen.tsx similarity index 94% rename from app/src/components/buttons/HeldPrimaryButtonProveScreen.tsx rename to packages/mobile-sdk-alpha/src/components/buttons/HeldPrimaryButtonProveScreen.tsx index 05aa961ab..72be9f09f 100644 --- a/app/src/components/buttons/HeldPrimaryButtonProveScreen.tsx +++ b/packages/mobile-sdk-alpha/src/components/buttons/HeldPrimaryButtonProveScreen.tsx @@ -2,16 +2,17 @@ // SPDX-License-Identifier: BUSL-1.1 // NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. -import React, { useEffect } from 'react'; +import type React from 'react'; +import { useEffect } from 'react'; import { ActivityIndicator, View } from 'react-native'; import { assign, createMachine } from 'xstate'; -import { useMachine } from '@xstate/react'; -import { ProofEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; +import { ProofEvents } from '../../constants/analytics'; +import { black } from '../../constants/colors'; +import Description from '../typography/Description'; +import { HeldPrimaryButton } from './PrimaryButtonLongHold'; -import { HeldPrimaryButton } from '@/components/buttons/PrimaryButtonLongHold'; -import Description from '@/components/typography/Description'; -import { black } from '@/utils/colors'; +import { useMachine } from '@xstate/react'; interface HeldPrimaryButtonProveScreenProps { onVerify: () => void; @@ -184,9 +185,7 @@ const buttonMachine = createMachine( }, ); -export const HeldPrimaryButtonProveScreen: React.FC< - HeldPrimaryButtonProveScreenProps -> = ({ +export const HeldPrimaryButtonProveScreen: React.FC = ({ onVerify, selectedAppSessionId, hasScrolledToBottom, diff --git a/app/src/components/buttons/PrimaryButton.tsx b/packages/mobile-sdk-alpha/src/components/buttons/PrimaryButton.tsx similarity index 72% rename from app/src/components/buttons/PrimaryButton.tsx rename to packages/mobile-sdk-alpha/src/components/buttons/PrimaryButton.tsx index 4c2ce4eb6..99bfa3a28 100644 --- a/app/src/components/buttons/PrimaryButton.tsx +++ b/packages/mobile-sdk-alpha/src/components/buttons/PrimaryButton.tsx @@ -2,12 +2,10 @@ // SPDX-License-Identifier: BUSL-1.1 // NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. -import React from 'react'; - -import type { ButtonProps } from '@/components/buttons/AbstractButton'; -import AbstractButton from '@/components/buttons/AbstractButton'; -import { amber50, black, slate300, white } from '@/utils/colors'; -import { normalizeBorderWidth } from '@/utils/styleUtils'; +import { amber50, black, slate300, white } from '../../constants/colors'; +import { normalizeBorderWidth } from '../../utils/styleUtils'; +import type { ButtonProps } from './AbstractButton'; +import AbstractButton from './AbstractButton'; export function PrimaryButton({ children, ...props }: ButtonProps) { const { borderWidth, ...restProps } = props; diff --git a/app/src/components/buttons/PrimaryButtonLongHold.shared.ts b/packages/mobile-sdk-alpha/src/components/buttons/PrimaryButtonLongHold.shared.ts similarity index 86% rename from app/src/components/buttons/PrimaryButtonLongHold.shared.ts rename to packages/mobile-sdk-alpha/src/components/buttons/PrimaryButtonLongHold.shared.ts index 03e9c5087..fcad55581 100644 --- a/app/src/components/buttons/PrimaryButtonLongHold.shared.ts +++ b/packages/mobile-sdk-alpha/src/components/buttons/PrimaryButtonLongHold.shared.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: BUSL-1.1 // NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. -import type { ButtonProps } from '@/components/buttons/AbstractButton'; +import type { ButtonProps } from './AbstractButton'; export interface HeldPrimaryButtonProps extends ButtonProps { onLongPress: () => void; diff --git a/app/src/components/buttons/PrimaryButtonLongHold.tsx b/packages/mobile-sdk-alpha/src/components/buttons/PrimaryButtonLongHold.tsx similarity index 85% rename from app/src/components/buttons/PrimaryButtonLongHold.tsx rename to packages/mobile-sdk-alpha/src/components/buttons/PrimaryButtonLongHold.tsx index f6aecedf6..ef819d641 100644 --- a/app/src/components/buttons/PrimaryButtonLongHold.tsx +++ b/packages/mobile-sdk-alpha/src/components/buttons/PrimaryButtonLongHold.tsx @@ -2,22 +2,15 @@ // SPDX-License-Identifier: BUSL-1.1 // NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. -import React, { useEffect, useState } from 'react'; +import { useEffect, useState } from 'react'; import type { LayoutChangeEvent } from 'react-native'; import { Animated, StyleSheet, useAnimatedValue } from 'react-native'; -import { PrimaryButton } from '@/components/buttons/PrimaryButton'; -import type { HeldPrimaryButtonProps } from '@/components/buttons/PrimaryButtonLongHold.shared'; -import { - ACTION_TIMER, - COLORS, -} from '@/components/buttons/PrimaryButtonLongHold.shared'; +import { PrimaryButton } from './PrimaryButton'; +import type { HeldPrimaryButtonProps } from './PrimaryButtonLongHold.shared'; +import { ACTION_TIMER, COLORS } from './PrimaryButtonLongHold.shared'; -export function HeldPrimaryButton({ - children, - onLongPress, - ...props -}: HeldPrimaryButtonProps) { +export function HeldPrimaryButton({ children, onLongPress, ...props }: HeldPrimaryButtonProps) { const [hasTriggered, setHasTriggered] = useState(false); const [size, setSize] = useState({ width: 0, height: 0 }); diff --git a/packages/mobile-sdk-alpha/src/components/buttons/PrimaryButtonLongHold.web.tsx b/packages/mobile-sdk-alpha/src/components/buttons/PrimaryButtonLongHold.web.tsx new file mode 100644 index 000000000..5b9a7bb40 --- /dev/null +++ b/packages/mobile-sdk-alpha/src/components/buttons/PrimaryButtonLongHold.web.tsx @@ -0,0 +1,93 @@ +// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc. +// SPDX-License-Identifier: BUSL-1.1 +// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. + +import { useEffect, useState } from 'react'; +import type { LayoutChangeEvent } from 'react-native'; +import { Animated } from 'react-native'; + +import { PrimaryButton } from './PrimaryButton'; +import type { HeldPrimaryButtonProps } from './PrimaryButtonLongHold.shared'; +import { ACTION_TIMER, COLORS } from './PrimaryButtonLongHold.shared'; + +export function HeldPrimaryButton({ children, onLongPress, ...props }: HeldPrimaryButtonProps) { + const [hasTriggered, setHasTriggered] = useState(false); + const [size, setSize] = useState({ width: 0, height: 0 }); + const [isPressed, setIsPressed] = useState(false); + const animationValue = new Animated.Value(0); + + const onPressIn = () => { + setHasTriggered(false); + setIsPressed(true); + Animated.timing(animationValue, { + toValue: 1, + duration: ACTION_TIMER, + useNativeDriver: false, + }).start(); + }; + + const onPressOut = () => { + setIsPressed(false); + if (!hasTriggered) { + Animated.timing(animationValue, { + toValue: 0, + duration: 200, + useNativeDriver: false, + }).start(); + } + }; + + const getButtonSize = (e: LayoutChangeEvent) => { + const width = e.nativeEvent.layout.width - 1; + const height = e.nativeEvent.layout.height - 1; + setSize({ width, height }); + }; + + useEffect(() => { + // Use animation listener to trigger onLongPress + const listener = animationValue.addListener(({ value }) => { + if (value >= 0.95 && !hasTriggered && isPressed) { + setHasTriggered(true); + onLongPress(); + } + }); + return () => { + animationValue.removeListener(listener); + }; + }, [animationValue, hasTriggered, onLongPress, isPressed]); + + const renderAnimatedComponent = () => { + // Use React Native Animated.View for consistent behavior + const width = animationValue.interpolate({ + inputRange: [0, 1], + outputRange: [0, size.width], + }); + + return ( + + ); + }; + + return ( + + {children} + + ); +} diff --git a/app/src/components/buttons/SecondaryButton.tsx b/packages/mobile-sdk-alpha/src/components/buttons/SecondaryButton.tsx similarity index 71% rename from app/src/components/buttons/SecondaryButton.tsx rename to packages/mobile-sdk-alpha/src/components/buttons/SecondaryButton.tsx index 935150e82..0212bd9c8 100644 --- a/app/src/components/buttons/SecondaryButton.tsx +++ b/packages/mobile-sdk-alpha/src/components/buttons/SecondaryButton.tsx @@ -2,12 +2,10 @@ // SPDX-License-Identifier: BUSL-1.1 // NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. -import React from 'react'; - -import type { ButtonProps } from '@/components/buttons/AbstractButton'; -import AbstractButton from '@/components/buttons/AbstractButton'; -import { slate200, slate300, slate500, white } from '@/utils/colors'; -import { normalizeBorderWidth } from '@/utils/styleUtils'; +import { slate200, slate300, slate500, white } from '../../constants/colors'; +import { normalizeBorderWidth } from '../../utils/styleUtils'; +import type { ButtonProps } from './AbstractButton'; +import AbstractButton from './AbstractButton'; export function SecondaryButton({ children, ...props }: ButtonProps) { const { borderWidth, ...restProps } = props; diff --git a/app/src/components/buttons/pressedStyle.tsx b/packages/mobile-sdk-alpha/src/components/buttons/pressedStyle.tsx similarity index 100% rename from app/src/components/buttons/pressedStyle.tsx rename to packages/mobile-sdk-alpha/src/components/buttons/pressedStyle.tsx diff --git a/app/src/components/flag/RoundFlag.tsx b/packages/mobile-sdk-alpha/src/components/flag/RoundFlag.tsx similarity index 79% rename from app/src/components/flag/RoundFlag.tsx rename to packages/mobile-sdk-alpha/src/components/flag/RoundFlag.tsx index a5c06da3e..86c0a7ca0 100644 --- a/app/src/components/flag/RoundFlag.tsx +++ b/packages/mobile-sdk-alpha/src/components/flag/RoundFlag.tsx @@ -2,13 +2,13 @@ // SPDX-License-Identifier: BUSL-1.1 // NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. -import React from 'react'; +import type React from 'react'; import { View } from 'react-native'; import * as CountryFlags from 'react-native-svg-circle-country-flags'; import { alpha3ToAlpha2 } from '@selfxyz/common/constants/countries'; -import { slate300 } from '@/utils/colors'; +import { slate300 } from '../../constants/colors'; type CountryFlagComponent = React.ComponentType<{ width: number; @@ -22,16 +22,15 @@ interface RoundFlagProps { size: number; } -const findFlagComponent = (formattedCode: string) => { +const findFlagComponent = (CountryFlags: CountryFlagsRecord, formattedCode: string) => { const patterns = [ formattedCode, formattedCode.toLowerCase(), - formattedCode.charAt(0).toUpperCase() + - formattedCode.charAt(1).toLowerCase(), + formattedCode.charAt(0).toUpperCase() + formattedCode.charAt(1).toLowerCase(), ]; for (const pattern of patterns) { - const component = (CountryFlags as unknown as CountryFlagsRecord)[pattern]; + const component = CountryFlags[pattern]; if (component) { return component; } @@ -48,7 +47,7 @@ const getCountryFlag = (countryCode: string): CountryFlagComponent | null => { } const formattedCode = iso2.toUpperCase(); - return findFlagComponent(formattedCode); + return findFlagComponent(CountryFlags as unknown as CountryFlagsRecord, formattedCode); } catch (error) { console.error('Error getting country flag:', error); return null; @@ -64,6 +63,7 @@ export const RoundFlag: React.FC = ({ countryCode, size }) => { style={{ width: size, height: size, + borderRadius: size / 2, backgroundColor: slate300, }} /> diff --git a/packages/mobile-sdk-alpha/src/components/index.ts b/packages/mobile-sdk-alpha/src/components/index.ts index 595a0e96a..2be12d7e2 100644 --- a/packages/mobile-sdk-alpha/src/components/index.ts +++ b/packages/mobile-sdk-alpha/src/components/index.ts @@ -2,4 +2,37 @@ // SPDX-License-Identifier: BUSL-1.1 // NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. +export { default as AbstractButton } from './buttons/AbstractButton'; + +export { default as Additional } from './typography/Additional'; + +// Typography components +export { BodyText } from './typography/BodyText'; + +export { Caption } from './typography/Caption'; + +export { default as Caution } from './typography/Caution'; + +export { default as Description } from './typography/Description'; + +export { DescriptionTitle } from './typography/DescriptionTitle'; + +export { HeldPrimaryButton } from './buttons/PrimaryButtonLongHold'; + +export { HeldPrimaryButtonProveScreen } from './buttons/HeldPrimaryButtonProveScreen'; + export { MRZScannerView } from './MRZScannerView'; +// Button components +export { PrimaryButton } from './buttons/PrimaryButton'; +// Flag components +export { RoundFlag } from './flag/RoundFlag'; + +export { SecondaryButton } from './buttons/SecondaryButton'; + +export { SubHeader } from './typography/SubHeader'; + +export { Title } from './typography/Title'; + +export { pressedStyle } from './buttons/pressedStyle'; + +export { typography } from './typography/styles'; diff --git a/packages/mobile-sdk-alpha/src/components/screens/NFCScannerScreen.tsx b/packages/mobile-sdk-alpha/src/components/screens/NFCScannerScreen.tsx index ef7b17e92..a1f17fed7 100644 --- a/packages/mobile-sdk-alpha/src/components/screens/NFCScannerScreen.tsx +++ b/packages/mobile-sdk-alpha/src/components/screens/NFCScannerScreen.tsx @@ -3,8 +3,7 @@ // NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. import { useCallback } from 'react'; -import { StyleSheet, Text, TouchableOpacity } from 'react-native'; -import { View } from 'tamagui'; +import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import { getSKIPEM, initPassportDataParsing } from '@selfxyz/common'; diff --git a/packages/mobile-sdk-alpha/src/components/screens/PassportCameraScreen.tsx b/packages/mobile-sdk-alpha/src/components/screens/PassportCameraScreen.tsx index 5e78c36b6..8400b105a 100644 --- a/packages/mobile-sdk-alpha/src/components/screens/PassportCameraScreen.tsx +++ b/packages/mobile-sdk-alpha/src/components/screens/PassportCameraScreen.tsx @@ -2,8 +2,7 @@ // SPDX-License-Identifier: BUSL-1.1 // NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. -import { StyleSheet, Text, TouchableOpacity } from 'react-native'; -import { View } from 'tamagui'; +import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import type { PassportCameraProps } from '../../types/ui'; import { MRZScannerView } from '../MRZScannerView'; diff --git a/packages/mobile-sdk-alpha/src/components/screens/QRCodeScreen.tsx b/packages/mobile-sdk-alpha/src/components/screens/QRCodeScreen.tsx index 1320a0ab9..4e5aa4e17 100644 --- a/packages/mobile-sdk-alpha/src/components/screens/QRCodeScreen.tsx +++ b/packages/mobile-sdk-alpha/src/components/screens/QRCodeScreen.tsx @@ -2,8 +2,7 @@ // SPDX-License-Identifier: BUSL-1.1 // NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. -import { StyleSheet, Text, TouchableOpacity } from 'react-native'; -import { View } from 'tamagui'; +import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import type { ScreenProps } from '../../types/ui'; diff --git a/app/src/components/typography/Additional.tsx b/packages/mobile-sdk-alpha/src/components/typography/Additional.tsx similarity index 86% rename from app/src/components/typography/Additional.tsx rename to packages/mobile-sdk-alpha/src/components/typography/Additional.tsx index 1aac09b21..5aa93c0be 100644 --- a/app/src/components/typography/Additional.tsx +++ b/packages/mobile-sdk-alpha/src/components/typography/Additional.tsx @@ -2,12 +2,11 @@ // SPDX-License-Identifier: BUSL-1.1 // NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. -import React from 'react'; import type { TextProps } from 'react-native'; import { StyleSheet, Text } from 'react-native'; -import { slate400 } from '@/utils/colors'; -import { dinot } from '@/utils/fonts'; +import { slate400 } from '../../constants/colors'; +import { dinot } from '../../utils/fonts'; type AdditionalProps = TextProps; diff --git a/packages/mobile-sdk-alpha/src/components/typography/BodyText.tsx b/packages/mobile-sdk-alpha/src/components/typography/BodyText.tsx new file mode 100644 index 000000000..6f8c15dac --- /dev/null +++ b/packages/mobile-sdk-alpha/src/components/typography/BodyText.tsx @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc. +// SPDX-License-Identifier: BUSL-1.1 +// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. + +import type React from 'react'; +import type { TextProps } from 'react-native'; +import { Text } from 'react-native'; + +import { dinot } from '../../utils/fonts'; + +export const BodyText: React.FC = ({ style, ...props }) => ( + +); diff --git a/packages/mobile-sdk-alpha/src/components/typography/Caption.tsx b/packages/mobile-sdk-alpha/src/components/typography/Caption.tsx new file mode 100644 index 000000000..9d9c545d9 --- /dev/null +++ b/packages/mobile-sdk-alpha/src/components/typography/Caption.tsx @@ -0,0 +1,19 @@ +// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc. +// SPDX-License-Identifier: BUSL-1.1 +// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. + +import type React from 'react'; +import type { TextProps } from 'react-native'; + +import { slate400 } from '../../constants/colors'; +import { BodyText } from './BodyText'; + +type CaptionProps = TextProps & { + size?: 'small' | 'large'; +}; + +export const Caption: React.FC = ({ size, style, ...props }) => { + const fontSize = size === 'small' ? 14 : size === 'large' ? 16 : 15; + + return ; +}; diff --git a/app/src/components/typography/Caution.tsx b/packages/mobile-sdk-alpha/src/components/typography/Caution.tsx similarity index 85% rename from app/src/components/typography/Caution.tsx rename to packages/mobile-sdk-alpha/src/components/typography/Caution.tsx index 42dd54056..86556e558 100644 --- a/app/src/components/typography/Caution.tsx +++ b/packages/mobile-sdk-alpha/src/components/typography/Caution.tsx @@ -2,12 +2,11 @@ // SPDX-License-Identifier: BUSL-1.1 // NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. -import React from 'react'; import type { TextProps } from 'react-native'; import { StyleSheet, Text } from 'react-native'; -import { slate700 } from '@/utils/colors'; -import { dinot } from '@/utils/fonts'; +import { slate700 } from '../../constants/colors'; +import { dinot } from '../../utils/fonts'; type CautionProps = TextProps; diff --git a/packages/mobile-sdk-alpha/src/components/typography/Description.tsx b/packages/mobile-sdk-alpha/src/components/typography/Description.tsx new file mode 100644 index 000000000..43b845381 --- /dev/null +++ b/packages/mobile-sdk-alpha/src/components/typography/Description.tsx @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc. +// SPDX-License-Identifier: BUSL-1.1 +// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. + +import type { TextProps } from 'react-native'; +import { StyleSheet, Text } from 'react-native'; + +import { slate500 } from '../../constants/colors'; +import { dinot } from '../../utils/fonts'; + +type DescriptionProps = TextProps & { + color?: string; +}; + +const Description = ({ children, style, color, ...props }: DescriptionProps) => { + return ( + + {children} + + ); +}; + +export default Description; + +const styles = StyleSheet.create({ + description: { + color: slate500, + fontSize: 18, + lineHeight: 23, + textAlign: 'center', + fontFamily: dinot, + }, +}); diff --git a/packages/mobile-sdk-alpha/src/components/typography/DescriptionTitle.tsx b/packages/mobile-sdk-alpha/src/components/typography/DescriptionTitle.tsx new file mode 100644 index 000000000..1ea05aa84 --- /dev/null +++ b/packages/mobile-sdk-alpha/src/components/typography/DescriptionTitle.tsx @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc. +// SPDX-License-Identifier: BUSL-1.1 +// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. + +import type React from 'react'; +import type { TextProps } from 'react-native'; +import { Text } from 'react-native'; + +import { dinot } from '../../utils/fonts'; + +export const DescriptionTitle: React.FC = ({ style, ...props }) => ( + +); diff --git a/packages/mobile-sdk-alpha/src/components/typography/SubHeader.tsx b/packages/mobile-sdk-alpha/src/components/typography/SubHeader.tsx new file mode 100644 index 000000000..12f0c1009 --- /dev/null +++ b/packages/mobile-sdk-alpha/src/components/typography/SubHeader.tsx @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc. +// SPDX-License-Identifier: BUSL-1.1 +// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. + +import type React from 'react'; +import type { TextProps } from 'react-native'; +import { Text } from 'react-native'; + +import { dinot } from '../../utils/fonts'; + +export const SubHeader: React.FC = ({ style, ...props }) => ( + +); diff --git a/packages/mobile-sdk-alpha/src/components/typography/Title.tsx b/packages/mobile-sdk-alpha/src/components/typography/Title.tsx new file mode 100644 index 000000000..938752634 --- /dev/null +++ b/packages/mobile-sdk-alpha/src/components/typography/Title.tsx @@ -0,0 +1,36 @@ +// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc. +// SPDX-License-Identifier: BUSL-1.1 +// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. + +import type React from 'react'; +import type { StyleProp, TextProps, TextStyle } from 'react-native'; +import { Text } from 'react-native'; + +import { advercase } from '../../utils/fonts'; + +type TitleProps = TextProps & { + size?: 'large'; + style?: StyleProp; +}; + +export const Title: React.FC = ({ size, style, children, ...rest }) => { + const baseStyle: TextStyle = { + fontSize: 28, + lineHeight: 35, + fontFamily: advercase, + }; + + const largeStyle: TextStyle = + size === 'large' + ? { + fontSize: 38, + lineHeight: 47, + } + : {}; + + return ( + + {children} + + ); +}; diff --git a/app/src/components/typography/styles.ts b/packages/mobile-sdk-alpha/src/components/typography/styles.ts similarity index 86% rename from app/src/components/typography/styles.ts rename to packages/mobile-sdk-alpha/src/components/typography/styles.ts index 0ba262674..f123b9cce 100644 --- a/app/src/components/typography/styles.ts +++ b/packages/mobile-sdk-alpha/src/components/typography/styles.ts @@ -4,7 +4,7 @@ import { StyleSheet } from 'react-native'; -import { black } from '@/utils/colors'; +import { black } from '../../constants/colors'; export const typography = StyleSheet.create({ strong: { diff --git a/packages/mobile-sdk-alpha/src/utils/fonts.ts b/packages/mobile-sdk-alpha/src/utils/fonts.ts new file mode 100644 index 000000000..c47b2f486 --- /dev/null +++ b/packages/mobile-sdk-alpha/src/utils/fonts.ts @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc. +// SPDX-License-Identifier: BUSL-1.1 +// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. + +import { Platform } from 'react-native'; + +export const advercase = 'Advercase-Regular'; +export const dinot = 'DINOT-Medium'; +export const plexMono = Platform.OS === 'ios' ? 'IBM Plex Mono' : 'IBMPlexMono-Regular'; diff --git a/packages/mobile-sdk-alpha/src/utils/styleUtils.ts b/packages/mobile-sdk-alpha/src/utils/styleUtils.ts new file mode 100644 index 000000000..2c76debf1 --- /dev/null +++ b/packages/mobile-sdk-alpha/src/utils/styleUtils.ts @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc. +// SPDX-License-Identifier: BUSL-1.1 +// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. + +/** + * Utility functions for style, design, and layout operations. + */ + +/** + * Normalizes borderWidth value. + * Validates and converts borderWidth to a non-negative number or undefined. + * @param borderWidth - The borderWidth value to normalize + * @returns Normalized borderWidth (non-negative number) or undefined + */ +export function normalizeBorderWidth(borderWidth: unknown): number | undefined { + if (typeof borderWidth === 'number' && borderWidth >= 0) { + return borderWidth; + } + return undefined; +} diff --git a/packages/mobile-sdk-alpha/tsup.config.ts b/packages/mobile-sdk-alpha/tsup.config.ts index 5271cfefe..6d5144aa9 100644 --- a/packages/mobile-sdk-alpha/tsup.config.ts +++ b/packages/mobile-sdk-alpha/tsup.config.ts @@ -39,6 +39,7 @@ const entry = { browser: 'src/browser.ts', 'constants/analytics': 'src/constants/analytics.ts', 'constants/colors': 'src/constants/colors.ts', + 'components/index': 'src/components/index.ts', stores: 'src/stores/index.ts', ...flowEntries, }; @@ -69,6 +70,7 @@ export default defineConfig([ '@react-native-async-storage/async-storage', 'react-native-keychain', 'react-native-sqlite-storage', + // State management (xstate included in bundle) ], esbuildOptions(options) { options.supported = { @@ -113,6 +115,7 @@ export default defineConfig([ '@react-native-async-storage/async-storage', 'react-native-keychain', 'react-native-sqlite-storage', + // State management (xstate included in bundle) ], outExtension: ({ format }) => ({ js: format === 'cjs' ? '.cjs' : '.js' }), esbuildOptions(options) { diff --git a/yarn.lock b/yarn.lock index 2fe87e5ba..ba96bd4fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7416,7 +7416,6 @@ __metadata: react-native-screens: "npm:4.15.3" react-native-sqlite-storage: "npm:^6.0.1" react-native-svg: "npm:15.12.1" - react-native-svg-circle-country-flags: "npm:^0.2.2" react-native-svg-transformer: "npm:^1.5.1" react-native-svg-web: "npm:^1.0.9" react-native-web: "npm:^0.19.0" @@ -7443,12 +7442,12 @@ __metadata: dependencies: "@babel/runtime": "npm:^7.28.3" "@selfxyz/common": "workspace:^" - "@tamagui/types": "npm:1.126.14" "@testing-library/react": "npm:^14.1.2" "@types/react": "npm:^18.3.4" "@types/react-dom": "npm:^18.3.0" "@typescript-eslint/eslint-plugin": "npm:^8.0.0" "@typescript-eslint/parser": "npm:^8.0.0" + "@xstate/react": "npm:^5.0.5" eslint: "npm:^8.57.0" eslint-config-prettier: "npm:^10.1.8" eslint-import-resolver-typescript: "npm:^4.4.4" @@ -7464,9 +7463,9 @@ __metadata: react-dom: "npm:^18.3.1" react-native: "npm:0.76.9" react-native-localize: "npm:^3.5.2" + react-native-svg-circle-country-flags: "npm:^0.2.2" react-native-web: "npm:^0.21.1" socket.io-client: "npm:^4.8.1" - tamagui: "npm:1.126.14" tsup: "npm:^8.0.1" typescript: "npm:^5.9.2" uuid: "npm:^11.1.0" @@ -7477,10 +7476,7 @@ __metadata: react: ^18.3.1 react-native: 0.76.9 react-native-localize: "*" - tamagui: 1.126.x - peerDependenciesMeta: - tamagui: - optional: false + react-native-svg: "*" languageName: unknown linkType: soft @@ -12914,7 +12910,7 @@ __metadata: languageName: node linkType: hard -"@xstate/react@npm:^5.0.3": +"@xstate/react@npm:^5.0.3, @xstate/react@npm:^5.0.5": version: 5.0.5 resolution: "@xstate/react@npm:5.0.5" dependencies: