├── .gitignore ├── .npmrc ├── .vscode └── settings.json ├── App.tsx ├── README.md ├── app.json ├── assets ├── adaptive-icon.png ├── dark-logo.svg ├── display │ ├── image1.png │ ├── image10.png │ ├── image11.png │ ├── image12.png │ ├── image13.png │ ├── image14.png │ ├── image15.png │ ├── image16.png │ ├── image17.png │ ├── image18.png │ ├── image19.png │ ├── image2.png │ ├── image20.png │ ├── image21.png │ ├── image22.png │ ├── image23.png │ ├── image24.png │ ├── image25.png │ ├── image26.png │ ├── image27.png │ ├── image28.png │ ├── image29.png │ ├── image3.png │ ├── image30.png │ ├── image31.png │ ├── image32.png │ ├── image33.png │ ├── image4.png │ ├── image5.png │ ├── image6.png │ ├── image7.png │ ├── image8.png │ └── image9.png ├── favicon.png ├── icon.png ├── light-logo.svg └── splash.png ├── babel.config.js ├── components └── ui │ ├── accordion │ └── index.tsx │ ├── actionsheet │ └── index.tsx │ ├── alert-dialog │ └── index.tsx │ ├── alert │ └── index.tsx │ ├── avatar │ └── index.tsx │ ├── badge │ └── index.tsx │ ├── bottomsheet │ └── index.tsx │ ├── box │ ├── index.tsx │ ├── index.web.tsx │ └── styles.tsx │ ├── button │ └── index.tsx │ ├── card │ ├── index.tsx │ ├── index.web.tsx │ └── styles.tsx │ ├── center │ ├── index.tsx │ ├── index.web.tsx │ └── styles.tsx │ ├── checkbox │ └── index.tsx │ ├── divider │ └── index.tsx │ ├── drawer │ └── index.tsx │ ├── fab │ └── index.tsx │ ├── flat-list │ └── index.tsx │ ├── form-control │ └── index.tsx │ ├── gluestack-ui-provider │ ├── config.ts │ ├── index.tsx │ ├── index.web.tsx │ └── script.ts │ ├── grid │ ├── index.tsx │ ├── index.web.tsx │ └── styles.tsx │ ├── heading │ ├── index.tsx │ ├── index.web.tsx │ └── styles.tsx │ ├── hstack │ ├── index.tsx │ ├── index.web.tsx │ └── styles.tsx │ ├── icon │ ├── index.tsx │ └── index.web.tsx │ ├── image-background │ └── index.tsx │ ├── image │ └── index.tsx │ ├── index.ts │ ├── input-accessory-view │ └── index.tsx │ ├── input │ └── index.tsx │ ├── keyboard-avoiding-view │ └── index.tsx │ ├── linear-gradient │ └── index.tsx │ ├── link │ └── index.tsx │ ├── menu │ └── index.tsx │ ├── modal │ └── index.tsx │ ├── popover │ └── index.tsx │ ├── portal │ └── index.tsx │ ├── pressable │ └── index.tsx │ ├── progress │ └── index.tsx │ ├── radio │ └── index.tsx │ ├── refresh-control │ └── index.tsx │ ├── safe-area-view │ └── index.tsx │ ├── scroll-view │ └── index.tsx │ ├── section-list │ └── index.tsx │ ├── select │ ├── index.tsx │ └── select-actionsheet.tsx │ ├── skeleton │ ├── index.tsx │ ├── index.web.tsx │ └── styles.tsx │ ├── slider │ └── index.tsx │ ├── spinner │ └── index.tsx │ ├── status-bar │ └── index.tsx │ ├── switch │ └── index.tsx │ ├── table │ ├── index.tsx │ ├── index.web.tsx │ └── styles.tsx │ ├── text │ ├── index.tsx │ ├── index.web.tsx │ └── styles.tsx │ ├── textarea │ └── index.tsx │ ├── toast │ └── index.tsx │ ├── tooltip │ └── index.tsx │ ├── utils │ └── use-break-point-value.ts │ ├── view │ └── index.tsx │ ├── virtualized-list │ └── index.tsx │ └── vstack │ ├── index.tsx │ ├── index.web.tsx │ └── styles.tsx ├── dist ├── _expo │ └── static │ │ ├── css │ │ └── web-10a4177ad4fbe2b4aaf7f8972f8e688b.css │ │ └── js │ │ └── web │ │ └── AppEntry-02ab48960a21a80af7f4efeea989e86d.js ├── assets │ └── assets │ │ ├── dark-logo.b527d8072c144a767174c3a10fd79f45.svg │ │ ├── display │ │ ├── image1.f03012cb3e1fa62e6a3bef4f58e780ea.png │ │ ├── image10.a04d294a2c8df2cb183dafb0394f5a8b.png │ │ ├── image11.2dbf29763057a86efea8f78a033be313.png │ │ ├── image12.2568f80d2af0653461b80a728b10fe4d.png │ │ ├── image13.1414ade9dd20e838a93c706d5dba297f.png │ │ ├── image14.2b82ad88c8c8c3c5a128937916a375ac.png │ │ ├── image16.09e3beb535742777cd9a62aabc4b8ade.png │ │ ├── image17.17cf69e5e37ceda06b0259ff8c0a2796.png │ │ ├── image18.386a3ee5f314f83304490cebaddab084.png │ │ ├── image19.372d6ab1f73dcba58c2432d14cb77117.png │ │ ├── image2.392989858ef89d1e4bf5a320e4380e94.png │ │ ├── image20.a450e9a13ced9740a774d2a89d07d48e.png │ │ ├── image21.45c531ac257876e285f72dba1ac8446f.png │ │ ├── image22.8a3dd9460578286a6bcd941ede291c44.png │ │ ├── image23.9d58dee797ec7a27486ea8a65275c057.png │ │ ├── image24.49170de6e0ceae7fa8a994e9c6e78458.png │ │ ├── image25.86770e527c5216dfd1dd3d538667272c.png │ │ ├── image26.614aeca8a60ba55e4dc6acae7270449b.png │ │ ├── image27.7f82f059a42d45ca347061013defd8a1.png │ │ ├── image28.2ffb46b57751ea319adac24e82c5dd8b.png │ │ ├── image29.7177b3ab9287dbea295fd99ed9057727.png │ │ ├── image3.b1208f026bb71ba90311b0a96849e52c.png │ │ ├── image30.c3e43159d5cc6bdb9c4467cbface2c4d.png │ │ ├── image31.97a127c0817686518e32960de38fb4ae.png │ │ ├── image32.e074677fb4fc90611226a00006a17ec8.png │ │ ├── image33.884833822e22bfea6692626436ad8998.png │ │ ├── image4.7bb26fc7910fe122f3df1dde7026534b.png │ │ ├── image6.5f0e22ae2b49beed20510b1960eb9952.png │ │ └── image8.322108b62cd5c39fe9f29479c0f637f9.png │ │ └── light-logo.c13af6dd1401fb12975578cb353f2fec.svg ├── favicon.ico ├── index.html └── metadata.json ├── eas.json ├── global.css ├── gluestack-ui.config.json ├── kitchensink-components ├── Banner.tsx ├── ExplorePage.tsx ├── Header.tsx ├── HomestayPage.tsx ├── LogoutAlertDialog.tsx ├── MobileBottomTabs.tsx ├── MobileModeChangeButton.tsx ├── MobileProfilePage.tsx ├── MobileSidebarActionsheet.tsx ├── Sidebar.tsx ├── WebSidebar.tsx ├── header │ ├── HeaderTabs.tsx │ ├── HomestayLogo.tsx │ ├── ToggleMode.tsx │ └── UserProfile.tsx ├── main-content │ ├── HomestayInformationFold.tsx │ ├── ListYourPlaceModal.tsx │ ├── MainContent.tsx │ ├── MainContentHeader.tsx │ ├── NewThisWeekFold.tsx │ └── PriceRangeSection.tsx └── sidebar │ ├── AmenitiesSection.tsx │ ├── BookingOptions.tsx │ ├── CustomerRatingSection.tsx │ ├── FiltersAppliedSection.tsx │ ├── PlaceTypeSection.tsx │ ├── PriceRangeSection.tsx │ └── SortBySection.tsx ├── metro.config.js ├── nativewind-env.d.ts ├── package-lock.json ├── package.json ├── patches └── react-native-css-interop+0.0.36.patch ├── tailwind.config.js ├── tsconfig.json └── vercle.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files 2 | 3 | # dependencies 4 | node_modules/ 5 | 6 | # Expo 7 | .expo/ 8 | web-build/ 9 | android/ 10 | ios/ 11 | 12 | # Native 13 | *.orig.* 14 | *.jks 15 | *.p8 16 | *.p12 17 | *.key 18 | *.mobileprovision 19 | 20 | # Metro 21 | .metro-health-check* 22 | 23 | # debug 24 | npm-debug.* 25 | yarn-debug.* 26 | yarn-error.* 27 | 28 | # macOS 29 | .DS_Store 30 | *.pem 31 | 32 | # local env files 33 | .env*.local 34 | 35 | # typescript 36 | *.tsbuildinfo 37 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | legacy-peer-deps=true 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": ["Ammenities", "ammenity"] 3 | } 4 | -------------------------------------------------------------------------------- /App.tsx: -------------------------------------------------------------------------------- 1 | import "./global.css"; 2 | import React from "react"; 3 | import HomestayPage from "./kitchensink-components/HomestayPage"; 4 | import { SafeAreaView, GluestackUIProvider } from "./components/ui"; 5 | import * as Linking from "expo-linking"; 6 | 7 | let defaultTheme: "dark" | "light" = "light"; 8 | 9 | Linking.getInitialURL().then((url: any) => { 10 | let { queryParams } = Linking.parse(url) as any; 11 | defaultTheme = queryParams?.iframeMode ?? defaultTheme; 12 | }); 13 | 14 | type ThemeContextType = { 15 | colorMode?: "dark" | "light"; 16 | toggleColorMode?: () => void; 17 | }; 18 | export const ThemeContext = React.createContext({ 19 | colorMode: "light", 20 | toggleColorMode: () => {}, 21 | }); 22 | 23 | export default function App() { 24 | const [colorMode, setColorMode] = React.useState<"dark" | "light">( 25 | defaultTheme 26 | ); 27 | 28 | const toggleColorMode = async () => { 29 | setColorMode((prev) => (prev === "light" ? "dark" : "light")); 30 | }; 31 | 32 | return ( 33 | <> 34 | {/* top SafeAreaView */} 35 | 38 | 39 | 40 | {/* bottom SafeAreaView */} 41 | 46 | 47 | 48 | 49 | 50 | 51 | ); 52 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gluestack-ui v2 Dashboard Application 2 | 3 | ## Installation 4 | Ensure you have Node.js and Expo CLI installed on your machine. 5 | 6 | Clone this repository: 7 | 8 | ```bash 9 | git clone git@github.com:gluestack/ui-example-nativewind.git dashboard-app 10 | cd dashboard-app 11 | ``` 12 | 13 | Install dependencies: 14 | 15 | ```bash 16 | npm install 17 | or 18 | yarn 19 | ``` 20 | 21 | Run the Dashboard app: 22 | ```bash 23 | expo start 24 | ``` 25 | 26 | This will start the Expo development server, and you can choose to run the app on an emulator, a physical device, or the web. 27 | 28 | For detailed information on each component and its props, refer to the documentation provided. => https://gluestack.io/ui/docs/home/overview/introduction 29 | 30 | ## Give it a shot! 31 | [Try it in your browser](https://ui-example-nativewind.vercel.app) or scan the QR code below

32 | expo-icon
33 | with the Expo Go app on your phone. 34 | 35 | ## Created By GeekyAnts 36 | 37 | GeekyAnts is a team of React Native experts who love open-source and solving developers problems. We’ve been working on React Native since 2015 and have designed and built React Native apps for almost 200+ clients across the globe. Our clients include startups to big enterprises! Need help with your React Native app? 38 | 39 | [Contact Us](https://geekyants.com/?utm_source=gluestack-ui-home&utm_medium=home-page&utm_campaign=meet-the-creators) 40 | 41 | ## Contributing 42 | We welcome contributions from the community! If you want to report bugs, suggest improvements, or add new features, please create an issue, we will actively look into it. 43 | 44 | ## License 45 | This project is licensed under the MIT License. 46 | 47 | ## Contact 48 | For any inquiries or feedback join our Discord Channel => https://discord.com/invite/V5SU7HZSAQ 49 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "ui-example-nativewind", 4 | "slug": "ui-example-nativewind", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/icon.png", 8 | "userInterfaceStyle": "light", 9 | "newArchEnabled": true, 10 | "splash": { 11 | "image": "./assets/splash.png", 12 | "resizeMode": "contain", 13 | "backgroundColor": "#ffffff" 14 | }, 15 | "assetBundlePatterns": [ 16 | "**/*" 17 | ], 18 | "ios": { 19 | "supportsTablet": true, 20 | "bundleIdentifier": "com.gluestack.uiexamplenativewind" 21 | }, 22 | "android": { 23 | "adaptiveIcon": { 24 | "foregroundImage": "./assets/adaptive-icon.png", 25 | "backgroundColor": "#ffffff" 26 | }, 27 | "package": "com.gluestack.uiexamplenativewind" 28 | }, 29 | "web": { 30 | "favicon": "./assets/favicon.png", 31 | "bundler": "metro" 32 | }, 33 | "extra": { 34 | "eas": { 35 | "projectId": "42cce9b5-9fbe-4572-92ba-fc43b2437a85" 36 | } 37 | }, 38 | "owner": "gluestack", 39 | "runtimeVersion": { 40 | "policy": "appVersion" 41 | }, 42 | "updates": { 43 | "url": "https://u.expo.dev/42cce9b5-9fbe-4572-92ba-fc43b2437a85" 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/adaptive-icon.png -------------------------------------------------------------------------------- /assets/display/image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image1.png -------------------------------------------------------------------------------- /assets/display/image10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image10.png -------------------------------------------------------------------------------- /assets/display/image11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image11.png -------------------------------------------------------------------------------- /assets/display/image12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image12.png -------------------------------------------------------------------------------- /assets/display/image13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image13.png -------------------------------------------------------------------------------- /assets/display/image14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image14.png -------------------------------------------------------------------------------- /assets/display/image15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image15.png -------------------------------------------------------------------------------- /assets/display/image16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image16.png -------------------------------------------------------------------------------- /assets/display/image17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image17.png -------------------------------------------------------------------------------- /assets/display/image18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image18.png -------------------------------------------------------------------------------- /assets/display/image19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image19.png -------------------------------------------------------------------------------- /assets/display/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image2.png -------------------------------------------------------------------------------- /assets/display/image20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image20.png -------------------------------------------------------------------------------- /assets/display/image21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image21.png -------------------------------------------------------------------------------- /assets/display/image22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image22.png -------------------------------------------------------------------------------- /assets/display/image23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image23.png -------------------------------------------------------------------------------- /assets/display/image24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image24.png -------------------------------------------------------------------------------- /assets/display/image25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image25.png -------------------------------------------------------------------------------- /assets/display/image26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image26.png -------------------------------------------------------------------------------- /assets/display/image27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image27.png -------------------------------------------------------------------------------- /assets/display/image28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image28.png -------------------------------------------------------------------------------- /assets/display/image29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image29.png -------------------------------------------------------------------------------- /assets/display/image3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image3.png -------------------------------------------------------------------------------- /assets/display/image30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image30.png -------------------------------------------------------------------------------- /assets/display/image31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image31.png -------------------------------------------------------------------------------- /assets/display/image32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image32.png -------------------------------------------------------------------------------- /assets/display/image33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image33.png -------------------------------------------------------------------------------- /assets/display/image4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image4.png -------------------------------------------------------------------------------- /assets/display/image5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image5.png -------------------------------------------------------------------------------- /assets/display/image6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image6.png -------------------------------------------------------------------------------- /assets/display/image7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image7.png -------------------------------------------------------------------------------- /assets/display/image8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image8.png -------------------------------------------------------------------------------- /assets/display/image9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/display/image9.png -------------------------------------------------------------------------------- /assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/favicon.png -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/icon.png -------------------------------------------------------------------------------- /assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gluestack/ui-example-nativewind/d0117f4f13b65b3b9be5a3c9a2945e0d2f114908/assets/splash.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | return { 4 | presets: [ 5 | ['babel-preset-expo', { jsxImportSource: 'nativewind' }], 6 | 'nativewind/babel' 7 | ], 8 | 9 | plugins: [["module-resolver", { 10 | root: ["./"], 11 | 12 | alias: { 13 | "@": "./", 14 | "tailwind.config": "./tailwind.config.js" 15 | } 16 | }]] 17 | }; 18 | }; 19 | -------------------------------------------------------------------------------- /components/ui/alert/index.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import { createAlert } from '@gluestack-ui/alert'; 3 | import { View, Text } from 'react-native'; 4 | import { tva } from '@gluestack-ui/nativewind-utils/tva'; 5 | import { 6 | withStyleContext, 7 | useStyleContext, 8 | } from '@gluestack-ui/nativewind-utils/withStyleContext'; 9 | import React from 'react'; 10 | import { cssInterop } from 'nativewind'; 11 | import type { VariantProps } from '@gluestack-ui/nativewind-utils'; 12 | import { PrimitiveIcon, UIIcon } from '@gluestack-ui/icon'; 13 | 14 | const SCOPE = 'ALERT'; 15 | 16 | const alertStyle = tva({ 17 | base: 'items-center py-3 px-4 rounded-md flex-row gap-2 border-outline-100', 18 | 19 | variants: { 20 | action: { 21 | error: 'bg-background-error', 22 | warning: 'bg-background-warning', 23 | success: 'bg-background-success', 24 | info: 'bg-background-info', 25 | muted: 'bg-background-muted', 26 | }, 27 | 28 | variant: { 29 | solid: '', 30 | outline: 'border bg-background-0', 31 | }, 32 | }, 33 | }); 34 | 35 | const alertTextStyle = tva({ 36 | base: 'font-normal font-body', 37 | 38 | variants: { 39 | isTruncated: { 40 | true: 'web:truncate', 41 | }, 42 | bold: { 43 | true: 'font-bold', 44 | }, 45 | underline: { 46 | true: 'underline', 47 | }, 48 | strikeThrough: { 49 | true: 'line-through', 50 | }, 51 | size: { 52 | '2xs': 'text-2xs', 53 | 'xs': 'text-xs', 54 | 'sm': 'text-sm', 55 | 'md': 'text-md', 56 | 'lg': 'text-lg', 57 | 'xl': 'text-xl', 58 | '2xl': 'text-2xl', 59 | '3xl': 'text-3xl', 60 | '4xl': 'text-4xl', 61 | '5xl': 'text-5xl', 62 | '6xl': 'text-6xl', 63 | }, 64 | sub: { 65 | true: 'text-xs', 66 | }, 67 | italic: { 68 | true: 'italic', 69 | }, 70 | highlight: { 71 | true: 'bg-yellow-500', 72 | }, 73 | }, 74 | parentVariants: { 75 | action: { 76 | error: 'text-error-800', 77 | warning: 'text-warning-800', 78 | success: 'text-success-800', 79 | info: 'text-info-800', 80 | muted: 'text-background-800', 81 | }, 82 | }, 83 | }); 84 | 85 | const alertIconStyle = tva({ 86 | base: 'fill-none', 87 | variants: { 88 | size: { 89 | '2xs': 'h-3 w-3', 90 | 'xs': 'h-3.5 w-3.5', 91 | 'sm': 'h-4 w-4', 92 | 'md': 'h-[18px] w-[18px]', 93 | 'lg': 'h-5 w-5', 94 | 'xl': 'h-6 w-6', 95 | }, 96 | }, 97 | parentVariants: { 98 | action: { 99 | error: 'text-error-800', 100 | warning: 'text-warning-800', 101 | success: 'text-success-800', 102 | info: 'text-info-800', 103 | muted: 'text-background-800', 104 | }, 105 | }, 106 | }); 107 | 108 | export const UIAlert = createAlert({ 109 | Root: withStyleContext(View, SCOPE), 110 | Text: Text, 111 | Icon: UIIcon, 112 | }); 113 | 114 | cssInterop(PrimitiveIcon, { 115 | className: { 116 | target: 'style', 117 | nativeStyleToProp: { 118 | height: true, 119 | width: true, 120 | fill: true, 121 | color: 'classNameColor', 122 | stroke: true, 123 | }, 124 | }, 125 | }); 126 | 127 | type IAlertProps = Omit< 128 | React.ComponentPropsWithoutRef, 129 | 'context' 130 | > & 131 | VariantProps; 132 | 133 | const Alert = React.forwardRef, IAlertProps>( 134 | ({ className, variant = 'solid', action = 'muted', ...props }, ref) => { 135 | return ( 136 | 142 | ); 143 | } 144 | ); 145 | 146 | type IAlertTextProps = React.ComponentPropsWithoutRef & 147 | VariantProps; 148 | 149 | const AlertText = React.forwardRef< 150 | React.ElementRef, 151 | IAlertTextProps 152 | >( 153 | ( 154 | { 155 | className, 156 | isTruncated, 157 | bold, 158 | underline, 159 | strikeThrough, 160 | size = 'md', 161 | sub, 162 | italic, 163 | highlight, 164 | ...props 165 | }, 166 | ref 167 | ) => { 168 | const { action: parentAction } = useStyleContext(SCOPE); 169 | return ( 170 | 188 | ); 189 | } 190 | ); 191 | 192 | type IAlertIconProps = React.ComponentPropsWithoutRef & 193 | VariantProps; 194 | 195 | const AlertIcon = React.forwardRef< 196 | React.ElementRef, 197 | IAlertIconProps 198 | >(({ className, size = 'md', ...props }, ref) => { 199 | const { action: parentAction } = useStyleContext(SCOPE); 200 | 201 | if (typeof size === 'number') { 202 | return ( 203 | 209 | ); 210 | } else if ( 211 | (props.height !== undefined || props.width !== undefined) && 212 | size === undefined 213 | ) { 214 | return ( 215 | 220 | ); 221 | } 222 | return ( 223 | 234 | ); 235 | }); 236 | 237 | Alert.displayName = 'Alert'; 238 | AlertText.displayName = 'AlertText'; 239 | AlertIcon.displayName = 'AlertIcon'; 240 | 241 | export { Alert, AlertText, AlertIcon }; 242 | -------------------------------------------------------------------------------- /components/ui/avatar/index.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import React from 'react'; 3 | import { createAvatar } from '@gluestack-ui/avatar'; 4 | 5 | import { View, Text, Image, Platform } from 'react-native'; 6 | 7 | import { tva } from '@gluestack-ui/nativewind-utils/tva'; 8 | import { 9 | withStyleContext, 10 | useStyleContext, 11 | } from '@gluestack-ui/nativewind-utils/withStyleContext'; 12 | const SCOPE = 'AVATAR'; 13 | import type { VariantProps } from '@gluestack-ui/nativewind-utils'; 14 | 15 | const UIAvatar = createAvatar({ 16 | Root: withStyleContext(View, SCOPE), 17 | Badge: View, 18 | Group: View, 19 | Image: Image, 20 | FallbackText: Text, 21 | }); 22 | 23 | const avatarStyle = tva({ 24 | base: 'rounded-full justify-center items-center relative bg-primary-600 group-[.avatar-group]/avatar-group:-ml-2.5', 25 | variants: { 26 | size: { 27 | 'xs': 'w-6 h-6', 28 | 'sm': 'w-8 h-8', 29 | 'md': 'w-12 h-12', 30 | 'lg': 'w-16 h-16', 31 | 'xl': 'w-24 h-24', 32 | '2xl': 'w-32 h-32', 33 | }, 34 | }, 35 | }); 36 | 37 | const avatarFallbackTextStyle = tva({ 38 | base: 'text-typography-0 font-semibold overflow-hidden text-transform:uppercase web:cursor-default', 39 | 40 | parentVariants: { 41 | size: { 42 | 'xs': 'text-2xs', 43 | 'sm': 'text-xs', 44 | 'md': 'text-base', 45 | 'lg': 'text-xl', 46 | 'xl': 'text-3xl', 47 | '2xl': 'text-5xl', 48 | }, 49 | }, 50 | }); 51 | 52 | const avatarGroupStyle = tva({ 53 | base: 'group/avatar-group flex-row-reverse relative avatar-group', 54 | }); 55 | 56 | const avatarBadgeStyle = tva({ 57 | base: 'w-5 h-5 bg-success-500 rounded-full absolute right-0 bottom-0 border-background-0 border-2', 58 | parentVariants: { 59 | size: { 60 | 'xs': 'w-2 h-2', 61 | 'sm': 'w-2 h-2', 62 | 'md': 'w-3 h-3', 63 | 'lg': 'w-4 h-4', 64 | 'xl': 'w-6 h-6', 65 | '2xl': 'w-8 h-8', 66 | }, 67 | }, 68 | }); 69 | 70 | const avatarImageStyle = tva({ 71 | base: 'h-full w-full rounded-full absolute', 72 | }); 73 | 74 | type IAvatarProps = Omit< 75 | React.ComponentPropsWithoutRef, 76 | 'context' 77 | > & 78 | VariantProps; 79 | 80 | export const Avatar = React.forwardRef< 81 | React.ElementRef, 82 | IAvatarProps 83 | >(({ className, size = 'md', ...props }, ref) => { 84 | return ( 85 | 91 | ); 92 | }); 93 | 94 | type IAvatarBadgeProps = React.ComponentPropsWithoutRef & 95 | VariantProps; 96 | 97 | export const AvatarBadge = React.forwardRef< 98 | React.ElementRef, 99 | IAvatarBadgeProps 100 | >(({ className, size, ...props }, ref) => { 101 | const { size: parentSize } = useStyleContext(SCOPE); 102 | 103 | return ( 104 | 115 | ); 116 | }); 117 | 118 | type IAvatarFallbackTextProps = React.ComponentPropsWithoutRef< 119 | typeof UIAvatar.FallbackText 120 | > & 121 | VariantProps; 122 | export const AvatarFallbackText = React.forwardRef< 123 | React.ElementRef, 124 | IAvatarFallbackTextProps 125 | >(({ className, size, ...props }, ref) => { 126 | const { size: parentSize } = useStyleContext(SCOPE); 127 | 128 | return ( 129 | 140 | ); 141 | }); 142 | 143 | type IAvatarImageProps = React.ComponentPropsWithoutRef & 144 | VariantProps; 145 | 146 | export const AvatarImage = React.forwardRef< 147 | React.ElementRef, 148 | IAvatarImageProps 149 | >(({ className, ...props }, ref) => { 150 | return ( 151 | 165 | ); 166 | }); 167 | 168 | type IAvatarGroupProps = React.ComponentPropsWithoutRef & 169 | VariantProps; 170 | 171 | export const AvatarGroup = React.forwardRef< 172 | React.ElementRef, 173 | IAvatarGroupProps 174 | >(({ className, ...props }, ref) => { 175 | return ( 176 | 183 | ); 184 | }); 185 | -------------------------------------------------------------------------------- /components/ui/badge/index.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import React from 'react'; 3 | import { Text, View } from 'react-native'; 4 | import { PrimitiveIcon, UIIcon } from '@gluestack-ui/icon'; 5 | import { tva } from '@gluestack-ui/nativewind-utils/tva'; 6 | import { 7 | withStyleContext, 8 | useStyleContext, 9 | } from '@gluestack-ui/nativewind-utils/withStyleContext'; 10 | import { cssInterop } from 'nativewind'; 11 | import type { VariantProps } from '@gluestack-ui/nativewind-utils'; 12 | const SCOPE = 'BADGE'; 13 | 14 | const badgeStyle = tva({ 15 | base: 'flex-row items-center rounded-sm data-[disabled=true]:opacity-50 px-2 py-1', 16 | variants: { 17 | action: { 18 | error: 'bg-background-error border-error-300', 19 | warning: 'bg-background-warning border-warning-300', 20 | success: 'bg-background-success border-success-300', 21 | info: 'bg-background-info border-info-300', 22 | muted: 'bg-background-muted border-background-300', 23 | }, 24 | variant: { 25 | solid: '', 26 | outline: 'border', 27 | }, 28 | size: { 29 | sm: '', 30 | md: '', 31 | lg: '', 32 | }, 33 | }, 34 | }); 35 | 36 | const badgeTextStyle = tva({ 37 | base: 'text-typography-700 font-body font-normal tracking-normal uppercase', 38 | 39 | parentVariants: { 40 | action: { 41 | error: 'text-error-600', 42 | warning: 'text-warning-600', 43 | success: 'text-success-600', 44 | info: 'text-info-600', 45 | muted: 'text-background-800', 46 | }, 47 | size: { 48 | sm: 'text-2xs', 49 | md: 'text-xs', 50 | lg: 'text-sm', 51 | }, 52 | }, 53 | variants: { 54 | isTruncated: { 55 | true: 'web:truncate', 56 | }, 57 | bold: { 58 | true: 'font-bold', 59 | }, 60 | underline: { 61 | true: 'underline', 62 | }, 63 | strikeThrough: { 64 | true: 'line-through', 65 | }, 66 | sub: { 67 | true: 'text-xs', 68 | }, 69 | italic: { 70 | true: 'italic', 71 | }, 72 | highlight: { 73 | true: 'bg-yellow-500', 74 | }, 75 | }, 76 | }); 77 | 78 | const badgeIconStyle = tva({ 79 | base: 'fill-none', 80 | parentVariants: { 81 | action: { 82 | error: 'text-error-600', 83 | warning: 'text-warning-600', 84 | success: 'text-success-600', 85 | info: 'text-info-600', 86 | muted: 'text-background-800', 87 | }, 88 | size: { 89 | sm: 'h-3 w-3', 90 | md: 'h-3.5 w-3.5', 91 | lg: 'h-4 w-4', 92 | }, 93 | }, 94 | }); 95 | 96 | const ContextView = withStyleContext(View, SCOPE); 97 | 98 | cssInterop(PrimitiveIcon, { 99 | className: { 100 | target: 'style', 101 | nativeStyleToProp: { 102 | height: true, 103 | width: true, 104 | //@ts-expect-error 105 | fill: true, 106 | color: 'classNameColor', 107 | stroke: true, 108 | }, 109 | }, 110 | }); 111 | 112 | type IBadgeProps = React.ComponentPropsWithoutRef & 113 | VariantProps; 114 | const Badge = ({ 115 | children, 116 | action = 'muted', 117 | variant = 'solid', 118 | size = 'md', 119 | className, 120 | ...props 121 | }: { className?: string } & IBadgeProps) => { 122 | return ( 123 | 132 | {children} 133 | 134 | ); 135 | }; 136 | 137 | type IBadgeTextProps = React.ComponentPropsWithoutRef & 138 | VariantProps; 139 | 140 | const BadgeText = React.forwardRef< 141 | React.ElementRef, 142 | IBadgeTextProps 143 | >(({ children, className, size, ...props }, ref) => { 144 | const { size: parentSize, action: parentAction } = useStyleContext(SCOPE); 145 | return ( 146 | 158 | {children} 159 | 160 | ); 161 | }); 162 | 163 | type IBadgeIconProps = React.ComponentPropsWithoutRef & 164 | VariantProps; 165 | 166 | const BadgeIcon = React.forwardRef< 167 | React.ElementRef, 168 | IBadgeIconProps 169 | >(({ className, size, ...props }, ref) => { 170 | const { size: parentSize, action: parentAction } = useStyleContext(SCOPE); 171 | 172 | if (typeof size === 'number') { 173 | return ( 174 | 180 | ); 181 | } else if ( 182 | (props?.height !== undefined || props?.width !== undefined) && 183 | size === undefined 184 | ) { 185 | return ( 186 | 191 | ); 192 | } 193 | return ( 194 | 206 | ); 207 | }); 208 | 209 | Badge.displayName = 'Badge'; 210 | BadgeText.displayName = 'BadgeText'; 211 | BadgeIcon.displayName = 'BadgeIcon'; 212 | 213 | export { Badge, BadgeIcon, BadgeText }; 214 | -------------------------------------------------------------------------------- /components/ui/box/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, ViewProps } from 'react-native'; 3 | 4 | import type { VariantProps } from '@gluestack-ui/nativewind-utils'; 5 | import { boxStyle } from './styles'; 6 | 7 | type IBoxProps = ViewProps & 8 | VariantProps & { className?: string }; 9 | 10 | const Box = React.forwardRef, IBoxProps>( 11 | ({ className, ...props }, ref) => { 12 | return ( 13 | 14 | ); 15 | } 16 | ); 17 | 18 | Box.displayName = 'Box'; 19 | export { Box }; 20 | -------------------------------------------------------------------------------- /components/ui/box/index.web.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { boxStyle } from './styles'; 3 | 4 | import type { VariantProps } from '@gluestack-ui/nativewind-utils'; 5 | 6 | type IBoxProps = React.ComponentPropsWithoutRef<'div'> & 7 | VariantProps & { className?: string }; 8 | 9 | const Box = React.forwardRef( 10 | ({ className, ...props }, ref) => { 11 | return ( 12 |
13 | ); 14 | } 15 | ); 16 | 17 | Box.displayName = 'Box'; 18 | export { Box }; 19 | -------------------------------------------------------------------------------- /components/ui/box/styles.tsx: -------------------------------------------------------------------------------- 1 | import { tva } from '@gluestack-ui/nativewind-utils/tva'; 2 | import { isWeb } from '@gluestack-ui/nativewind-utils/IsWeb'; 3 | 4 | const baseStyle = isWeb 5 | ? 'flex flex-col relative z-0 box-border border-0 list-none min-w-0 min-h-0 bg-transparent items-stretch m-0 p-0 text-decoration-none' 6 | : ''; 7 | 8 | export const boxStyle = tva({ 9 | base: baseStyle, 10 | }); 11 | -------------------------------------------------------------------------------- /components/ui/card/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type { VariantProps } from '@gluestack-ui/nativewind-utils'; 3 | import { View, ViewProps } from 'react-native'; 4 | import { cardStyle } from './styles'; 5 | 6 | type ICardProps = ViewProps & 7 | VariantProps & { className?: string }; 8 | 9 | const Card = React.forwardRef, ICardProps>( 10 | ({ className, size = 'md', variant = 'elevated', ...props }, ref) => { 11 | return ( 12 | 17 | ); 18 | } 19 | ); 20 | 21 | Card.displayName = 'Card'; 22 | 23 | export { Card }; 24 | -------------------------------------------------------------------------------- /components/ui/card/index.web.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { cardStyle } from './styles'; 3 | import type { VariantProps } from '@gluestack-ui/nativewind-utils'; 4 | 5 | type ICardProps = React.ComponentPropsWithoutRef<'div'> & 6 | VariantProps; 7 | 8 | const Card = React.forwardRef( 9 | ({ className, size = 'md', variant = 'elevated', ...props }, ref) => { 10 | return ( 11 |
16 | ); 17 | } 18 | ); 19 | 20 | Card.displayName = 'Card'; 21 | 22 | export { Card }; 23 | -------------------------------------------------------------------------------- /components/ui/card/styles.tsx: -------------------------------------------------------------------------------- 1 | import { tva } from '@gluestack-ui/nativewind-utils/tva'; 2 | import { isWeb } from '@gluestack-ui/nativewind-utils/IsWeb'; 3 | const baseStyle = isWeb ? 'flex flex-col relative z-0' : ''; 4 | 5 | export const cardStyle = tva({ 6 | base: baseStyle, 7 | variants: { 8 | size: { 9 | sm: 'p-3 rounded', 10 | md: 'p-4 rounded-md', 11 | lg: 'p-6 rounded-xl', 12 | }, 13 | variant: { 14 | elevated: 'bg-background-0', 15 | outline: 'border border-outline-200 ', 16 | ghost: 'rounded-none', 17 | filled: 'bg-background-50', 18 | }, 19 | }, 20 | }); 21 | -------------------------------------------------------------------------------- /components/ui/center/index.tsx: -------------------------------------------------------------------------------- 1 | import { View, ViewProps } from 'react-native'; 2 | import React from 'react'; 3 | import { centerStyle } from './styles'; 4 | import type { VariantProps } from '@gluestack-ui/nativewind-utils'; 5 | 6 | type ICenterProps = ViewProps & VariantProps; 7 | 8 | const Center = React.forwardRef, ICenterProps>( 9 | ({ className, ...props }, ref) => { 10 | return ( 11 | 16 | ); 17 | } 18 | ); 19 | 20 | Center.displayName = 'Center'; 21 | 22 | export { Center }; 23 | -------------------------------------------------------------------------------- /components/ui/center/index.web.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { centerStyle } from './styles'; 3 | 4 | import type { VariantProps } from '@gluestack-ui/nativewind-utils'; 5 | 6 | type ICenterProps = React.ComponentPropsWithoutRef<'div'> & 7 | VariantProps; 8 | 9 | const Center = React.forwardRef( 10 | ({ className, ...props }, ref) => { 11 | return ( 12 |
13 | ); 14 | } 15 | ); 16 | 17 | Center.displayName = 'Center'; 18 | 19 | export { Center }; 20 | -------------------------------------------------------------------------------- /components/ui/center/styles.tsx: -------------------------------------------------------------------------------- 1 | import { tva } from '@gluestack-ui/nativewind-utils/tva'; 2 | import { isWeb } from '@gluestack-ui/nativewind-utils/IsWeb'; 3 | 4 | const baseStyle = isWeb ? 'flex flex-col relative z-0' : ''; 5 | 6 | export const centerStyle = tva({ 7 | base: `justify-center items-center ${baseStyle}`, 8 | }); 9 | -------------------------------------------------------------------------------- /components/ui/divider/index.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import React from 'react'; 3 | import { tva } from '@gluestack-ui/nativewind-utils/tva'; 4 | import { Platform, View } from 'react-native'; 5 | import type { VariantProps } from '@gluestack-ui/nativewind-utils'; 6 | 7 | const dividerStyle = tva({ 8 | base: 'bg-background-200', 9 | variants: { 10 | orientation: { 11 | vertical: 'w-px h-full', 12 | horizontal: 'h-px w-full', 13 | }, 14 | }, 15 | }); 16 | 17 | type IUIDividerProps = React.ComponentPropsWithoutRef & 18 | VariantProps; 19 | 20 | const Divider = React.forwardRef< 21 | React.ElementRef, 22 | IUIDividerProps 23 | >(({ className, orientation = 'horizontal', ...props }, ref) => { 24 | return ( 25 | 35 | ); 36 | }); 37 | 38 | Divider.displayName = 'Divider'; 39 | 40 | export { Divider }; 41 | -------------------------------------------------------------------------------- /components/ui/fab/index.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import React from 'react'; 3 | import { createFab } from '@gluestack-ui/fab'; 4 | import { Pressable, Text } from 'react-native'; 5 | import { tva } from '@gluestack-ui/nativewind-utils/tva'; 6 | import { 7 | withStyleContext, 8 | useStyleContext, 9 | } from '@gluestack-ui/nativewind-utils/withStyleContext'; 10 | import { cssInterop } from 'nativewind'; 11 | import type { VariantProps } from '@gluestack-ui/nativewind-utils'; 12 | import { PrimitiveIcon, UIIcon } from '@gluestack-ui/icon'; 13 | 14 | const SCOPE = 'FAB'; 15 | const Root = withStyleContext(Pressable, SCOPE); 16 | const UIFab = createFab({ 17 | Root: Root, 18 | Label: Text, 19 | Icon: UIIcon, 20 | }); 21 | 22 | cssInterop(PrimitiveIcon, { 23 | className: { 24 | target: 'style', 25 | nativeStyleToProp: { 26 | height: true, 27 | width: true, 28 | fill: true, 29 | color: 'classNameColor', 30 | stroke: true, 31 | }, 32 | }, 33 | }); 34 | 35 | const fabStyle = tva({ 36 | base: 'group/fab bg-primary-500 rounded-full z-20 p-4 flex-row items-center justify-center absolute hover:bg-primary-600 active:bg-primary-700 disabled:opacity-40 disabled:pointer-events-all disabled:cursor-not-allowed data-[focus=true]:web:outline-none data-[focus-visible=true]:web:ring-2 data-[focus-visible=true]:web:ring-indicator-info shadow-hard-2', 37 | variants: { 38 | size: { 39 | sm: 'px-2.5 py-2.5', 40 | md: 'px-3 py-3', 41 | lg: 'px-4 py-4', 42 | }, 43 | placement: { 44 | 'top right': 'top-4 right-4', 45 | 'top left': 'top-4 left-4', 46 | 'bottom right': 'bottom-4 right-4', 47 | 'bottom left': 'bottom-4 left-4', 48 | 'top center': 'top-4 self-center', 49 | 'bottom center': 'bottom-4 self-center', 50 | }, 51 | }, 52 | }); 53 | 54 | const fabLabelStyle = tva({ 55 | base: 'text-typography-50 font-normal font-body tracking-md text-left mx-2', 56 | variants: { 57 | isTruncated: { 58 | true: '', 59 | }, 60 | bold: { 61 | true: 'font-bold', 62 | }, 63 | underline: { 64 | true: 'underline', 65 | }, 66 | strikeThrough: { 67 | true: 'line-through', 68 | }, 69 | size: { 70 | '2xs': 'text-2xs', 71 | 'xs': 'text-xs', 72 | 'sm': 'text-sm', 73 | 'md': 'text-base', 74 | 'lg': 'text-lg', 75 | 'xl': 'text-xl', 76 | '2xl': 'text-2xl', 77 | '3xl': 'text-3xl', 78 | '4xl': 'text-4xl', 79 | '5xl': 'text-5xl', 80 | '6xl': 'text-6xl', 81 | }, 82 | sub: { 83 | true: 'text-xs', 84 | }, 85 | italic: { 86 | true: 'italic', 87 | }, 88 | highlight: { 89 | true: 'bg-yellow-500', 90 | }, 91 | }, 92 | parentVariants: { 93 | size: { 94 | sm: 'text-sm', 95 | md: 'text-base', 96 | lg: 'text-lg', 97 | }, 98 | }, 99 | }); 100 | 101 | const fabIconStyle = tva({ 102 | base: 'text-typography-50 fill-none', 103 | variants: { 104 | size: { 105 | '2xs': 'h-3 w-3', 106 | 'xs': 'h-3.5 w-3.5', 107 | 'sm': 'h-4 w-4', 108 | 'md': 'w-[18px] h-[18px]', 109 | 'lg': 'h-5 w-5', 110 | 'xl': 'h-6 w-6', 111 | }, 112 | }, 113 | }); 114 | 115 | type IFabProps = Omit, 'context'> & 116 | VariantProps; 117 | 118 | const Fab = React.forwardRef, IFabProps>( 119 | ({ size = 'md', placement = 'bottom right', className, ...props }, ref) => { 120 | return ( 121 | 127 | ); 128 | } 129 | ); 130 | 131 | type IFabLabelProps = React.ComponentPropsWithoutRef & 132 | VariantProps; 133 | 134 | const FabLabel = React.forwardRef< 135 | React.ElementRef, 136 | IFabLabelProps 137 | >( 138 | ( 139 | { 140 | size, 141 | isTruncated = false, 142 | bold = false, 143 | underline = false, 144 | strikeThrough = false, 145 | className, 146 | ...props 147 | }, 148 | ref 149 | ) => { 150 | const { size: parentSize } = useStyleContext(SCOPE); 151 | return ( 152 | 167 | ); 168 | } 169 | ); 170 | 171 | type IFabIconProps = React.ComponentPropsWithoutRef & 172 | VariantProps; 173 | 174 | const FabIcon = React.forwardRef< 175 | React.ElementRef, 176 | IFabIconProps 177 | >(({ size, className, ...props }, ref) => { 178 | const { size: parentSize } = useStyleContext(SCOPE); 179 | 180 | if (typeof size === 'number') { 181 | return ( 182 | 188 | ); 189 | } else if ( 190 | //@ts-expect-error 191 | (props.height !== undefined || props.width !== undefined) && 192 | size === undefined 193 | ) { 194 | return ( 195 | 200 | ); 201 | } 202 | return ( 203 | 214 | ); 215 | }); 216 | 217 | Fab.displayName = 'Fab'; 218 | FabLabel.displayName = 'FabLabel'; 219 | FabIcon.displayName = 'FabIcon'; 220 | 221 | export { Fab, FabLabel, FabIcon }; 222 | -------------------------------------------------------------------------------- /components/ui/flat-list/index.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | export { FlatList } from 'react-native'; 3 | -------------------------------------------------------------------------------- /components/ui/gluestack-ui-provider/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { config } from './config'; 3 | import { ColorSchemeName, useColorScheme, View, ViewProps } from 'react-native'; 4 | import { OverlayProvider } from '@gluestack-ui/overlay'; 5 | import { ToastProvider } from '@gluestack-ui/toast'; 6 | import { colorScheme as colorSchemeNW } from 'nativewind'; 7 | 8 | type ModeType = 'light' | 'dark' | 'system'; 9 | 10 | const getColorSchemeName = ( 11 | colorScheme: ColorSchemeName, 12 | mode: ModeType 13 | ): 'light' | 'dark' => { 14 | if (mode === 'system') { 15 | return colorScheme ?? 'light'; 16 | } 17 | return mode; 18 | }; 19 | 20 | export function GluestackUIProvider({ 21 | mode = 'light', 22 | ...props 23 | }: { 24 | mode?: 'light' | 'dark' | 'system'; 25 | children?: React.ReactNode; 26 | style?: ViewProps['style']; 27 | }) { 28 | const colorScheme = useColorScheme(); 29 | 30 | const colorSchemeName = getColorSchemeName(colorScheme, mode); 31 | 32 | colorSchemeNW.set(mode); 33 | 34 | return ( 35 | 43 | 44 | {props.children} 45 | 46 | 47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /components/ui/gluestack-ui-provider/index.web.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import React, { useEffect, useLayoutEffect } from 'react'; 3 | import { config } from './config'; 4 | import { OverlayProvider } from '@gluestack-ui/overlay'; 5 | import { ToastProvider } from '@gluestack-ui/toast'; 6 | import { setFlushStyles } from '@gluestack-ui/nativewind-utils/flush'; 7 | import { script } from './script'; 8 | 9 | const variableStyleTagId = 'nativewind-style'; 10 | const createStyle = (styleTagId: string) => { 11 | const style = document.createElement('style'); 12 | style.id = styleTagId; 13 | style.appendChild(document.createTextNode('')); 14 | return style; 15 | }; 16 | 17 | export const useSafeLayoutEffect = 18 | typeof window !== 'undefined' ? useLayoutEffect : useEffect; 19 | 20 | export function GluestackUIProvider({ 21 | mode = 'light', 22 | ...props 23 | }: { 24 | mode?: 'light' | 'dark' | 'system'; 25 | children?: React.ReactNode; 26 | }) { 27 | let cssVariablesWithMode = ``; 28 | Object.keys(config).forEach((configKey) => { 29 | cssVariablesWithMode += 30 | configKey === 'dark' ? `\n .dark {\n ` : `\n:root {\n`; 31 | const cssVariables = Object.keys( 32 | config[configKey as keyof typeof config] 33 | ).reduce((acc: string, curr: string) => { 34 | acc += `${curr}:${config[configKey as keyof typeof config][curr]}; `; 35 | return acc; 36 | }, ''); 37 | cssVariablesWithMode += `${cssVariables} \n}`; 38 | }); 39 | 40 | setFlushStyles(cssVariablesWithMode); 41 | 42 | const handleMediaQuery = React.useCallback((e: MediaQueryListEvent) => { 43 | script(e.matches ? 'dark' : 'light'); 44 | }, []); 45 | 46 | useSafeLayoutEffect(() => { 47 | if (mode !== 'system') { 48 | const documentElement = document.documentElement; 49 | if (documentElement) { 50 | documentElement.classList.add(mode); 51 | documentElement.classList.remove(mode === 'light' ? 'dark' : 'light'); 52 | documentElement.style.colorScheme = mode; 53 | } 54 | } 55 | }, [mode]); 56 | 57 | useSafeLayoutEffect(() => { 58 | if (mode !== 'system') return; 59 | const media = window.matchMedia('(prefers-color-scheme: dark)'); 60 | 61 | media.addListener(handleMediaQuery); 62 | 63 | return () => media.removeListener(handleMediaQuery); 64 | }, [handleMediaQuery]); 65 | 66 | useSafeLayoutEffect(() => { 67 | if (typeof window !== 'undefined') { 68 | const documentElement = document.documentElement; 69 | if (documentElement) { 70 | const head = documentElement.querySelector('head'); 71 | let style = head?.querySelector(`[id='${variableStyleTagId}']`); 72 | if (!style) { 73 | style = createStyle(variableStyleTagId); 74 | style.innerHTML = cssVariablesWithMode; 75 | if (head) head.appendChild(style); 76 | } 77 | } 78 | } 79 | }, []); 80 | 81 | return ( 82 | <> 83 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /dist/metadata.json: -------------------------------------------------------------------------------- 1 | {"version":0,"bundler":"metro","fileMetadata":{}} -------------------------------------------------------------------------------- /eas.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "preview": { 4 | "android": { 5 | "buildType": "apk" 6 | } 7 | }, 8 | "preview2": { 9 | "android": { 10 | "gradleCommand": ":app:assembleRelease" 11 | } 12 | }, 13 | "preview3": { 14 | "developmentClient": true 15 | }, 16 | "preview4": { 17 | "distribution": "internal" 18 | }, 19 | "production": {} 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /global.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | body { 6 | @apply overflow-hidden h-full; 7 | } 8 | 9 | ::-webkit-scrollbar { 10 | @apply w-1.5 h-2; 11 | } 12 | 13 | ::-webkit-scrollbar-corner, 14 | ::-webkit-scrollbar-track { 15 | @apply bg-transparent; 16 | } 17 | 18 | ::-webkit-scrollbar-thumb { 19 | @apply bg-secondary-200 rounded-[20px] border-[3px] border-solid border-transparent; 20 | } -------------------------------------------------------------------------------- /gluestack-ui.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "tailwind": { 3 | "config": "tailwind.config.js", 4 | "css": "global.css" 5 | }, 6 | "app": { 7 | "entry": "App.tsx", 8 | "components": "components/ui" 9 | } 10 | } -------------------------------------------------------------------------------- /kitchensink-components/Banner.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { HStack, Link, LinkText, Text } from "../components/ui"; 3 | 4 | const Banner = () => { 5 | return ( 6 | 10 | 11 | Show total prices up front 12 | 13 | 14 | 15 | Learn more 16 | 17 | 18 | 19 | ); 20 | }; 21 | export default Banner; 22 | -------------------------------------------------------------------------------- /kitchensink-components/ExplorePage.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Box, HStack } from "../components/ui"; 3 | import Banner from "./Banner"; 4 | import Header from "./Header"; 5 | import WebSidebar from "./WebSidebar"; 6 | import MainContent from "./main-content/MainContent"; 7 | import { ScrollView } from "react-native"; 8 | 9 | const Explorepage = ({ activeTab, setActiveTab }: any) => { 10 | return ( 11 | <> 12 | 13 | {/* top banner */} 14 | 15 | {/* header */} 16 |
17 | 18 | 19 | {/* mobile */} 20 | 23 | 26 | 27 | 28 | 29 | 30 | {/* web */} 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | ); 39 | }; 40 | 41 | export default Explorepage; 42 | -------------------------------------------------------------------------------- /kitchensink-components/Header.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import { 3 | Box, 4 | HStack, 5 | Input, 6 | InputField, 7 | InputIcon, 8 | InputSlot, 9 | SearchIcon, 10 | } from "../components/ui"; 11 | import HeaderTabs from "./header/HeaderTabs"; 12 | import HomestayLogo from "./header/HomestayLogo"; 13 | import ToggleMode from "./header/ToggleMode"; 14 | import UserProfile from "./header/UserProfile"; 15 | import { ThemeContext } from "@/App"; 16 | 17 | const Header = React.memo(() => { 18 | const { colorMode } = useContext(ThemeContext); 19 | return ( 20 | <> 21 | {/* big screen */} 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | {/* small screen */} 33 | 34 | 35 | 36 | 37 | 41 | 42 | 43 | 44 | 45 | ); 46 | }); 47 | export default Header; 48 | -------------------------------------------------------------------------------- /kitchensink-components/HomestayPage.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from "react"; 2 | import { StatusBar, Platform } from "react-native"; 3 | import { Box } from "../components/ui"; 4 | import MobileBottomTabs from "./MobileBottomTabs"; 5 | import MobileModeChangeButton from "./MobileModeChangeButton"; 6 | import { 7 | Plus, 8 | Home, 9 | MessageCircle, 10 | User, 11 | SlidersHorizontal, 12 | } from "lucide-react-native"; 13 | import MobileProfilePage from "./MobileProfilePage"; 14 | import Explorepage from "./ExplorePage"; 15 | 16 | const bottomTabs = [ 17 | { 18 | icon: Home, 19 | label: "Home", 20 | }, 21 | { 22 | icon: SlidersHorizontal, 23 | label: "Filter", 24 | }, 25 | { 26 | icon: Plus, 27 | label: "Listing", 28 | }, 29 | { 30 | icon: MessageCircle, 31 | label: "Inbox", 32 | disabled: true, 33 | }, 34 | { 35 | icon: User, 36 | label: "Profile", 37 | }, 38 | ]; 39 | 40 | const HomestayPage = () => { 41 | useEffect(() => { 42 | if (Platform.OS === "web") { 43 | document.body.style.overflow = "hidden"; 44 | document.body.style.height = "100%"; 45 | } 46 | }, []); 47 | 48 | const [activeTab, setActiveTab] = React.useState("Home"); 49 | 50 | return ( 51 | <> 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | {/* mobile bottom tabs */} 63 | 64 | 69 | 70 | 71 | {/* )} */} 72 | 73 | ); 74 | }; 75 | export default HomestayPage; 76 | -------------------------------------------------------------------------------- /kitchensink-components/LogoutAlertDialog.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { 3 | Text, 4 | Heading, 5 | Icon, 6 | Button, 7 | CloseIcon, 8 | ButtonText, 9 | AlertDialog, 10 | AlertDialogBackdrop, 11 | AlertDialogContent, 12 | AlertDialogHeader, 13 | AlertDialogCloseButton, 14 | AlertDialogBody, 15 | AlertDialogFooter, 16 | } from "../components/ui"; 17 | 18 | const LogoutAlertDialog = ({ 19 | openLogoutAlertDialog, 20 | setOpenLogoutAlertDialog, 21 | }: any) => { 22 | const handleClose = () => { 23 | setOpenLogoutAlertDialog(false); 24 | }; 25 | 26 | return ( 27 | 28 | 29 | 30 | 31 | Logout 32 | 33 | 34 | 35 | 36 | 37 | Are you sure, you want to logout? 38 | 39 | 40 | 43 | 46 | 47 | 48 | 49 | ); 50 | }; 51 | 52 | export default LogoutAlertDialog; 53 | -------------------------------------------------------------------------------- /kitchensink-components/MobileBottomTabs.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import { HStack, Icon, Pressable, Text, VStack } from "../components/ui"; 3 | import ListYourPlaceModal from "./main-content/ListYourPlaceModal"; 4 | import MobileSidebarActionsheet from "./MobileSidebarActionsheet"; 5 | import { ThemeContext } from "@/App"; 6 | 7 | const MobileBottomTabs = ({ bottomTabs, activeTab, setActiveTab }: any) => { 8 | const { colorMode } = useContext(ThemeContext); 9 | const [modalVisible, setModalVisible] = React.useState(false); 10 | const [actionsheetVisible, setActionsheetVisible] = React.useState(false); 11 | 12 | return ( 13 | <> 14 | 15 | {bottomTabs.map((tab: any) => { 16 | return ( 17 | { 20 | if (tab.label !== "Listing" && tab.label !== "Filter") { 21 | setActiveTab(tab.label); 22 | } 23 | if (tab.label === "Listing") { 24 | setModalVisible(true); 25 | } 26 | if (tab.label === "Filter") { 27 | setActionsheetVisible(true); 28 | } 29 | }} 30 | disabled={tab.disabled} 31 | //@ts-ignore 32 | opacity={tab.disabled ? 0.5 : 1} 33 | > 34 | 35 | 44 | 52 | {tab.label} 53 | 54 | 55 | 56 | ); 57 | })} 58 | 59 | 60 | 64 | 65 | 69 | 70 | ); 71 | }; 72 | 73 | export default MobileBottomTabs; 74 | -------------------------------------------------------------------------------- /kitchensink-components/MobileModeChangeButton.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import { Fab, FabIcon } from "../components/ui"; 3 | import { Moon, Sun } from "lucide-react-native"; 4 | import { ThemeContext } from "../App"; 5 | 6 | const MobileModeChangeButton = () => { 7 | const { colorMode, toggleColorMode } = useContext(ThemeContext); 8 | return ( 9 | 10 | 14 | 15 | ); 16 | }; 17 | 18 | export default MobileModeChangeButton; 19 | -------------------------------------------------------------------------------- /kitchensink-components/MobileProfilePage.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { 3 | HStack, 4 | Text, 5 | Heading, 6 | Avatar, 7 | VStack, 8 | Link, 9 | Icon, 10 | Pressable, 11 | Divider, 12 | Button, 13 | ButtonText, 14 | AvatarFallbackText, 15 | AvatarImage, 16 | LinkText, 17 | } from "../components/ui"; 18 | import { 19 | Blinds, 20 | ChevronRight, 21 | Settings, 22 | Tablets, 23 | User, 24 | MessageCircleQuestionIcon, 25 | HeadsetIcon, 26 | } from "lucide-react-native"; 27 | import { ScrollView } from "react-native"; 28 | import LogoutAlertDialog from "./LogoutAlertDialog"; 29 | 30 | const MobileProfilePage = ({ isActive }: any) => { 31 | const [openLogoutAlertDialog, setOpenLogoutAlertDialog] = 32 | React.useState(false); 33 | return ( 34 | 35 | 36 | Profile 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 49 | 50 | 54 | 55 | ); 56 | }; 57 | 58 | const ProfileCard = () => { 59 | return ( 60 | 61 | 62 | 63 | Henry Stan 64 | 69 | 70 | 71 | Henry Stan 72 | 73 | 77 | Show Profile 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | ); 87 | }; 88 | 89 | const PersonalInfoSection = () => { 90 | return ( 91 | 92 | 93 | 94 | 95 | Personal Info 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | Account 105 | 106 | 107 | 108 | 109 | 110 | 111 | ); 112 | }; 113 | 114 | const HostingSection = () => { 115 | return ( 116 | 117 | Hosting 118 | 119 | 120 | 121 | Host a home 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | Host an experience 131 | 132 | 133 | 134 | 135 | 136 | 137 | ); 138 | }; 139 | 140 | const SupportSection = () => { 141 | return ( 142 | 143 | Support 144 | 145 | 146 | 147 | Get Help 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | Contact Support 157 | 158 | 159 | 160 | 161 | 162 | 163 | ); 164 | }; 165 | 166 | const LogoutButton = ({ setOpenLogoutAlertDialog }: any) => { 167 | return ( 168 | 177 | ); 178 | }; 179 | 180 | export default MobileProfilePage; 181 | -------------------------------------------------------------------------------- /kitchensink-components/MobileSidebarActionsheet.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { 3 | Actionsheet, 4 | ActionsheetDragIndicatorWrapper, 5 | ActionsheetDragIndicator, 6 | ActionsheetBackdrop, 7 | ActionsheetContent, 8 | } from "../components/ui"; 9 | import Sidebar from "./Sidebar"; 10 | 11 | const MobileSidebarActionsheet = ({ 12 | actionsheetVisible, 13 | setActionsheetVisible, 14 | }: any) => { 15 | const handleClose = () => { 16 | setActionsheetVisible(false); 17 | }; 18 | return ( 19 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | ); 33 | }; 34 | export default MobileSidebarActionsheet; 35 | -------------------------------------------------------------------------------- /kitchensink-components/Sidebar.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { VStack, ScrollView } from "../components/ui"; 3 | import AmenitiesSection from "./sidebar/AmenitiesSection"; 4 | import BookingOptions from "./sidebar/BookingOptions"; 5 | import CustomerRatingSection from "./sidebar/CustomerRatingSection"; 6 | import FiltersAppliedSection from "./sidebar/FiltersAppliedSection"; 7 | import PlaceTypeSection from "./sidebar/PlaceTypeSection"; 8 | import PriceRangeSection from "./sidebar/PriceRangeSection"; 9 | import SortBySection from "./sidebar/SortBySection"; 10 | 11 | const Sidebar = () => { 12 | const [scrollEnabled, setScrollEnabled] = React.useState(true); 13 | return ( 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | ); 26 | }; 27 | export default Sidebar; 28 | -------------------------------------------------------------------------------- /kitchensink-components/WebSidebar.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Box } from "../components/ui"; 3 | import Sidebar from "./Sidebar"; 4 | 5 | const WebSidebar = () => { 6 | return ( 7 | 8 | {/* common sidebar contents for web and mobile */} 9 | 10 | 11 | ); 12 | }; 13 | export default WebSidebar; 14 | -------------------------------------------------------------------------------- /kitchensink-components/header/HeaderTabs.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { HStack, Icon, Pressable, Text, SearchIcon } from "../../components/ui"; 3 | 4 | const HeaderTabs = () => { 5 | const [selectedTab, setSelectedTab] = React.useState("Anywhere"); 6 | return ( 7 | 8 | 9 | setSelectedTab("Anywhere")} 14 | > 15 | 16 | Anywhere 17 | 18 | 19 | setSelectedTab("Anyweek")} 24 | > 25 | 26 | Anyweek 27 | 28 | 29 | setSelectedTab("Add guests")} 36 | > 37 | 38 | Add guests 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | ); 47 | }; 48 | export default HeaderTabs; 49 | -------------------------------------------------------------------------------- /kitchensink-components/header/HomestayLogo.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import { Image } from "@/components/ui"; 3 | import { ThemeContext } from "@/App"; 4 | 5 | const HomestayLogo = () => { 6 | const { colorMode } = useContext(ThemeContext); 7 | return ( 8 | homestaylogo 17 | ); 18 | }; 19 | 20 | export default HomestayLogo; 21 | -------------------------------------------------------------------------------- /kitchensink-components/header/ToggleMode.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import { Icon, MoonIcon, SunIcon, Pressable } from "../../components/ui"; 3 | import { ThemeContext } from "../../App"; 4 | 5 | const ToggleMode = () => { 6 | const { colorMode, toggleColorMode } = useContext(ThemeContext); 7 | return ( 8 | 9 | 14 | 15 | ); 16 | }; 17 | 18 | export default ToggleMode; 19 | -------------------------------------------------------------------------------- /kitchensink-components/header/UserProfile.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { 3 | Avatar, 4 | AvatarFallbackText, 5 | AvatarImage, 6 | AvatarBadge, 7 | Pressable, 8 | Menu, 9 | MenuItem, 10 | MenuItemLabel, 11 | } from "../../components/ui"; 12 | import LogoutAlertDialog from "../LogoutAlertDialog"; 13 | 14 | const userMenuItems = [ 15 | { 16 | title: "Messages", 17 | }, 18 | { 19 | title: "Notifications", 20 | }, 21 | { 22 | title: "Trips", 23 | }, 24 | { 25 | title: "Wishlists", 26 | }, 27 | { 28 | title: "Post your home", 29 | }, 30 | { 31 | title: "Host an experience", 32 | }, 33 | { 34 | title: "Accounts", 35 | }, 36 | { 37 | title: "Help", 38 | }, 39 | { 40 | title: "Log out", 41 | }, 42 | ]; 43 | const UserProfile = () => { 44 | const [openLogoutAlertDialog, setOpenLogoutAlertDialog] = useState(false); 45 | return ( 46 | <> 47 | { 53 | if (e.currentKey === "Log out") { 54 | setOpenLogoutAlertDialog(true); 55 | } 56 | }} 57 | trigger={({ ...triggerProps }) => { 58 | return ( 59 | 60 | 61 | Henry Stan 62 | 67 | 68 | 69 | 70 | ); 71 | }} 72 | > 73 | {userMenuItems.map((item) => ( 74 | 75 | {item.title} 76 | 77 | ))} 78 | 79 | 83 | 84 | ); 85 | }; 86 | 87 | export default UserProfile; 88 | -------------------------------------------------------------------------------- /kitchensink-components/main-content/MainContent.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Box } from "../../components/ui"; 3 | import HomestayInformationFold from "./HomestayInformationFold"; 4 | import MainContentHeader from "./MainContentHeader"; 5 | import NewThisWeekFold from "./NewThisWeekFold"; 6 | 7 | const MainContent = ({ 8 | modalVisible, 9 | setModalVisible, 10 | setActiveTab, 11 | activeTab, 12 | }: any) => { 13 | return ( 14 | 15 | {/* explore page main content header */} 16 | 22 | {/* explore page new this week fold 1 */} 23 | 24 | {/* explore page homestay info fold 2 */} 25 | 26 | 27 | ); 28 | }; 29 | export default MainContent; 30 | -------------------------------------------------------------------------------- /kitchensink-components/main-content/MainContentHeader.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import { 3 | Box, 4 | Button, 5 | ButtonIcon, 6 | ButtonText, 7 | Heading, 8 | HStack, 9 | } from "../../components/ui"; 10 | import { List } from "lucide-react-native"; 11 | import ListYourPlaceModal from "./ListYourPlaceModal"; 12 | import { ThemeContext } from "../../App"; 13 | 14 | const MainContentHeader = ({ setActiveTab, activeTab }: any) => { 15 | const [modalVisible, setModalVisible] = React.useState(false); 16 | const { colorMode } = useContext(ThemeContext); 17 | 18 | return ( 19 | 20 | 21 | New this week 22 | {/* Hidden for mobile screens */} 23 | 39 | 40 | {modalVisible && ( 41 | // list your place modal 42 | 48 | )} 49 | 50 | ); 51 | }; 52 | 53 | export default MainContentHeader; 54 | -------------------------------------------------------------------------------- /kitchensink-components/main-content/NewThisWeekFold.tsx: -------------------------------------------------------------------------------- 1 | import React, { useRef, useState, useContext } from "react"; 2 | import { 3 | Box, 4 | HStack, 5 | Center, 6 | Image, 7 | Icon, 8 | Pressable, 9 | } from "../../components/ui"; 10 | import { ScrollView } from "react-native"; 11 | import { ChevronLeft, ChevronRight } from "lucide-react-native"; 12 | import { ThemeContext } from "../../App"; 13 | 14 | const data = [ 15 | { 16 | src: require("../../assets/display/image1.png"), 17 | }, 18 | { 19 | src: require("../../assets/display/image2.png"), 20 | }, 21 | 22 | { 23 | src: require("../../assets/display/image4.png"), 24 | }, 25 | // { 26 | // src: require("../../assets/display/image5.png"), 27 | // }, 28 | { 29 | src: require("../../assets/display/image6.png"), 30 | }, 31 | // { 32 | // src: require("../../assets/display/image7.png"), 33 | // }, 34 | { 35 | src: require("../../assets/display/image8.png"), 36 | }, 37 | // { 38 | // src: require("../../assets/display/image9.png"), 39 | // }, 40 | { 41 | src: require("../../assets/display/image10.png"), 42 | }, 43 | { 44 | src: require("../../assets/display/image3.png"), 45 | }, 46 | { 47 | src: require("../../assets/display/image11.png"), 48 | }, 49 | { 50 | src: require("../../assets/display/image12.png"), 51 | }, 52 | { 53 | src: require("../../assets/display/image13.png"), 54 | }, 55 | { 56 | src: require("../../assets/display/image14.png"), 57 | }, 58 | // { 59 | // src: require("../../assets/display/image15.png"), 60 | // }, 61 | ]; 62 | 63 | const NewThisWeekFold = () => { 64 | const scrollViewRef = useRef(null); 65 | const scrollAmount = 400; 66 | const [scrollPosition, setScrollPosition] = useState(0); 67 | const [isContentAtRight, setIsContentAtRight] = useState(true); 68 | 69 | const handleScrollLeft = () => { 70 | const newScrollPosition = scrollPosition - scrollAmount; 71 | if (scrollViewRef.current) { 72 | // @ts-ignore 73 | scrollViewRef?.current?.scrollTo({ 74 | x: newScrollPosition, 75 | animated: true, 76 | }); 77 | setScrollPosition(newScrollPosition); 78 | } 79 | }; 80 | 81 | const handleScrollRight = () => { 82 | const newScrollPosition = scrollPosition + scrollAmount; 83 | if (scrollViewRef.current) 84 | // @ts-ignore 85 | scrollViewRef?.current?.scrollTo({ 86 | x: newScrollPosition, 87 | animated: true, 88 | }); 89 | setScrollPosition(newScrollPosition); 90 | }; 91 | 92 | const checkContentAtLeft = () => { 93 | if (scrollPosition > 0) { 94 | return true; 95 | } 96 | return false; 97 | }; 98 | 99 | const isCloseToRight = (event: any) => { 100 | const { contentOffset, layoutMeasurement, contentSize } = event.nativeEvent; 101 | const isScrollAtEnd = 102 | contentOffset.x + layoutMeasurement.width >= contentSize.width; 103 | if (isScrollAtEnd) { 104 | return true; 105 | } 106 | return false; 107 | }; 108 | 109 | return ( 110 | 111 | { 118 | if (isCloseToRight(event)) { 119 | setIsContentAtRight(false); 120 | } else { 121 | setIsContentAtRight(true); 122 | } 123 | setScrollPosition(event.nativeEvent.contentOffset.x); 124 | }} 125 | > 126 | 127 | {data.map((image, index) => { 128 | return ( 129 | 130 | {"place" 137 | 138 | ); 139 | })} 140 | 141 | 142 | 146 | 150 | 151 | ); 152 | }; 153 | 154 | const ScrollLeft = ({ handleScrollLeft, disabled }: any) => { 155 | const { colorMode } = useContext(ThemeContext); 156 | return ( 157 |
158 | 167 | 172 | 173 |
174 | ); 175 | }; 176 | 177 | const ScrollRight = ({ handleScrollRight, disabled }: any) => { 178 | const { colorMode } = useContext(ThemeContext); 179 | return ( 180 |
181 | 190 | 195 | 196 |
197 | ); 198 | }; 199 | 200 | export default NewThisWeekFold; 201 | -------------------------------------------------------------------------------- /kitchensink-components/main-content/PriceRangeSection.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { 3 | Checkbox, 4 | Slider, 5 | Text, 6 | Tooltip, 7 | VStack, 8 | Heading, 9 | CheckboxGroup, 10 | SliderTrack, 11 | SliderFilledTrack, 12 | CheckboxIndicator, 13 | CheckboxLabel, 14 | CheckboxIcon, 15 | CheckIcon 16 | } from "../../components/ui"; 17 | 18 | const PriceRangeSection = () => { 19 | const [sliderValue, setSliderValue] = React.useState(3500); 20 | const [values, setValues] = React.useState(["entirePlace"]); 21 | const handleChange = (value: any) => { 22 | setSliderValue(value); 23 | }; 24 | 25 | const sidebarFiltersPriceRange = [ 26 | { 27 | label: "below ₹2001", 28 | value: "below ₹2001", 29 | }, 30 | { 31 | label: "₹2001 - ₹3000", 32 | value: "₹2001 - ₹3000", 33 | }, 34 | { 35 | label: "₹3001 - ₹4001", 36 | value: "₹3001 - ₹4001", 37 | }, 38 | { 39 | label: "above ₹3001", 40 | value: "above ₹3001", 41 | }, 42 | ]; 43 | 44 | return ( 45 | 46 | Price Range 47 | { 54 | handleChange(value); 55 | }} 56 | > 57 | 58 | 59 | 60 | { 63 | return ; 64 | }} 65 | > 66 | 67 | ₹{sliderValue} 68 | 69 | 70 | 71 | 77 | {sidebarFiltersPriceRange.map((priceRange: any) => { 78 | return ( 79 | 86 | 87 | 88 | 89 | {priceRange.label} 90 | 91 | ); 92 | })} 93 | 94 | 95 | ); 96 | }; 97 | export default PriceRangeSection; 98 | -------------------------------------------------------------------------------- /kitchensink-components/sidebar/AmenitiesSection.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import { 3 | Checkbox, 4 | CheckboxGroup, 5 | CheckboxIcon, 6 | CheckboxIndicator, 7 | CheckboxLabel, 8 | HStack, 9 | Heading, 10 | Icon, 11 | Pressable, 12 | Text, 13 | VStack, 14 | CheckIcon, 15 | ChevronDownIcon, 16 | ChevronUpIcon, 17 | } from "../../components/ui"; 18 | import { ThemeContext } from "@/App"; 19 | 20 | const AmenitiesSection = () => { 21 | const sidebarFiltersAmmenities = [ 22 | { 23 | label: "Wifi", 24 | value: "wifi", 25 | }, 26 | { 27 | label: "Washing machine", 28 | value: "washing-machine", 29 | }, 30 | { 31 | label: "Air conditioning", 32 | value: "air-conditioning", 33 | }, 34 | { 35 | label: "Kitchen", 36 | value: "kitchen", 37 | }, 38 | { 39 | label: "Dryer", 40 | value: "dryer", 41 | }, 42 | { 43 | label: "Iron", 44 | value: "iron", 45 | }, 46 | { 47 | label: "Hair Dryer", 48 | value: "hair-dryer", 49 | }, 50 | ]; 51 | const { colorMode } = useContext(ThemeContext); 52 | const [values, setValues] = React.useState(["wifi", "air-conditioning"]); 53 | const [viewAllComponents, setViewAllComponents] = React.useState(false); 54 | 55 | return ( 56 | 57 | Ammenities 58 | 63 | {sidebarFiltersAmmenities.map((ammenity: any, index: any) => { 64 | if (index > 4 && !viewAllComponents) return null; 65 | return ( 66 | 73 | 74 | 78 | 79 | {ammenity.label} 80 | 81 | ); 82 | })} 83 | 84 | {viewAllComponents ? ( 85 | { 87 | setViewAllComponents(false); 88 | }} 89 | > 90 | 91 | 92 | Show less 93 | 94 | 95 | 96 | 97 | ) : ( 98 | { 100 | setViewAllComponents(true); 101 | }} 102 | > 103 | 104 | 105 | Show more 106 | 107 | 108 | 109 | 110 | )} 111 | 112 | ); 113 | }; 114 | export default AmenitiesSection; 115 | -------------------------------------------------------------------------------- /kitchensink-components/sidebar/BookingOptions.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { HStack, Heading, Switch, Text, VStack } from "../../components/ui"; 3 | import colors from "tailwindcss/colors"; 4 | 5 | const BookingOptions = () => { 6 | const [selfCheckIn, setSelfCheckIn] = React.useState(false); 7 | const [mealsIncluded, setMealsIncluded] = React.useState(false); 8 | 9 | return ( 10 | 11 | Booking Options 12 | 13 | 14 | 15 | 16 | 17 | Self check-in 18 | 19 | 20 | Access a place without needing the Host 21 | 22 | 23 | setSelfCheckIn(val)} 27 | trackColor={{ false: colors.gray[300], true: colors.gray[500] }} 28 | thumbColor={colors.gray[50]} 29 | activeThumbColor={colors.gray[50]} 30 | ios_backgroundColor={colors.gray[300]} 31 | /> 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | Meals included 40 | 41 | 42 | Have a preferred meal for your comfy stay 43 | 44 | 45 | setMealsIncluded(val)} 49 | trackColor={{ false: colors.gray[300], true: colors.gray[500] }} 50 | thumbColor={colors.gray[50]} 51 | activeThumbColor={colors.gray[50]} 52 | ios_backgroundColor={colors.gray[300]} 53 | /> 54 | 55 | 56 | 57 | ); 58 | }; 59 | export default BookingOptions; 60 | -------------------------------------------------------------------------------- /kitchensink-components/sidebar/CustomerRatingSection.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import { ThemeContext } from "../../App"; 3 | import { 4 | Checkbox, 5 | CheckboxGroup, 6 | CheckboxIcon, 7 | CheckboxIndicator, 8 | CheckboxLabel, 9 | CheckIcon, 10 | Heading, 11 | Icon, 12 | VStack, 13 | StarIcon, 14 | } from "../../components/ui"; 15 | 16 | const CustomerRatingSection = () => { 17 | const sidebarFiltersCustomerRatings = [ 18 | { 19 | label: "5 stars", 20 | value: "5 stars", 21 | }, 22 | { 23 | label: "4+ stars", 24 | value: "4+ stars", 25 | }, 26 | { 27 | label: "3+ stars", 28 | value: "3+ stars", 29 | }, 30 | { 31 | label: "2+ stars", 32 | value: "2+ stars", 33 | }, 34 | ]; 35 | const [values, setValues] = React.useState(["wifi", "air-conditioning"]); 36 | const { colorMode } = useContext(ThemeContext); 37 | 38 | return ( 39 | 40 | Customer Ratings 41 | 46 | {sidebarFiltersCustomerRatings.map((placeType: any, index: any) => { 47 | return ( 48 | 55 | 56 | 60 | 61 | 62 | {" "} 67 | {placeType.label} 68 | 69 | 70 | ); 71 | })} 72 | 73 | 74 | ); 75 | }; 76 | export default CustomerRatingSection; 77 | -------------------------------------------------------------------------------- /kitchensink-components/sidebar/FiltersAppliedSection.tsx: -------------------------------------------------------------------------------- 1 | import React, {useContext} from "react"; 2 | import { 3 | Badge, 4 | BadgeText, 5 | Box, 6 | Button, 7 | HStack, 8 | Icon, 9 | Pressable, 10 | Text, 11 | CloseIcon, 12 | ButtonText 13 | } from "../../components/ui"; 14 | import { ThemeContext } from "../../App"; 15 | 16 | const FiltersAppliedSection = () => { 17 | const {colorMode} = useContext(ThemeContext); 18 | const filters = ["Private room", "Wifi", "Air conditioning"]; 19 | const [appliedFilters, setAppliedFilters]: any = React.useState(filters); 20 | 21 | return ( 22 | 23 | 24 | 25 | Filters applied 26 | 27 | 37 | 38 | 39 | 40 | {appliedFilters?.map((item: any) => ( 41 | 45 | 46 | {item} 47 | 48 | { 51 | const newFilters = appliedFilters.filter((item1: any) => { 52 | return item1 !== item; 53 | }); 54 | setAppliedFilters(newFilters); 55 | }} 56 | > 57 | 62 | 63 | 64 | ))} 65 | 66 | 67 | ); 68 | }; 69 | export default FiltersAppliedSection; 70 | -------------------------------------------------------------------------------- /kitchensink-components/sidebar/PlaceTypeSection.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import { 3 | Checkbox, 4 | CheckboxGroup, 5 | CheckboxIcon, 6 | CheckboxIndicator, 7 | CheckboxLabel, 8 | Heading, 9 | VStack, 10 | CheckIcon, 11 | } from "../../components/ui"; 12 | import { ThemeContext } from "@/App"; 13 | 14 | const PlaceTypeSection = () => { 15 | const sidebarFiltersPlaceType = [ 16 | { 17 | label: "Entire place", 18 | value: "entirePlace", 19 | }, 20 | { 21 | label: "Private room", 22 | value: "privateRoom", 23 | }, 24 | { 25 | label: "Shared room", 26 | value: "sharedRoom", 27 | }, 28 | ]; 29 | const { colorMode } = useContext(ThemeContext); 30 | const [values, setValues] = React.useState(["entirePlace"]); 31 | 32 | return ( 33 | 34 | Type of place 35 | 40 | {sidebarFiltersPlaceType.map((placeType: any) => { 41 | return ( 42 | 49 | 50 | 54 | 55 | {placeType.label} 56 | 57 | ); 58 | })} 59 | 60 | 61 | ); 62 | }; 63 | export default PlaceTypeSection; 64 | -------------------------------------------------------------------------------- /kitchensink-components/sidebar/PriceRangeSection.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import { 3 | Checkbox, 4 | Slider, 5 | VStack, 6 | Heading, 7 | SliderTrack, 8 | SliderFilledTrack, 9 | SliderThumb, 10 | CheckboxIndicator, 11 | CheckboxLabel, 12 | CheckIcon, 13 | CheckboxIcon, 14 | CheckboxGroup, 15 | Tooltip, 16 | TooltipContent, 17 | TooltipText, 18 | } from "../../components/ui"; 19 | import { ThemeContext } from "@/App"; 20 | 21 | const PriceRangeSection = ({ setScrollEnabled }: { setScrollEnabled: any }) => { 22 | const { colorMode } = useContext(ThemeContext); 23 | const [sliderValue, setSliderValue] = React.useState(3500); 24 | const [values, setValues] = React.useState(["entirePlace"]); 25 | const handleChange = (value: any) => { 26 | setSliderValue(value); 27 | }; 28 | 29 | const sidebarFiltersPriceRange = [ 30 | { 31 | label: "below ₹2001", 32 | value: "below ₹2001", 33 | }, 34 | { 35 | label: "₹2001 - ₹3000", 36 | value: "₹2001 - ₹3000", 37 | }, 38 | { 39 | label: "₹3001 - ₹4001", 40 | value: "₹3001 - ₹4001", 41 | }, 42 | { 43 | label: "above ₹3001", 44 | value: "above ₹3001", 45 | }, 46 | ]; 47 | 48 | return ( 49 | 50 | Price Range 51 | { 57 | handleChange(value); 58 | }} 59 | className="w-full" 60 | onTouchStart={() => setScrollEnabled(false)} 61 | onTouchEnd={() => setScrollEnabled(true)} 62 | > 63 | 64 | 65 | 66 | { 70 | return ; 71 | }} 72 | > 73 | 74 | 75 | ₹{sliderValue} 76 | 77 | 78 | 79 | 80 | 86 | {sidebarFiltersPriceRange.map((priceRange: any) => { 87 | return ( 88 | 95 | 96 | 100 | 101 | {priceRange.label} 102 | 103 | ); 104 | })} 105 | 106 | 107 | ); 108 | }; 109 | export default PriceRangeSection; 110 | -------------------------------------------------------------------------------- /kitchensink-components/sidebar/SortBySection.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import { 3 | CircleIcon, 4 | Heading, 5 | Radio, 6 | RadioGroup, 7 | RadioIndicator, 8 | RadioLabel, 9 | VStack, 10 | RadioIcon, 11 | } from "../../components/ui"; 12 | import { ThemeContext } from "@/App"; 13 | 14 | const SortBySection = () => { 15 | const sidebarFiltersCustomerRatings = [ 16 | { 17 | label: "Top ratings", 18 | value: "Top ratings", 19 | }, 20 | { 21 | label: "Best price", 22 | value: "Best price", 23 | }, 24 | { 25 | label: "Discount", 26 | value: "Discount", 27 | }, 28 | { 29 | label: "What’s new", 30 | value: "What’s new", 31 | }, 32 | ]; 33 | const { colorMode } = useContext(ThemeContext); 34 | const [values, setValues] = React.useState("Top ratings"); 35 | 36 | return ( 37 | 38 | Sort by 39 | 44 | {sidebarFiltersCustomerRatings.map((placeType: any) => { 45 | return ( 46 | 52 | 53 | 57 | 58 | {placeType.label} 59 | 60 | ); 61 | })} 62 | 63 | 64 | ); 65 | }; 66 | export default SortBySection; 67 | -------------------------------------------------------------------------------- /metro.config.js: -------------------------------------------------------------------------------- 1 | const { getDefaultConfig } = require("expo/metro-config"); 2 | const { withNativeWind } = require("nativewind/metro"); 3 | 4 | const config = getDefaultConfig(__dirname, { 5 | isCSSEnabled: true, 6 | }); 7 | 8 | module.exports = withNativeWind(config, { 9 | input: "./global.css", 10 | inlineRem: 16, 11 | }); -------------------------------------------------------------------------------- /nativewind-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ui-example-nativewind", 3 | "version": "1.0.0", 4 | "main": "node_modules/expo/AppEntry.js", 5 | "scripts": { 6 | "start": "expo start", 7 | "android": "DARK_MODE=media expo run:android", 8 | "ios": "DARK_MODE=media expo run:ios", 9 | "web": "DARK_MODE=media expo start --web" 10 | }, 11 | "dependencies": { 12 | "@expo-google-fonts/inter": "^0.2.3", 13 | "@expo/config-plugins": "~9.0.0", 14 | "@expo/html-elements": "^0.4.2", 15 | "@expo/metro-runtime": "~4.0.0", 16 | "@gluestack-ui/accordion": "^1.0.8", 17 | "@gluestack-ui/actionsheet": "^0.2.46", 18 | "@gluestack-ui/alert": "^0.1.16", 19 | "@gluestack-ui/alert-dialog": "^0.1.32", 20 | "@gluestack-ui/avatar": "^0.1.18", 21 | "@gluestack-ui/button": "^1.0.8", 22 | "@gluestack-ui/checkbox": "^0.1.33", 23 | "@gluestack-ui/divider": "^0.1.10", 24 | "@gluestack-ui/fab": "^0.1.22", 25 | "@gluestack-ui/form-control": "^0.1.19", 26 | "@gluestack-ui/icon": "^0.1.24-alpha.0", 27 | "@gluestack-ui/image": "^0.1.11", 28 | "@gluestack-ui/input": "^0.1.32", 29 | "@gluestack-ui/link": "^0.1.23", 30 | "@gluestack-ui/menu": "^0.2.37", 31 | "@gluestack-ui/modal": "^0.1.35", 32 | "@gluestack-ui/nativewind-utils": "^1.0.26-alpha.2", 33 | "@gluestack-ui/overlay": "^0.1.16", 34 | "@gluestack-ui/popover": "^0.1.43", 35 | "@gluestack-ui/pressable": "^0.1.17", 36 | "@gluestack-ui/progress": "^0.1.18", 37 | "@gluestack-ui/radio": "^0.1.34", 38 | "@gluestack-ui/select": "^0.1.30", 39 | "@gluestack-ui/slider": "^0.1.26", 40 | "@gluestack-ui/spinner": "^0.1.15", 41 | "@gluestack-ui/switch": "^0.1.23", 42 | "@gluestack-ui/textarea": "^0.1.24", 43 | "@gluestack-ui/toast": "^1.0.8", 44 | "@gluestack-ui/tooltip": "^0.1.36-alpha.0", 45 | "@legendapp/motion": "^2.4.0", 46 | "babel-plugin-module-resolver": "^5.0.2", 47 | "expo": "52.0.11", 48 | "expo-linking": "~7.0.3", 49 | "expo-status-bar": "~2.0.0", 50 | "expo-updates": "~0.26.9", 51 | "lucide-react-native": "^0.445.0", 52 | "nativewind": "^4.1.23", 53 | "react": "18.3.1", 54 | "react-dom": "18.3.1", 55 | "react-native": "0.76.3", 56 | "react-native-reanimated": "~3.16.1", 57 | "react-native-safe-area-context": "^4.14.0", 58 | "react-native-svg": "15.2.0", 59 | "react-native-web": "~0.19.13", 60 | "serve": "^14.2.2", 61 | "tailwindcss": "^3.4.15" 62 | }, 63 | "devDependencies": { 64 | "@babel/core": "^7.20.0", 65 | "@types/react": "~18.3.12", 66 | "jscodeshift": "^0.15.2", 67 | "typescript": "~5.3.3" 68 | }, 69 | "private": true 70 | } 71 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "expo/tsconfig.base", 3 | "compilerOptions": { 4 | "strict": true, 5 | "paths": { 6 | "@/*": [ 7 | "./*" 8 | ], 9 | "tailwind.config": [ 10 | "./tailwind.config.js" 11 | ] 12 | } 13 | }, 14 | "paths": { 15 | "@/*": [ 16 | "./src/*" 17 | ] 18 | } 19 | } -------------------------------------------------------------------------------- /vercle.json: -------------------------------------------------------------------------------- 1 | { 2 | "buildCommand": "echo 'hello world'", 3 | "outputDirectory": "dist", 4 | "devCommand": "expo", 5 | "cleanUrls": true, 6 | "framework": null, 7 | "rewrites": [ 8 | { 9 | "source": "/:path*", 10 | "destination": "/" 11 | } 12 | ] 13 | } 14 | --------------------------------------------------------------------------------