diff --git a/packages/authentication/types/user.ts b/packages/authentication/types/user.ts index c8dff51f..27162d6f 100644 --- a/packages/authentication/types/user.ts +++ b/packages/authentication/types/user.ts @@ -1,3 +1,5 @@ +import { MinimalProfile } from '@baseapp-frontend/utils' + export interface User { id: number email: string @@ -5,19 +7,16 @@ export interface User { newEmail: string isNewEmailConfirmed: boolean referralCode: string - avatar: { - fullSize: string - small: string - } firstName: string lastName: string + profile: MinimalProfile phoneNumber: string preferredLanguage: string } export interface UserUpdateParams> { userId: TUser['id'] - data: Partial> & { + data: Partial> & { avatar?: File | string } } diff --git a/packages/components/.storybook/decorators/withProviders.tsx b/packages/components/.storybook/decorators/withProviders.tsx index 3f3227d4..36914f44 100644 --- a/packages/components/.storybook/decorators/withProviders.tsx +++ b/packages/components/.storybook/decorators/withProviders.tsx @@ -6,8 +6,8 @@ import { NotificationProvider } from '@baseapp-frontend/utils' import type { StoryContext, StoryFn } from '@storybook/react' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { Provider as JotaiProvider } from 'jotai' -import CurrentProfileProvider from '../../modules/profiles/context/CurrentProfileProvider' import '../../styles/tailwind/globals.css' import defaultTheme from '../__mocks__/theme' @@ -34,19 +34,19 @@ const withProviders = (Story: StoryFn, context: StoryContext) => { }, [mockData, resolveMostRecentOperation, queueOperationResolver, mockResolvers]) return ( - - - }> - - - + + + + }> + + - - - - - - + + + + + + ) } diff --git a/packages/components/modules/messages/MessageItem/index.tsx b/packages/components/modules/messages/MessageItem/index.tsx index 05d6fbcc..f487083f 100644 --- a/packages/components/modules/messages/MessageItem/index.tsx +++ b/packages/components/modules/messages/MessageItem/index.tsx @@ -9,7 +9,7 @@ import { MessageItemContainer } from './styled' import { MessageItemProps } from './types' const MessageItem: FC = ({ messageRef, isFirstGroupedMessage }) => { - const { profile: currentProfile } = useCurrentProfile() + const { currentProfile } = useCurrentProfile() const message = useFragment(MessageItemFragment, messageRef) const isOwnMessage = currentProfile?.id === message?.profile?.id diff --git a/packages/components/modules/messages/MessagesGroup/index.tsx b/packages/components/modules/messages/MessagesGroup/index.tsx index 74d23fe6..91c0dd04 100644 --- a/packages/components/modules/messages/MessagesGroup/index.tsx +++ b/packages/components/modules/messages/MessagesGroup/index.tsx @@ -27,7 +27,7 @@ const MessagesGroup: FC = ({ MessageItem = DefaultMessageItem, MessageItemProps = {}, }) => { - const { profile: currentProfile } = useCurrentProfile() + const { currentProfile } = useCurrentProfile() const renderDateOnTopOfMessagesGroup = useCallback( (index: number) => { diff --git a/packages/components/modules/messages/SendMessage/index.tsx b/packages/components/modules/messages/SendMessage/index.tsx index b9977214..56d7ddfe 100644 --- a/packages/components/modules/messages/SendMessage/index.tsx +++ b/packages/components/modules/messages/SendMessage/index.tsx @@ -75,7 +75,7 @@ let nextClientMutationId = 0 */ const SendMessage = forwardRef( ({ roomId, SocialInput = DefaultSocialInput, SocialInputProps = {} }, ref) => { - const { profile: currentProfile } = useCurrentProfile() + const { currentProfile } = useCurrentProfile() const form = useForm({ defaultValues: DEFAULT_SOCIAL_UPSERT_FORM_VALUES, diff --git a/packages/components/modules/navigations/Header/AccountMenu/AccountPopover/__storybook__/stories.tsx b/packages/components/modules/navigations/Header/AccountMenu/AccountPopover/__storybook__/stories.tsx index 220d34e1..7eb5958d 100644 --- a/packages/components/modules/navigations/Header/AccountMenu/AccountPopover/__storybook__/stories.tsx +++ b/packages/components/modules/navigations/Header/AccountMenu/AccountPopover/__storybook__/stories.tsx @@ -2,10 +2,11 @@ import { User, UserApi } from '@baseapp-frontend/authentication' import { createTestEnvironment } from '@baseapp-frontend/graphql' import { Meta, StoryObj } from '@storybook/react' +import Cookies from 'js-cookie' import AccountPopover from '..' import { withTokenSetup } from '../../../../../../.storybook/decorators' -import { CURRENT_PROFILE_STORAGE_KEY } from '../../../../../profiles/context/CurrentProfileProvider/constants' +import { PROFILE_KEY } from '../../../../../profiles/useCurrentProfile/constants' import { AccountPopoverProps } from '../types' import { mockResolvers } from './mockResolvers' @@ -31,7 +32,15 @@ export default { decorators: [ withTokenSetup, (Story, context) => { - localStorage.removeItem(CURRENT_PROFILE_STORAGE_KEY) + Cookies.set( + PROFILE_KEY, + JSON.stringify({ + id: '1234', + name: 'test', + image: null, + url: { path: 'path' }, + }), + ) const { queueOperationResolver } = context.parameters.relayMockEnvironment as ReturnType< typeof createTestEnvironment diff --git a/packages/components/modules/navigations/Header/AccountMenu/AccountPopover/__tests__/__utils__/withProviders/index.tsx b/packages/components/modules/navigations/Header/AccountMenu/AccountPopover/__tests__/__utils__/withProviders/index.tsx index 444dc69c..cde93c53 100644 --- a/packages/components/modules/navigations/Header/AccountMenu/AccountPopover/__tests__/__utils__/withProviders/index.tsx +++ b/packages/components/modules/navigations/Header/AccountMenu/AccountPopover/__tests__/__utils__/withProviders/index.tsx @@ -5,8 +5,8 @@ import { RelayTestProvider } from '@baseapp-frontend/graphql' import { NotificationProvider } from '@baseapp-frontend/utils' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { Provider as JotaiProvider } from 'jotai' -import CurrentProfileProvider from '../../../../../../../profiles/context/CurrentProfileProvider' import { AccountPopoverProps } from '../../../types' import defaultTheme from '../../__mocks__/theme' import { WithProvidersOptions } from './types' @@ -16,17 +16,17 @@ const queryClient = new QueryClient() const withProviders = (Component: FC) => ({ environment, ...props }: WithProvidersOptions & AccountPopoverProps) => ( - - - - - + + + + + - - - - - + + + + + ) export default withProviders diff --git a/packages/components/modules/navigations/Header/AccountMenu/AccountPopover/index.tsx b/packages/components/modules/navigations/Header/AccountMenu/AccountPopover/index.tsx index 1fcda6bd..71610a01 100644 --- a/packages/components/modules/navigations/Header/AccountMenu/AccountPopover/index.tsx +++ b/packages/components/modules/navigations/Header/AccountMenu/AccountPopover/index.tsx @@ -2,9 +2,7 @@ import { FC, useEffect, useState } from 'react' -import { User as BaseUser, useJWTUser } from '@baseapp-frontend/authentication' import { ClickableAvatar, Popover, usePopover } from '@baseapp-frontend/design-system' -import { JWTContent } from '@baseapp-frontend/utils' import Divider from '@mui/material/Divider' @@ -35,8 +33,7 @@ const AccountPopover: FC = ({ AddProfileMenuItemProps = {}, LogoutItemProps = {}, }) => { - const { user } = useJWTUser() - const { profile } = useCurrentProfile() + const profile = useCurrentProfile({ noSSR: false }).currentProfile const popover = usePopover() const [openProfilesList, setOpenProfilesList] = useState(false) @@ -69,7 +66,7 @@ const AccountPopover: FC = ({ <> { - const { profile } = useCurrentProfile() + const profile = useCurrentProfile().currentProfile if (!profile) return null @@ -16,7 +16,7 @@ const CurrentProfile: FC = () => { @@ -25,9 +25,9 @@ const CurrentProfile: FC = () => { {profile.name} - {profile.urlPath?.path && ( + {profile.urlPath && ( - {profile.urlPath?.path} + {profile.urlPath} )} diff --git a/packages/components/modules/profiles/ProfilePopover/ProfilesList/ProfileMenuItem/types.ts b/packages/components/modules/profiles/ProfilePopover/ProfilesList/ProfileMenuItem/types.ts index 1b595028..685aeb1b 100644 --- a/packages/components/modules/profiles/ProfilePopover/ProfilesList/ProfileMenuItem/types.ts +++ b/packages/components/modules/profiles/ProfilePopover/ProfilesList/ProfileMenuItem/types.ts @@ -1,3 +1,4 @@ +import type { MinimalProfile } from '@baseapp-frontend/authentication' import type { AvatarWithPlaceholderProps } from '@baseapp-frontend/design-system' import { MenuItemProps } from '@mui/material' @@ -10,7 +11,7 @@ import type { export interface ProfileMenuItemProps { profileRef: ProfileItemFragment$key onProfileChange: (newProfile: ProfileItemFragment$data) => void - currentProfile?: ProfileItemFragment$data + currentProfile?: MinimalProfile | null avatarProps?: AvatarWithPlaceholderProps width?: number height?: number diff --git a/packages/components/modules/profiles/ProfilePopover/ProfilesList/index.tsx b/packages/components/modules/profiles/ProfilePopover/ProfilesList/index.tsx index 4e45abe2..1b71e7e7 100644 --- a/packages/components/modules/profiles/ProfilePopover/ProfilesList/index.tsx +++ b/packages/components/modules/profiles/ProfilePopover/ProfilesList/index.tsx @@ -10,8 +10,8 @@ import { useLazyLoadQuery } from 'react-relay' import { ProfileItemFragment$data } from '../../../../__generated__/ProfileItemFragment.graphql' import { ProfilesListQuery as ProfilesListQueryType } from '../../../../__generated__/ProfilesListQuery.graphql' -import useCurrentProfile from '../../context/useCurrentProfile' import { ProfilesListQuery } from '../../graphql/queries/ProfilesList' +import useCurrentProfile, { getMinimalProfile } from '../../useCurrentProfile' import LoadingState from './LoadingState' import ProfileMenuItem from './ProfileMenuItem' import { CancelMenuItem, StyledList } from './styled' @@ -20,11 +20,11 @@ import { ProfilesListProps } from './types' const ProfilesList: FC = ({ handleCloseSubmenu, MenuItemProps }) => { const { me } = useLazyLoadQuery(ProfilesListQuery, {}) const { sendToast } = useNotification() - const { profile: currentProfile, setCurrentProfile } = useCurrentProfile() + const { currentProfile, setCurrentProfile } = useCurrentProfile() const handleProfileChange = (profile: ProfileItemFragment$data) => { if (currentProfile?.id !== profile.id) { - setCurrentProfile({ profile }) + setCurrentProfile(getMinimalProfile(profile)) sendToast(`Switched to ${profile.name}`) handleCloseSubmenu() } diff --git a/packages/components/modules/profiles/context/CurrentProfileProvider/__tests__/CurrentProfileProvider.test.tsx b/packages/components/modules/profiles/context/CurrentProfileProvider/__tests__/CurrentProfileProvider.test.tsx deleted file mode 100644 index 68d779e8..00000000 --- a/packages/components/modules/profiles/context/CurrentProfileProvider/__tests__/CurrentProfileProvider.test.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import { createTestEnvironment } from '@baseapp-frontend/graphql' -import { act, render, waitFor } from '@baseapp-frontend/test' -import { LOGOUT_EVENT, eventEmitter } from '@baseapp-frontend/utils' - -import { ProfileItemFragment$data } from '../../../../../__generated__/ProfileItemFragment.graphql' -import { CURRENT_PROFILE_STORAGE_KEY } from '../constants' -import { CurrentProfileState } from '../types' -import { mockUserProfileFactory } from './__mock__/profiles' -import { userMockData, userMockData2 } from './__mock__/user' -import TestComponentWithProviders from './__utils__/TestComponentWithProvider' - -jest.mock('@baseapp-frontend/authentication', () => ({ - useJWTUser: jest.fn(), -})) - -describe('CurrentProfileProvider', () => { - const { useJWTUser } = require('@baseapp-frontend/authentication') - - beforeEach(() => { - localStorage.clear() - jest.clearAllMocks() - - useJWTUser.mockReturnValue({ - user: userMockData, - }) - }) - - const loadPreStoredData = (customUserMockData: any, customUserProfileMockData: any) => { - const storedCurrentProfile: CurrentProfileState = { - profile: customUserProfileMockData.data.me.profile as ProfileItemFragment$data, - userId: customUserMockData.id, - } - - localStorage.setItem( - CURRENT_PROFILE_STORAGE_KEY, - JSON.stringify({ state: storedCurrentProfile, version: 0 }), - ) - } - - it('should get the user from local storage and not trigger the user profile fetch', async () => { - const { environment } = createTestEnvironment() - - const newUserProfileMockData = mockUserProfileFactory('user-profile-1') - loadPreStoredData(userMockData, newUserProfileMockData) - - const { getByText } = render() - - await waitFor(() => { - expect(getByText(newUserProfileMockData.data.me.profile.id)).toBeInTheDocument() - }) - }) - - it("should not use another user's current profile as the current profile", async () => { - const { environment, resolveMostRecentOperation } = createTestEnvironment() - - const diffUserProfileMockData = mockUserProfileFactory('user-profile-2') - loadPreStoredData(userMockData2, diffUserProfileMockData) - - const newUserProfileMockData = mockUserProfileFactory('user-profile-1') - - const { getByText } = render() - - act(() => { - resolveMostRecentOperation({ - data: newUserProfileMockData, - }) - }) - - await waitFor(() => { - expect(getByText(newUserProfileMockData.data.me.profile.id)).toBeInTheDocument() - }) - }) - - it('should erase current profile when user logs out', async () => { - const { environment } = createTestEnvironment() - - const newUserProfileMockData = mockUserProfileFactory('user-profile-2') - loadPreStoredData(userMockData, newUserProfileMockData) - - render() - - act(() => { - eventEmitter.emit(LOGOUT_EVENT) - }) - - await waitFor(() => { - const storedData = JSON.parse(localStorage.getItem(CURRENT_PROFILE_STORAGE_KEY) || '{}') - expect(storedData.state).toEqual({}) - - expect(document.getElementById('profile-id')).toBeNull() - }) - }) - - it('should keep the current profile empty when it fails to fetch the profile', async () => { - const { environment, rejectMostRecentOperation } = createTestEnvironment() - - render() - - act(() => { - rejectMostRecentOperation('Profile not found') - }) - - await waitFor(() => { - const storedData = JSON.parse(localStorage.getItem(CURRENT_PROFILE_STORAGE_KEY) || '{}') - expect(storedData.state).toEqual({}) - - expect(document.getElementById('profile-id')).toBeNull() - }) - }) -}) diff --git a/packages/components/modules/profiles/context/CurrentProfileProvider/constants.ts b/packages/components/modules/profiles/context/CurrentProfileProvider/constants.ts deleted file mode 100644 index aa33ad3e..00000000 --- a/packages/components/modules/profiles/context/CurrentProfileProvider/constants.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { CurrentProfileState } from './types' - -export const CURRENT_PROFILE_STORAGE_KEY = 'currentProfile' -export const INITIAL_CURRENT_PROFILE_STATE: CurrentProfileState = { - profile: undefined, - userId: undefined, -} diff --git a/packages/components/modules/profiles/context/CurrentProfileProvider/index.tsx b/packages/components/modules/profiles/context/CurrentProfileProvider/index.tsx deleted file mode 100644 index 933153b6..00000000 --- a/packages/components/modules/profiles/context/CurrentProfileProvider/index.tsx +++ /dev/null @@ -1,105 +0,0 @@ -'use client' - -import { FC, PropsWithChildren, createContext, useCallback, useEffect, useRef } from 'react' - -import { User, useJWTUser } from '@baseapp-frontend/authentication' -import { JWTContent, LOGOUT_EVENT, eventEmitter } from '@baseapp-frontend/utils' - -import { Environment, fetchQuery, readInlineData, useRelayEnvironment } from 'react-relay' -import { StoreApi, create } from 'zustand' -import { persist } from 'zustand/middleware' - -import { ProfileItemFragment$key } from '../../../../__generated__/ProfileItemFragment.graphql' -import { UserProfileQuery as UserProfileQueryType } from '../../../../__generated__/UserProfileQuery.graphql' -import { ProfileItemFragment } from '../../graphql/queries/ProfileItem' -import { UserProfileQuery } from '../../graphql/queries/UserProfile' -import { CURRENT_PROFILE_STORAGE_KEY, INITIAL_CURRENT_PROFILE_STATE } from './constants' -import { UseCurrentProfile } from './types' - -export const CurrentProfileContext = createContext | null>(null) - -const fetchUserProfile = async (environment: Environment) => { - const data = await fetchQuery( - environment, - UserProfileQuery, - {}, - { fetchPolicy: 'store-or-network' }, - ).toPromise() - - const userProfile = data?.me?.profile - ? readInlineData(ProfileItemFragment, data.me.profile) - : null - - return userProfile -} - -const CurrentProfileProvider: FC = ({ children }) => { - const { user } = useJWTUser() - const environment = useRelayEnvironment() - const storeRef = useRef>() - - if (!storeRef.current) { - storeRef.current = create( - persist( - (set) => ({ - ...INITIAL_CURRENT_PROFILE_STATE, - setCurrentProfile: set, - }), - { - name: CURRENT_PROFILE_STORAGE_KEY, - }, - ), - ) - } - - const fetchAndStoreUserProfile = useCallback(() => { - const shouldFetchProfile = Boolean(storeRef.current && !storeRef.current.getState().profile) - if (shouldFetchProfile && environment && user?.id) { - fetchUserProfile(environment) - .then((userProfile) => { - if (userProfile) { - storeRef.current?.setState({ profile: userProfile, userId: user.id }) - } - }) - // If the user profile request fails, the current profile state will remain empty. - .catch(() => {}) - } - }, [environment, user]) - - const validateStoredState = useCallback(() => { - if (!storeRef.current) { - return - } - if (user?.id) { - if (storeRef.current.getState().userId !== user.id) { - storeRef.current.setState({ ...INITIAL_CURRENT_PROFILE_STATE }) - fetchAndStoreUserProfile() - } - } else { - storeRef.current.setState({ ...INITIAL_CURRENT_PROFILE_STATE }) - } - }, [fetchAndStoreUserProfile, user]) - - const logoutListener = () => { - storeRef.current?.setState({ ...INITIAL_CURRENT_PROFILE_STATE }) - } - - useEffect(() => fetchAndStoreUserProfile(), [fetchAndStoreUserProfile]) - - useEffect(() => validateStoredState(), [validateStoredState]) - - useEffect(() => { - eventEmitter.on(LOGOUT_EVENT, logoutListener) - return () => { - eventEmitter.off(LOGOUT_EVENT, logoutListener) - } - }, []) - - return ( - - {children} - - ) -} - -export default CurrentProfileProvider diff --git a/packages/components/modules/profiles/context/CurrentProfileProvider/types.ts b/packages/components/modules/profiles/context/CurrentProfileProvider/types.ts deleted file mode 100644 index 4ff5e0b3..00000000 --- a/packages/components/modules/profiles/context/CurrentProfileProvider/types.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { ProfileItemFragment$data } from '../../../../__generated__/ProfileItemFragment.graphql' - -export type CurrentProfileState = { - profile?: ProfileItemFragment$data - userId?: number -} - -type CurrentProfileFunctions = { - setCurrentProfile: (newCurrentProfile: Partial) => void -} - -export type UseCurrentProfile = CurrentProfileState & CurrentProfileFunctions diff --git a/packages/components/modules/profiles/context/useCurrentProfile/index.tsx b/packages/components/modules/profiles/context/useCurrentProfile/index.tsx deleted file mode 100644 index 98cd2a16..00000000 --- a/packages/components/modules/profiles/context/useCurrentProfile/index.tsx +++ /dev/null @@ -1,19 +0,0 @@ -'use client' - -import { useContext } from 'react' - -import { useStore } from 'zustand' - -import { CurrentProfileContext } from '../CurrentProfileProvider' - -const useCurrentProfile = () => { - const store = useContext(CurrentProfileContext) - - if (!store) { - throw new Error('Missing CurrentProfileProvider') - } - - return useStore(store, (state) => state) -} - -export default useCurrentProfile diff --git a/packages/components/modules/profiles/index.ts b/packages/components/modules/profiles/index.ts index 697b3eef..e261d6e5 100644 --- a/packages/components/modules/profiles/index.ts +++ b/packages/components/modules/profiles/index.ts @@ -1,5 +1,3 @@ -// Contexts & Providers -export { default as useCurrentProfile } from './context/useCurrentProfile' +export { default as useCurrentProfile, getMinimalProfile } from './useCurrentProfile' -// Components export * from './ProfilePopover' diff --git a/packages/components/modules/profiles/useCurrentProfile/__tests__/CurrentProfileProvider.test.tsx b/packages/components/modules/profiles/useCurrentProfile/__tests__/CurrentProfileProvider.test.tsx new file mode 100644 index 00000000..1ce1a80c --- /dev/null +++ b/packages/components/modules/profiles/useCurrentProfile/__tests__/CurrentProfileProvider.test.tsx @@ -0,0 +1,65 @@ +import { createTestEnvironment } from '@baseapp-frontend/graphql' +import { act, render, waitFor } from '@baseapp-frontend/test' +import { MinimalProfile } from '@baseapp-frontend/utils' +import { LOGOUT_EVENT, eventEmitter, getCookie, setCookie } from '@baseapp-frontend/utils' + +import { CURRENT_PROFILE_KEY } from '../constants' +import { mockUserProfileFactory } from './__mock__/profiles' +import { userMockData, userMockData2 } from './__mock__/user' + +jest.mock('@baseapp-frontend/authentication', () => ({ + useJWTUser: jest.fn(), +})) + +describe('CurrentProfileProvider', () => { + const { useJWTUser } = require('@baseapp-frontend/authentication') + + beforeEach(() => { + localStorage.clear() + jest.clearAllMocks() + + useJWTUser.mockReturnValue({ + user: userMockData, + }) + }) + + const loadPreStoredData = (customUserProfileMockData: any) => { + const profile = customUserProfileMockData.data.me.profile as MinimalProfile + + setCookie(CURRENT_PROFILE_KEY, profile, { stringfyValue: true }) + } + + it('should get the user from local storage and not trigger the user profile fetch', async () => { + const { environment } = createTestEnvironment() + + const newUserProfileMockData = mockUserProfileFactory('user-profile-1') + loadPreStoredData(newUserProfileMockData) + + const TestComponentWithProviders = require('./__utils__/TestComponentWithProvider').default + const { getByText } = render() + + await waitFor(() => { + expect(getByText(newUserProfileMockData.data.me.profile.id)).toBeInTheDocument() + }) + }) + + it('should erase current profile when user logs out', async () => { + const { environment } = createTestEnvironment() + + const newUserProfileMockData = mockUserProfileFactory('user-profile-1') + loadPreStoredData(newUserProfileMockData) + + const TestComponentWithProviders = require('./__utils__/TestComponentWithProvider').default + render() + + act(() => { + eventEmitter.emit(LOGOUT_EVENT) + }) + + await waitFor(() => { + expect(getCookie(CURRENT_PROFILE_KEY, { parseJSON: true })).toEqual(undefined) + + expect(document.getElementById('profile-id')).toBeNull() + }) + }) +}) diff --git a/packages/components/modules/profiles/context/CurrentProfileProvider/__tests__/__mock__/profiles.ts b/packages/components/modules/profiles/useCurrentProfile/__tests__/__mock__/profiles.ts similarity index 100% rename from packages/components/modules/profiles/context/CurrentProfileProvider/__tests__/__mock__/profiles.ts rename to packages/components/modules/profiles/useCurrentProfile/__tests__/__mock__/profiles.ts diff --git a/packages/components/modules/profiles/context/CurrentProfileProvider/__tests__/__mock__/user.ts b/packages/components/modules/profiles/useCurrentProfile/__tests__/__mock__/user.ts similarity index 100% rename from packages/components/modules/profiles/context/CurrentProfileProvider/__tests__/__mock__/user.ts rename to packages/components/modules/profiles/useCurrentProfile/__tests__/__mock__/user.ts diff --git a/packages/components/modules/profiles/context/CurrentProfileProvider/__tests__/__utils__/TestComponent/index.tsx b/packages/components/modules/profiles/useCurrentProfile/__tests__/__utils__/TestComponent/index.tsx similarity index 63% rename from packages/components/modules/profiles/context/CurrentProfileProvider/__tests__/__utils__/TestComponent/index.tsx rename to packages/components/modules/profiles/useCurrentProfile/__tests__/__utils__/TestComponent/index.tsx index fa78e293..7f36299d 100644 --- a/packages/components/modules/profiles/context/CurrentProfileProvider/__tests__/__utils__/TestComponent/index.tsx +++ b/packages/components/modules/profiles/useCurrentProfile/__tests__/__utils__/TestComponent/index.tsx @@ -1,7 +1,7 @@ -import useCurrentProfile from '../../../../useCurrentProfile' +import useCurrentProfile from '../../..' const TestComponent = () => { - const { profile } = useCurrentProfile() + const profile = useCurrentProfile().currentProfile if (!profile) { return null diff --git a/packages/components/modules/profiles/context/CurrentProfileProvider/__tests__/__utils__/TestComponentWithProvider/index.tsx b/packages/components/modules/profiles/useCurrentProfile/__tests__/__utils__/TestComponentWithProvider/index.tsx similarity index 59% rename from packages/components/modules/profiles/context/CurrentProfileProvider/__tests__/__utils__/TestComponentWithProvider/index.tsx rename to packages/components/modules/profiles/useCurrentProfile/__tests__/__utils__/TestComponentWithProvider/index.tsx index ef267191..cbb59b7c 100644 --- a/packages/components/modules/profiles/context/CurrentProfileProvider/__tests__/__utils__/TestComponentWithProvider/index.tsx +++ b/packages/components/modules/profiles/useCurrentProfile/__tests__/__utils__/TestComponentWithProvider/index.tsx @@ -1,15 +1,15 @@ +import { Provider as JotaiProvider } from 'jotai' import { Environment, RelayEnvironmentProvider } from 'react-relay' -import CurrentProfileProvider from '../../..' import TestComponent from '../TestComponent' const TestComponentWithProviders = ({ environment }: { environment: Environment }) => { return ( - - + + - - + + ) } diff --git a/packages/components/modules/profiles/useCurrentProfile/constants.ts b/packages/components/modules/profiles/useCurrentProfile/constants.ts new file mode 100644 index 00000000..72d8d735 --- /dev/null +++ b/packages/components/modules/profiles/useCurrentProfile/constants.ts @@ -0,0 +1 @@ +export const CURRENT_PROFILE_KEY = 'CurrentProfile' diff --git a/packages/components/modules/profiles/useCurrentProfile/index.ts b/packages/components/modules/profiles/useCurrentProfile/index.ts new file mode 100644 index 00000000..7269c726 --- /dev/null +++ b/packages/components/modules/profiles/useCurrentProfile/index.ts @@ -0,0 +1,98 @@ +'use client' + +import { useEffect } from 'react' + +import { + LOGOUT_EVENT, + MinimalProfile, + ServerSideRenderingOption, + eventEmitter, + getCookie, + removeCookie, + setCookie, +} from '@baseapp-frontend/utils' + +import { atom, useAtom } from 'jotai' + +import { ProfileItemFragment$data } from '../../../__generated__/ProfileItemFragment.graphql' +import { CURRENT_PROFILE_KEY } from './constants' + +export const getMinimalProfile = function ( + profile: T, +): MinimalProfile { + return { + id: profile.id, + name: profile.name ?? null, + image: profile.image?.url ?? null, + urlPath: profile.urlPath?.path ?? null, + } +} + +export const getProfileFromCookie = ({ noSSR = true }: ServerSideRenderingOption = {}) => { + const settings = + getCookie(CURRENT_PROFILE_KEY, { noSSR, parseJSON: true }) ?? null + + return settings +} + +const initialProfile = getProfileFromCookie() + +const profileAtom = atom(initialProfile) + +/** + * By using `useCurrentProfile` with the `noSSR` option set to `false`, causes Next.js to dynamically render the affected pages, instead of statically rendering them. + */ +const useCurrentProfile = ({ noSSR = true }: ServerSideRenderingOption = {}) => { + const [currentProfile, setProfile] = useAtom(profileAtom) + const isSSR = typeof window === typeof undefined + + const setCurrentProfile = (newProfile: MinimalProfile) => { + setProfile(() => { + try { + setCookie(CURRENT_PROFILE_KEY, newProfile, { stringfyValue: true }) + } catch (error) { + console.log(error) + } + return newProfile + }) + } + + const updateProfileIfActive = (newProfile: MinimalProfile) => { + if (currentProfile?.id === newProfile.id) { + setCurrentProfile(newProfile) + } + } + + const removeCurrentProfile = () => { + setProfile(() => { + try { + removeCookie(CURRENT_PROFILE_KEY) + } catch (error) { + console.log(error) + } + return null + }) + } + + useEffect(() => { + eventEmitter.on(LOGOUT_EVENT, removeCurrentProfile) + return () => { + eventEmitter.off(LOGOUT_EVENT, removeCurrentProfile) + } + }, []) + + if (isSSR) { + return { + currentProfile: getProfileFromCookie({ noSSR }), + setCurrentProfile, + updateProfileIfActive, + } + } + return { + currentProfile, + setCurrentProfile, + updateProfileIfActive, + } +} + +export default useCurrentProfile diff --git a/packages/components/package.json b/packages/components/package.json index 5d6bc9b1..5aa2b828 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -29,6 +29,7 @@ "@tanstack/react-query": "catalog:", "framer-motion": "^11.5.4", "graphql": "catalog:graphql", + "jotai": "catalog:", "js-cookie": "catalog:", "luxon": "catalog:", "next": "catalog:", diff --git a/packages/utils/index.ts b/packages/utils/index.ts index b60cfc47..47771756 100644 --- a/packages/utils/index.ts +++ b/packages/utils/index.ts @@ -31,5 +31,6 @@ export type * from './types/date' export type * from './types/django' export type * from './types/form' export type * from './types/jwt' +export type * from './types/profile' export type * from './types/server' export type * from './types/typescript' diff --git a/packages/utils/types/profile.ts b/packages/utils/types/profile.ts new file mode 100644 index 00000000..b893f092 --- /dev/null +++ b/packages/utils/types/profile.ts @@ -0,0 +1,6 @@ +export type MinimalProfile = { + id: string + name: string | null + image: string | null + urlPath: string | null +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9af19176..ea8b5d2e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -490,6 +490,9 @@ importers: graphql: specifier: catalog:graphql version: 16.9.0 + jotai: + specifier: 'catalog:' + version: 2.10.1(@types/react@18.3.11)(react@18.3.1) js-cookie: specifier: 'catalog:' version: 3.0.5 @@ -547,7 +550,7 @@ importers: version: 1.9.0(react@18.3.1) '@cypress/webpack-dev-server': specifier: catalog:test - version: 3.11.0(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + version: 3.11.0(webpack-cli@5.1.4)(webpack@5.95.0) '@faker-js/faker': specifier: catalog:test version: 9.0.3 @@ -565,16 +568,16 @@ importers: version: 8.3.6(react@18.3.1)(storybook@8.3.6) '@storybook/addon-styling-webpack': specifier: catalog:storybook - version: 1.0.0(storybook@8.3.6)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + version: 1.0.0(storybook@8.3.6)(webpack@5.95.0) '@storybook/addon-webpack5-compiler-babel': specifier: catalog:storybook - version: 3.0.3(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + version: 3.0.3(webpack@5.95.0) '@storybook/blocks': specifier: catalog:storybook version: 8.3.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.6) '@storybook/react-webpack5': specifier: catalog:storybook - version: 8.3.6(@storybook/test@8.3.6(storybook@8.3.6))(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.6)(typescript@5.6.3)(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0)) + version: 8.3.6(@storybook/test@8.3.6(storybook@8.3.6))(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.6)(typescript@5.6.3)(webpack-cli@5.1.4) '@storybook/test': specifier: catalog:storybook version: 8.3.6(storybook@8.3.6) @@ -622,13 +625,13 @@ importers: version: 29.7.0(@babel/core@7.25.8) babel-loader: specifier: catalog:storybook - version: 9.2.1(@babel/core@7.25.8)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + version: 9.2.1(@babel/core@7.25.8)(webpack@5.95.0) babel-plugin-relay: specifier: catalog:graphql version: 17.0.0 css-loader: specifier: catalog:storybook - version: 7.1.2(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + version: 7.1.2(webpack@5.95.0) cypress: specifier: catalog:test version: 13.15.0 @@ -652,7 +655,7 @@ importers: version: 2.1.2 html-webpack-plugin: specifier: catalog:storybook - version: 5.6.2(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + version: 5.6.2(webpack@5.95.0) jest: specifier: catalog:test version: 29.7.0(@types/node@22.7.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.36(@swc/helpers@0.5.13))(@types/node@22.7.7)(typescript@5.6.3)) @@ -670,7 +673,7 @@ importers: version: 8.4.47 postcss-loader: specifier: catalog:storybook - version: 8.1.1(postcss@8.4.47)(typescript@5.6.3)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + version: 8.1.1(postcss@8.4.47)(typescript@5.6.3)(webpack@5.95.0) relay-compiler: specifier: catalog:graphql version: 16.2.0 @@ -682,7 +685,7 @@ importers: version: 8.3.6 style-loader: specifier: catalog:storybook - version: 4.0.0(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + version: 4.0.0(webpack@5.95.0) tailwindcss: specifier: catalog:tailwind version: 3.4.14(ts-node@10.9.2(@swc/core@1.7.36(@swc/helpers@0.5.13))(@types/node@22.7.7)(typescript@5.6.3)) @@ -730,10 +733,10 @@ importers: version: 8.57.1 eslint-config-airbnb: specifier: catalog:lint - version: 19.0.4(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint-plugin-jsx-a11y@6.10.1(eslint@8.57.1))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.1))(eslint-plugin-react@7.37.1(eslint@8.57.1))(eslint@8.57.1) + version: 19.0.4(eslint-plugin-import@2.31.0)(eslint-plugin-jsx-a11y@6.10.1(eslint@8.57.1))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.1))(eslint-plugin-react@7.37.1(eslint@8.57.1))(eslint@8.57.1) eslint-config-airbnb-typescript: specifier: catalog:lint - version: 17.1.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3))(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1) + version: 17.1.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3))(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1) eslint-config-next: specifier: catalog:lint version: 13.5.7(eslint@8.57.1)(typescript@5.6.3) @@ -742,7 +745,7 @@ importers: version: 8.10.0(eslint@8.57.1) eslint-plugin-import: specifier: catalog:lint - version: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + version: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) eslint-plugin-jsx-a11y: specifier: catalog:lint version: 6.10.1(eslint@8.57.1) @@ -11120,17 +11123,17 @@ snapshots: tunnel-agent: 0.6.0 uuid: 8.3.2 - '@cypress/webpack-dev-server@3.11.0(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4))': + '@cypress/webpack-dev-server@3.11.0(webpack-cli@5.1.4)(webpack@5.95.0)': dependencies: find-up: 6.3.0 fs-extra: 9.1.0 - html-webpack-plugin-4: html-webpack-plugin@4.5.2(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) - html-webpack-plugin-5: html-webpack-plugin@5.6.2(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + html-webpack-plugin-4: html-webpack-plugin@4.5.2(webpack@5.95.0) + html-webpack-plugin-5: html-webpack-plugin@5.6.2(webpack@5.95.0) local-pkg: 0.4.1 semver: 7.6.3 - speed-measure-webpack-plugin: 1.4.2(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + speed-measure-webpack-plugin: 1.4.2(webpack@5.95.0) tslib: 2.8.0 - webpack-dev-server: 4.15.2(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + webpack-dev-server: 4.15.2(webpack-cli@5.1.4)(webpack@5.95.0) webpack-merge: 5.10.0 transitivePeerDependencies: - '@rspack/core' @@ -13239,17 +13242,17 @@ snapshots: storybook: 8.3.6 ts-dedent: 2.2.0 - '@storybook/addon-styling-webpack@1.0.0(storybook@8.3.6)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4))': + '@storybook/addon-styling-webpack@1.0.0(storybook@8.3.6)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)))': dependencies: '@storybook/node-logger': 8.3.6(storybook@8.3.6) - webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) + webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) transitivePeerDependencies: - storybook - '@storybook/addon-styling-webpack@1.0.0(storybook@8.3.6)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)))': + '@storybook/addon-styling-webpack@1.0.0(storybook@8.3.6)(webpack@5.95.0)': dependencies: '@storybook/node-logger': 8.3.6(storybook@8.3.6) - webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) + webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) transitivePeerDependencies: - storybook @@ -13262,18 +13265,18 @@ snapshots: memoizerific: 1.11.3 storybook: 8.3.6 - '@storybook/addon-webpack5-compiler-babel@3.0.3(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4))': + '@storybook/addon-webpack5-compiler-babel@3.0.3(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)))': dependencies: '@babel/core': 7.25.8 - babel-loader: 9.2.1(@babel/core@7.25.8)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + babel-loader: 9.2.1(@babel/core@7.25.8)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))) transitivePeerDependencies: - supports-color - webpack - '@storybook/addon-webpack5-compiler-babel@3.0.3(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)))': + '@storybook/addon-webpack5-compiler-babel@3.0.3(webpack@5.95.0)': dependencies: '@babel/core': 7.25.8 - babel-loader: 9.2.1(@babel/core@7.25.8)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))) + babel-loader: 9.2.1(@babel/core@7.25.8)(webpack@5.95.0) transitivePeerDependencies: - supports-color - webpack @@ -13299,7 +13302,7 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@storybook/builder-webpack5@8.3.6(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(storybook@8.3.6)(typescript@5.6.3)(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0))': + '@storybook/builder-webpack5@8.3.6(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(storybook@8.3.6)(typescript@5.6.3)(webpack-cli@5.1.4)': dependencies: '@storybook/core-webpack': 8.3.6(storybook@8.3.6) '@types/node': 22.7.7 @@ -13308,25 +13311,25 @@ snapshots: case-sensitive-paths-webpack-plugin: 2.4.0 cjs-module-lexer: 1.4.1 constants-browserify: 1.0.0 - css-loader: 6.11.0(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + css-loader: 6.11.0(webpack@5.95.0) es-module-lexer: 1.5.4 express: 4.21.1 - fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.6.3)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.6.3)(webpack@5.95.0) fs-extra: 11.2.0 - html-webpack-plugin: 5.6.2(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + html-webpack-plugin: 5.6.2(webpack@5.95.0) magic-string: 0.30.12 path-browserify: 1.0.1 process: 0.11.10 semver: 7.6.3 storybook: 8.3.6 - style-loader: 3.3.4(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) - terser-webpack-plugin: 5.3.10(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + style-loader: 3.3.4(webpack@5.95.0) + terser-webpack-plugin: 5.3.10(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack@5.95.0) ts-dedent: 2.2.0 url: 0.11.4 util: 0.12.5 util-deprecate: 1.0.2 webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) - webpack-dev-middleware: 6.1.3(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + webpack-dev-middleware: 6.1.3(webpack@5.95.0) webpack-hot-middleware: 2.26.1 webpack-virtual-modules: 0.6.2 optionalDependencies: @@ -13446,11 +13449,11 @@ snapshots: dependencies: storybook: 8.3.6 - '@storybook/preset-react-webpack@8.3.6(@storybook/test@8.3.6(storybook@8.3.6))(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.6)(typescript@5.6.3)(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0))': + '@storybook/preset-react-webpack@8.3.6(@storybook/test@8.3.6(storybook@8.3.6))(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.6)(typescript@5.6.3)(webpack-cli@5.1.4)': dependencies: '@storybook/core-webpack': 8.3.6(storybook@8.3.6) '@storybook/react': 8.3.6(@storybook/test@8.3.6(storybook@8.3.6))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.6)(typescript@5.6.3) - '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.6.3)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.6.3)(webpack@5.95.0) '@types/node': 22.7.7 '@types/semver': 7.5.8 find-up: 5.0.0 @@ -13506,7 +13509,7 @@ snapshots: dependencies: storybook: 8.3.6 - '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.6.3)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4))': + '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.6.3)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)))': dependencies: debug: 4.3.7(supports-color@8.1.1) endent: 2.1.0 @@ -13516,11 +13519,11 @@ snapshots: react-docgen-typescript: 2.2.2(typescript@5.6.3) tslib: 2.8.0 typescript: 5.6.3 - webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) + webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) transitivePeerDependencies: - supports-color - '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.6.3)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)))': + '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.6.3)(webpack@5.95.0)': dependencies: debug: 4.3.7(supports-color@8.1.1) endent: 2.1.0 @@ -13530,7 +13533,7 @@ snapshots: react-docgen-typescript: 2.2.2(typescript@5.6.3) tslib: 2.8.0 typescript: 5.6.3 - webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) + webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) transitivePeerDependencies: - supports-color @@ -13540,10 +13543,10 @@ snapshots: react-dom: 18.3.1(react@18.3.1) storybook: 8.3.6 - '@storybook/react-webpack5@8.3.6(@storybook/test@8.3.6(storybook@8.3.6))(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.6)(typescript@5.6.3)(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0))': + '@storybook/react-webpack5@8.3.6(@storybook/test@8.3.6(storybook@8.3.6))(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.6)(typescript@5.6.3)(webpack-cli@5.1.4)': dependencies: - '@storybook/builder-webpack5': 8.3.6(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(storybook@8.3.6)(typescript@5.6.3)(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0)) - '@storybook/preset-react-webpack': 8.3.6(@storybook/test@8.3.6(storybook@8.3.6))(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.6)(typescript@5.6.3)(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0)) + '@storybook/builder-webpack5': 8.3.6(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(storybook@8.3.6)(typescript@5.6.3)(webpack-cli@5.1.4) + '@storybook/preset-react-webpack': 8.3.6(@storybook/test@8.3.6(storybook@8.3.6))(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.6)(typescript@5.6.3)(webpack-cli@5.1.4) '@storybook/react': 8.3.6(@storybook/test@8.3.6(storybook@8.3.6))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.6)(typescript@5.6.3) '@types/node': 22.7.7 react: 18.3.1 @@ -14263,17 +14266,17 @@ snapshots: '@webassemblyjs/ast': 1.12.1 '@xtuc/long': 4.2.2 - '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4))': + '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4)(webpack@5.95.0)': dependencies: webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0) - '@webpack-cli/info@2.0.2(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4))': + '@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.95.0)': dependencies: webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0) - '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0))(webpack-dev-server@5.1.0(webpack-cli@5.1.4)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4))': + '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack-dev-server@5.1.0)(webpack@5.95.0)': dependencies: webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0) @@ -14585,19 +14588,19 @@ snapshots: transitivePeerDependencies: - supports-color - babel-loader@9.2.1(@babel/core@7.25.8)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)): + babel-loader@9.2.1(@babel/core@7.25.8)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))): dependencies: '@babel/core': 7.25.8 find-cache-dir: 4.0.0 schema-utils: 4.2.0 - webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) + webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) - babel-loader@9.2.1(@babel/core@7.25.8)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))): + babel-loader@9.2.1(@babel/core@7.25.8)(webpack@5.95.0): dependencies: '@babel/core': 7.25.8 find-cache-dir: 4.0.0 schema-utils: 4.2.0 - webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) + webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) babel-plugin-istanbul@6.1.1: dependencies: @@ -15231,7 +15234,7 @@ snapshots: crypto-random-string@2.0.0: {} - css-loader@6.11.0(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)): + css-loader@6.11.0(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))): dependencies: icss-utils: 5.1.0(postcss@8.4.47) postcss: 8.4.47 @@ -15242,9 +15245,9 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.6.3 optionalDependencies: - webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) + webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) - css-loader@6.11.0(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))): + css-loader@6.11.0(webpack@5.95.0): dependencies: icss-utils: 5.1.0(postcss@8.4.47) postcss: 8.4.47 @@ -15255,9 +15258,9 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.6.3 optionalDependencies: - webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) + webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) - css-loader@7.1.2(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)): + css-loader@7.1.2(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))): dependencies: icss-utils: 5.1.0(postcss@8.4.47) postcss: 8.4.47 @@ -15268,9 +15271,9 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.6.3 optionalDependencies: - webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) + webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) - css-loader@7.1.2(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))): + css-loader@7.1.2(webpack@5.95.0): dependencies: icss-utils: 5.1.0(postcss@8.4.47) postcss: 8.4.47 @@ -15281,7 +15284,7 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.6.3 optionalDependencies: - webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) + webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) css-select@4.3.0: dependencies: @@ -15800,28 +15803,28 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1): + eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.31.0)(eslint@8.57.1): dependencies: confusing-browser-globals: 1.0.11 eslint: 8.57.1 - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) object.assign: 4.1.5 object.entries: 1.1.8 semver: 6.3.1 - eslint-config-airbnb-typescript@17.1.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3))(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1): + eslint-config-airbnb-typescript@17.1.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3))(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1): dependencies: '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3) '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.6.3) eslint: 8.57.1 - eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.31.0)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) - eslint-config-airbnb@19.0.4(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint-plugin-jsx-a11y@6.10.1(eslint@8.57.1))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.1))(eslint-plugin-react@7.37.1(eslint@8.57.1))(eslint@8.57.1): + eslint-config-airbnb@19.0.4(eslint-plugin-import@2.31.0)(eslint-plugin-jsx-a11y@6.10.1(eslint@8.57.1))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.1))(eslint-plugin-react@7.37.1(eslint@8.57.1))(eslint@8.57.1): dependencies: eslint: 8.57.1 - eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.31.0)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.10.1(eslint@8.57.1) eslint-plugin-react: 7.37.1(eslint@8.57.1) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1) @@ -15835,8 +15838,8 @@ snapshots: '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.6.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.10.1(eslint@8.57.1) eslint-plugin-react: 7.37.1(eslint@8.57.1) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1) @@ -15859,37 +15862,37 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1): + eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.3.7(supports-color@8.1.1) enhanced-resolve: 5.17.1 eslint: 8.57.1 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) fast-glob: 3.3.2 get-tsconfig: 4.8.1 is-bun-module: 1.2.1 is-glob: 4.0.3 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) transitivePeerDependencies: - '@typescript-eslint/parser' - eslint-import-resolver-node - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): + eslint-module-utils@2.12.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1): dependencies: debug: 3.2.7(supports-color@8.1.1) optionalDependencies: '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.6.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -15900,7 +15903,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 @@ -16432,7 +16435,7 @@ snapshots: forever-agent@0.6.1: {} - fork-ts-checker-webpack-plugin@8.0.0(typescript@5.6.3)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)): + fork-ts-checker-webpack-plugin@8.0.0(typescript@5.6.3)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))): dependencies: '@babel/code-frame': 7.25.7 chalk: 4.1.2 @@ -16447,9 +16450,9 @@ snapshots: semver: 7.6.3 tapable: 2.2.1 typescript: 5.6.3 - webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) + webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) - fork-ts-checker-webpack-plugin@8.0.0(typescript@5.6.3)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))): + fork-ts-checker-webpack-plugin@8.0.0(typescript@5.6.3)(webpack@5.95.0): dependencies: '@babel/code-frame': 7.25.7 chalk: 4.1.2 @@ -16464,7 +16467,7 @@ snapshots: semver: 7.6.3 tapable: 2.2.1 typescript: 5.6.3 - webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) + webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) form-data@3.0.2: dependencies: @@ -16805,7 +16808,7 @@ snapshots: html-tags@3.3.1: {} - html-webpack-plugin@4.5.2(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)): + html-webpack-plugin@4.5.2(webpack@5.95.0): dependencies: '@types/html-minifier-terser': 5.1.2 '@types/tapable': 1.0.12 @@ -16818,7 +16821,7 @@ snapshots: util.promisify: 1.0.0 webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) - html-webpack-plugin@5.6.2(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)): + html-webpack-plugin@5.6.2(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 @@ -16826,9 +16829,9 @@ snapshots: pretty-error: 4.0.0 tapable: 2.2.1 optionalDependencies: - webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) + webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) - html-webpack-plugin@5.6.2(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))): + html-webpack-plugin@5.6.2(webpack@5.95.0): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 @@ -16836,7 +16839,7 @@ snapshots: pretty-error: 4.0.0 tapable: 2.2.1 optionalDependencies: - webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) + webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) htmlnano@2.1.1(postcss@8.4.47)(relateurl@0.2.7)(svgo@2.8.0)(terser@5.36.0)(typescript@5.6.3): dependencies: @@ -18721,25 +18724,25 @@ snapshots: postcss: 8.4.47 ts-node: 10.9.2(@swc/core@1.7.36(@swc/helpers@0.5.13))(@types/node@22.7.7)(typescript@5.6.3) - postcss-loader@8.1.1(postcss@8.4.47)(typescript@5.6.3)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)): + postcss-loader@8.1.1(postcss@8.4.47)(typescript@5.6.3)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))): dependencies: cosmiconfig: 9.0.0(typescript@5.6.3) jiti: 1.21.6 postcss: 8.4.47 semver: 7.6.3 optionalDependencies: - webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) + webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) transitivePeerDependencies: - typescript - postcss-loader@8.1.1(postcss@8.4.47)(typescript@5.6.3)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))): + postcss-loader@8.1.1(postcss@8.4.47)(typescript@5.6.3)(webpack@5.95.0): dependencies: cosmiconfig: 9.0.0(typescript@5.6.3) jiti: 1.21.6 postcss: 8.4.47 semver: 7.6.3 optionalDependencies: - webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) + webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) transitivePeerDependencies: - typescript @@ -19576,7 +19579,7 @@ snapshots: transitivePeerDependencies: - supports-color - speed-measure-webpack-plugin@1.4.2(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)): + speed-measure-webpack-plugin@1.4.2(webpack@5.95.0): dependencies: chalk: 4.1.2 webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) @@ -19745,15 +19748,11 @@ snapshots: structured-headers@0.4.1: {} - style-loader@3.3.4(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)): - dependencies: - webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) - style-loader@3.3.4(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))): dependencies: webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) - style-loader@4.0.0(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)): + style-loader@3.3.4(webpack@5.95.0): dependencies: webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) @@ -19761,6 +19760,10 @@ snapshots: dependencies: webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) + style-loader@4.0.0(webpack@5.95.0): + dependencies: + webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) + styled-jsx@5.1.1(@babel/core@7.25.8)(babel-plugin-macros@3.1.0)(react@18.3.1): dependencies: client-only: 0.0.1 @@ -19899,7 +19902,7 @@ snapshots: ansi-escapes: 4.3.2 supports-hyperlinks: 2.3.0 - terser-webpack-plugin@5.3.10(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)): + terser-webpack-plugin@5.3.10(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack@5.95.0): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 @@ -20367,9 +20370,9 @@ snapshots: webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0): dependencies: '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0))(webpack-dev-server@5.1.0(webpack-cli@5.1.4)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4)(webpack@5.95.0) + '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4)(webpack@5.95.0) + '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4)(webpack-dev-server@5.1.0)(webpack@5.95.0) colorette: 2.0.20 commander: 10.0.1 cross-spawn: 7.0.3 @@ -20383,7 +20386,7 @@ snapshots: optionalDependencies: webpack-dev-server: 5.1.0(webpack-cli@5.1.4)(webpack@5.95.0) - webpack-dev-middleware@5.3.4(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)): + webpack-dev-middleware@5.3.4(webpack@5.95.0): dependencies: colorette: 2.0.20 memfs: 3.5.3 @@ -20392,7 +20395,7 @@ snapshots: schema-utils: 4.2.0 webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) - webpack-dev-middleware@6.1.3(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)): + webpack-dev-middleware@6.1.3(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))): dependencies: colorette: 2.0.20 memfs: 3.5.3 @@ -20400,9 +20403,9 @@ snapshots: range-parser: 1.2.1 schema-utils: 4.2.0 optionalDependencies: - webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) + webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) - webpack-dev-middleware@6.1.3(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))): + webpack-dev-middleware@6.1.3(webpack@5.95.0): dependencies: colorette: 2.0.20 memfs: 3.5.3 @@ -20410,9 +20413,9 @@ snapshots: range-parser: 1.2.1 schema-utils: 4.2.0 optionalDependencies: - webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13)) + webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) - webpack-dev-middleware@7.4.2(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)): + webpack-dev-middleware@7.4.2(webpack@5.95.0): dependencies: colorette: 2.0.20 memfs: 4.14.0 @@ -20423,7 +20426,7 @@ snapshots: optionalDependencies: webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) - webpack-dev-server@4.15.2(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)): + webpack-dev-server@4.15.2(webpack-cli@5.1.4)(webpack@5.95.0): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 @@ -20453,7 +20456,7 @@ snapshots: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 5.3.4(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + webpack-dev-middleware: 5.3.4(webpack@5.95.0) ws: 8.18.0 optionalDependencies: webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) @@ -20492,7 +20495,7 @@ snapshots: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 7.4.2(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + webpack-dev-middleware: 7.4.2(webpack@5.95.0) ws: 8.18.0 optionalDependencies: webpack: 5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4) @@ -20571,7 +20574,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack@5.95.0(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack-cli@5.1.4)) + terser-webpack-plugin: 5.3.10(@swc/core@1.7.36(@swc/helpers@0.5.13))(esbuild@0.23.1)(webpack@5.95.0) watchpack: 2.4.2 webpack-sources: 3.2.3 optionalDependencies: