diff options
| author | MohamedBassem <me@mbassem.com> | 2024-03-11 01:37:22 +0000 |
|---|---|---|
| committer | MohamedBassem <me@mbassem.com> | 2024-03-11 01:37:22 +0000 |
| commit | 2b720405ae3a19ac78fbf3e7231394364ba83c99 (patch) | |
| tree | 9fb5ab84f827aa81239acb3e58198f99505575db /packages | |
| parent | 00dd4d0b549fdfe1c5224fc94141926925aab13d (diff) | |
| download | karakeep-2b720405ae3a19ac78fbf3e7231394364ba83c99.tar.zst | |
mobile: Prepare to merge into main repo
Diffstat (limited to 'packages')
23 files changed, 469 insertions, 0 deletions
diff --git a/packages/mobile/.eslintrc.js b/packages/mobile/.eslintrc.js new file mode 100644 index 00000000..53beac49 --- /dev/null +++ b/packages/mobile/.eslintrc.js @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: ["universe/native"], +}; diff --git a/packages/mobile/.gitignore b/packages/mobile/.gitignore new file mode 100644 index 00000000..05647d55 --- /dev/null +++ b/packages/mobile/.gitignore @@ -0,0 +1,35 @@ +# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files + +# dependencies +node_modules/ + +# Expo +.expo/ +dist/ +web-build/ + +# Native +*.orig.* +*.jks +*.p8 +*.p12 +*.key +*.mobileprovision + +# Metro +.metro-health-check* + +# debug +npm-debug.* +yarn-debug.* +yarn-error.* + +# macOS +.DS_Store +*.pem + +# local env files +.env*.local + +# typescript +*.tsbuildinfo diff --git a/packages/mobile/.npmrc b/packages/mobile/.npmrc new file mode 100644 index 00000000..d67f3748 --- /dev/null +++ b/packages/mobile/.npmrc @@ -0,0 +1 @@ +node-linker=hoisted diff --git a/packages/mobile/app.json b/packages/mobile/app.json new file mode 100644 index 00000000..9ebea4ea --- /dev/null +++ b/packages/mobile/app.json @@ -0,0 +1,34 @@ +{ + "expo": { + "name": "hoarder-mobile", + "slug": "hoarder-mobile", + "scheme": "hoarder", + "version": "1.0.0", + "orientation": "portrait", + "icon": "./assets/icon.png", + "userInterfaceStyle": "light", + "splash": { + "image": "./assets/splash.png", + "resizeMode": "contain", + "backgroundColor": "#ffffff" + }, + "assetBundlePatterns": [ + "**/*" + ], + "ios": { + "supportsTablet": true + }, + "android": { + "adaptiveIcon": { + "foregroundImage": "./assets/adaptive-icon.png", + "backgroundColor": "#ffffff" + } + }, + "web": { + "favicon": "./assets/favicon.png" + }, + "plugins": [ + "expo-router" + ] + } +} diff --git a/packages/mobile/app/_layout.tsx b/packages/mobile/app/_layout.tsx new file mode 100644 index 00000000..7403c6ff --- /dev/null +++ b/packages/mobile/app/_layout.tsx @@ -0,0 +1,14 @@ +import "@/globals.css"; + +import { Slot } from "expo-router"; +import { StatusBar } from "expo-status-bar"; +import { View } from "react-native"; + +export default function RootLayout() { + return ( + <View className="w-full h-full bg-white"> + <Slot /> + <StatusBar style="auto" /> + </View> + ); +} diff --git a/packages/mobile/app/index.tsx b/packages/mobile/app/index.tsx new file mode 100644 index 00000000..e352ba54 --- /dev/null +++ b/packages/mobile/app/index.tsx @@ -0,0 +1,12 @@ +import { Link } from "expo-router"; +import { View } from "react-native"; + +export default function App() { + return ( + <View className="flex-1 items-center justify-center bg-white"> + <Link href="/signin" className=""> + Signin + </Link> + </View> + ); +} diff --git a/packages/mobile/app/signin.tsx b/packages/mobile/app/signin.tsx new file mode 100644 index 00000000..f500e36e --- /dev/null +++ b/packages/mobile/app/signin.tsx @@ -0,0 +1,24 @@ +import { View, Text } from "react-native"; + +import Logo from "@/components/Logo"; +import { Button } from "@/components/ui/Button"; +import { Input } from "@/components/ui/Input"; + +export default function Signin() { + return ( + <View className="container justify-center h-full flex flex-col gap-2"> + <View className="items-center"> + <Logo /> + </View> + <View className="gap-2"> + <Text className="font-bold">Email</Text> + <Input className="w-full" placeholder="Email" /> + </View> + <View className="gap-2"> + <Text className="font-bold">Password</Text> + <Input className="w-full" placeholder="Password" secureTextEntry /> + </View> + <Button className="w-full" label="Sign In" /> + </View> + ); +} diff --git a/packages/mobile/assets/adaptive-icon.png b/packages/mobile/assets/adaptive-icon.png Binary files differnew file mode 100644 index 00000000..03d6f6b6 --- /dev/null +++ b/packages/mobile/assets/adaptive-icon.png diff --git a/packages/mobile/assets/favicon.png b/packages/mobile/assets/favicon.png Binary files differnew file mode 100644 index 00000000..e75f697b --- /dev/null +++ b/packages/mobile/assets/favicon.png diff --git a/packages/mobile/assets/icon.png b/packages/mobile/assets/icon.png Binary files differnew file mode 100644 index 00000000..a0b1526f --- /dev/null +++ b/packages/mobile/assets/icon.png diff --git a/packages/mobile/assets/splash.png b/packages/mobile/assets/splash.png Binary files differnew file mode 100644 index 00000000..0e89705a --- /dev/null +++ b/packages/mobile/assets/splash.png diff --git a/packages/mobile/babel.config.js b/packages/mobile/babel.config.js new file mode 100644 index 00000000..f3c649bb --- /dev/null +++ b/packages/mobile/babel.config.js @@ -0,0 +1,9 @@ +module.exports = function (api) { + api.cache(true); + return { + presets: [ + ["babel-preset-expo", { jsxImportSource: "nativewind" }], + "nativewind/babel", + ], + }; +}; diff --git a/packages/mobile/bun.lockb b/packages/mobile/bun.lockb Binary files differnew file mode 100755 index 00000000..219082f9 --- /dev/null +++ b/packages/mobile/bun.lockb diff --git a/packages/mobile/components/Logo.tsx b/packages/mobile/components/Logo.tsx new file mode 100644 index 00000000..a15d8561 --- /dev/null +++ b/packages/mobile/components/Logo.tsx @@ -0,0 +1,11 @@ +import { PackageOpen } from "lucide-react-native"; +import { View, Text } from "react-native"; + +export default function Logo() { + return ( + <View className="flex flex-row gap-2 justify-center items-center "> + <PackageOpen color="black" size={70} /> + <Text className="text-5xl">Hoarder</Text> + </View> + ); +} diff --git a/packages/mobile/components/ui/Button.tsx b/packages/mobile/components/ui/Button.tsx new file mode 100644 index 00000000..4c3cbc69 --- /dev/null +++ b/packages/mobile/components/ui/Button.tsx @@ -0,0 +1,81 @@ +import { type VariantProps, cva } from "class-variance-authority"; +import { Text, TouchableOpacity } from "react-native"; + +import { cn } from "@/lib/utils"; + +const buttonVariants = cva( + "flex flex-row items-center justify-center rounded-md", + { + variants: { + variant: { + default: "bg-primary", + secondary: "bg-secondary", + destructive: "bg-destructive", + ghost: "bg-slate-700", + link: "text-primary underline-offset-4", + }, + size: { + default: "h-10 px-4", + sm: "h-8 px-2", + lg: "h-12 px-8", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + }, +); + +const buttonTextVariants = cva("text-center font-medium", { + variants: { + variant: { + default: "text-primary-foreground", + secondary: "text-secondary-foreground", + destructive: "text-destructive-foreground", + ghost: "text-primary-foreground", + link: "text-primary-foreground underline", + }, + size: { + default: "text-base", + sm: "text-sm", + lg: "text-xl", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, +}); + +interface ButtonProps + extends React.ComponentPropsWithoutRef<typeof TouchableOpacity>, + VariantProps<typeof buttonVariants> { + label: string; + labelClasses?: string; +} +function Button({ + label, + labelClasses, + className, + variant, + size, + ...props +}: ButtonProps) { + return ( + <TouchableOpacity + className={cn(buttonVariants({ variant, size, className }))} + {...props} + > + <Text + className={cn( + buttonTextVariants({ variant, size, className: labelClasses }), + )} + > + {label} + </Text> + </TouchableOpacity> + ); +} + +export { Button, buttonVariants, buttonTextVariants }; diff --git a/packages/mobile/components/ui/Input.tsx b/packages/mobile/components/ui/Input.tsx new file mode 100644 index 00000000..6fc90b8f --- /dev/null +++ b/packages/mobile/components/ui/Input.tsx @@ -0,0 +1,28 @@ +import { forwardRef } from "react"; +import { Text, TextInput, View } from "react-native"; + +import { cn } from "@/lib/utils"; + +export interface InputProps + extends React.ComponentPropsWithoutRef<typeof TextInput> { + label?: string; + labelClasses?: string; + inputClasses?: string; +} + +const Input = forwardRef<React.ElementRef<typeof TextInput>, InputProps>( + ({ className, label, labelClasses, inputClasses, ...props }, ref) => ( + <View className={cn("flex flex-col gap-1.5", className)}> + {label && <Text className={cn("text-base", labelClasses)}>{label}</Text>} + <TextInput + className={cn( + inputClasses, + "border border-input py-2.5 px-4 rounded-lg", + )} + {...props} + /> + </View> + ), +); + +export { Input }; diff --git a/packages/mobile/globals.css b/packages/mobile/globals.css new file mode 100644 index 00000000..de1cf559 --- /dev/null +++ b/packages/mobile/globals.css @@ -0,0 +1,80 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 222.2 47.4% 11.2%; + + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; + + --popover: 0 0% 100%; + --popover-foreground: 222.2 47.4% 11.2%; + + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + + --card: 0 0% 100%; + --card-foreground: 222.2 47.4% 11.2%; + + --primary: 222.2 47.4% 11.2%; + --primary-foreground: 210 40% 98%; + + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; + + --destructive: 0 100% 50%; + --destructive-foreground: 210 40% 98%; + + --ring: 215 20.2% 65.1%; + + --radius: 0.5rem; + } + + .dark:root { + --background: 224 71% 4%; + --foreground: 213 31% 91%; + + --muted: 223 47% 11%; + --muted-foreground: 215.4 16.3% 56.9%; + + --accent: 216 34% 17%; + --accent-foreground: 210 40% 98%; + + --popover: 224 71% 4%; + --popover-foreground: 215 20.2% 65.1%; + + --border: 216 34% 17%; + --input: 216 34% 17%; + + --card: 224 71% 4%; + --card-foreground: 213 31% 91%; + + --primary: 210 40% 98%; + --primary-foreground: 222.2 47.4% 1.2%; + + --secondary: 222.2 47.4% 11.2%; + --secondary-foreground: 210 40% 98%; + + --destructive: 0 63% 31%; + --destructive-foreground: 210 40% 98%; + + --ring: 216 34% 17%; + + --radius: 0.5rem; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} diff --git a/packages/mobile/lib/utils.ts b/packages/mobile/lib/utils.ts new file mode 100644 index 00000000..365058ce --- /dev/null +++ b/packages/mobile/lib/utils.ts @@ -0,0 +1,6 @@ +import { type ClassValue, clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} diff --git a/packages/mobile/metro.config.js b/packages/mobile/metro.config.js new file mode 100644 index 00000000..bbd30d1d --- /dev/null +++ b/packages/mobile/metro.config.js @@ -0,0 +1,7 @@ +const { getDefaultConfig } = require("expo/metro-config"); +const { withNativeWind } = require("nativewind/metro"); + +/** @type {import('expo/metro-config').MetroConfig} */ +const config = getDefaultConfig(__dirname); + +module.exports = withNativeWind(config, { input: "./globals.css" }); diff --git a/packages/mobile/nativewind-env.d.ts b/packages/mobile/nativewind-env.d.ts new file mode 100644 index 00000000..a13e3136 --- /dev/null +++ b/packages/mobile/nativewind-env.d.ts @@ -0,0 +1 @@ +/// <reference types="nativewind/types" /> diff --git a/packages/mobile/package.json b/packages/mobile/package.json new file mode 100644 index 00000000..4dbd0cf5 --- /dev/null +++ b/packages/mobile/package.json @@ -0,0 +1,41 @@ +{ + "name": "hoarder-mobile", + "version": "1.0.0", + "main": "expo-router/entry", + "scripts": { + "start": "expo start", + "android": "expo start --android", + "ios": "expo start --ios", + "web": "expo start --web", + "lint": "eslint ." + }, + "dependencies": { + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.0", + "expo": "~50.0.11", + "expo-constants": "~15.4.5", + "expo-linking": "~6.2.2", + "expo-router": "~3.4.8", + "expo-status-bar": "~1.11.1", + "lucide-react-native": "^0.354.0", + "nativewind": "^4.0.1", + "react": "18.2.0", + "react-native": "0.73.4", + "react-native-reanimated": "^3.8.0", + "react-native-safe-area-context": "4.8.2", + "react-native-screens": "~3.29.0", + "react-native-svg": "^15.1.0", + "tailwind-merge": "^2.2.1" + }, + "devDependencies": { + "@babel/core": "^7.20.0", + "@types/react": "~18.2.45", + "ajv": "latest", + "eslint": "^8.57.0", + "eslint-config-universe": "^12.0.0", + "prettier": "^3.2.5", + "tailwindcss": "3.3.2", + "typescript": "^5.1.3" + }, + "private": true +} diff --git a/packages/mobile/tailwind.config.js b/packages/mobile/tailwind.config.js new file mode 100644 index 00000000..b49f9598 --- /dev/null +++ b/packages/mobile/tailwind.config.js @@ -0,0 +1,71 @@ +const { hairlineWidth } = require("nativewind/theme"); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ["./app/**/*.{js,jsx,ts,tsx}", "./components/**/*.{js,jsx,ts,tsx}"], + plugins: [], + presets: [require("nativewind/preset")], + theme: { + container: { + center: true, + padding: "2rem", + screens: { + "2xl": "1400px", + }, + }, + extend: { + colors: { + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + }, + borderWidth: { + hairline: hairlineWidth(), + }, + keyframes: { + "accordion-down": { + from: { height: "0" }, + to: { height: "var(--radix-accordion-content-height)" }, + }, + "accordion-up": { + from: { height: "var(--radix-accordion-content-height)" }, + to: { height: "0" }, + }, + }, + animation: { + "accordion-down": "accordion-down 0.2s ease-out", + "accordion-up": "accordion-up 0.2s ease-out", + }, + }, + }, +}; diff --git a/packages/mobile/tsconfig.json b/packages/mobile/tsconfig.json new file mode 100644 index 00000000..84d97cb0 --- /dev/null +++ b/packages/mobile/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "expo/tsconfig.base", + "compilerOptions": { + "strict": true, + "baseUrl": ".", + "paths": { + "@/*": ["./*"] + } + } +} |
