From 9d7be21b29f7a33c3330d7f5482006a35187d698 Mon Sep 17 00:00:00 2001 From: Juan Castillo Date: Wed, 31 Jul 2024 00:08:47 -0700 Subject: [PATCH] Initial Commit --- .gitignore | 82 +++++++ components/Button/Button.tsx | 44 ++++ components/Button/index.ts | 2 + components/Button/styles/ButtonStyle.ts | 44 ++++ components/DateTimeInput/index.tsx | 172 ++++++++++++++ .../MenuItemDescription.tsx | 36 +++ components/MenuItemDescription/index.ts | 2 + components/Sheet/index.tsx | 163 +++++++++++++ components/SwitchToggle/SwitchToggle.tsx | 31 +++ components/Text/index.tsx | 74 ++++++ components/TextInput/TextInput.tsx | 214 ++++++++++++++++++ components/TextInput/index.tsx | 2 + components/index.ts | 5 + context/index.ts | 5 + hooks/index.ts | 2 + hooks/useTheme.ts | 7 + hooks/useThemedStyle.ts | 18 ++ index.ts | 3 + package.json | 15 ++ shared/styles/index.ts | 33 +++ themes/AtlasLightTheme.ts | 90 ++++++++ types/index.ts | 2 + types/theme.ts | 45 ++++ types/typography.ts | 14 ++ 24 files changed, 1105 insertions(+) create mode 100644 .gitignore create mode 100644 components/Button/Button.tsx create mode 100644 components/Button/index.ts create mode 100644 components/Button/styles/ButtonStyle.ts create mode 100644 components/DateTimeInput/index.tsx create mode 100644 components/MenuItemDescription/MenuItemDescription.tsx create mode 100644 components/MenuItemDescription/index.ts create mode 100644 components/Sheet/index.tsx create mode 100644 components/SwitchToggle/SwitchToggle.tsx create mode 100644 components/Text/index.tsx create mode 100644 components/TextInput/TextInput.tsx create mode 100644 components/TextInput/index.tsx create mode 100644 components/index.ts create mode 100644 context/index.ts create mode 100644 hooks/index.ts create mode 100644 hooks/useTheme.ts create mode 100644 hooks/useThemedStyle.ts create mode 100644 index.ts create mode 100644 package.json create mode 100644 shared/styles/index.ts create mode 100644 themes/AtlasLightTheme.ts create mode 100644 types/index.ts create mode 100644 types/theme.ts create mode 100644 types/typography.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..99a30c8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,82 @@ +# OSX +# +.DS_Store + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate +ios/.xcode.env.local + +# Android/IntelliJ +# +build/ +.idea +.gradle +local.properties +*.iml +*.hprof +.cxx/ +*.keystore +!debug.keystore +.history +.vscode +.git +.run + + +# node.js +# +node_modules/ +npm-debug.log +yarn-error.log + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/ + +**/fastlane/report.xml +**/fastlane/Preview.html +**/fastlane/screenshots +**/fastlane/test_output + +# Bundle artifact +*.jsbundle + +# Ruby / CocoaPods +/ios/Pods/ +/vendor/bundle/ +ios-dev.bundle.map +ios-dev.bundle +ios-release.bundle +ios-release.bundle.map +ios-release.bundle +ios-release.bundle.map + +# Coverage Directory +_coverage/* +!_coverage/lcov.info + + +# Temporary files created by Metro to check the health of the file watcher +.metro-health-check* + +# testing +/coverage \ No newline at end of file diff --git a/components/Button/Button.tsx b/components/Button/Button.tsx new file mode 100644 index 0000000..ee76989 --- /dev/null +++ b/components/Button/Button.tsx @@ -0,0 +1,44 @@ +import { ActivityIndicator, StyleProp, TouchableOpacity, ViewStyle } from 'react-native'; +import React from 'react'; + +import { useButtonStyles } from './styles/ButtonStyle'; +import Text from '../Text'; + +export enum ButtonType { + Primary, + Destructive, +} + +export interface ButtonProps { + disabled?: boolean; + type?: ButtonType; + onPress?: () => void; + text: string; + loading?: boolean; + testID?: string; + containerStyle?: StyleProp; +} + +const Button = ({ testID, disabled = false, onPress, text, loading, type = ButtonType.Primary, containerStyle = {} }: ButtonProps) => { + const { styles, theme } = useButtonStyles(); + const buttonStyle = type === ButtonType.Primary ? styles.default : styles.destructiveContainer; + + return ( + + {loading ? ( + + ) : ( + + {text} + + )} + + ); +}; + +export default Button; diff --git a/components/Button/index.ts b/components/Button/index.ts new file mode 100644 index 0000000..d5d5668 --- /dev/null +++ b/components/Button/index.ts @@ -0,0 +1,2 @@ +export { default } from './Button'; +export * from './Button'; diff --git a/components/Button/styles/ButtonStyle.ts b/components/Button/styles/ButtonStyle.ts new file mode 100644 index 0000000..da877cf --- /dev/null +++ b/components/Button/styles/ButtonStyle.ts @@ -0,0 +1,44 @@ +import { StyleSheet } from 'react-native'; +import { useCallback } from 'react'; + +import { useThemedStyle } from '../../../hooks'; + +export const useButtonStyles = () => + useThemedStyle( + useCallback( + theme => + StyleSheet.create({ + default: { + borderRadius: theme.borderRadius, + justifyContent: 'center', + backgroundColor: theme.colors.primary, + paddingHorizontal: theme.size.baseSize * 4, + paddingVertical: theme.size.baseSize * 2, + textAlign: 'center', + }, + destructiveContainer: { + borderRadius: theme.borderRadius, + justifyContent: 'center', + paddingHorizontal: theme.size.baseSize * 4, + paddingVertical: theme.size.baseSize * 2, + textAlign: 'center', + backgroundColor: theme.colors.secondaryNegative, + }, + destructiveText: { + textAlign: 'center', + color: theme.colors.backgroundPrimary, + }, + defaultText: { + textAlign: 'center', + color: theme.colors.foregroundOnPrimary, + }, + disabled: { + backgroundColor: theme.colors.primaryLowContrast, + }, + disabledText: { + color: theme.colors.foregroundOnPrimary, + }, + }), + [] + ) + ); diff --git a/components/DateTimeInput/index.tsx b/components/DateTimeInput/index.tsx new file mode 100644 index 0000000..da870e4 --- /dev/null +++ b/components/DateTimeInput/index.tsx @@ -0,0 +1,172 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import DateTimePicker, { IOSNativeProps, AndroidNativeProps } from '@react-native-community/datetimepicker'; +import { View, TouchableOpacity, StyleSheet, StyleProp, ViewStyle } from 'react-native'; +import Animated, { interpolate, interpolateColor, useAnimatedStyle, useSharedValue } from 'react-native-reanimated'; +import IonIcons from 'react-native-vector-icons/Ionicons'; +import moment from 'moment'; + +import Sheet from '../Sheet'; +import Text from '../Text'; +import MenuItemDescription from '../MenuItemDescription'; +import { useThemedStyle } from '../../hooks'; +import Button from '../Button'; + +type Props = { + label: string; + caption?: string; + value: Date; + onChange?: (date: Date) => void; + onSave?: (date: Date) => void; + disabled?: boolean; + testID?: string; + containerStyle?: StyleProp; + mode?: IOSNativeProps['mode'] | AndroidNativeProps['mode']; +}; + +const getFormat = (mode?: Props['mode']) => { + switch (mode) { + case 'date': { + return 'MMM D, YYYY'; + } + case 'time': { + return 'h:mm A'; + } + case 'datetime': + default: { + return 'MMM D, YYYY h:mm A'; + } + } +}; + +const DateTimeInput = ({ + value, + onChange, + testID, + containerStyle, + label, + caption, + mode = 'date', + disabled = false, + onSave, +}: Props) => { + const { styles, theme } = useStyles(disabled); + const [dateSheetOpen, setDateSheetOpen] = useState(false); + const [date, setDate] = useState(value); + + useEffect(() => { + if (dateSheetOpen) { + return; + } + + setDate(value); + }, [dateSheetOpen, value]); + + const animatedValue = useSharedValue(value ? 1 : 0); + + const animatedLabelStyles = useAnimatedStyle(() => { + return { + transform: [{ translateY: interpolate(animatedValue.value, [0, 1], [1, -8]) }], + fontSize: interpolate(animatedValue.value, [0, 1], [14, 10]), + }; + }, []); + + const animatedContainerStyles = useAnimatedStyle(() => { + return { + borderColor: interpolateColor(animatedValue.value, [0, 1], ['#ffffff00', theme.colors.border]), + }; + }); + + const animatedValueStyle = useAnimatedStyle(() => { + return { + flex: 1, + transform: [{ translateY: animatedValue.value * 6 }], + }; + }); + + return ( + <> + + setDateSheetOpen(true)} disabled={disabled}> + + + {label} + + + + {moment(value).format(getFormat(mode)).toString()} + + + + + + {!!caption && } + + + { + if (!newDate) { + return; + } + setDate(newDate); + onChange?.(newDate); + }} + /> +