about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--README.md13
-rw-r--r--android/app/src/main/java/com/app/MainActivity.java6
-rw-r--r--ios/Podfile.lock6
-rw-r--r--package.json2
-rw-r--r--public/index.html10
-rw-r--r--src/App.native.tsx59
-rw-r--r--src/App.web.tsx59
-rw-r--r--src/routes/index.tsx72
-rw-r--r--src/routes/types.ts24
-rw-r--r--src/screens/Home.tsx17
-rw-r--r--src/screens/Menu.tsx19
-rw-r--r--src/screens/NotFound.tsx27
-rw-r--r--src/screens/Notifications.tsx21
-rw-r--r--src/screens/Profile.tsx7
-rw-r--r--src/screens/Search.tsx19
-rw-r--r--yarn.lock50
16 files changed, 293 insertions, 118 deletions
diff --git a/README.md b/README.md
index 81f530018..159d374ad 100644
--- a/README.md
+++ b/README.md
@@ -20,4 +20,15 @@ Uses:
 - To run the Web app: `yarn web`
 - Tips
   - `npx react-native info` Checks what has been installed.
-  - Android instructions are a *little* inaccurate but not as much as you might think. I had to manually create a virtual device, then run `yarn android` twice (once to start the emulator and the second time to connect to it).
\ No newline at end of file
+  - Android instructions are a *little* inaccurate but not as much as you might think. I had to manually create a virtual device, then run `yarn android` twice (once to start the emulator and the second time to connect to it).
+
+## TODOs
+
+- Navigation
+  - Auth / Unauthed
+- Web
+  - Desktop vs mobile styling
+- API
+  - Create mock api
+- Tests
+  - Should just try to catch errors on basic load
diff --git a/android/app/src/main/java/com/app/MainActivity.java b/android/app/src/main/java/com/app/MainActivity.java
index 8502b9e3f..ba71d4819 100644
--- a/android/app/src/main/java/com/app/MainActivity.java
+++ b/android/app/src/main/java/com/app/MainActivity.java
@@ -3,6 +3,7 @@ package com.app;
 import com.facebook.react.ReactActivity;
 import com.facebook.react.ReactActivityDelegate;
 import com.facebook.react.ReactRootView;
+import android.os.Bundle;
 
 public class MainActivity extends ReactActivity {
 
@@ -36,5 +37,10 @@ public class MainActivity extends ReactActivity {
       reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED);
       return reactRootView;
     }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+      super.onCreate(null);
+    }
   }
 }
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 4d7b00974..fef825bb5 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -353,6 +353,8 @@ PODS:
     - React-jsi (= 0.68.2)
     - React-logger (= 0.68.2)
     - React-perflogger (= 0.68.2)
+  - RNCAsyncStorage (1.17.6):
+    - React-Core
   - RNScreens (3.13.1):
     - React-Core
     - React-RCTImage
@@ -417,6 +419,7 @@ DEPENDENCIES:
   - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
   - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`)
   - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
+  - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
   - RNScreens (from `../node_modules/react-native-screens`)
   - Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
 
@@ -501,6 +504,8 @@ EXTERNAL SOURCES:
     :path: "../node_modules/react-native/ReactCommon/runtimeexecutor"
   ReactCommon:
     :path: "../node_modules/react-native/ReactCommon"
+  RNCAsyncStorage:
+    :path: "../node_modules/@react-native-async-storage/async-storage"
   RNScreens:
     :path: "../node_modules/react-native-screens"
   Yoga:
@@ -551,6 +556,7 @@ SPEC CHECKSUMS:
   React-RCTVibration: 79040b92bfa9c3c2d2cb4f57e981164ec7ab9374
   React-runtimeexecutor: b960b687d2dfef0d3761fbb187e01812ebab8b23
   ReactCommon: 095366164a276d91ea704ce53cb03825c487a3f2
+  RNCAsyncStorage: 466b9df1a14bccda91da86e0b7d9a345d78e1673
   RNScreens: 40a2cb40a02a609938137a1e0acfbf8fc9eebf19
   SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
   Yoga: 99652481fcd320aefa4a7ef90095b95acd181952
diff --git a/package.json b/package.json
index 346cbcc9c..764c79b44 100644
--- a/package.json
+++ b/package.json
@@ -12,8 +12,10 @@
   },
   "dependencies": {
     "@react-native-async-storage/async-storage": "^1.17.6",
+    "@react-navigation/bottom-tabs": "^6.3.1",
     "@react-navigation/native": "^6.0.10",
     "@react-navigation/native-stack": "^6.6.2",
+    "@react-navigation/stack": "^6.2.1",
     "mobx": "^6.6.0",
     "mobx-state-tree": "^5.1.5",
     "react": "17.0.2",
diff --git a/public/index.html b/public/index.html
index c12fddc36..f6cb612b6 100644
--- a/public/index.html
+++ b/public/index.html
@@ -4,8 +4,16 @@
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width">     
     <title> WEBAPP </title>
+    <style>
+      /* These styles make the body full-height */
+      html, body { height: 100%; }
+      /* These styles disable body scrolling if you are using <ScrollView> */
+      body { overflow: hidden; }
+      /* These styles make the root element full-height */
+      #root { display:flex; height:100%; }
+    </style>
   </head>
   <body>
-      <div id="root"></div>
+    <div id="root"></div>
   </body>
 </html>
\ No newline at end of file
diff --git a/src/App.native.tsx b/src/App.native.tsx
index 40989caf0..2fadf993f 100644
--- a/src/App.native.tsx
+++ b/src/App.native.tsx
@@ -1,52 +1,6 @@
 import React, {useState, useEffect} from 'react'
-import {
-  SafeAreaView,
-  ScrollView,
-  StatusBar,
-  Text,
-  Button,
-  useColorScheme,
-  View,
-} from 'react-native'
-import {NavigationContainer} from '@react-navigation/native'
-import {
-  createNativeStackNavigator,
-  NativeStackScreenProps,
-} from '@react-navigation/native-stack'
 import {RootStore, setupState, RootStoreProvider} from './state'
-
-type RootStackParamList = {
-  Home: undefined
-  Profile: {name: string}
-}
-const Stack = createNativeStackNavigator()
-
-const HomeScreen = ({
-  navigation,
-}: NativeStackScreenProps<RootStackParamList, 'Home'>) => {
-  const isDarkMode = useColorScheme() === 'dark'
-
-  return (
-    <SafeAreaView>
-      <StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
-      <ScrollView contentInsetAdjustmentBehavior="automatic">
-        <View>
-          <Text>Native</Text>
-          <Button
-            title="Go to Jane's profile"
-            onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
-          />
-        </View>
-      </ScrollView>
-    </SafeAreaView>
-  )
-}
-
-const ProfileScreen = ({
-  route,
-}: NativeStackScreenProps<RootStackParamList, 'Profile'>) => {
-  return <Text>This is {route.params.name}'s profile</Text>
-}
+import * as Routes from './routes'
 
 function App() {
   const [rootStore, setRootStore] = useState<RootStore | undefined>(undefined)
@@ -63,16 +17,7 @@ function App() {
 
   return (
     <RootStoreProvider value={rootStore}>
-      <NavigationContainer>
-        <Stack.Navigator>
-          <Stack.Screen
-            name="Home"
-            component={HomeScreen}
-            options={{title: 'Welcome'}}
-          />
-          <Stack.Screen name="Profile" component={ProfileScreen} />
-        </Stack.Navigator>
-      </NavigationContainer>
+      <Routes.Root />
     </RootStoreProvider>
   )
 }
diff --git a/src/App.web.tsx b/src/App.web.tsx
index 18b15821b..2fadf993f 100644
--- a/src/App.web.tsx
+++ b/src/App.web.tsx
@@ -1,52 +1,6 @@
 import React, {useState, useEffect} from 'react'
-import {
-  SafeAreaView,
-  ScrollView,
-  StatusBar,
-  Text,
-  Button,
-  useColorScheme,
-  View,
-} from 'react-native'
-import {NavigationContainer} from '@react-navigation/native'
-import {
-  createNativeStackNavigator,
-  NativeStackScreenProps,
-} from '@react-navigation/native-stack'
 import {RootStore, setupState, RootStoreProvider} from './state'
-
-type RootStackParamList = {
-  Home: undefined
-  Profile: {name: string}
-}
-const Stack = createNativeStackNavigator()
-
-const HomeScreen = ({
-  navigation,
-}: NativeStackScreenProps<RootStackParamList, 'Home'>) => {
-  const isDarkMode = useColorScheme() === 'dark'
-
-  return (
-    <SafeAreaView>
-      <StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
-      <ScrollView contentInsetAdjustmentBehavior="automatic">
-        <View>
-          <Text>Web</Text>
-          <Button
-            title="Go to Jane's profile"
-            onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
-          />
-        </View>
-      </ScrollView>
-    </SafeAreaView>
-  )
-}
-
-const ProfileScreen = ({
-  route,
-}: NativeStackScreenProps<RootStackParamList, 'Profile'>) => {
-  return <Text>This is {route.params.name}'s profile</Text>
-}
+import * as Routes from './routes'
 
 function App() {
   const [rootStore, setRootStore] = useState<RootStore | undefined>(undefined)
@@ -63,16 +17,7 @@ function App() {
 
   return (
     <RootStoreProvider value={rootStore}>
-      <NavigationContainer>
-        <Stack.Navigator>
-          <Stack.Screen
-            name="Home"
-            component={HomeScreen}
-            options={{title: 'Welcome'}}
-          />
-          <Stack.Screen name="Profile" component={ProfileScreen} />
-        </Stack.Navigator>
-      </NavigationContainer>
+      <Routes.Root />
     </RootStoreProvider>
   )
 }
diff --git a/src/routes/index.tsx b/src/routes/index.tsx
new file mode 100644
index 000000000..9ea1766f5
--- /dev/null
+++ b/src/routes/index.tsx
@@ -0,0 +1,72 @@
+import React from 'react'
+import {Text} from 'react-native'
+import {
+  NavigationContainer,
+  LinkingOptions,
+  RouteProp,
+  ParamListBase,
+} from '@react-navigation/native'
+import {createNativeStackNavigator} from '@react-navigation/native-stack'
+import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'
+import type {RootStackParamList} from './types'
+import {Home} from '../screens/Home'
+import {Search} from '../screens/Search'
+import {Notifications} from '../screens/Notifications'
+import {Menu} from '../screens/Menu'
+import {Profile} from '../screens/Profile'
+import {NotFound} from '../screens/NotFound'
+
+const linking: LinkingOptions<RootStackParamList> = {
+  prefixes: [
+    'http://localhost:3000', // local dev
+  ],
+  config: {
+    screens: {
+      Primary: {
+        screens: {
+          Home: '',
+          Search: 'search',
+          Notifications: 'notifications',
+          Menu: 'menu',
+        },
+      },
+      Profile: 'profile/:name',
+      NotFound: '*',
+    },
+  },
+}
+
+export const RootStack = createNativeStackNavigator()
+export const PrimaryTab = createBottomTabNavigator()
+
+const tabBarScreenOptions = ({
+  route,
+}: {
+  route: RouteProp<ParamListBase, string>
+}) => ({
+  tabBarIcon: (_state: {focused: boolean; color: string; size: number}) => {
+    // TODO: icons
+    return <Text>{route.name.at(0)}</Text>
+  },
+})
+
+const Primary = () => (
+  <PrimaryTab.Navigator
+    screenOptions={tabBarScreenOptions}
+    initialRouteName="Home">
+    <PrimaryTab.Screen name="Home" component={Home} />
+    <PrimaryTab.Screen name="Search" component={Search} />
+    <PrimaryTab.Screen name="Notifications" component={Notifications} />
+    <PrimaryTab.Screen name="Menu" component={Menu} />
+  </PrimaryTab.Navigator>
+)
+
+export const Root = () => (
+  <NavigationContainer linking={linking} fallback={<Text>Loading...</Text>}>
+    <RootStack.Navigator initialRouteName="Primary">
+      <RootStack.Screen name="Primary" component={Primary} />
+      <RootStack.Screen name="Profile" component={Profile} />
+      <RootStack.Screen name="NotFound" component={NotFound} />
+    </RootStack.Navigator>
+  </NavigationContainer>
+)
diff --git a/src/routes/types.ts b/src/routes/types.ts
new file mode 100644
index 000000000..668dc2e2f
--- /dev/null
+++ b/src/routes/types.ts
@@ -0,0 +1,24 @@
+import type {NavigatorScreenParams} from '@react-navigation/native'
+import type {CompositeScreenProps} from '@react-navigation/native'
+import type {StackScreenProps} from '@react-navigation/stack'
+import type {BottomTabScreenProps} from '@react-navigation/bottom-tabs'
+
+export type RootStackParamList = {
+  Primary: undefined
+  Profile: {name: string}
+  NotFound: undefined
+}
+export type RootStackScreenProps<T extends keyof RootStackParamList> =
+  StackScreenProps<RootStackParamList, T>
+
+export type PrimaryTabParamList = {
+  Home: NavigatorScreenParams<RootStackParamList>
+  Search: undefined
+  Notifications: undefined
+  Menu: undefined
+}
+export type PrimaryTabScreenProps<T extends keyof PrimaryTabParamList> =
+  CompositeScreenProps<
+    BottomTabScreenProps<PrimaryTabParamList, T>,
+    RootStackScreenProps<keyof RootStackParamList>
+  >
diff --git a/src/screens/Home.tsx b/src/screens/Home.tsx
new file mode 100644
index 000000000..f4b8ffb63
--- /dev/null
+++ b/src/screens/Home.tsx
@@ -0,0 +1,17 @@
+import React from 'react'
+import {Text, Button, View, SafeAreaView} from 'react-native'
+import type {PrimaryTabScreenProps} from '../routes/types'
+
+export const Home = ({navigation}: PrimaryTabScreenProps<'Home'>) => {
+  return (
+    <SafeAreaView style={{flex: 1}}>
+      <View style={{flex: 1}}>
+        <Text>Hello world</Text>
+        <Button
+          title="Go to Jane's profile"
+          onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
+        />
+      </View>
+    </SafeAreaView>
+  )
+}
diff --git a/src/screens/Menu.tsx b/src/screens/Menu.tsx
new file mode 100644
index 000000000..2e0376a49
--- /dev/null
+++ b/src/screens/Menu.tsx
@@ -0,0 +1,19 @@
+import React from 'react'
+import {SafeAreaView, ScrollView, Text, Button, View} from 'react-native'
+import type {PrimaryTabScreenProps} from '../routes/types'
+
+export const Menu = ({navigation}: PrimaryTabScreenProps<'Menu'>) => {
+  return (
+    <SafeAreaView>
+      <ScrollView contentInsetAdjustmentBehavior="automatic">
+        <View>
+          <Text>Hello world</Text>
+          <Button
+            title="Go to Jane's profile"
+            onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
+          />
+        </View>
+      </ScrollView>
+    </SafeAreaView>
+  )
+}
diff --git a/src/screens/NotFound.tsx b/src/screens/NotFound.tsx
new file mode 100644
index 000000000..afb91b402
--- /dev/null
+++ b/src/screens/NotFound.tsx
@@ -0,0 +1,27 @@
+import React from 'react'
+import {
+  SafeAreaView,
+  ScrollView,
+  StatusBar,
+  Text,
+  Button,
+  useColorScheme,
+  View,
+} from 'react-native'
+import type {RootStackScreenProps} from '../routes/types'
+
+export const NotFound = ({navigation}: RootStackScreenProps<'NotFound'>) => {
+  const isDarkMode = useColorScheme() === 'dark'
+
+  return (
+    <SafeAreaView>
+      <StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
+      <ScrollView contentInsetAdjustmentBehavior="automatic">
+        <View>
+          <Text>Page not found</Text>
+          <Button title="Home" onPress={() => navigation.navigate('Primary')} />
+        </View>
+      </ScrollView>
+    </SafeAreaView>
+  )
+}
diff --git a/src/screens/Notifications.tsx b/src/screens/Notifications.tsx
new file mode 100644
index 000000000..8ffb5bb87
--- /dev/null
+++ b/src/screens/Notifications.tsx
@@ -0,0 +1,21 @@
+import React from 'react'
+import {SafeAreaView, ScrollView, Text, Button, View} from 'react-native'
+import type {PrimaryTabScreenProps} from '../routes/types'
+
+export const Notifications = ({
+  navigation,
+}: PrimaryTabScreenProps<'Notifications'>) => {
+  return (
+    <SafeAreaView>
+      <ScrollView contentInsetAdjustmentBehavior="automatic">
+        <View>
+          <Text>Hello world</Text>
+          <Button
+            title="Go to Jane's profile"
+            onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
+          />
+        </View>
+      </ScrollView>
+    </SafeAreaView>
+  )
+}
diff --git a/src/screens/Profile.tsx b/src/screens/Profile.tsx
new file mode 100644
index 000000000..ffd30a499
--- /dev/null
+++ b/src/screens/Profile.tsx
@@ -0,0 +1,7 @@
+import React from 'react'
+import {Text} from 'react-native'
+import type {RootStackScreenProps} from '../routes/types'
+
+export const Profile = ({route}: RootStackScreenProps<'Profile'>) => {
+  return <Text>This is {route.params.name}'s profile</Text>
+}
diff --git a/src/screens/Search.tsx b/src/screens/Search.tsx
new file mode 100644
index 000000000..85943190a
--- /dev/null
+++ b/src/screens/Search.tsx
@@ -0,0 +1,19 @@
+import React from 'react'
+import {SafeAreaView, ScrollView, Text, Button, View} from 'react-native'
+import type {PrimaryTabScreenProps} from '../routes/types'
+
+export const Search = ({navigation}: PrimaryTabScreenProps<'Search'>) => {
+  return (
+    <SafeAreaView>
+      <ScrollView contentInsetAdjustmentBehavior="automatic">
+        <View>
+          <Text>Hello world</Text>
+          <Button
+            title="Go to Jane's profile"
+            onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
+          />
+        </View>
+      </ScrollView>
+    </SafeAreaView>
+  )
+}
diff --git a/yarn.lock b/yarn.lock
index 0001c9378..9202cfe7b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2012,6 +2012,15 @@
   resolved "https://registry.yarnpkg.com/@react-native/polyfills/-/polyfills-2.0.0.tgz#4c40b74655c83982c8cf47530ee7dc13d957b6aa"
   integrity sha512-K0aGNn1TjalKj+65D7ycc1//H9roAQ51GJVk5ZJQFb2teECGmzd86bYDC0aYdbRf7gtovescq4Zt6FR0tgXiHQ==
 
+"@react-navigation/bottom-tabs@^6.3.1":
+  version "6.3.1"
+  resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-6.3.1.tgz#1552ccdb789b6c9fc05af0877f8f3a50ab28870c"
+  integrity sha512-sL9F4WMhhR6I9bE7bpsPVHnK1cN9doaFHAuy5YmD+Sw6OyO0TAmNgQFx4xZWqboA5ZwSkN0tWcRCr6wGXaRRag==
+  dependencies:
+    "@react-navigation/elements" "^1.3.3"
+    color "^3.1.3"
+    warn-once "^0.1.0"
+
 "@react-navigation/core@^6.2.1":
   version "6.2.1"
   resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-6.2.1.tgz#90459f9afd25b71a9471b0706ebea2cdd2534fc4"
@@ -2053,6 +2062,15 @@
   dependencies:
     nanoid "^3.1.23"
 
+"@react-navigation/stack@^6.2.1":
+  version "6.2.1"
+  resolved "https://registry.yarnpkg.com/@react-navigation/stack/-/stack-6.2.1.tgz#2b14473579eced6def5cca06860044d60e59d06e"
+  integrity sha512-JI7boxtPAMCBXi4VJHVEq61jLVHFW5f3npvbndS+XfOsv7Gf0f91HOVJ28DS5c2Fn4+CO4AByjUozzlN296X+A==
+  dependencies:
+    "@react-navigation/elements" "^1.3.3"
+    color "^3.1.3"
+    warn-once "^0.1.0"
+
 "@rollup/plugin-babel@^5.2.0":
   version "5.3.1"
   resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz#04bc0608f4aa4b2e4b1aebf284344d0f68fda283"
@@ -3998,7 +4016,7 @@ collection-visit@^1.0.0:
     map-visit "^1.0.0"
     object-visit "^1.0.0"
 
-color-convert@^1.9.0:
+color-convert@^1.9.0, color-convert@^1.9.3:
   version "1.9.3"
   resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
   integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
@@ -4017,11 +4035,27 @@ color-name@1.1.3:
   resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
   integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
 
-color-name@^1.1.4, color-name@~1.1.4:
+color-name@^1.0.0, color-name@^1.1.4, color-name@~1.1.4:
   version "1.1.4"
   resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
   integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
 
+color-string@^1.6.0:
+  version "1.9.1"
+  resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4"
+  integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==
+  dependencies:
+    color-name "^1.0.0"
+    simple-swizzle "^0.2.2"
+
+color@^3.1.3:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164"
+  integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==
+  dependencies:
+    color-convert "^1.9.3"
+    color-string "^1.6.0"
+
 colord@^2.9.1:
   version "2.9.2"
   resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.2.tgz#25e2bacbbaa65991422c07ea209e2089428effb1"
@@ -6468,6 +6502,11 @@ is-arrayish@^0.2.1:
   resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
   integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
 
+is-arrayish@^0.3.1:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
+  integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
+
 is-bigint@^1.0.1:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3"
@@ -10832,6 +10871,13 @@ simple-plist@^1.1.0:
     bplist-parser "0.3.1"
     plist "^3.0.5"
 
+simple-swizzle@^0.2.2:
+  version "0.2.2"
+  resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
+  integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==
+  dependencies:
+    is-arrayish "^0.3.1"
+
 sisteransi@^1.0.5:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"