diff --git a/ui/.yarnclean b/ui/.yarnclean new file mode 100644 index 0000000..b591611 --- /dev/null +++ b/ui/.yarnclean @@ -0,0 +1,45 @@ +# test directories +__tests__ +test +tests +powered-test + +# asset directories +docs +doc +website +images +assets + +# examples +example +examples + +# code coverage directories +coverage +.nyc_output + +# build scripts +Makefile +Gulpfile.js +Gruntfile.js + +# configs +appveyor.yml +circle.yml +codeship-services.yml +codeship-steps.yml +wercker.yml +.tern-project +.gitattributes +.editorconfig +.*ignore +.eslintrc +.jshintrc +.flowconfig +.documentup.json +.yarn-metadata.json +.travis.yml + +# misc +*.md diff --git a/ui/package.json b/ui/package.json index 5a87da3..42ffe56 100644 --- a/ui/package.json +++ b/ui/package.json @@ -13,7 +13,6 @@ "@types/react-dom": "^18.0.2", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-redux": "^8.0.1", "react-scripts": "5.0.1", "react-use-websocket": "^4.3.1", "sass": "^1.58.3", diff --git a/ui/src/App.test.tsx b/ui/src/App.test.tsx index 659cc13..46610f2 100644 --- a/ui/src/App.test.tsx +++ b/ui/src/App.test.tsx @@ -1,15 +1,11 @@ import React from 'react'; import { render } from '@testing-library/react'; -import { Provider } from 'react-redux'; -import { store } from './app/store'; import App from './App'; test('renders learn react link', () => { - const { getByText } = render( - - - - ); + const { getByText } = render( + + ); - expect(getByText(/learn/i)).toBeInTheDocument(); + expect(getByText(/recupera stato/i)).toBeInTheDocument(); }); diff --git a/ui/src/App.tsx b/ui/src/App.tsx index b1f25f2..e3cff10 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { RadioToggler } from './features/radio/Radio'; -import { LogViewer } from './features/radio/LogViewer'; +import { RadioToggler } from './Radio'; +import { LogViewer } from './LogViewer'; import './App.css'; function App() { diff --git a/ui/src/features/radio/LogViewer.module.scss b/ui/src/LogViewer.module.scss similarity index 100% rename from ui/src/features/radio/LogViewer.module.scss rename to ui/src/LogViewer.module.scss diff --git a/ui/src/features/radio/LogViewer.tsx b/ui/src/LogViewer.tsx similarity index 73% rename from ui/src/features/radio/LogViewer.tsx rename to ui/src/LogViewer.tsx index 36c6138..ebc4d2c 100644 --- a/ui/src/features/radio/LogViewer.tsx +++ b/ui/src/LogViewer.tsx @@ -1,21 +1,25 @@ import React, { useState } from 'react'; -import { useAppSelector, useAppDispatch } from '../../app/hooks'; -import { selectLogsLoading, selectLogs, requestLogsThunk } from './radioSlice'; +import { requestLogs } from './radioAPI'; import styles from './LogViewer.module.scss'; export function LogViewer() { - const loading = useAppSelector(selectLogsLoading); - const logs = useAppSelector(selectLogs); + const [loading, setLoading] = useState(false); + const [logs, setLogs] = useState(undefined); const [hidden, setHidden] = useState(true); - const dispatch = useAppDispatch(); + const onRequestLogsButtonClick = async () => { + setLoading(true); + const logs = await requestLogs(); + setLogs(logs); + setLoading(false); + }; return ( dispatch(requestLogsThunk())} + onClick={onRequestLogsButtonClick} >Recupera stato { + const proto = (window.location.protocol === "http:") ? "ws" : "wss" + const wsUrl = process.env.WS_ADDR ? + process.env.WS_ADDR : + proto + "://" + window.location.host + window.location.pathname + "liveness"; + console.log("WS ADDR: %s", wsUrl); + return wsUrl; +}; + +export function RadioToggler() { + const [loading, setLoading] = useState(false); + const [radioState, setRadioState] = useState(undefined); + const [connectionState, setConnectionState] = useState(ConnectionState.DISCONNECTED); + + const { lastJsonMessage } = useWebSocket(getWSUrl, + { + onOpen: () => setConnectionState(ConnectionState.CONNECTED), + onClose: () => setConnectionState(ConnectionState.DISCONNECTED), + }); + + const onButtonClick = async () => { + if (radioState === RadioState.STARTED) { + setLoading(true); + const stopped = await requestToStop(); + if (stopped) { + setRadioState(RadioState.STOPPED); + } + setLoading(false); + } else if (radioState === RadioState.STOPPED) { + setLoading(true); + const started = await requestToStart(); + if (started) { + setRadioState(RadioState.STARTED); + } + setLoading(false); + } + }; + + const setRadioStateFromWS = (message: any) => { + switch (message.status) { + case "STARTED": + setRadioState(RadioState.STARTED); + break; + case "STOPPED": + setRadioState(RadioState.STOPPED); + break; + default: + setRadioState(undefined); + break; + } + }; + + useEffect(() => { + if (lastJsonMessage != null) { + if (!loading && lastJsonMessage.hasOwnProperty('status')) { + setRadioStateFromWS(lastJsonMessage); + } + } + }, [lastJsonMessage]); + + let buttonStatus = ""; + let circleStyle = styles.circleDisconnected; + if (loading) { + buttonStatus = "Attesa"; + circleStyle = styles.circleLoading; + } else if (connectionState && connectionState !== ConnectionState.DISCONNECTED) { + switch (radioState) { + case RadioState.STARTED: + buttonStatus = "ON AIR"; + circleStyle = styles.circleStarted; + break; + case RadioState.STOPPED: + buttonStatus = "SPENTA"; + circleStyle = styles.circleStopped; + break; + } + } + + return ( + + + {buttonStatus} + + + + ); +} diff --git a/ui/src/app/hooks.ts b/ui/src/app/hooks.ts deleted file mode 100644 index 520e84e..0000000 --- a/ui/src/app/hooks.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'; -import type { RootState, AppDispatch } from './store'; - -// Use throughout your app instead of plain `useDispatch` and `useSelector` -export const useAppDispatch = () => useDispatch(); -export const useAppSelector: TypedUseSelectorHook = useSelector; diff --git a/ui/src/app/store.ts b/ui/src/app/store.ts deleted file mode 100644 index 26c7abf..0000000 --- a/ui/src/app/store.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit'; -import radioReducer from '../features/radio/radioSlice'; - -export const store = configureStore({ - reducer: { - globalState: radioReducer, - }, -}); - -export type AppDispatch = typeof store.dispatch; -export type RootState = ReturnType; -export type AppThunk = ThunkAction< - ReturnType, - RootState, - unknown, - Action ->; diff --git a/ui/src/features/radio/Radio.tsx b/ui/src/features/radio/Radio.tsx deleted file mode 100644 index 62e710f..0000000 --- a/ui/src/features/radio/Radio.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import React, { useEffect } from 'react'; -import useWebSocket from 'react-use-websocket'; - -import { useAppSelector, useAppDispatch } from '../../app/hooks'; -import { RadioState, ConnectionState } from '../../app/types'; -import { - toggleRadioState, - selectRadioLoading, - selectRadio, - selectConnection, -} from './radioSlice'; -import { - getOnWSOpen, - getOnWSClose, - getOnWSMessage, -} from './radioWS'; -import styles from './Radio.module.scss'; - -const getWSUrl = async () => { - const proto = (window.location.protocol === "http:") ? "ws" : "wss" - const wsUrl = process.env.WS_ADDR ? - process.env.WS_ADDR : - proto + "://" + window.location.host + window.location.pathname + "liveness"; - console.log("WS ADDR: %s", wsUrl); - return wsUrl; -}; - -export function RadioToggler() { - const loading = useAppSelector(selectRadioLoading); - const radioState = useAppSelector(selectRadio); - const connectionState = useAppSelector(selectConnection); - - const dispatch = useAppDispatch(); - - const { lastJsonMessage } = useWebSocket(getWSUrl, - { - onOpen: getOnWSOpen(dispatch), - onClose: getOnWSClose(dispatch), - }); - - const onWSMessage = getOnWSMessage(dispatch); - useEffect(() => { - if (lastJsonMessage != null) { - if (!loading) { - onWSMessage(lastJsonMessage); - } - } - }, [lastJsonMessage]); - - let buttonStatus = ""; - let circleStyle = styles.circleDisconnected; - if (loading) { - buttonStatus = "Attesa"; - circleStyle = styles.circleLoading; - } else if (connectionState && connectionState !== ConnectionState.DISCONNECTED) { - switch (radioState) { - case RadioState.STARTED: - buttonStatus = "ON AIR"; - circleStyle = styles.circleStarted; - break; - case RadioState.STOPPED: - buttonStatus = "SPENTA"; - circleStyle = styles.circleStopped; - break; - } - } - - return ( - - - dispatch(toggleRadioState())} - >{buttonStatus} - - - - ); -} diff --git a/ui/src/features/radio/radioSlice.spec.ts b/ui/src/features/radio/radioSlice.spec.ts deleted file mode 100644 index d59cc1b..0000000 --- a/ui/src/features/radio/radioSlice.spec.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { RadioState, ConnectionState } from '../../app/types'; -import reducer, { - AppState, - toggleRadioLoading, - setRadioStarted, - setRadioStopped, - toggleRadio, - setConnected, - setDisconnected, - toggleConnection, - selectRadioLoading, - selectRadio, - selectConnection, -} from './radioSlice'; - -describe('radio reducer', () => { - const initialState: AppState = { - loading: { radio: false, logs: false }, - connection: ConnectionState.DISCONNECTED, - }; - - const connectedStarted: AppState = { - radio: RadioState.STARTED, - loading: { radio: false, logs: false }, - connection: ConnectionState.CONNECTED, - }; - - const connectedStopped: AppState = { - radio: RadioState.STOPPED, - loading: { radio: false, logs: false }, - connection: ConnectionState.CONNECTED, - }; - - it('should handle initial state', () => { - expect(reducer(undefined, { type: 'unknown' })).toEqual({ - loading: { radio: false, logs: false }, - connection: ConnectionState.DISCONNECTED, - }); - }); - - it('should handle set loading', () => { - const actual = reducer(initialState, toggleRadioLoading()); - expect(actual.loading.radio).toEqual(true); - }); - - it('should hande toggle radio started', () => { - const actual = reducer(connectedStopped, toggleRadio()); - expect(actual.radio).toEqual(RadioState.STARTED); - }) - - it('should hande toggle radio stopped', () => { - const actual = reducer(connectedStarted, toggleRadio()); - expect(actual.radio).toEqual(RadioState.STOPPED); - }) - - it('should hande set radio started', () => { - const actual = reducer(connectedStopped, setRadioStarted()); - expect(actual.radio).toEqual(RadioState.STARTED); - }) - - it('should hande set radio stopped', () => { - const actual = reducer(connectedStarted, setRadioStopped()); - expect(actual.radio).toEqual(RadioState.STOPPED); - }) - - it('should noop set radio started', () => { - const actual = reducer(connectedStarted, setRadioStarted()); - expect(actual.radio).toEqual(RadioState.STARTED); - }) - - it('should noop set radio stopped', () => { - const actual = reducer(connectedStopped, setRadioStopped()); - expect(actual.radio).toEqual(RadioState.STOPPED); - }) -}); diff --git a/ui/src/features/radio/radioSlice.ts b/ui/src/features/radio/radioSlice.ts deleted file mode 100644 index cd0e1f3..0000000 --- a/ui/src/features/radio/radioSlice.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'; -import { RootState, AppThunk } from '../../app/store'; -import { RadioState, ConnectionState } from '../../app/types'; -import { requestToStart, requestToStop, requestLogs } from './radioAPI'; - -export interface LoadingState { - radio: boolean, - logs: boolean, -} - -export interface AppState { - radio?: RadioState, - logs?: Array, - loading: LoadingState, - connection: ConnectionState -} - -const initialState: AppState = { - radio: undefined, - loading: { radio: false, logs: false }, - connection: ConnectionState.DISCONNECTED, -}; - -export const requestToStartThunk = createAsyncThunk( - 'radio/restStart', - async () => { - const success = await requestToStart(); - return success; - } -); - -export const requestToStopThunk = createAsyncThunk( - 'radio/restStop', - async () => { - const success = await requestToStop(); - return success; - } -); - -export const requestLogsThunk = createAsyncThunk( - 'radio/restStatus', - async () => { - return await requestLogs(); - } -); - -export const radioSlice = createSlice({ - name: 'radio', - initialState, - reducers: { - toggleRadioLoading: (state) => { state.loading.radio = !state.loading.radio }, - toggleLogsLoading: (state) => { state.loading.logs = !state.loading.logs }, - setRadioStarted: (state) => { console.log("[Redux] STARTED"); state.radio = RadioState.STARTED }, - setRadioStopped: (state) => { console.log("[Redux] STOPPED"); state.radio = RadioState.STOPPED }, - unsetRadio: (state) => { state.radio = undefined }, - toggleRadio: (state) => { - if (state.radio === RadioState.STARTED) { - state.radio = RadioState.STOPPED - } else if (state.radio === RadioState.STOPPED) { - state.radio = RadioState.STARTED - } - }, - setConnected: (state) => { state.connection = ConnectionState.CONNECTED }, - setDisconnected: (state) => { state.connection = ConnectionState.DISCONNECTED }, - toggleConnection: (state) => { - if (state.connection === ConnectionState.CONNECTED) { - state.connection = ConnectionState.DISCONNECTED - } else if (state.connection === ConnectionState.DISCONNECTED) { - state.connection = ConnectionState.CONNECTED - } - }, - }, - extraReducers: builder => { - builder - .addCase(requestToStartThunk.pending, (state) => { - state.loading.radio = true; - return state; - }) - .addCase(requestToStartThunk.fulfilled, (state, action) => { - state.loading.radio = false; - if (action.payload) { - state.radio = RadioState.STARTED; - } - return state; - }) - .addCase(requestToStopThunk.pending, (state, _) => { - state.loading.radio = true; - return state; - }) - .addCase(requestToStopThunk.fulfilled, (state, action) => { - state.loading.radio = false; - if (action.payload) { - state.radio = RadioState.STOPPED; - } - return state; - }) - .addCase(requestLogsThunk.pending, (state, _) => { - state.loading.logs = true; - return state; - }) - .addCase(requestLogsThunk.fulfilled, (state, action) => { - state.loading.logs = false; - state.logs = action.payload; - return state; - }) - }, -}); - -export const { - toggleRadioLoading, - toggleLogsLoading, - setRadioStarted, - setRadioStopped, - unsetRadio, - toggleRadio, - setConnected, - setDisconnected, - toggleConnection, -} = radioSlice.actions; - -export const selectRadioLoading = (state: RootState) => state.globalState.loading.radio; -export const selectLogsLoading = (state: RootState) => state.globalState.loading.logs; -export const selectRadio = (state: RootState) => state.globalState.radio; -export const selectLogs = (state: RootState) => state.globalState.logs; -export const selectConnection = (state: RootState) => state.globalState.connection; - -export const toggleRadioState = - (): AppThunk => - async (dispatch, getState) => { - const currentRadioState = selectRadio(getState()); - if (currentRadioState === RadioState.STARTED) { - dispatch(requestToStopThunk()); - } else if (currentRadioState === RadioState.STOPPED) { - dispatch(requestToStartThunk()); - } - }; - -export default radioSlice.reducer diff --git a/ui/src/features/radio/radioWS.ts b/ui/src/features/radio/radioWS.ts deleted file mode 100644 index b8d6638..0000000 --- a/ui/src/features/radio/radioWS.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { AppDispatch } from '../../app/store'; -import { - setRadioStarted, - setRadioStopped, - unsetRadio, - setConnected, - setDisconnected, -} from './radioSlice'; - - -export const getOnWSOpen = (dispatch: AppDispatch) => { - return () => { - console.log("[WS] Opened"); - dispatch(setConnected()); - } -}; - -export const getOnWSClose = (dispatch: AppDispatch) => { - return () => { - console.log("[WS] Closed") - dispatch(setDisconnected()); - return true - } -}; - -export const getOnWSMessage = (dispatch: AppDispatch) => { - return (message: any) => { - console.log("[WS] Message: %s", JSON.stringify(message)); - - switch (message.status) { - case "STARTED": - dispatch(setRadioStarted()); - break; - case "STOPPED": - dispatch(setRadioStopped()); - break; - default: - dispatch(unsetRadio()); - } - } -}; diff --git a/ui/src/index.tsx b/ui/src/index.tsx index e692bd1..079dffb 100644 --- a/ui/src/index.tsx +++ b/ui/src/index.tsx @@ -1,7 +1,5 @@ import React from 'react'; import { createRoot } from 'react-dom/client'; -import { Provider } from 'react-redux'; -import { store } from './app/store'; import App from './App'; import './index.css'; @@ -10,8 +8,6 @@ const root = createRoot(container); root.render( - - - + ); diff --git a/ui/src/logo.svg b/ui/src/logo.svg deleted file mode 100644 index 8466738..0000000 --- a/ui/src/logo.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ui/src/features/radio/radioAPI.ts b/ui/src/radioAPI.ts similarity index 97% rename from ui/src/features/radio/radioAPI.ts rename to ui/src/radioAPI.ts index e2007b3..949d7cd 100644 --- a/ui/src/features/radio/radioAPI.ts +++ b/ui/src/radioAPI.ts @@ -1,4 +1,4 @@ -import { RadioState } from '../../app/types'; +import { RadioState } from './types'; export const requestToStart = async () => { console.log("[REST] request to start"); diff --git a/ui/src/app/types.ts b/ui/src/types.ts similarity index 100% rename from ui/src/app/types.ts rename to ui/src/types.ts diff --git a/ui/yarn.lock b/ui/yarn.lock index 101cca7..b75afce 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -1034,7 +1034,7 @@ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.20.7", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.20.7", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": version "7.20.13" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.13.tgz#7055ab8a7cff2b8f6058bf6ae45ff84ad2aded4b" integrity sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA== @@ -1940,14 +1940,6 @@ dependencies: "@types/node" "*" -"@types/hoist-non-react-statics@^3.3.1": - version "3.3.1" - resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" - integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== - dependencies: - "@types/react" "*" - hoist-non-react-statics "^3.3.0" - "@types/html-minifier-terser@^6.0.0": version "6.1.0" resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" @@ -2127,11 +2119,6 @@ resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.3.tgz#a136f83b0758698df454e328759dbd3d44555311" integrity sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g== -"@types/use-sync-external-store@^0.0.3": - version "0.0.3" - resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43" - integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA== - "@types/ws@^8.5.1": version "8.5.4" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.4.tgz#bb10e36116d6e570dd943735f86c933c1587b8a5" @@ -4810,13 +4797,6 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" - integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== - dependencies: - react-is "^16.7.0" - hoopy@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" @@ -7515,7 +7495,7 @@ react-error-overlay@^6.0.11: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb" integrity sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg== -react-is@^16.13.1, react-is@^16.7.0: +react-is@^16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -7530,18 +7510,6 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== -react-redux@^8.0.1: - version "8.0.5" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-8.0.5.tgz#e5fb8331993a019b8aaf2e167a93d10af469c7bd" - integrity sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw== - dependencies: - "@babel/runtime" "^7.12.1" - "@types/hoist-non-react-statics" "^3.3.1" - "@types/use-sync-external-store" "^0.0.3" - hoist-non-react-statics "^3.3.2" - react-is "^18.0.0" - use-sync-external-store "^1.0.0" - react-refresh@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046" @@ -8781,11 +8749,6 @@ url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" -use-sync-external-store@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" - integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== - util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"