diff --git a/apps/landing/src/components/NavBar.tsx b/apps/landing/src/components/NavBar.tsx index 1c36dccd9..ad9c7101b 100644 --- a/apps/landing/src/components/NavBar.tsx +++ b/apps/landing/src/components/NavBar.tsx @@ -142,6 +142,7 @@ export default function NavBar() { buttonIcon={} buttonProps={{ className: '!p-1 ml-[140px] hover:!bg-transparent' }} /> +
diff --git a/core/src/api/locations.rs b/core/src/api/locations.rs index d5a0b617f..b8572f481 100644 --- a/core/src/api/locations.rs +++ b/core/src/api/locations.rs @@ -126,7 +126,7 @@ pub(crate) fn mount() -> rspc::RouterBuilder< .join(&object.cas_id) .with_extension("webp"); - object.has_thumbnail = thumb_path.exists(); + object.has_thumbnail = thumb_path.try_exists().unwrap(); } ExplorerItem::Path(Box::new(file_path)) }) diff --git a/core/src/api/mod.rs b/core/src/api/mod.rs index a50376443..d24b8e011 100644 --- a/core/src/api/mod.rs +++ b/core/src/api/mod.rs @@ -43,11 +43,6 @@ mod tags; pub mod utils; pub mod volumes; -pub use files::*; -pub use jobs::*; -pub use libraries::*; -pub use tags::*; - #[derive(Serialize, Deserialize, Debug, Type)] struct NodeState { #[serde(flatten)] diff --git a/core/src/api/tags.rs b/core/src/api/tags.rs index b69238220..50e67522b 100644 --- a/core/src/api/tags.rs +++ b/core/src/api/tags.rs @@ -61,7 +61,7 @@ pub(crate) fn mount() -> RouterBuilder { .join(&object.cas_id) .with_extension("webp"); - object.has_thumbnail = thumb_path.exists(); + object.has_thumbnail = thumb_path.try_exists().unwrap(); ExplorerItem::Object(Box::new(object)) }) diff --git a/core/src/api/utils/library.rs b/core/src/api/utils/library.rs index aff888476..7fb2a6c05 100644 --- a/core/src/api/utils/library.rs +++ b/core/src/api/utils/library.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use futures::{Future, Stream}; +use futures::Stream; use rspc::{ internal::{ specta, BuiltProcedureBuilder, MiddlewareBuilderLike, RequestResult, diff --git a/core/src/library/library_manager.rs b/core/src/library/library_manager.rs index f21237151..70577b536 100644 --- a/core/src/library/library_manager.rs +++ b/core/src/library/library_manager.rs @@ -93,7 +93,7 @@ impl LibraryManager { }; let db_path = config_path.clone().with_extension("db"); - if !db_path.exists() { + if !db_path.try_exists().unwrap() { println!( "Found library '{}' but no matching database file was found. Skipping...", config_path.display() diff --git a/core/src/location/mod.rs b/core/src/location/mod.rs index 4d5d29551..8621942d4 100644 --- a/core/src/location/mod.rs +++ b/core/src/location/mod.rs @@ -44,7 +44,7 @@ impl LocationCreateArgs { ctx: &LibraryContext, ) -> Result { // check if we have access to this location - if !self.path.exists() { + if !self.path.try_exists().unwrap() { return Err(LocationError::PathNotFound(self.path)); } diff --git a/core/src/node/config.rs b/core/src/node/config.rs index 21d61ef47..92f79cd57 100644 --- a/core/src/node/config.rs +++ b/core/src/node/config.rs @@ -115,7 +115,7 @@ impl NodeConfigManager { async fn read(base_path: &PathBuf) -> Result { let path = Path::new(base_path).join(NODE_STATE_CONFIG_NAME); - match path.exists() { + match path.try_exists().unwrap() { true => { let mut file = File::open(&path)?; let base_config: ConfigMetadata = diff --git a/core/src/object/cas.rs b/core/src/object/cas.rs index 58f6858de..3c558b3f1 100644 --- a/core/src/object/cas.rs +++ b/core/src/object/cas.rs @@ -51,20 +51,20 @@ pub async fn generate_cas_id(path: PathBuf, size: u64) -> Result Result { - const BLOCK_SIZE: usize = 1048576; - //read file as buffer and convert to digest - let mut reader = File::open(path).await?; - let mut context = Hasher::new(); - let mut buffer = [0; 1048576]; - loop { - let read_count = reader.read(&mut buffer).await?; - context.update(&buffer[..read_count]); - if read_count != BLOCK_SIZE { - break; - } - } - let hex = to_hex_string(context.finalize().as_bytes()); +// pub async fn full_checksum(path: &str) -> Result { +// const BLOCK_SIZE: usize = 1048576; +// //read file as buffer and convert to digest +// let mut reader = File::open(path).await?; +// let mut context = Hasher::new(); +// let mut buffer = [0; 1048576]; +// loop { +// let read_count = reader.read(&mut buffer).await?; +// context.update(&buffer[..read_count]); +// if read_count != BLOCK_SIZE { +// break; +// } +// } +// let hex = to_hex_string(context.finalize().as_bytes()); - Ok(hex) -} +// Ok(hex) +// } diff --git a/core/src/object/preview/thumb.rs b/core/src/object/preview/thumb.rs index 49de6d157..f13b43acf 100644 --- a/core/src/object/preview/thumb.rs +++ b/core/src/object/preview/thumb.rs @@ -5,7 +5,7 @@ use crate::{ library::LibraryContext, prisma::{file_path, location}, }; -use sd_file_ext::extensions::{Extension, ImageExtension, VideoExtension, ALL_VIDEO_EXTENSIONS}; +use sd_file_ext::extensions::{Extension, ImageExtension, VideoExtension}; use image::{self, imageops, DynamicImage, GenericImageView}; use serde::{Deserialize, Serialize}; @@ -120,8 +120,8 @@ impl StatefulJob for ThumbnailJob { &library_ctx, state.init.location_id, &state.init.path, - ALL_VIDEO_EXTENSIONS - .into_iter() + sd_file_ext::extensions::ALL_VIDEO_EXTENSIONS + .iter() .map(Clone::clone) .filter(can_generate_thumbnail_for_video) .map(Extension::Video) @@ -189,7 +189,7 @@ impl StatefulJob for ThumbnailJob { let output_path = data.thumbnail_dir.join(&cas_id).with_extension("webp"); // check if file exists at output path - if !output_path.exists() { + if !output_path.try_exists().unwrap() { info!("Writing {:?} to {:?}", path, output_path); match step.kind { @@ -317,10 +317,8 @@ async fn get_files_by_extensions( .collect()) } +#[allow(unused)] pub fn can_generate_thumbnail_for_video(video_extension: &VideoExtension) -> bool { use VideoExtension::*; - match video_extension { - Mpg | Swf | M2v => false, - _ => true, - } + !matches!(video_extension, Mpg | Swf | M2v) } diff --git a/crates/file-ext/src/magic.rs b/crates/file-ext/src/magic.rs index 4e44a293e..8e449a1de 100644 --- a/crates/file-ext/src/magic.rs +++ b/crates/file-ext/src/magic.rs @@ -1,10 +1,7 @@ #![allow(dead_code)] -use crate::extensions::{ - ArchiveExtension, AudioExtension, CodeExtension, DatabaseExtension, ExecutableExtension, - Extension, FontExtension, ImageExtension, MeshExtension, VideoExtension, -}; +use crate::extensions::{CodeExtension, Extension, VideoExtension}; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub enum ExtensionPossibility { Known(Extension), Conflicts(Vec), @@ -30,7 +27,7 @@ macro_rules! magic_byte_value { $val as u8 }}; } -pub(crate) use magic_byte_value; +// pub(crate) use magic_byte_value; #[macro_export] macro_rules! magic_byte_offset { @@ -41,7 +38,7 @@ macro_rules! magic_byte_offset { $val }; } -pub(crate) use magic_byte_offset; +// pub(crate) use magic_byte_offset; macro_rules! extension_enum { ( @@ -50,11 +47,12 @@ macro_rules! extension_enum { } ) => { // construct enum - #[derive(Debug, ::serde::Serialize, ::serde::Deserialize, PartialEq)] + #[derive(Debug, ::serde::Serialize, ::serde::Deserialize, PartialEq, Eq)] pub enum Extension { $( $variant($type), )* } impl Extension { + #[allow(clippy::should_implement_trait)] pub fn from_str(s: &str) -> Option { use std::str::FromStr; let mut exts = [$( @@ -100,7 +98,7 @@ macro_rules! extension_category_enum { $($(#[$variant_attr:meta])* $variant:ident $(= $( [$($magic_bytes:tt),*] $(+ $offset:literal)? )|+ )? ,)* } ) => { - #[derive(Debug, ::serde::Serialize, ::serde::Deserialize, Clone, Copy, PartialEq)] + #[derive(Debug, ::serde::Serialize, ::serde::Deserialize, Clone, Copy, PartialEq, Eq)] #[serde(rename_all = "snake_case")] $(#[$enum_attr])* @@ -195,10 +193,10 @@ impl Extension { Self::Audio(x) => verify_magic_bytes(x, file).map(Self::Audio), Self::Video(x) => verify_magic_bytes(x, file).map(Self::Video), Self::Executable(x) => verify_magic_bytes(x, file).map(Self::Executable), - _ => return None, + _ => None, } } else { - Some(Extension::from(e)) + Some(e) } } ExtensionPossibility::Conflicts(ext) => match ext_str { diff --git a/crates/p2p/tunnel/src/bin/generate-env.rs b/crates/p2p/tunnel/src/bin/generate-env.rs index b2de3ca8a..4b3990795 100644 --- a/crates/p2p/tunnel/src/bin/generate-env.rs +++ b/crates/p2p/tunnel/src/bin/generate-env.rs @@ -7,7 +7,7 @@ fn main() { println!("Issuing sdtunnel certificate..."); let env_file = Path::new("./.env"); - if env_file.exists() { + if env_file.try_exists().unwrap() { println!("File '{}' already exists. Exiting...", env_file.display()); return; } diff --git a/packages/client/package.json b/packages/client/package.json index 9f8fd64dc..6e0ca3c10 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -20,7 +20,6 @@ "@rspc/client": "^0.1.2", "@rspc/react": "^0.1.2", "@sd/config": "workspace:*", - "@sd/interface": "workspace:*", "@tanstack/react-query": "^4.10.1", "eventemitter3": "^4.0.7", "immer": "^9.0.15", diff --git a/packages/interface/package.json b/packages/interface/package.json index 387b62f82..bc17a2b6a 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -18,6 +18,7 @@ "@fontsource/inter": "^4.5.13", "@headlessui/react": "^1.7.3", "@heroicons/react": "^2.0.12", + "@loadable/component": "^5.15.2", "@radix-ui/react-dialog": "^1.0.0", "@radix-ui/react-dropdown-menu": "^1.0.0", "@radix-ui/react-icons": "^1.1.1", @@ -77,6 +78,7 @@ "@sd/config": "workspace:*", "@types/babel-core": "^6.25.7", "@types/byte-size": "^8.1.0", + "@types/loadable__component": "^5.13.4", "@types/lodash": "^4.14.186", "@types/node": "^18.8.2", "@types/pretty-bytes": "^5.2.0", diff --git a/packages/interface/src/AppRouter.tsx b/packages/interface/src/AppRouter.tsx index eb5db1787..54333b529 100644 --- a/packages/interface/src/AppRouter.tsx +++ b/packages/interface/src/AppRouter.tsx @@ -1,42 +1,44 @@ +import loadable from '@loadable/component'; import { useCurrentLibrary, useInvalidateQuery } from '@sd/client'; -import { Suspense, lazy } from 'react'; +import { Suspense } from 'react'; import { Navigate, Route, Routes } from 'react-router-dom'; import { AppLayout } from './AppLayout'; import { useKeybindHandler } from './hooks/useKeyboardHandler'; -const DebugScreen = lazy(() => import('./screens/Debug')); -const SettingsScreen = lazy(() => import('./screens/settings/Settings')); -const TagExplorer = lazy(() => import('./screens/TagExplorer')); -const PhotosScreen = lazy(() => import('./screens/Photos')); -const OverviewScreen = lazy(() => import('./screens/Overview')); -const ContentScreen = lazy(() => import('./screens/Content')); -const LocationExplorer = lazy(() => import('./screens/LocationExplorer')); -const OnboardingScreen = lazy(() => import('./components/onboarding/Onboarding')); -const NotFound = lazy(() => import('./NotFound')); +// Using React.lazy breaks hot reload so we don't use it. +const DebugScreen = loadable(() => import('./screens/Debug')); +const SettingsScreen = loadable(() => import('./screens/settings/Settings')); +const TagExplorer = loadable(() => import('./screens/TagExplorer')); +const PhotosScreen = loadable(() => import('./screens/Photos')); +const OverviewScreen = loadable(() => import('./screens/Overview')); +const ContentScreen = loadable(() => import('./screens/Content')); +const LocationExplorer = loadable(() => import('./screens/LocationExplorer')); +const OnboardingScreen = loadable(() => import('./components/onboarding/Onboarding')); +const NotFound = loadable(() => import('./NotFound')); -const AppearanceSettings = lazy(() => import('./screens/settings/client/AppearanceSettings')); -const ExtensionSettings = lazy(() => import('./screens/settings/client/ExtensionsSettings')); -const GeneralSettings = lazy(() => import('./screens/settings/client/GeneralSettings')); -const KeybindingSettings = lazy(() => import('./screens/settings/client/KeybindingSettings')); -const PrivacySettings = lazy(() => import('./screens/settings/client/PrivacySettings')); -const AboutSpacedrive = lazy(() => import('./screens/settings/info/AboutSpacedrive')); -const Changelog = lazy(() => import('./screens/settings/info/Changelog')); -const Support = lazy(() => import('./screens/settings/info/Support')); -const ContactsSettings = lazy(() => import('./screens/settings/library/ContactsSettings')); -const KeysSettings = lazy(() => import('./screens/settings/library/KeysSetting')); -const LibraryGeneralSettings = lazy( +const AppearanceSettings = loadable(() => import('./screens/settings/client/AppearanceSettings')); +const ExtensionSettings = loadable(() => import('./screens/settings/client/ExtensionsSettings')); +const GeneralSettings = loadable(() => import('./screens/settings/client/GeneralSettings')); +const KeybindingSettings = loadable(() => import('./screens/settings/client/KeybindingSettings')); +const PrivacySettings = loadable(() => import('./screens/settings/client/PrivacySettings')); +const AboutSpacedrive = loadable(() => import('./screens/settings/info/AboutSpacedrive')); +const Changelog = loadable(() => import('./screens/settings/info/Changelog')); +const Support = loadable(() => import('./screens/settings/info/Support')); +const ContactsSettings = loadable(() => import('./screens/settings/library/ContactsSettings')); +const KeysSettings = loadable(() => import('./screens/settings/library/KeysSetting')); +const LibraryGeneralSettings = loadable( () => import('./screens/settings/library/LibraryGeneralSettings') ); -const LocationSettings = lazy(() => import('./screens/settings/library/LocationSettings')); -const NodesSettings = lazy(() => import('./screens/settings/library/NodesSettings')); -const SecuritySettings = lazy(() => import('./screens/settings/library/SecuritySettings')); -const SharingSettings = lazy(() => import('./screens/settings/library/SharingSettings')); -const SyncSettings = lazy(() => import('./screens/settings/library/SyncSettings')); -const TagsSettings = lazy(() => import('./screens/settings/library/TagsSettings')); -const ExperimentalSettings = lazy(() => import('./screens/settings/node/ExperimentalSettings')); -const LibrarySettings = lazy(() => import('./screens/settings/node/LibrariesSettings')); -const P2PSettings = lazy(() => import('./screens/settings/node/P2PSettings')); +const LocationSettings = loadable(() => import('./screens/settings/library/LocationSettings')); +const NodesSettings = loadable(() => import('./screens/settings/library/NodesSettings')); +const SecuritySettings = loadable(() => import('./screens/settings/library/SecuritySettings')); +const SharingSettings = loadable(() => import('./screens/settings/library/SharingSettings')); +const SyncSettings = loadable(() => import('./screens/settings/library/SyncSettings')); +const TagsSettings = loadable(() => import('./screens/settings/library/TagsSettings')); +const ExperimentalSettings = loadable(() => import('./screens/settings/node/ExperimentalSettings')); +const LibrarySettings = loadable(() => import('./screens/settings/node/LibrariesSettings')); +const P2PSettings = loadable(() => import('./screens/settings/node/P2PSettings')); export function AppRouter() { const { library } = useCurrentLibrary(); diff --git a/packages/interface/src/components/dialog/CreateLibraryDialog.tsx b/packages/interface/src/components/dialog/CreateLibraryDialog.tsx index 04d4438fd..a45fed7f5 100644 --- a/packages/interface/src/components/dialog/CreateLibraryDialog.tsx +++ b/packages/interface/src/components/dialog/CreateLibraryDialog.tsx @@ -16,8 +16,6 @@ export default function CreateLibraryDialog({ 'library.create', { onSuccess: (library: any) => { - console.log('SUBMITTING'); - setOpenCreateModal(false); queryClient.setQueryData(['library.list'], (libraries: any) => [ diff --git a/packages/interface/src/components/layout/Modal.tsx b/packages/interface/src/components/layout/Modal.tsx index 4f0d7989b..675ae4326 100644 --- a/packages/interface/src/components/layout/Modal.tsx +++ b/packages/interface/src/components/layout/Modal.tsx @@ -1,8 +1,7 @@ import { Transition } from '@headlessui/react'; import { XMarkIcon } from '@heroicons/react/24/solid'; -import { Button } from '@sd/ui'; +import { ButtonLink } from '@sd/ui'; import clsx from 'clsx'; -import { useNavigate } from 'react-router-dom'; export interface ModalProps { full?: boolean; @@ -10,7 +9,6 @@ export interface ModalProps { } export const Modal: React.FC = (props) => { - const navigate = useNavigate(); return (
= (props) => { >
navigate('/')} className="absolute top-0 left-0 w-screen h-screen bg-white -z-50 rounded-2xl dark:bg-gray-800 bg-opacity-90" /> - + navigate('settings/library') + to: 'settings/library' }, { name: 'Add Library', diff --git a/packages/interface/src/screens/settings/node/LibrariesSettings.tsx b/packages/interface/src/screens/settings/node/LibrariesSettings.tsx index 3d8665755..a213a72ba 100644 --- a/packages/interface/src/screens/settings/node/LibrariesSettings.tsx +++ b/packages/interface/src/screens/settings/node/LibrariesSettings.tsx @@ -1,10 +1,9 @@ import { PencilIcon, TrashIcon } from '@heroicons/react/24/outline'; import { useBridgeMutation, useBridgeQuery } from '@sd/client'; import { LibraryConfigWrapped } from '@sd/client'; -import { Button } from '@sd/ui'; +import { Button, ButtonLink } from '@sd/ui'; import { DotsSixVertical } from 'phosphor-react'; import { useState } from 'react'; -import { useNavigate } from 'react-router'; import CreateLibraryDialog from '../../../components/dialog/CreateLibraryDialog'; import DeleteLibraryDialog from '../../../components/dialog/DeleteLibraryDialog'; @@ -13,7 +12,6 @@ import { SettingsContainer } from '../../../components/settings/SettingsContaine import { SettingsHeader } from '../../../components/settings/SettingsHeader'; function LibraryListItem(props: { library: LibraryConfigWrapped }) { - const navigate = useNavigate(); const [openDeleteModal, setOpenDeleteModal] = useState(false); const { mutate: deleteLib, isLoading: libDeletePending } = useBridgeMutation('library.delete', { @@ -22,14 +20,6 @@ function LibraryListItem(props: { library: LibraryConfigWrapped }) { } }); - function handleEditLibrary() { - // switch library if requesting to edit non-current library - navigate('/settings/library'); - // if (props.library.uuid !== store.currentLibraryUuid) { - // switchLibrary(props.library.uuid); - // } - } - return ( @@ -38,9 +28,9 @@ function LibraryListItem(props: { library: LibraryConfigWrapped }) {

{props.library.uuid}

- + + {button.to ? ( + + {button.icon && ( + + )} + {button.name} + + ) : ( + + )} ); }} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 95c463bc8..100f00cc9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -278,7 +278,6 @@ importers: '@rspc/client': ^0.1.2 '@rspc/react': ^0.1.2 '@sd/config': workspace:* - '@sd/interface': workspace:* '@tanstack/react-query': ^4.10.1 '@types/lodash': ^4.14.186 '@types/react': ^18.0.21 @@ -295,7 +294,6 @@ importers: '@rspc/client': 0.1.2 '@rspc/react': 0.1.2_2j6p62nqyqxwo4xyixi65nw6l4 '@sd/config': link:../config - '@sd/interface': link:../interface '@tanstack/react-query': 4.10.1 eventemitter3: 4.0.7 immer: 9.0.15 @@ -331,6 +329,7 @@ importers: '@fontsource/inter': ^4.5.13 '@headlessui/react': ^1.7.3 '@heroicons/react': ^2.0.12 + '@loadable/component': ^5.15.2 '@radix-ui/react-dialog': ^1.0.0 '@radix-ui/react-dropdown-menu': ^1.0.0 '@radix-ui/react-icons': ^1.1.1 @@ -349,6 +348,7 @@ importers: '@tanstack/react-virtual': 3.0.0-beta.18 '@types/babel-core': ^6.25.7 '@types/byte-size': ^8.1.0 + '@types/loadable__component': ^5.13.4 '@types/lodash': ^4.14.186 '@types/node': ^18.8.2 '@types/pretty-bytes': ^5.2.0 @@ -406,6 +406,7 @@ importers: '@fontsource/inter': 4.5.13 '@headlessui/react': 1.7.3_biqbaboplfbrettd7655fr4n2y '@heroicons/react': 2.0.12_react@18.2.0 + '@loadable/component': 5.15.2_react@18.2.0 '@radix-ui/react-dialog': 1.0.0_rj7ozvcq3uehdlnj3cbwzbi5ce '@radix-ui/react-dropdown-menu': 1.0.0_rj7ozvcq3uehdlnj3cbwzbi5ce '@radix-ui/react-icons': 1.1.1_react@18.2.0 @@ -464,6 +465,7 @@ importers: '@sd/config': link:../config '@types/babel-core': 6.25.7 '@types/byte-size': 8.1.0 + '@types/loadable__component': 5.13.4 '@types/lodash': 4.14.186 '@types/node': 18.8.2 '@types/pretty-bytes': 5.2.0 @@ -516,6 +518,7 @@ importers: react: ^18.2.0 react-dom: ^18.2.0 react-loading-icons: ^1.1.0 + react-router-dom: 6.4.2 react-spring: ^9.5.5 sass: ^1.55.0 sass-loader: ^13.0.2 @@ -541,6 +544,7 @@ importers: react: 18.2.0 react-dom: 18.2.0_react@18.2.0 react-loading-icons: 1.1.0 + react-router-dom: 6.4.2_biqbaboplfbrettd7655fr4n2y react-spring: 9.5.5_biqbaboplfbrettd7655fr4n2y storybook: 6.5.12_yalvw3r2waubxycyb7k7qsruca tailwindcss: 3.1.8 @@ -2977,6 +2981,18 @@ packages: '@jridgewell/sourcemap-codec': 1.4.14 dev: false + /@loadable/component/5.15.2_react@18.2.0: + resolution: {integrity: sha512-ryFAZOX5P2vFkUdzaAtTG88IGnr9qxSdvLRvJySXcUA4B4xVWurUNADu3AnKPksxOZajljqTrDEDcYjeL4lvLw==} + engines: {node: '>=8'} + peerDependencies: + react: '>=16.3.0' + dependencies: + '@babel/runtime': 7.19.0 + hoist-non-react-statics: 3.3.2 + react: 18.2.0 + react-is: 16.13.1 + dev: false + /@mdx-js/mdx/1.6.22: resolution: {integrity: sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==} dependencies: @@ -6056,6 +6072,12 @@ packages: dependencies: '@types/node': 18.8.2 + /@types/loadable__component/5.13.4: + resolution: {integrity: sha512-YhoCCxyuvP2XeZNbHbi8Wb9EMaUJuA2VGHxJffcQYrJKIKSkymJrhbzsf9y4zpTmr5pExAAEh5hbF628PAZ8Dg==} + dependencies: + '@types/react': 18.0.21 + dev: true + /@types/lodash/4.14.186: resolution: {integrity: sha512-eHcVlLXP0c2FlMPm56ITode2AgLMSa6aJ05JTTbYbI+7EMkCEE5qk2E41d5g2lCVTqRe0GnnRFurmlCsDODrPw==} @@ -11484,6 +11506,12 @@ packages: minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 + /hoist-non-react-statics/3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + dependencies: + react-is: 16.13.1 + dev: false + /hosted-git-info/2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}