This commit is contained in:
louiscklaw
2025-06-06 11:50:25 +08:00
parent d453144500
commit 3217a8d594
22 changed files with 501 additions and 494 deletions

View File

@@ -3,13 +3,5 @@
"semi": true,
"singleQuote": true,
"trailingComma": "es5",
"printWidth": 160,
"overrides": [
{
"files": "src/App.tsx",
"options": {
"printWidth": 240
}
}
]
}
"printWidth": 100
}

View File

@@ -12,6 +12,7 @@ dependencies {
implementation project(':capacitor-barcode-scanner')
implementation project(':capacitor-clipboard')
implementation project(':capacitor-geolocation')
implementation project(':capacitor-google-maps')
implementation project(':capacitor-preferences')
implementation project(':capacitor-share')

View File

@@ -11,6 +11,9 @@ project(':capacitor-clipboard').projectDir = new File('../node_modules/@capacito
include ':capacitor-geolocation'
project(':capacitor-geolocation').projectDir = new File('../node_modules/@capacitor/geolocation/android')
include ':capacitor-google-maps'
project(':capacitor-google-maps').projectDir = new File('../node_modules/@capacitor/google-maps/android')
include ':capacitor-preferences'
project(':capacitor-preferences').projectDir = new File('../node_modules/@capacitor/preferences/android')

View File

@@ -14,6 +14,7 @@ def capacitor_pods
pod 'CapacitorBarcodeScanner', :path => '../../node_modules/@capacitor/barcode-scanner'
pod 'CapacitorClipboard', :path => '../../node_modules/@capacitor/clipboard'
pod 'CapacitorGeolocation', :path => '../../node_modules/@capacitor/geolocation'
pod 'CapacitorGoogleMaps', :path => '../../node_modules/@capacitor/google-maps'
pod 'CapacitorPreferences', :path => '../../node_modules/@capacitor/preferences'
pod 'CapacitorShare', :path => '../../node_modules/@capacitor/share'
end

View File

@@ -11,6 +11,7 @@
"@capacitor/clipboard": "^7.0.1",
"@capacitor/core": "^7.0.0",
"@capacitor/geolocation": "^7.1.2",
"@capacitor/google-maps": "^7.0.2",
"@capacitor/ios": "7.0.1",
"@capacitor/preferences": "^7.0.0",
"@capacitor/share": "^7.0.1",
@@ -49,7 +50,7 @@
},
"scripts": {
"start": "npm run dev",
"dev": "vite --host 0.0.0.0 --cors",
"dev": "vite --force --host 0.0.0.0 --cors",
"ionic:serve": "vite",
"ionic:build": "tsc && vite build",
"build": "tsc && vite build",

View File

@@ -90,7 +90,12 @@ import DemoRestaurantFinder from './pages/DemoRestaurantFinder';
import DemoReactOverlayHooks from './pages/DemoReactOverlayHooks';
import DemoReactSwitchTabs from './pages/DemoReactSwitchTabs';
import DemoReactPollApp from './pages/DemoReactPollApp';
// import DemoReactWhatsAppClone from './pages/DemoReactWhatsAppClone';
import DemoReactWhatsAppClone from './pages/DemoReactWhatsAppClone';
import Demo2FaExample from './pages/Demo2FaExample';
import DemoAccordionTutorial from './pages/DemoAccordionTutorial';
import DemoBankingUi from './pages/DemoBankingUi';
import DemoCapacitorGoogleMapsTutorial from './pages/DemoCapacitorGoogleMapsTutorial';
import DemoColorTutorial from './pages/DemoColorTutorial';
setupIonicReact();
@@ -116,7 +121,14 @@ interface DispatchProps {
interface IonicAppProps extends StateProps, DispatchProps {}
const IonicApp: React.FC<IonicAppProps> = ({ darkMode, schedule, setIsLoggedIn, setUsername, loadConfData, loadUserData }) => {
const IonicApp: React.FC<IonicAppProps> = ({
darkMode,
schedule,
setIsLoggedIn,
setUsername,
loadConfData,
loadUserData,
}) => {
useEffect(() => {
loadUserData();
loadConfData();
@@ -145,8 +157,66 @@ const IonicApp: React.FC<IonicAppProps> = ({ darkMode, schedule, setIsLoggedIn,
{/* */}
{/* */}
{/* */}
{/* */}
{/* */}
{/* */}
{/* */}
{/* */}
{/* TODO: review DemoReactWhatsAppClone */}
<Route path={paths.DEMO_ACCORDION_TUTORIAL} render={() => <DemoAccordionTutorial />} />
{/* */}
{/* */}
{/* */}
{/* */}
{/* */}
{/* */}
<Route path={paths.DEMO_BANKING_UI} render={() => <DemoBankingUi />} />
<Route
path={paths.DEMO_CAPACITOR_GOOGLE_MAPS_TUTORIAL}
render={() => <DemoCapacitorGoogleMapsTutorial />}
/>
<Route path={paths.DEMO_COLOR_TUTORIAL} render={() => <DemoColorTutorial />} />
{/*
<Route path={paths.DEMO_ECOMMERCE_EXAMPLE} render={() => <DemoEcommerceExample />} />
<Route path={paths.DEMO_FACEBOOK_CLONE} render={() => <DemoFacebookClone />} />
<Route path={paths.DEMO_FAST_FOOD_APP} render={() => <DemoFastFoodApp />} />
<Route path={paths.DEMO_FLOATING_TABS} render={() => <DemoFloatingTabs />} />
<Route path={paths.DEMO_INSTAGRAM_CLONE} render={() => <DemoInstagramClone />} />
<Route path={paths.DEMO_KANBAN_BOARD} render={() => <DemoKanbanBoard />} />
<Route path={paths.DEMO_ORDERING_APP} render={() => <DemoOrderingApp />} />
<Route path={paths.DEMO_PROFILE_EXAMPLE} render={() => <DemoProfileExample />} />
<Route path={paths.DEMO_PULLSTATE_TUTORIAL} render={() => <DemoPullstateTutorial />} />
<Route path={paths.DEMO_REACT_ADD_TO_CART} render={() => <DemoReactAddToCart />} />
<Route path={paths.DEMO_REACT_CALCULATOR} render={() => <DemoReactCalculator />} />
<Route path={paths.DEMO_REACT_DRAWING_CANVAS} render={() => <DemoReactDrawingCanvas />} />
<Route path={paths.DEMO_REACT_HOOK_FORM_EXAMPLE} render={() => <DemoReactHookFormExample />} />
<Route path={paths.DEMO_REACT_ITEM_LIST} render={() => <DemoReactItemList />} />
<Route path={paths.DEMO_REACT_LIFECYCLES} render={() => <DemoReactLifecycles />} />
<Route path={paths.DEMO_REACT_LOGIN} render={() => <DemoReactLogin />} />
<Route path={paths.DEMO_REACT_MARVEL_APP} render={() => <DemoReactMarvelApp />} />
<Route path={paths.DEMO_REACT_MOVIE_APP_WITH_ALGOLIA} render(() => <DemoReactMovieAppWithAlgolia />} />
<Route path={paths.DEMO_REACT_NOTES} render={() => <DemoReactNotes />} />
<Route path={paths.DEMO_REACT_ONBOARDING_UI} render={() => <DemoReactOnboardingUI />} />
<Route path={paths.DEMO_REACT_PROFILE_DASHBOARD_UI} render(() => <DemoReactProfileDashboardUI />} />
<Route path={paths.DEMO_REACT_QR_CODE} render={() => <DemoReactQRCode />} />
<Route path={paths.DEMO_REACT_QUOTES} render(() => <DemoReactQuotes />} />
<Route path={paths.DEMO_REACT_SHOP_UI} render(() => <DemoReactShopUI />} />
<Route path={paths.DEMO_REACT_TABS_MENUS_CUSTOM} render(() => <DemoReactTabsMenusCustom />} />
<Route path={paths.DEMO_REACT_THEME_SWITCHER} render(() => <DemoReactThemeSwitcher />} />
<Route path={paths.DEMO_REACT_WHATSAPP_CLONE} render(() => <DemoReactWhatsAppClone />} />
<Route path={paths.DEMO_SKELETON_TEXT} render(() => <DemoSkeletonText />} />
<Route path={paths.DEMO_STICKY_BOTTOM_SHEET_EXAMPLE} render(() => <DemoStickyBottomSheetExample />} />
<Route path={paths.DEMO_STORAGE_EXAMPLE} render(() => <DemoStorageExample />} />
<Route path={paths.DEMO_SWIPERJS_TUTORIAL} render(() => <DemoSwiperjsTutorial />} />
<Route path={paths.DEMO_WEATHER_APP_UI} render(() => <DemoWeatherAppUI />} />
*/}
<Route path={paths.DEMO_2FA_EXAMPLE} render={() => <Demo2FaExample />} />
{/* have problemx` */}
{/* <Route path={paths.DEMO_REACT_WHATSAPP_CLONE} render={() => <DemoReactWhatsAppClone />} /> */}
<Route path={paths.DEMO_REACT_POLL_APP} render={() => <DemoReactPollApp />} />
@@ -154,7 +224,10 @@ const IonicApp: React.FC<IonicAppProps> = ({ darkMode, schedule, setIsLoggedIn,
<Route path={paths.DEMO_BLOG_POST_UI} render={() => <DemoBlogPostUi />} />
<Route path={paths.DEMO_CLUB_HOUSE} render={() => <DemoClubHouse />} />
<Route path={paths.DEMO_DICTIONARY_APP} render={() => <DemoDictionaryApp />} />
<Route path={paths.DEMO_PINTEREST_FLOATING_TAB_BAR} render={() => <DemoPinterestFloatingTabBar />} />
<Route
path={paths.DEMO_PINTEREST_FLOATING_TAB_BAR}
render={() => <DemoPinterestFloatingTabBar />}
/>
<Route path={paths.DEMO_QR_SCANNER} render={() => <DemoQrScanner />} />
<Route path={paths.DEMO_QUIZ_APP} render={() => <DemoQuizApp />} />
<Route path={paths.DEMO_QUOTE_APP} render={() => <DemoQuoteApp />} />

View File

@@ -6,8 +6,8 @@ import { Route, Redirect } from 'react-router';
// import Tab1 from './AppPages/Tab1';
// import Tab2 from './AppPages/Tab2';
import Topic from './pages/Topic.jsx';
import Home from './pages/Home.jsx';
import Topic from './pages/Topic';
import Home from './pages/Home';
import './style.scss';
@@ -15,12 +15,14 @@ function DemoAccordionTutorial() {
return (
<IonTabs className="demo-accordion-tutorial">
<IonRouterOutlet>
{/* <Route exact path="/demo-accordion-tutorial/tab1">
{/*
<Route exact path="/demo-accordion-tutorial/tab1">
<Tab1 />
</Route>
<Route exact path="/demo-accordion-tutorial/tab2">
<Tab2 />
</Route> */}
</Route>
*/}
<Route exact path="/demo-accordion-tutorial/home">
<Home />
@@ -30,7 +32,9 @@ function DemoAccordionTutorial() {
<Topic />
</Route>
<Redirect exact path="/demo-accordion-tutorial" to="/demo-accordion-tutorial/tab1" />
<Redirect exact path="/demo-accordion-tutorial" to="/demo-accordion-tutorial/home" />
{/* <Redirect exact path="/demo-accordion-tutorial" to="/demo-accordion-tutorial/tab1" /> */}
</IonRouterOutlet>
{/*

View File

@@ -51,11 +51,13 @@ import {
book,
car,
cart,
cashOutline,
chatbubbleEllipses,
chatbubbleOutline,
chevronBackOutline,
chevronForward,
chevronForwardOutline,
colorPaletteOutline,
createOutline,
document,
documentTextOutline,
@@ -63,9 +65,12 @@ import {
giftOutline,
globeSharp,
heart,
keyOutline,
languageOutline,
layers,
list,
listCircle,
mapOutline,
menuOutline,
people,
person,
@@ -202,6 +207,313 @@ const SettingsPage: React.FC<SettingsProps> = ({ speakers, speakerSessions, logo
{/* */}
{/* */}
{/* */}
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_ACCORDION_TUTORIAL, 'forward')}>
<IonIcon slot="start" icon={list} size="large"></IonIcon>
<IonLabel>Demo Accordion Tutorial</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_BANKING_UI, 'forward')}>
<IonIcon slot="start" icon={cashOutline} size="large"></IonIcon>
<IonLabel>
Demo Banking UI <span style={{ fontWeight: 'bold' }}>(in the middle, style outstanding)</span>
</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_CAPACITOR_GOOGLE_MAPS_TUTORIAL, 'forward')}>
<IonIcon slot="start" icon={mapOutline} size="large"></IonIcon>
<IonLabel>
Demo Capacitor Google Maps Tutorial <span style={{ fontWeight: 'bold' }}>need a google map api key</span>
</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_COLOR_TUTORIAL, 'forward')}>
<IonIcon slot="start" icon={colorPaletteOutline} size="large"></IonIcon>
<IonLabel>Demo Color Tutorial</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
{/*
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_ECOMMERCE_EXAMPLE, 'forward')}>
<IonIcon slot="start" icon={cartOutline} size="large"></IonIcon>
<IonLabel>Demo Ecommerce Example</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_FACEBOOK_CLONE, 'forward')}>
<IonIcon slot="start" icon={logoFacebook} size="large"></IonIcon>
<IonLabel>Demo Facebook Clone</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_FAST_FOOD_APP, 'forward')}>
<IonIcon slot="start" icon={restaurantOutline} size="large"></IonIcon>
<IonLabel>Demo Fast Food App</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_FLOATING_TABS, 'forward')}>
<IonIcon slot="start" icon={layersOutline} size="large"></IonIcon>
<IonLabel>Demo Floating Tabs</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_INSTAGRAM_CLONE, 'forward')}>
<IonIcon slot="start" icon={imageOutline} size="large"></IonIcon>
<IonLabel>Demo Instagram Clone</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_KANBAN_BOARD, 'forward')}>
<IonIcon slot="start" icon={gridOutline} size="large"></IonIcon>
<IonLabel>Demo Kanban Board</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_ORDERING_APP, 'forward')}>
<IonIcon slot="start" icon={pizzaOutline} size="large"></IonIcon>
<IonLabel>Demo Ordering App</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_PROFILE_EXAMPLE, 'forward')}>
<IonIcon slot="start" icon={personOutline} size="large"></IonIcon>
<IonLabel>Demo Profile Example</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_PULLSTATE_TUTORIAL, 'forward')}>
<IonIcon slot="start" icon={codeWorkingOutline} size="large"></IonIcon>
<IonLabel>Demo Pullstate Tutorial</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_REACT_ADD_TO_CART, 'forward')}>
<IonIcon slot="start" icon={cartOutline} size="large"></IonIcon>
<IonLabel>Demo React Add to Cart</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_REACT_CALCULATOR, 'forward')}>
<IonIcon slot="start" icon={calculatorOutline} size="large"></IonIcon>
<IonLabel>Demo React Calculator</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_REACT_DRAWING_CANVAS, 'forward')}>
<IonIcon slot="start" icon={brushOutline} size="large"></IonIcon>
<IonLabel>Demo React Drawing Canvas</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_REACT_HOOK_FORM_EXAMPLE, 'forward')}>
<IonIcon slot="start" icon={codeSlashOutline} size="large"></IonIcon>
<IonLabel>Demo React Hook Form Example</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_REACT_ITEM_LIST, 'forward')}>
<IonIcon slot="start" icon={listOutline} size="large"></IonIcon>
<IonLabel>Demo React Item List</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_REACT_LIFECYCLES, 'forward')}>
<IonIcon slot="start" icon={refreshOutline} size="large"></IonIcon>
<IonLabel>Demo React Lifecycles</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_REACT_LOGIN, 'forward')}>
<IonIcon slot="start" icon={logInOutline} size="large"></IonIcon>
<IonLabel>Demo React Login</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_REACT_MARVEL_APP, 'forward')}>
<IonIcon slot="start" icon={flashOutline} size="large"></IonIcon>
<IonLabel>Demo React Marvel App</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_REACT_MOVIE_APP_WITH_ALGOLIA, 'forward')}>
<IonIcon slot="start" icon={filmOutline} size="large"></IonIcon>
<IonLabel>Demo React Movie App with Algolia</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_REACT_NOTES, 'forward')}>
<IonIcon slot="start" icon={documentTextOutline} size="large"></IonIcon>
<IonLabel>Demo React Notes</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_REACT_ONBOARDING_UI, 'forward')}>
<IonIcon slot="start" icon={walkOutline} size="large"></IonIcon>
<IonLabel>Demo React Onboarding UI</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick(() => router.push(paths.DEMO_REACT_PROFILE_DASHBOARD_UI, 'forward')):
<IonIcon slot="start" icon={personCircleOutline} size="large"></IonIcon>
<IonLabel>Demo React Profile Dashboard UI</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_REACT_QR_CODE, 'forward')}>
<IonIcon slot="start" icon={qrCodeOutline} size="large"></IonIcon>
<IonLabel>Demo React QR Code</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick(() => router.push(paths.DEMO_REACT_QUOTES, 'forward')):
<IonIcon slot="start" icon={bookOutline} size="large"></IonIcon>
<IonLabel>Demo React Quotes</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick(() => router.push(paths.DEMO_REACT_SHOP_UI, 'forward')):
<IonIcon slot="start" icon={cartOutline} size="large"></IonIcon>
<IonLabel>Demo React Shop UI</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick(() => router.push(paths.DEMO_REACT_TABS_MENUS_CUSTOM, 'forward')):
<IonIcon slot="start" icon={layersOutline} size="large"></IonIcon>
<IonLabel>Demo React Tabs Menus Custom</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick(() => router.push(paths.DEMO_REACT_THEME_SWITCHER, 'forward')):
<IonIcon slot="start" icon={colorPaletteOutline} size="large"></IonIcon>
<IonLabel>Demo React Theme Switcher</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick(() => router.push(paths.DEMO_REACT_WHATSAPP_CLONE, 'forward')):
<IonIcon slot="start" icon={chatbubbleEllipsesOutline} size="large"></IonIcon>
<IonLabel>Demo React WhatsApp Clone</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick(() => router.push(paths.DEMO_SKELETON_TEXT, 'forward')):
<IonIcon slot="start" icon={codeWorkingOutline} size="large"></IonIcon>
<IonLabel>Demo Skeleton Text</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick(() => router.push(paths.DEMO_STICKY_BOTTOM_SHEET_EXAMPLE, 'forward')):
<IonIcon slot="start" icon={paperPlaneOutline} size="large"></IonIcon>
<IonLabel>Demo Sticky Bottom Sheet Example</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick(() => router.push(paths.DEMO_STORAGE_EXAMPLE, 'forward')):
<IonIcon slot="start" icon={cloudOutline} size="large"></IonIcon>
<IonLabel>Demo Storage Example</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick(() => router.push(paths.DEMO_SWIPERJS_TUTORIAL, 'forward')):
<IonIcon slot="start" icon={imagesOutline} size="large"></IonIcon>
<IonLabel>Demo SwiperJS Tutorial</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
<IonList inset={false}>
<IonItem button={true} onClick(() => router.push(paths.DEMO_WEATHER_APP_UI, 'forward')):
<IonIcon slot="start" icon={sunnyOutline} size="large"></IonIcon>
<IonLabel>Demo Weather App UI</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
*/}
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_2FA_EXAMPLE, 'forward')}>
<IonIcon slot="start" icon={keyOutline} size="large"></IonIcon>
<IonLabel>Demo 2FA Example</IonLabel>
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
{/*
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_REACT_WHATSAPP_CLONE, 'forward')}>
<IonIcon slot="start" icon={chatbubbleEllipses} size="large"></IonIcon>
@@ -211,6 +523,7 @@ const SettingsPage: React.FC<SettingsProps> = ({ speakers, speakerSessions, logo
<IonIcon icon={chevronForwardOutline}></IonIcon>
</IonItem>
</IonList>
*/}
<IonList inset={false}>
<IonItem button={true} onClick={() => router.push(paths.DEMO_REACT_POLL_APP, 'forward')}>

View File

@@ -16,7 +16,7 @@ import {
import { heartOutline } from 'ionicons/icons';
import { useStoreState } from 'pullstate';
import { useState } from 'react';
import { ProductModal } from '../components/ProductModal';
import { ProductModal } from '../TestComponents/ProductModal';
import { FavouritesStore } from '../store';
import { getFavourites } from '../store/Selectors';

View File

@@ -23,8 +23,8 @@ import { chevronBack, filter } from 'ionicons/icons';
import { useRef } from 'react';
import { useEffect, useState } from 'react';
import { useParams } from 'react-router';
import { FilterModal } from '../components/FilterModal';
import { ProductModal } from '../components/ProductModal';
import { FilterModal } from '../TestComponents/FilterModal';
import { ProductModal } from '../TestComponents/ProductModal';
import { capitalize, productInfo } from '../utils';
const ProductType = () => {

View File

@@ -13,8 +13,8 @@ import Place from '../pages/Place';
// If using ionicons, import here and pass as ref to tabRoutes
// Import custom tab menu
import Tabs from '../components/Tabs';
import SubPages from '../components/SubPages';
import Tabs from '../TestComponents/Tabs';
import SubPages from '../TestComponents/SubPages';
// Array of objects representing tab pages
// These will be the main tabs across the app

View File

@@ -1,16 +1,4 @@
import {
IonButton,
IonButtons,
IonCol,
IonContent,
IonHeader,
IonIcon,
IonPage,
IonRow,
IonTitle,
IonToolbar,
useIonRouter,
} from '@ionic/react';
import { IonButton, IonButtons, IonCol, IonContent, IonHeader, IonIcon, IonPage, IonRow, IonTitle, IonToolbar, useIonRouter } from '@ionic/react';
import { Geolocation } from '@capacitor/geolocation';
import { useEffect, useState } from 'react';
@@ -35,9 +23,7 @@ function Tab1() {
const getAddress = async (coords) => {
const query = `${coords.latitude},${coords.longitude}`;
const response = await fetch(
`https://api.weatherapi.com/v1/current.json?key=f93eb660b2424258bf5155016210712&q=${query}`
);
const response = await fetch(`https://api.weatherapi.com/v1/current.json?key=f93eb660b2424258bf5155016210712&q=${query}`);
const data = await response.json();
console.log(data);
@@ -81,13 +67,7 @@ function Tab1() {
</IonCol>
</IonRow>
<div style={{ marginTop: '-1.5rem' }}>
{currentWeather ? (
<CurrentWeather currentWeather={currentWeather} />
) : (
<SkeletonDashboard />
)}
</div>
<div style={{ marginTop: '-1.5rem' }}>{currentWeather ? <CurrentWeather currentWeather={currentWeather} /> : <SkeletonDashboard />}</div>
</IonContent>
</IonPage>
);

View File

@@ -1,58 +0,0 @@
import { CreateAnimation, IonButton, IonIcon } from "@ionic/react";
import { cartOutline } from "ionicons/icons";
import { useRef, useState } from "react";
import { addToCart } from "../store/CartStore";
export const AddToCartButton = ({product}) => {
const animationRef = useRef();
const [hidden, setHidden] = useState(true);
const floatStyle = {
display: hidden ? "none" : "",
position: "absolute"
};
const floatGrowAnimation = {
property: "transform",
fromValue: "translateY(0) scale(1)",
toValue: "translateY(-55px) scale(1.5)"
};
const colorAnimation = {
property: "color",
fromValue: "green",
toValue: "green"
};
const mainAnimation = {
duration: 1500,
iterations: "1",
fromTo: [ floatGrowAnimation, colorAnimation ],
easing: "cubic-bezier(0.25, 0.7, 0.25, 0.7)"
};
const handleAddToCart = async product => {
setHidden(false);
await animationRef.current.animation.play();
setHidden(true);
addToCart(product);
}
return (
<IonButton color="dark" expand="full" onClick={() => handleAddToCart(product)}>
<IonIcon icon={cartOutline} />&nbsp;
Add to Cart
<CreateAnimation ref={animationRef} {...mainAnimation}>
<IonIcon icon={cartOutline} size="large" style={floatStyle} />
</CreateAnimation>
</IonButton>
);
}

View File

@@ -1,23 +0,0 @@
import { IonBreadcrumb, IonBreadcrumbs, IonIcon } from "@ionic/react";
import { fastFoodOutline } from "ionicons/icons";
import { useState } from "react";
export const Breadcrumbs = () => {
const [maxItems, setMaxItems] = useState(2);
const handleClick = () => {
setMaxItems(undefined);
}
return (
<IonBreadcrumbs maxItems={maxItems} onIonCollapsedClick={handleClick}>
<IonBreadcrumb color="medium">Page 1</IonBreadcrumb>
<IonBreadcrumb color="medium">Page 2</IonBreadcrumb>
<IonBreadcrumb color="medium">Page 3</IonBreadcrumb>
<IonBreadcrumb>Page 4</IonBreadcrumb>
</IonBreadcrumbs>
);
}

View File

@@ -1,82 +0,0 @@
import { useStoreState } from "pullstate";
import { useEffect, useState } from "react";
import { CartStore } from "../store";
import { addToCart } from "../store/CartStore";
import { getCart } from "../store/Selectors";
const { IonPage, IonHeader, IonToolbar, IonTitle, IonButtons, IonIcon, IonContent, IonGrid, IonRow, IonItem, IonLabel, IonText, IonThumbnail, IonFooter, IonCol, IonButton, IonItemSliding, IonItemOptions, IonItemOption } = require("@ionic/react");
const { close } = require("ionicons/icons");
export const CartModal = props => {
const cart = useStoreState(CartStore, getCart);
const [totalPrice, setTotalPrice] = useState(0);
useEffect(() => {
let total = 0;
cart.forEach(item => total += parseInt(item.price.replace("£", "")));
setTotalPrice(total);
}, [cart]);
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>Cart</IonTitle>
<IonButtons slot="end" onClick={props.close}>
<IonIcon icon={close} size="large" />
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent>
<IonGrid>
<IonRow style={{borderBottom: "1px solid black"}} className="ion-margin-bottom">
<IonItem lines="none">
<IonLabel>
<h1>{cart.length} products in your cart</h1>
<IonText color="medium">
<h2>Review products and checkout</h2>
</IonText>
</IonLabel>
</IonItem>
</IonRow>
</IonGrid>
{cart.map((item, index) => (
<IonItemSliding>
<IonItem key={index} lines="none" className="ion-padding-end" style={{paddingTop: "0.75rem", paddingBottom: "0.75rem"}}>
<IonThumbnail>
<img src={item.image} alt="item" />
</IonThumbnail>
<IonLabel className="ion-padding-start ion-text-wrap">
<h2>{item.title}</h2>
<p>{item.price}</p>
</IonLabel>
</IonItem>
<IonItemOptions side="end">
<IonItemOption color="danger" onClick={() => addToCart(item)}>
Remove
</IonItemOption>
</IonItemOptions>
</IonItemSliding>
))}
</IonContent>
<IonFooter className="ion-padding-bottom ion-padding-start ion-padding-end" style={{paddingBottom: "3rem"}}>
<IonRow className="ion-justify-content-between">
<IonCol size="8">
<h1>Total</h1>
</IonCol>
<IonCol size="4">
<h1>£{totalPrice.toFixed(2)}</h1>
</IonCol>
</IonRow>
<IonButton expand="block" color="dark">Checkout &rarr;</IonButton>
</IonFooter>
</IonPage>
);
}

View File

@@ -1,36 +0,0 @@
import { IonButton, IonCol, IonContent, IonGrid, IonHeader, IonRow, IonTitle, IonToolbar } from "@ionic/react";
export const FilterModal = ({productsRef, filterCriteria, setFilterCriteria, dismiss, filters}) => {
const filterProducts = async filter => {
await productsRef.current.classList.add("animate__fadeOutLeft");
setTimeout(() => {
productsRef.current.classList.remove("animate__fadeOutLeft");
productsRef.current.classList.add("animate__fadeInRight");
setFilterCriteria(filter);
}, 500);
dismiss();
}
return (
<IonContent>
<IonHeader>
<IonToolbar color="none" style={{"--border-style": "none"}}>
<IonTitle className="ion-margin-top">Filter</IonTitle>
</IonToolbar>
</IonHeader>
<IonGrid>
<IonRow>
{filters.map(f => (
<IonCol key={f} size="3">
<IonButton expand="full" color={filterCriteria === f ? "dark" : "light"} onClick={() => filterProducts(f)}>{f}</IonButton>
</IonCol>
))}
</IonRow>
</IonGrid>
</IonContent>
);
}

View File

@@ -1,88 +0,0 @@
ion-card {
margin: 0;
/* margin-top: var(--ion-safe-area-top); */
z-index: -1;
border-radius: 0px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
box-shadow: none;
aspect-ratio: 1 / 1;
}
@supports not (aspect-ratio: 1 / 1) {
ion-card::before {
float: left;
padding-top: 100%;
content: '';
}
ion-card::after {
display: block;
content: '';
clear: both;
}
}
ion-card-header {
position: absolute;
bottom: 0;
width: 100%;
/* background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.7) 100%); */
background: rgba(0, 0, 0, 0.5)
}
ion-card-title,
ion-card-subtitle {
color: white;
}
ion-card-header ion-card-title {
margin: 0 0 6px 0;
font-size: 22px;
}
ion-card-header ion-card-subtitle {
text-transform: none;
font-weight: 500;
font-size: 16px;
}
ion-card-content {
height: calc(60px + var(--ion-safe-area-top));
background: linear-gradient(0deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.5) 100%);
}
#close-button {
position: fixed;
top: max(var(--ion-safe-area-top), 16px);
right: 8px;
}
#fave-button {
position: fixed;
top: max(var(--ion-safe-area-top), 16px);
left: 8px;
}
#product-view-buttons {
z-index: 10;
background: linear-gradient(360deg, rgba(0, 0, 0, 0) 0%, rgba(82, 82, 82, 0.9) 100%) !important;
position: absolute;
width: 100%;
height: 4rem;
}
.sticky-bottom {
position: fixed;
bottom: 0;
}

View File

@@ -1,76 +0,0 @@
import { IonButton, IonButtons, IonCard, IonCardHeader, IonCardSubtitle, IonCardTitle, IonCol, IonContent, IonFooter, IonIcon, IonLabel, IonNote, IonRow, IonText, IonToolbar } from "@ionic/react";
import { closeCircle, heart, heartOutline } from "ionicons/icons";
import { useStoreState } from "pullstate";
import { useRef } from "react";
import { checkFavourites } from "../store/Selectors";
import { addToFavourites } from "../store/FavouritesStore";
import { FavouritesStore } from "../store";
import "./ProductModal.css";
import { ProductReviews } from "./ProductReviews";
import { ProductSpecificationsAccordion } from "./ProductSpecificationsAccordion";
import { AddToCartButton } from "./AddToCartButton";
export const ProductModal = props => {
const { dismiss, category = false, product } = props;
const isFavourite = useStoreState(FavouritesStore, checkFavourites(product));
const contentRef = useRef(null);
return (
<>
<IonContent ref={contentRef}>
<IonButtons id="product-view-buttons">
<IonButton color="light" onClick={dismiss} id="close-button">
<IonIcon icon={closeCircle} size="large" />
</IonButton>
<IonButton color="danger" onClick={() => addToFavourites(product, category)} id="fave-button">
<IonIcon icon={isFavourite ? heart : heartOutline} size="large" />
</IonButton>
</IonButtons>
<IonCard style={{backgroundImage: `url('${product.image}')`}}>
<IonCardHeader>
<IonCardTitle>{product.title}</IonCardTitle>
<IonCardSubtitle>{product.price}</IonCardSubtitle>
</IonCardHeader>
</IonCard>
<div className="ion-padding">
<IonRow className="ion-align-items-center">
<IonCol>
<IonText size="large" className="page-title">
<IonNote>shop</IonNote>
<IonLabel>{category ? category : "Favourite"}</IonLabel>
</IonText>
</IonCol>
<ProductReviews reviews={product.reviews} />
</IonRow>
<h2>Product Description</h2>
<IonText>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam elit felis, molestie id venenatis at, commodo ac tortor. Pellentesque tempus aliquet purus, sed vulputate elit tempus ut.</IonText>
<h2>Product Specifications</h2>
<ProductSpecificationsAccordion contentRef={contentRef} type={category} />
</div>
</IonContent>
<IonFooter collapse="fade">
<IonToolbar>
<IonRow className="ion-justify-content-between ion-align-items-center">
<IonCol size="3">
<IonButton expand="full" color="light">{product.price}</IonButton>
</IonCol>
<IonCol size="8" className="ion-text-right">
<AddToCartButton product={product} />
</IonCol>
</IonRow>
</IonToolbar>
</IonFooter>
</>
);
}

View File

@@ -1,23 +0,0 @@
import { IonCol, IonIcon, IonNote } from "@ionic/react";
import { star } from "ionicons/icons";
import { useEffect, useState } from "react";
import { randomCount } from "../utils";
export const ProductReviews = () => {
// This count could come from the product (if real data was fed)
const [reviewCount, setReviewCount] = useState(0);
useEffect(() => {
setReviewCount(randomCount());
}, []);
return (
<IonCol className="ion-text-right">
<IonIcon color="warning" icon={star} />
&nbsp;&nbsp;
<IonNote>{reviewCount} review{reviewCount > 1 && "s"}</IonNote>
</IonCol>
);
}

View File

@@ -1,58 +0,0 @@
import { IonAccordion, IonAccordionGroup, IonItem, IonLabel, IonList, IonNote } from "@ionic/react";
import { useRef } from "react";
import { productSpecs } from "../utils";
export const ProductSpecificationsAccordion = ({type, contentRef}) => {
const accordionGroupRef = useRef(null);
const log = () => {
const selectedAccordion = accordionGroupRef.current.value;
if (selectedAccordion) {
setTimeout(() => contentRef.current.scrollToBottom(400), 200);
}
}
return (
<IonAccordionGroup ref={accordionGroupRef} onIonChange={log}>
{Object.keys(productSpecs).map((spec, index) => {
const {header, options, wrapText = false, noteColor = false} = productSpecs[spec];
return (
<IonAccordion key={`accordion_${header}_${index}`}>
<IonItem slot="header" className="ion-no-padding">
<IonLabel>{header}</IonLabel>
</IonItem>
<IonList slot="content" className="ion-no-padding">
{options.map((option, index2) => {
const {label, value} = option;
return (
<IonItem key={`accordion_${header}_${option}_${index2}`} className="ion-no-padding">
<IonLabel>
<h3>{label}</h3>
</IonLabel>
<IonLabel className={wrapText && "ion-text-wrap"}>
<IonNote color={noteColor ? (value ? "success" : "danger") : "medium"}>
{noteColor ? (value ? "In stock" : "Out of stock") : value}
</IonNote>
</IonLabel>
</IonItem>
);
})}
</IonList>
</IonAccordion>
);
})}
</IonAccordionGroup>
);
}

View File

@@ -29,9 +29,53 @@ const paths = {
//
//
//
DEMO_REACT_WHATSAPP_CLONE: '/demo-react-whatsapp-clone',
//
//
//
//
//
//
//
//
//
DEMO_ACCORDION_TUTORIAL: '/demo-accordion-tutorial',
DEMO_BANKING_UI: '/demo-banking-ui',
DEMO_CAPACITOR_GOOGLE_MAPS_TUTORIAL: '/demo-capacitor-google-maps-tutorial',
DEMO_COLOR_TUTORIAL: '/demo-color-tutorial',
// DEMO_ECOMMERCE_EXAMPLE: '/demo-ecommerce-example',
// DEMO_FACEBOOK_CLONE: '/demo-facebook-clone',
// DEMO_FAST_FOOD_APP: '/demo-fast-food-app',
// DEMO_FLOATING_TABS: '/demo-floating-tabs',
// DEMO_INSTAGRAM_CLONE: '/demo-instagram-clone',
// DEMO_KANBAN_BOARD: '/demo-kanban-board',
// DEMO_ORDERING_APP: '/demo-ordering-app',
// DEMO_PROFILE_EXAMPLE: '/demo-profile-example',
// DEMO_PULLSTATE_TUTORIAL: '/demo-pullstate-tutorial',
// DEMO_REACT_ADD_TO_CART: '/demo-react-add-to-cart',
// DEMO_REACT_CALCULATOR: '/demo-react-calculator',
// DEMO_REACT_DRAWING_CANVAS: '/demo-react-drawing-canvas',
// DEMO_REACT_HOOK_FORM_EXAMPLE: '/demo-react-hook-form-example',
// DEMO_REACT_ITEM_LIST: '/demo-react-item-list',
// DEMO_REACT_LIFECYCLES: '/demo-react-lifecycles',
// DEMO_REACT_LOGIN: '/demo-react-login',
// DEMO_REACT_MARVEL_APP: '/demo-react-marvel-app',
// DEMO_REACT_MOVIE_APP_WITH_ALGOLIA: '/demo-react-movie-app-with-algolia',
// DEMO_REACT_NOTES: '/demo-react-notes',
// DEMO_REACT_ONBOARDING_UI: '/demo-react-onboarding-ui',
// DEMO_REACT_PROFILE_DASHBOARD_UI: '/demo-react-profile-dashboard-ui',
// DEMO_REACT_QR_CODE: '/demo-react-qr-code',
// DEMO_REACT_QUOTES: '/demo-react-quotes',
// DEMO_REACT_SHOP_UI: '/demo-react-shop-ui',
// DEMO_REACT_TABS_MENUS_CUSTOM: '/demo-react-tabs-menus-custom',
// DEMO_REACT_THEME_SWITCHER: '/demo-react-theme-switcher',
// DEMO_SKELETON_TEXT: '/demo-skeleton-text',
// DEMO_STICKY_BOTTOM_SHEET_EXAMPLE: '/demo-sticky-bottom-sheet-example',
// DEMO_STORAGE_EXAMPLE: '/demo-storage-example',
// DEMO_SWIPERJS_TUTORIAL: '/demo-swiperjs-tutorial',
// DEMO_WEATHER_APP_UI: '/demo-weather-app-ui',
DEMO_REACT_POLL_APP: '/demo-react-poll-app',
DEMO_2FA_EXAMPLE: '/demo-2fa-example',
DEMO_REACT_WHATSAPP_CLONE: '/demo-react-whatsapp-clone',
DEMO_BLOG_POST_UI: '/demo-blog-post-ui',
DEMO_CLUB_HOUSE: '/demo-club-house',

View File

@@ -229,6 +229,15 @@
dependencies:
"@capacitor/synapse" "^1.0.1"
"@capacitor/google-maps@^7.0.2":
version "7.0.2"
resolved "https://registry.yarnpkg.com/@capacitor/google-maps/-/google-maps-7.0.2.tgz#1fc79bece5afe452431289d080043745ddb406cf"
integrity sha512-OLwOB3vhXTpvV3OxJe+PEJld/U9VWYYl8LHkciV4rSoMn+/xKsUdfiztEpi+LhpbB4idTAO1H/D/IIxMqJcc4A==
dependencies:
"@googlemaps/js-api-loader" "~1.16.8"
"@googlemaps/markerclusterer" "~2.5.3"
"@types/google.maps" "~3.58.1"
"@capacitor/ios@7.0.1":
version "7.0.1"
resolved "https://registry.npmjs.org/@capacitor/ios/-/ios-7.0.1.tgz"
@@ -374,6 +383,19 @@
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz#0b17ec8a70b2385827d52314c1253160a0b9bacc"
integrity sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==
"@googlemaps/js-api-loader@~1.16.8":
version "1.16.8"
resolved "https://registry.yarnpkg.com/@googlemaps/js-api-loader/-/js-api-loader-1.16.8.tgz#1595a2af80ca07e551fc961d921a2437d1cb3643"
integrity sha512-CROqqwfKotdO6EBjZO/gQGVTbeDps5V7Mt9+8+5Q+jTg5CRMi3Ii/L9PmV3USROrt2uWxtGzJHORmByxyo9pSQ==
"@googlemaps/markerclusterer@~2.5.3":
version "2.5.3"
resolved "https://registry.yarnpkg.com/@googlemaps/markerclusterer/-/markerclusterer-2.5.3.tgz#9f891ce7e8e161775f3a3e2c9f66956810284591"
integrity sha512-x7lX0R5yYOoiNectr10wLgCBasNcXFHiADIBdmn7jQllF2B5ENQw5XtZK+hIw4xnV0Df0xhN4LN98XqA5jaiOw==
dependencies:
fast-deep-equal "^3.1.3"
supercluster "^8.0.1"
"@hookform/resolvers@^4.1.3":
version "4.1.3"
resolved "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-4.1.3.tgz"
@@ -899,6 +921,11 @@
resolved "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz"
integrity sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==
"@types/google.maps@~3.58.1":
version "3.58.1"
resolved "https://registry.yarnpkg.com/@types/google.maps/-/google.maps-3.58.1.tgz#71ce3dec44de1452f56641d2c87c7dd8ea964b4d"
integrity sha512-X9QTSvGJ0nCfMzYOnaVs/k6/4L+7F5uCS+4iUmkLEls6J9S/Phv+m/i3mDeyc49ZBgwab3EFO1HEoBY7k98EGQ==
"@types/hast@^3.0.0":
version "3.0.4"
resolved "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz"
@@ -2041,6 +2068,11 @@ jsonfile@^6.0.1:
optionalDependencies:
graceful-fs "^4.1.6"
kdbush@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/kdbush/-/kdbush-4.0.2.tgz#2f7b7246328b4657dd122b6c7f025fbc2c868e39"
integrity sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==
kleur@^3.0.3:
version "3.0.3"
resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz"
@@ -3285,6 +3317,13 @@ stylis@^4.3.0:
resolved "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz"
integrity sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==
supercluster@^8.0.1:
version "8.0.1"
resolved "https://registry.yarnpkg.com/supercluster/-/supercluster-8.0.1.tgz#9946ba123538e9e9ab15de472531f604e7372df5"
integrity sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==
dependencies:
kdbush "^4.0.2"
supports-color@^7.1.0:
version "7.2.0"
resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"