diff --git a/apps/admin-x-settings/src/admin-x-ds/global/Icon.tsx b/apps/admin-x-settings/src/admin-x-ds/global/Icon.tsx index 3e6bc3106b..4a082527f9 100644 --- a/apps/admin-x-settings/src/admin-x-ds/global/Icon.tsx +++ b/apps/admin-x-settings/src/admin-x-ds/global/Icon.tsx @@ -1,48 +1,7 @@ -import React, {useEffect, useState} from 'react'; +import React from 'react'; import clsx from 'clsx'; -interface UseDynamicSVGImportOptions { - onCompleted?: ( - name: string, - SvgIcon: React.FC> | undefined - ) => void; - onError?: (err: Error) => void; -} - -function useDynamicSVGImport( - name: string, - options: UseDynamicSVGImportOptions = {} -) { - const [loading, setLoading] = useState(false); - const [SvgComponent, setSvgComponent] = useState> | null | undefined>(null); - const [error, setError] = useState(); - - const {onCompleted, onError} = options; - useEffect(() => { - setLoading(true); - const importIcon = async (): Promise => { - try { - const SvgIcon: React.FC> = ( - await import(`../assets/icons/${name}.svg`) - ).ReactComponent; - setSvgComponent(() => SvgIcon); - onCompleted?.(name, SvgIcon); - } catch (err) { - if (err instanceof Error) { - onError?.(err); - setError(err); - } else { - throw err; - } - } finally { - setLoading(() => false); - } - }; - importIcon(); - }, [name, onCompleted, onError]); - - return {error, loading, SvgComponent}; -} +const icons: Record>}> = import.meta.glob('../assets/icons/*.svg', {eager: true}); export type IconSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | number; @@ -69,7 +28,7 @@ interface IconProps { * - all strokes must be paths and _NOT_ outlined objects. Stroke width should be set to 1.5px */ const Icon: React.FC = ({name, size = 'md', colorClass = '', className = ''}) => { - const {SvgComponent} = useDynamicSVGImport(name); + const {ReactComponent: SvgComponent} = icons[`../assets/icons/${name}.svg`]; let styles = ''; diff --git a/apps/admin-x-settings/src/assets/images/footer-marketplace-bg.png b/apps/admin-x-settings/src/assets/images/footer-marketplace-bg.png index fafec0d024..cfd4bd841d 100644 Binary files a/apps/admin-x-settings/src/assets/images/footer-marketplace-bg.png and b/apps/admin-x-settings/src/assets/images/footer-marketplace-bg.png differ diff --git a/apps/admin-x-settings/src/assets/images/orb-pink.png b/apps/admin-x-settings/src/assets/images/orb-pink.png index b1eef95a6c..8acec98a3e 100644 Binary files a/apps/admin-x-settings/src/assets/images/orb-pink.png and b/apps/admin-x-settings/src/assets/images/orb-pink.png differ diff --git a/apps/admin-x-settings/src/assets/images/stripe-thumb.jpg b/apps/admin-x-settings/src/assets/images/stripe-thumb.jpg index 1d4f4e76d6..2dbc24e9e1 100644 Binary files a/apps/admin-x-settings/src/assets/images/stripe-thumb.jpg and b/apps/admin-x-settings/src/assets/images/stripe-thumb.jpg differ diff --git a/apps/admin-x-settings/src/components/providers/RoutingProvider.tsx b/apps/admin-x-settings/src/components/providers/RoutingProvider.tsx index 312ce8dce8..d60c13d524 100644 --- a/apps/admin-x-settings/src/components/providers/RoutingProvider.tsx +++ b/apps/admin-x-settings/src/components/providers/RoutingProvider.tsx @@ -1,6 +1,7 @@ -import NiceModal, {NiceModalHocProps} from '@ebay/nice-modal-react'; +import NiceModal from '@ebay/nice-modal-react'; import React, {createContext, useCallback, useEffect, useState} from 'react'; import {ScrollSectionProvider} from '../../hooks/useScrollSection'; +import type {ModalComponent, ModalName} from './routing/modals'; export type RouteParams = {[key: string]: string} @@ -32,32 +33,7 @@ export type RoutingModalProps = { params?: Record } -const modals: {[key: string]: () => Promise<{default: React.FC}>} = { - AddIntegrationModal: () => import('../settings/advanced/integrations/AddIntegrationModal'), - AddNewsletterModal: () => import('../settings/email/newsletters/AddNewsletterModal'), - AddRecommendationModal: () => import('../settings/site/recommendations/AddRecommendationModal'), - AmpModal: () => import('../settings/advanced/integrations/AmpModal'), - CustomIntegrationModal: () => import('../settings/advanced/integrations/CustomIntegrationModal'), - DesignAndThemeModal: () => import('../settings/site/DesignAndThemeModal'), - EditRecommendationModal: () => import('../settings/site/recommendations/EditRecommendationModal'), - FirstpromoterModal: () => import('../settings/advanced/integrations/FirstPromoterModal'), - HistoryModal: () => import('../settings/advanced/HistoryModal'), - InviteUserModal: () => import('../settings/general/InviteUserModal'), - NavigationModal: () => import('../settings/site/NavigationModal'), - NewsletterDetailModal: () => import('../settings/email/newsletters/NewsletterDetailModal'), - PinturaModal: () => import('../settings/advanced/integrations/PinturaModal'), - PortalModal: () => import('../settings/membership/portal/PortalModal'), - SlackModal: () => import('../settings/advanced/integrations/SlackModal'), - StripeConnectModal: () => import('../settings/membership/stripe/StripeConnectModal'), - TierDetailModal: () => import('../settings/membership/tiers/TierDetailModal'), - UnsplashModal: () => import('../settings/advanced/integrations/UnsplashModal'), - UserDetailModal: () => import('../settings/general/UserDetailModal'), - ZapierModal: () => import('../settings/advanced/integrations/ZapierModal'), - AnnouncementBarModal: () => import('../settings/site/AnnouncementBarModal'), - EmbedSignupFormModal: () => import('../settings/membership/embedSignup/EmbedSignupFormModal') -}; - -const modalPaths: {[key: string]: keyof typeof modals} = { +const modalPaths: {[key: string]: ModalName} = { 'design/edit/themes': 'DesignAndThemeModal', 'design/edit': 'DesignAndThemeModal', 'navigation/edit': 'NavigationModal', @@ -118,8 +94,8 @@ const handleNavigation = (currentRoute: string | undefined) => { pathName, changingModal: modalName && modalName !== currentModalName, modal: (path && modalName) ? - modals[modalName]().then(({default: component}) => { - NiceModal.show(component, {pathName, params: matchRoute(pathName, path)}); + import('./routing/modals').then(({default: modals}) => { + NiceModal.show(modals[modalName] as ModalComponent, {pathName, params: matchRoute(pathName, path)}); }) : undefined }; @@ -147,7 +123,7 @@ const RoutingProvider: React.FC = ({externalNavigate, childr useEffect(() => { // Preload all the modals after initial render to avoid a delay when opening them setTimeout(() => { - Object.values(modalPaths).forEach(modal => modals[modal]()); + import('./routing/modals'); }, 1000); }, []); diff --git a/apps/admin-x-settings/src/components/providers/routing/modals.tsx b/apps/admin-x-settings/src/components/providers/routing/modals.tsx new file mode 100644 index 0000000000..2dd2ed7384 --- /dev/null +++ b/apps/admin-x-settings/src/components/providers/routing/modals.tsx @@ -0,0 +1,55 @@ +import type {NiceModalHocProps} from '@ebay/nice-modal-react'; +import type {RoutingModalProps} from '../RoutingProvider'; + +import AddIntegrationModal from '../../settings/advanced/integrations/AddIntegrationModal'; +import AddNewsletterModal from '../../settings/email/newsletters/AddNewsletterModal'; +import AddRecommendationModal from '../../settings/site/recommendations/AddRecommendationModal'; +import AmpModal from '../../settings/advanced/integrations/AmpModal'; +import AnnouncementBarModal from '../../settings/site/AnnouncementBarModal'; +import CustomIntegrationModal from '../../settings/advanced/integrations/CustomIntegrationModal'; +import DesignAndThemeModal from '../../settings/site/DesignAndThemeModal'; +import EditRecommendationModal from '../../settings/site/recommendations/EditRecommendationModal'; +import EmbedSignupFormModal from '../../settings/membership/embedSignup/EmbedSignupFormModal'; +import FirstpromoterModal from '../../settings/advanced/integrations/FirstPromoterModal'; +import HistoryModal from '../../settings/advanced/HistoryModal'; +import InviteUserModal from '../../settings/general/InviteUserModal'; +import NavigationModal from '../../settings/site/NavigationModal'; +import NewsletterDetailModal from '../../settings/email/newsletters/NewsletterDetailModal'; +import PinturaModal from '../../settings/advanced/integrations/PinturaModal'; +import PortalModal from '../../settings/membership/portal/PortalModal'; +import SlackModal from '../../settings/advanced/integrations/SlackModal'; +import StripeConnectModal from '../../settings/membership/stripe/StripeConnectModal'; +import TierDetailModal from '../../settings/membership/tiers/TierDetailModal'; +import UnsplashModal from '../../settings/advanced/integrations/UnsplashModal'; +import UserDetailModal from '../../settings/general/UserDetailModal'; +import ZapierModal from '../../settings/advanced/integrations/ZapierModal'; + +const modals = { + AddIntegrationModal, + AddNewsletterModal, + AddRecommendationModal, + AmpModal, + CustomIntegrationModal, + DesignAndThemeModal, + EditRecommendationModal, + FirstpromoterModal, + HistoryModal, + InviteUserModal, + NavigationModal, + NewsletterDetailModal, + PinturaModal, + PortalModal, + SlackModal, + StripeConnectModal, + TierDetailModal, + UnsplashModal, + UserDetailModal, + ZapierModal, + AnnouncementBarModal, + EmbedSignupFormModal +} satisfies {[key: string]: ModalComponent}; + +export default modals; + +export type ModalName = keyof typeof modals; +export type ModalComponent = React.FC diff --git a/apps/admin-x-settings/src/components/settings/advanced/integrations/AddIntegrationModal.tsx b/apps/admin-x-settings/src/components/settings/advanced/integrations/AddIntegrationModal.tsx index 1da604d562..440caaf15d 100644 --- a/apps/admin-x-settings/src/components/settings/advanced/integrations/AddIntegrationModal.tsx +++ b/apps/admin-x-settings/src/components/settings/advanced/integrations/AddIntegrationModal.tsx @@ -6,11 +6,10 @@ import React, {useEffect, useState} from 'react'; import TextField from '../../../../admin-x-ds/global/form/TextField'; import useRouting from '../../../../hooks/useRouting'; import {HostLimitError, useLimiter} from '../../../../hooks/useLimiter'; +import {RoutingModalProps} from '../../../providers/RoutingProvider'; import {useCreateIntegration} from '../../../../api/integrations'; -interface AddIntegrationModalProps {} - -const AddIntegrationModal: React.FC = () => { +const AddIntegrationModal: React.FC = () => { const modal = useModal(); const {updateRoute} = useRouting(); const [name, setName] = useState(''); diff --git a/apps/admin-x-settings/src/components/settings/email/newsletters/AddNewsletterModal.tsx b/apps/admin-x-settings/src/components/settings/email/newsletters/AddNewsletterModal.tsx index a1071e10a7..d848e266f9 100644 --- a/apps/admin-x-settings/src/components/settings/email/newsletters/AddNewsletterModal.tsx +++ b/apps/admin-x-settings/src/components/settings/email/newsletters/AddNewsletterModal.tsx @@ -9,14 +9,13 @@ import Toggle from '../../../../admin-x-ds/global/form/Toggle'; import useForm from '../../../../hooks/useForm'; import useRouting from '../../../../hooks/useRouting'; import {HostLimitError, useLimiter} from '../../../../hooks/useLimiter'; +import {RoutingModalProps} from '../../../providers/RoutingProvider'; import {showToast} from '../../../../admin-x-ds/global/Toast'; import {toast} from 'react-hot-toast'; import {useAddNewsletter} from '../../../../api/newsletters'; import {useBrowseMembers} from '../../../../api/members'; -interface AddNewsletterModalProps {} - -const AddNewsletterModal: React.FC = () => { +const AddNewsletterModal: React.FC = () => { const modal = useModal(); const {updateRoute} = useRouting(); diff --git a/apps/admin-x-settings/src/components/settings/site/recommendations/AddRecommendationModal.tsx b/apps/admin-x-settings/src/components/settings/site/recommendations/AddRecommendationModal.tsx index daf1c07a3a..0ea2a0d1fc 100644 --- a/apps/admin-x-settings/src/components/settings/site/recommendations/AddRecommendationModal.tsx +++ b/apps/admin-x-settings/src/components/settings/site/recommendations/AddRecommendationModal.tsx @@ -7,6 +7,7 @@ import URLTextField from '../../../../admin-x-ds/global/form/URLTextField'; import useForm from '../../../../hooks/useForm'; import useRouting from '../../../../hooks/useRouting'; import {EditOrAddRecommendation, useBrowseRecommendations} from '../../../../api/recommendations'; +import {RoutingModalProps} from '../../../providers/RoutingProvider'; import {arePathsEqual, trimSearchAndHash} from '../../../../utils/url'; import {showToast} from '../../../../admin-x-ds/global/Toast'; import {toast} from 'react-hot-toast'; @@ -18,7 +19,7 @@ interface AddRecommendationModalProps { animate?: boolean } -const AddRecommendationModal: React.FC = ({recommendation, animate}) => { +const AddRecommendationModal: React.FC = ({recommendation, animate}) => { const modal = useModal(); const {updateRoute} = useRouting(); const {query: queryOembed} = useGetOembed(); diff --git a/apps/admin-x-settings/src/components/settings/site/recommendations/AddRecommendationModalConfirm.tsx b/apps/admin-x-settings/src/components/settings/site/recommendations/AddRecommendationModalConfirm.tsx index 0253223c38..62dc4bfd90 100644 --- a/apps/admin-x-settings/src/components/settings/site/recommendations/AddRecommendationModalConfirm.tsx +++ b/apps/admin-x-settings/src/components/settings/site/recommendations/AddRecommendationModalConfirm.tsx @@ -15,7 +15,7 @@ interface AddRecommendationModalProps { const AddRecommendationModalConfirm: React.FC = ({recommendation, animate}) => { const modal = useModal(); - const {updateRoute} = useRouting(); + const {updateRoute, route} = useRouting(); const {mutateAsync: addRecommendation} = useAddRecommendation(); const {formState, updateForm, handleSave, saveState, errors} = useForm({ @@ -62,6 +62,7 @@ const AddRecommendationModalConfirm: React.FC = ({r // Switch modal without changing the route, but pass along any changes that were already made modal.remove(); NiceModal.show(AddRecommendationModal, { + pathName: route, animate: false, recommendation: { ...formState