mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
chore(deps): update dependency react-router-dom to v6.10.0 (#3238)
* chore(deps): update dependency react-router-dom to v6.10.0 * fix: lockfile * fix: react router * chore: add annotations about the type definition file * fix: bump version number for ui package --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Charles Zhao <charleszhao@silverhand.io>
This commit is contained in:
parent
4b6ad4c8c5
commit
e97fe2e1f3
7 changed files with 96 additions and 124 deletions
|
@ -93,7 +93,7 @@
|
||||||
"react-markdown": "^8.0.0",
|
"react-markdown": "^8.0.0",
|
||||||
"react-modal": "^3.15.1",
|
"react-modal": "^3.15.1",
|
||||||
"react-paginate": "^8.1.3",
|
"react-paginate": "^8.1.3",
|
||||||
"react-router-dom": "6.3.0",
|
"react-router-dom": "^6.10.0",
|
||||||
"react-syntax-highlighter": "^15.5.0",
|
"react-syntax-highlighter": "^15.5.0",
|
||||||
"react-timer-hook": "^3.0.5",
|
"react-timer-hook": "^3.0.5",
|
||||||
"recharts": "^2.1.13",
|
"recharts": "^2.1.13",
|
||||||
|
|
|
@ -1,97 +1,42 @@
|
||||||
import type { Blocker, Transition } from 'history';
|
import { useEffect } from 'react';
|
||||||
import { useCallback, useContext, useLayoutEffect, useState } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import type { Navigator } from 'react-router-dom';
|
import { unstable_useBlocker as useBlocker, useLocation } from 'react-router-dom';
|
||||||
import { UNSAFE_NavigationContext } from 'react-router-dom';
|
|
||||||
|
|
||||||
import ConfirmModal from '../ConfirmModal';
|
import ConfirmModal from '../ConfirmModal';
|
||||||
|
|
||||||
/**
|
|
||||||
* The `usePrompt` and `useBlock` hooks are removed from react-router v6, as the developers think
|
|
||||||
* they are not ready to be shipped in v6. Reference: https://github.com/remix-run/react-router/issues/8139
|
|
||||||
* Therefore we have to implement our own workaround to provide the same functionality, through `UNSAFE_NavigationContext`.
|
|
||||||
*/
|
|
||||||
type BlockFunction = (blocker: Blocker) => () => void;
|
|
||||||
|
|
||||||
type BlockerNavigator = Navigator & {
|
|
||||||
location: Location;
|
|
||||||
block: BlockFunction;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
hasUnsavedChanges: boolean;
|
hasUnsavedChanges: boolean;
|
||||||
parentPath?: string;
|
parentPath?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
function UnsavedChangesAlertModal({ hasUnsavedChanges, parentPath }: Props) {
|
function UnsavedChangesAlertModal({ hasUnsavedChanges, parentPath }: Props) {
|
||||||
const { navigator } = useContext(UNSAFE_NavigationContext);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Props `block` and `location` are removed from `Navigator` type in react-router, for the same reason as above.
|
|
||||||
* So we have to define our own type `BlockerNavigator` to acquire these props that actually exist in `navigator` object.
|
|
||||||
*/
|
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
|
||||||
const { block, location } = navigator as BlockerNavigator;
|
|
||||||
|
|
||||||
const [displayAlert, setDisplayAlert] = useState(false);
|
|
||||||
const [transition, setTransition] = useState<Transition>();
|
|
||||||
|
|
||||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||||
|
const { pathname } = useLocation();
|
||||||
|
const blocker = useBlocker(hasUnsavedChanges);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
// Reset the blocker if the conditions are met.
|
||||||
if (!hasUnsavedChanges) {
|
useEffect(() => {
|
||||||
|
if (blocker.state !== 'blocked') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { pathname } = location;
|
const targetPathname = blocker.location.pathname;
|
||||||
|
if (!hasUnsavedChanges || targetPathname === pathname) {
|
||||||
const unblock = block((transition) => {
|
blocker.reset();
|
||||||
const {
|
return;
|
||||||
location: { pathname: targetPathname },
|
}
|
||||||
} = transition;
|
if (parentPath && targetPathname.startsWith(parentPath)) {
|
||||||
|
blocker.proceed();
|
||||||
// Note: We don't want to show the alert if the user is navigating to the same page.
|
}
|
||||||
if (targetPathname === pathname) {
|
}, [blocker, pathname, hasUnsavedChanges, parentPath]);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parentPath && targetPathname.startsWith(parentPath)) {
|
|
||||||
unblock();
|
|
||||||
transition.retry();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setDisplayAlert(true);
|
|
||||||
|
|
||||||
setTransition({
|
|
||||||
...transition,
|
|
||||||
retry() {
|
|
||||||
unblock();
|
|
||||||
transition.retry();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return unblock;
|
|
||||||
}, [navigator, hasUnsavedChanges, location, block, parentPath]);
|
|
||||||
|
|
||||||
const leavePage = useCallback(() => {
|
|
||||||
transition?.retry();
|
|
||||||
setDisplayAlert(false);
|
|
||||||
}, [transition]);
|
|
||||||
|
|
||||||
const stayOnPage = useCallback(() => {
|
|
||||||
setDisplayAlert(false);
|
|
||||||
}, [setDisplayAlert]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
isOpen={displayAlert}
|
isOpen={blocker.state === 'blocked'}
|
||||||
confirmButtonText="general.leave_page"
|
confirmButtonText="general.leave_page"
|
||||||
cancelButtonText="general.stay_on_page"
|
cancelButtonText="general.stay_on_page"
|
||||||
onCancel={stayOnPage}
|
onCancel={blocker.reset}
|
||||||
onConfirm={leavePage}
|
onConfirm={blocker.proceed}
|
||||||
>
|
>
|
||||||
{t('general.unsaved_changes_warning')}
|
{t('general.unsaved_changes_warning')}
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
|
|
16
packages/console/src/include.d/react-router-dom.d.ts
vendored
Normal file
16
packages/console/src/include.d/react-router-dom.d.ts
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/**
|
||||||
|
* This type definition file is a workaround for the fact that react-router-dom
|
||||||
|
* declares location status type as `any` instead of `unknown`, which ends up
|
||||||
|
* causing issues with strict type narrowing in TypeScript.
|
||||||
|
*
|
||||||
|
* Reference: https://github.com/remix-run/react-router/issues/10241
|
||||||
|
*/
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/no-unassigned-import
|
||||||
|
import 'react-router-dom';
|
||||||
|
|
||||||
|
declare module 'react-router-dom' {
|
||||||
|
import { type Location } from 'react-router-dom';
|
||||||
|
|
||||||
|
function useLocation(): Omit<Location, 'state'> & { state: unknown };
|
||||||
|
}
|
|
@ -1,4 +1,9 @@
|
||||||
import { BrowserRouter, Route, Routes } from 'react-router-dom';
|
import {
|
||||||
|
Route,
|
||||||
|
RouterProvider,
|
||||||
|
createBrowserRouter,
|
||||||
|
createRoutesFromElements,
|
||||||
|
} from 'react-router-dom';
|
||||||
import { SWRConfig } from 'swr';
|
import { SWRConfig } from 'swr';
|
||||||
|
|
||||||
import Toast from '@/components/Toast';
|
import Toast from '@/components/Toast';
|
||||||
|
@ -14,23 +19,27 @@ import HandleSocialCallback from '../Profile/containers/HandleSocialCallback';
|
||||||
|
|
||||||
function Main() {
|
function Main() {
|
||||||
const swrOptions = useSwrOptions();
|
const swrOptions = useSwrOptions();
|
||||||
|
const router = createBrowserRouter(
|
||||||
|
createRoutesFromElements(
|
||||||
|
<>
|
||||||
|
<Route path="callback" element={<Callback />} />
|
||||||
|
<Route path="welcome" element={<Welcome />} />
|
||||||
|
<Route path="handle-social" element={<HandleSocialCallback />} />
|
||||||
|
<Route element={<AppContent />}>
|
||||||
|
<Route path="/*" element={<ConsoleContent />} />
|
||||||
|
</Route>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
{ basename: getBasename() }
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BrowserRouter basename={getBasename()}>
|
<SWRConfig value={swrOptions}>
|
||||||
<SWRConfig value={swrOptions}>
|
<AppBoundary>
|
||||||
<AppBoundary>
|
<Toast />
|
||||||
<Toast />
|
<RouterProvider router={router} />
|
||||||
<Routes>
|
</AppBoundary>
|
||||||
<Route path="callback" element={<Callback />} />
|
</SWRConfig>
|
||||||
<Route path="welcome" element={<Welcome />} />
|
|
||||||
<Route path="handle-social" element={<HandleSocialCallback />} />
|
|
||||||
<Route element={<AppContent />}>
|
|
||||||
<Route path="/*" element={<ConsoleContent />} />
|
|
||||||
</Route>
|
|
||||||
</Routes>
|
|
||||||
</AppBoundary>
|
|
||||||
</SWRConfig>
|
|
||||||
</BrowserRouter>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@
|
||||||
"react-hook-form": "^7.34.0",
|
"react-hook-form": "^7.34.0",
|
||||||
"react-i18next": "^11.18.3",
|
"react-i18next": "^11.18.3",
|
||||||
"react-modal": "^3.15.1",
|
"react-modal": "^3.15.1",
|
||||||
"react-router-dom": "^6.2.2",
|
"react-router-dom": "^6.10.0",
|
||||||
"react-string-replace": "^1.0.0",
|
"react-string-replace": "^1.0.0",
|
||||||
"react-timer-hook": "^3.0.5",
|
"react-timer-hook": "^3.0.5",
|
||||||
"react-top-loading-bar": "^2.3.1",
|
"react-top-loading-bar": "^2.3.1",
|
||||||
|
|
16
packages/ui/src/include.d/react-router-dom.d.ts
vendored
Normal file
16
packages/ui/src/include.d/react-router-dom.d.ts
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/**
|
||||||
|
* This type definition file is a workaround for the fact that react-router-dom
|
||||||
|
* declares location status type as `any` instead of `unknown`, which ends up
|
||||||
|
* causing issues with strict type narrowing in TypeScript.
|
||||||
|
*
|
||||||
|
* Reference: https://github.com/remix-run/react-router/issues/10241
|
||||||
|
*/
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/no-unassigned-import
|
||||||
|
import 'react-router-dom';
|
||||||
|
|
||||||
|
declare module 'react-router-dom' {
|
||||||
|
import { type Location } from 'react-router-dom';
|
||||||
|
|
||||||
|
function useLocation(): Omit<Location, 'state'> & { state: unknown };
|
||||||
|
}
|
|
@ -2970,8 +2970,8 @@ importers:
|
||||||
specifier: ^8.1.3
|
specifier: ^8.1.3
|
||||||
version: 8.1.3(react@18.2.0)
|
version: 8.1.3(react@18.2.0)
|
||||||
react-router-dom:
|
react-router-dom:
|
||||||
specifier: 6.3.0
|
specifier: ^6.10.0
|
||||||
version: 6.3.0(react-dom@18.2.0)(react@18.2.0)
|
version: 6.10.0(react-dom@18.2.0)(react@18.2.0)
|
||||||
react-syntax-highlighter:
|
react-syntax-highlighter:
|
||||||
specifier: ^15.5.0
|
specifier: ^15.5.0
|
||||||
version: 15.5.0(react@18.2.0)
|
version: 15.5.0(react@18.2.0)
|
||||||
|
@ -3952,8 +3952,8 @@ importers:
|
||||||
specifier: ^3.15.1
|
specifier: ^3.15.1
|
||||||
version: 3.15.1(react-dom@18.2.0)(react@18.2.0)
|
version: 3.15.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
react-router-dom:
|
react-router-dom:
|
||||||
specifier: ^6.2.2
|
specifier: ^6.10.0
|
||||||
version: 6.2.2(react-dom@18.2.0)(react@18.2.0)
|
version: 6.10.0(react-dom@18.2.0)(react@18.2.0)
|
||||||
react-string-replace:
|
react-string-replace:
|
||||||
specifier: ^1.0.0
|
specifier: ^1.0.0
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
|
@ -7464,6 +7464,11 @@ packages:
|
||||||
'@redis/client': 1.5.6
|
'@redis/client': 1.5.6
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@remix-run/router@1.5.0:
|
||||||
|
resolution: {integrity: sha512-bkUDCp8o1MvFO+qxkODcbhSqRa6P2GXgrGZVpt0dCXNW2HCSCqYI0ZoAqEOSAjRWmmlKcYgFvN4B4S+zo/f8kg==}
|
||||||
|
engines: {node: '>=14'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@rollup/plugin-commonjs@24.0.0(rollup@3.8.0):
|
/@rollup/plugin-commonjs@24.0.0(rollup@3.8.0):
|
||||||
resolution: {integrity: sha512-0w0wyykzdyRRPHOb0cQt14mIBLujfAv6GgP6g8nvg/iBxEm112t3YPPq+Buqe2+imvElTka+bjNlJ/gB56TD8g==}
|
resolution: {integrity: sha512-0w0wyykzdyRRPHOb0cQt14mIBLujfAv6GgP6g8nvg/iBxEm112t3YPPq+Buqe2+imvElTka+bjNlJ/gB56TD8g==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
|
@ -16577,45 +16582,26 @@ packages:
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/react-router-dom@6.2.2(react-dom@18.2.0)(react@18.2.0):
|
/react-router-dom@6.10.0(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-AtYEsAST7bDD4dLSQHDnk/qxWLJdad5t1HFa1qJyUrCeGgEuCSw0VB/27ARbF9Fi/W5598ujvJOm3ujUCVzuYQ==}
|
resolution: {integrity: sha512-E5dfxRPuXKJqzwSe/qGcqdwa18QiWC6f3H3cWXM24qj4N0/beCIf/CWTipop2xm7mR0RCS99NnaqPNjHtrAzCg==}
|
||||||
|
engines: {node: '>=14'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: '>=16.8 || ^18.0.0'
|
react: '>=16.8 || ^18.0.0'
|
||||||
react-dom: '>=16.8'
|
react-dom: '>=16.8'
|
||||||
dependencies:
|
dependencies:
|
||||||
history: 5.3.0
|
'@remix-run/router': 1.5.0
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
react-router: 6.2.2(react@18.2.0)
|
react-router: 6.10.0(react@18.2.0)
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/react-router-dom@6.3.0(react-dom@18.2.0)(react@18.2.0):
|
/react-router@6.10.0(react@18.2.0):
|
||||||
resolution: {integrity: sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==}
|
resolution: {integrity: sha512-Nrg0BWpQqrC3ZFFkyewrflCud9dio9ME3ojHCF/WLsprJVzkq3q3UeEhMCAW1dobjeGbWgjNn/PVF6m46ANxXQ==}
|
||||||
peerDependencies:
|
engines: {node: '>=14'}
|
||||||
react: '>=16.8 || ^18.0.0'
|
|
||||||
react-dom: '>=16.8'
|
|
||||||
dependencies:
|
|
||||||
history: 5.3.0
|
|
||||||
react: 18.2.0
|
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
|
||||||
react-router: 6.3.0(react@18.2.0)
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/react-router@6.2.2(react@18.2.0):
|
|
||||||
resolution: {integrity: sha512-/MbxyLzd7Q7amp4gDOGaYvXwhEojkJD5BtExkuKmj39VEE0m3l/zipf6h2WIB2jyAO0lI6NGETh4RDcktRm4AQ==}
|
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: '>=16.8 || ^18.0.0'
|
react: '>=16.8 || ^18.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
history: 5.3.0
|
'@remix-run/router': 1.5.0
|
||||||
react: 18.2.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/react-router@6.3.0(react@18.2.0):
|
|
||||||
resolution: {integrity: sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==}
|
|
||||||
peerDependencies:
|
|
||||||
react: '>=16.8 || ^18.0.0'
|
|
||||||
dependencies:
|
|
||||||
history: 5.3.0
|
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue