codeforlife 2.8.2 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Countdown-DFI1RljW.js +28 -0
- package/dist/Countdown-DFI1RljW.js.map +1 -0
- package/dist/Countdown-zY3nMzmi.cjs +2 -0
- package/dist/Countdown-zY3nMzmi.cjs.map +1 -0
- package/dist/Image-D5jC9UoX.js +21 -0
- package/dist/Image-D5jC9UoX.js.map +1 -0
- package/dist/Image-mgT45r_B.cjs +2 -0
- package/dist/Image-mgT45r_B.cjs.map +1 -0
- package/dist/LinkButton-BYFkvL_O.cjs +2 -0
- package/dist/LinkButton-BYFkvL_O.cjs.map +1 -0
- package/dist/LinkButton-oK0RThqn.js +12 -0
- package/dist/LinkButton-oK0RThqn.js.map +1 -0
- package/dist/Navigate-Dq47aqC8.js +25 -0
- package/dist/Navigate-Dq47aqC8.js.map +1 -0
- package/dist/Navigate-dQocLhzN.cjs +2 -0
- package/dist/Navigate-dQocLhzN.cjs.map +1 -0
- package/dist/api/endpoints/index.cjs.js +2 -0
- package/dist/api/endpoints/index.cjs.js.map +1 -0
- package/dist/api/endpoints/index.d.ts +81 -0
- package/dist/api/endpoints/index.es.js +78 -0
- package/dist/api/endpoints/index.es.js.map +1 -0
- package/dist/api/index.cjs.js +4 -0
- package/dist/api/index.cjs.js.map +1 -0
- package/dist/api/index.d.ts +77 -0
- package/dist/api/index.es.js +541 -0
- package/dist/api/index.es.js.map +1 -0
- package/dist/api-Cbyt3rw0.js +92 -0
- package/dist/api-Cbyt3rw0.js.map +1 -0
- package/dist/api-CnMfjRk3.cjs +2 -0
- package/dist/api-CnMfjRk3.cjs.map +1 -0
- package/dist/api-Cs4Y-WeI.js +20 -0
- package/dist/api-Cs4Y-WeI.js.map +1 -0
- package/dist/api-DIgp_6Vr.cjs +2 -0
- package/dist/api-DIgp_6Vr.cjs.map +1 -0
- package/dist/api.d.ts +123 -0
- package/dist/auth-BPfUPjmM.js +237 -0
- package/dist/auth-BPfUPjmM.js.map +1 -0
- package/dist/auth-Vf1MgMci.cjs +2 -0
- package/dist/auth-Vf1MgMci.cjs.map +1 -0
- package/dist/auth.d.ts +40 -0
- package/dist/components/form/index.cjs.js +2 -0
- package/dist/components/form/index.cjs.js.map +1 -0
- package/dist/components/form/index.d.ts +86 -0
- package/dist/components/form/index.es.js +18 -0
- package/dist/components/form/index.es.js.map +1 -0
- package/dist/components/index.cjs.js +11 -0
- package/dist/components/index.cjs.js.map +1 -0
- package/dist/components/index.d.ts +90 -0
- package/dist/components/index.es.js +383 -0
- package/dist/components/index.es.js.map +1 -0
- package/dist/components/page/index.cjs.js +2 -0
- package/dist/components/page/index.cjs.js.map +1 -0
- package/dist/components/page/index.d.ts +77 -0
- package/dist/components/page/index.es.js +9 -0
- package/dist/components/page/index.es.js.map +1 -0
- package/dist/components/router/index.cjs.js +2 -0
- package/dist/components/router/index.cjs.js.map +1 -0
- package/dist/components/router/index.d.ts +78 -0
- package/dist/components/router/index.es.js +11 -0
- package/dist/components/router/index.es.js.map +1 -0
- package/dist/components/table/index.cjs.js +2 -0
- package/dist/components/table/index.cjs.js.map +1 -0
- package/dist/components/table/index.d.ts +75 -0
- package/dist/components/table/index.es.js +9 -0
- package/dist/components/table/index.es.js.map +1 -0
- package/dist/en-gb-B_rK7Jx1.js +20 -0
- package/dist/en-gb-B_rK7Jx1.js.map +1 -0
- package/dist/en-gb-CpyEkKq3.cjs +2 -0
- package/dist/en-gb-CpyEkKq3.cjs.map +1 -0
- package/dist/features/index.cjs.js +2 -0
- package/dist/features/index.cjs.js.map +1 -0
- package/dist/features/index.d.ts +76 -0
- package/dist/features/index.es.js +47 -0
- package/dist/features/index.es.js.map +1 -0
- package/dist/form.d.ts +40 -0
- package/dist/general-BPbbmkeX.cjs +2 -0
- package/dist/general-BPbbmkeX.cjs.map +1 -0
- package/dist/general-CtTJPCJn.js +58 -0
- package/dist/general-CtTJPCJn.js.map +1 -0
- package/dist/general.d.ts +53 -0
- package/dist/hooks/index.cjs.js +2 -0
- package/dist/hooks/index.cjs.js.map +1 -0
- package/dist/hooks/index.d.ts +77 -0
- package/dist/hooks/index.es.js +25 -0
- package/dist/hooks/index.es.js.map +1 -0
- package/dist/index-2W--_sNE.js +30 -0
- package/dist/index-2W--_sNE.js.map +1 -0
- package/dist/index-BUMdUVBH.cjs +5 -0
- package/dist/index-BUMdUVBH.cjs.map +1 -0
- package/dist/index-B_Zy_zwA.cjs +2 -0
- package/dist/index-B_Zy_zwA.cjs.map +1 -0
- package/dist/index-BgsynEGX.cjs +2 -0
- package/dist/index-BgsynEGX.cjs.map +1 -0
- package/dist/index-CA-ugBSa.cjs +2 -0
- package/dist/index-CA-ugBSa.cjs.map +1 -0
- package/dist/index-CNtOlJ49.js +572 -0
- package/dist/index-CNtOlJ49.js.map +1 -0
- package/dist/index-DkM_cG3a.js +237 -0
- package/dist/index-DkM_cG3a.js.map +1 -0
- package/dist/index-Dqp7dpn3.js +1111 -0
- package/dist/index-Dqp7dpn3.js.map +1 -0
- package/dist/index.cjs.js +2 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +78 -0
- package/dist/index.es.js +7 -0
- package/dist/index.es.js.map +1 -0
- package/dist/jsx-runtime-CeSfJrVB.cjs +31 -0
- package/dist/jsx-runtime-CeSfJrVB.cjs.map +1 -0
- package/dist/jsx-runtime-Dpn_P65e.js +634 -0
- package/dist/jsx-runtime-Dpn_P65e.js.map +1 -0
- package/dist/middlewares/index.cjs.js +2 -0
- package/dist/middlewares/index.cjs.js.map +1 -0
- package/dist/middlewares/index.d.ts +73 -0
- package/dist/middlewares/index.es.js +10 -0
- package/dist/middlewares/index.es.js.map +1 -0
- package/dist/palette-CE2mKYse.cjs +2 -0
- package/dist/palette-CE2mKYse.cjs.map +1 -0
- package/dist/palette-C_L0akN_.js +43 -0
- package/dist/palette-C_L0akN_.js.map +1 -0
- package/dist/router.d.ts +48 -0
- package/dist/rtk-query.modern-CjetfYPg.js +3038 -0
- package/dist/rtk-query.modern-CjetfYPg.js.map +1 -0
- package/dist/rtk-query.modern-PBCErCqb.cjs +15 -0
- package/dist/rtk-query.modern-PBCErCqb.cjs.map +1 -0
- package/dist/schema.d.ts +89 -0
- package/dist/schemas-BZbJpkD5.cjs +2 -0
- package/dist/schemas-BZbJpkD5.cjs.map +1 -0
- package/dist/schemas-DlOtf2vf.js +162 -0
- package/dist/schemas-DlOtf2vf.js.map +1 -0
- package/dist/server.cjs.js +6 -0
- package/dist/server.cjs.js.map +1 -0
- package/dist/server.d.ts +129 -0
- package/dist/server.es.js +127 -0
- package/dist/server.es.js.map +1 -0
- package/dist/session-CE2U7oL1.cjs +2 -0
- package/dist/session-CE2U7oL1.cjs.map +1 -0
- package/dist/session-CacrgFSv.cjs +2 -0
- package/dist/session-CacrgFSv.cjs.map +1 -0
- package/dist/session-D312kYKk.js +32 -0
- package/dist/session-D312kYKk.js.map +1 -0
- package/dist/session-oI-Ht2C8.js +30 -0
- package/dist/session-oI-Ht2C8.js.map +1 -0
- package/dist/settings/index.cjs.js +2 -0
- package/dist/settings/index.cjs.js.map +1 -0
- package/dist/settings/index.d.ts +76 -0
- package/dist/settings/index.es.js +17 -0
- package/dist/settings/index.es.js.map +1 -0
- package/dist/slices/index.cjs.js +2 -0
- package/dist/slices/index.cjs.js.map +1 -0
- package/dist/slices/index.d.ts +74 -0
- package/dist/slices/index.es.js +6 -0
- package/dist/slices/index.es.js.map +1 -0
- package/dist/store.d.ts +17 -0
- package/dist/style.css +1 -0
- package/dist/test.d.ts +75 -0
- package/dist/theme/components/index.cjs.js +2 -0
- package/dist/theme/components/index.cjs.js.map +1 -0
- package/dist/theme/components/index.d.ts +75 -0
- package/dist/theme/components/index.es.js +6 -0
- package/dist/theme/components/index.es.js.map +1 -0
- package/dist/theme/index.cjs.js +2 -0
- package/dist/theme/index.cjs.js.map +1 -0
- package/dist/theme/index.d.ts +79 -0
- package/dist/theme/index.es.js +222 -0
- package/dist/theme/index.es.js.map +1 -0
- package/dist/theme.d.ts +19 -0
- package/dist/urls-DtHr1d3H.js +14 -0
- package/dist/urls-DtHr1d3H.js.map +1 -0
- package/dist/urls-MaVXL_C2.cjs +2 -0
- package/dist/urls-MaVXL_C2.cjs.map +1 -0
- package/dist/utils/api.cjs.js +2 -0
- package/dist/utils/api.cjs.js.map +1 -0
- package/dist/utils/api.d.ts +144 -0
- package/dist/utils/api.es.js +16 -0
- package/dist/utils/api.es.js.map +1 -0
- package/dist/utils/auth.cjs.js +2 -0
- package/dist/utils/auth.cjs.js.map +1 -0
- package/dist/utils/auth.d.ts +100 -0
- package/dist/utils/auth.es.js +117 -0
- package/dist/utils/auth.es.js.map +1 -0
- package/dist/utils/form.cjs.js +2 -0
- package/dist/utils/form.cjs.js.map +1 -0
- package/dist/utils/form.d.ts +97 -0
- package/dist/utils/form.es.js +76 -0
- package/dist/utils/form.es.js.map +1 -0
- package/dist/utils/general.cjs.js +2 -0
- package/dist/utils/general.cjs.js.map +1 -0
- package/dist/utils/general.d.ts +102 -0
- package/{src/utils/general.ts → dist/utils/general.es.js} +87 -165
- package/dist/utils/general.es.js.map +1 -0
- package/dist/utils/router.cjs.js +2 -0
- package/dist/utils/router.cjs.js.map +1 -0
- package/dist/utils/router.d.ts +91 -0
- package/dist/utils/router.es.js +33 -0
- package/dist/utils/router.es.js.map +1 -0
- package/dist/utils/schema.cjs.js +2 -0
- package/dist/utils/schema.cjs.js.map +1 -0
- package/dist/utils/schema.d.ts +115 -0
- package/dist/utils/schema.es.js +123 -0
- package/dist/utils/schema.es.js.map +1 -0
- package/dist/utils/store.cjs.js +2 -0
- package/dist/utils/store.cjs.js.map +1 -0
- package/dist/utils/store.d.ts +82 -0
- package/dist/utils/store.es.js +20 -0
- package/dist/utils/store.es.js.map +1 -0
- package/dist/utils/test.cjs.js +2 -0
- package/dist/utils/test.cjs.js.map +1 -0
- package/dist/utils/test.d.ts +125 -0
- package/dist/utils/test.es.js +60 -0
- package/dist/utils/test.es.js.map +1 -0
- package/dist/utils/theme.cjs.js +2 -0
- package/dist/utils/theme.cjs.js.map +1 -0
- package/dist/utils/theme.d.ts +83 -0
- package/dist/utils/theme.es.js +12 -0
- package/dist/utils/theme.es.js.map +1 -0
- package/dist/utils/window.cjs.js +2 -0
- package/dist/utils/window.cjs.js.map +1 -0
- package/dist/utils/window.d.ts +74 -0
- package/dist/utils/window.es.js +11 -0
- package/dist/utils/window.es.js.map +1 -0
- package/dist/window.d.ts +5 -0
- package/package.json +142 -37
- package/.github/workflows/main.yml +0 -55
- package/.prettierignore +0 -1
- package/CHANGELOG.md +0 -2020
- package/CONTRIBUTING.md +0 -3
- package/eslint.config.js +0 -17
- package/src/api/createApi.ts +0 -91
- package/src/api/endpoints/authFactor.ts +0 -31
- package/src/api/endpoints/index.ts +0 -9
- package/src/api/endpoints/klass.ts +0 -87
- package/src/api/endpoints/school.ts +0 -34
- package/src/api/endpoints/session.ts +0 -47
- package/src/api/endpoints/user.ts +0 -70
- package/src/api/index.ts +0 -5
- package/src/api/models.ts +0 -145
- package/src/api/schemas.ts +0 -243
- package/src/api/tagTypes.ts +0 -12
- package/src/api/urls.ts +0 -13
- package/src/components/App.css +0 -38
- package/src/components/App.tsx +0 -152
- package/src/components/ClickableTooltip.tsx +0 -43
- package/src/components/CopyIconButton.test.tsx +0 -16
- package/src/components/CopyIconButton.tsx +0 -27
- package/src/components/Countdown.tsx +0 -42
- package/src/components/DownloadFileButton.tsx +0 -55
- package/src/components/ElevatedAppBar.tsx +0 -41
- package/src/components/Image.tsx +0 -41
- package/src/components/InputFileButton.tsx +0 -27
- package/src/components/ItemizedList.tsx +0 -61
- package/src/components/OrderedGrid.tsx +0 -92
- package/src/components/ScrollIntoViewLink.tsx +0 -22
- package/src/components/SyncError.tsx +0 -14
- package/src/components/TablePagination.tsx +0 -142
- package/src/components/YouTubeVideo.tsx +0 -26
- package/src/components/form/ApiAutocompleteField.tsx +0 -187
- package/src/components/form/AutocompleteField.tsx +0 -135
- package/src/components/form/CheckboxField.tsx +0 -86
- package/src/components/form/CountryField.tsx +0 -75
- package/src/components/form/DatePickerField.tsx +0 -126
- package/src/components/form/EmailField.tsx +0 -38
- package/src/components/form/FirstNameField.tsx +0 -40
- package/src/components/form/Form.tsx +0 -165
- package/src/components/form/OtpField.tsx +0 -28
- package/src/components/form/PasswordField.tsx +0 -71
- package/src/components/form/RepeatField.tsx +0 -123
- package/src/components/form/SubmitButton.tsx +0 -57
- package/src/components/form/TextField.tsx +0 -150
- package/src/components/form/UkCountyField.tsx +0 -68
- package/src/components/form/index.tsx +0 -35
- package/src/components/index.ts +0 -28
- package/src/components/page/Banner.tsx +0 -95
- package/src/components/page/Notification.tsx +0 -71
- package/src/components/page/Page.tsx +0 -73
- package/src/components/page/Section.tsx +0 -21
- package/src/components/page/TabBar.tsx +0 -131
- package/src/components/page/index.ts +0 -10
- package/src/components/router/Link.tsx +0 -23
- package/src/components/router/LinkButton.tsx +0 -22
- package/src/components/router/LinkIconButton.tsx +0 -22
- package/src/components/router/LinkListItem.tsx +0 -22
- package/src/components/router/LinkTab.tsx +0 -22
- package/src/components/router/Navigate.tsx +0 -33
- package/src/components/router/index.tsx +0 -9
- package/src/components/table/CellStack.tsx +0 -19
- package/src/components/table/Table.tsx +0 -55
- package/src/components/table/index.tsx +0 -8
- package/src/features/InactiveDialog.tsx +0 -40
- package/src/features/ScreenTimeDialog.tsx +0 -30
- package/src/features/index.ts +0 -4
- package/src/fonts/ttf/Inter-VariableFont_slnt,wght.ttf +0 -0
- package/src/fonts/ttf/SpaceGrotesk-VariableFont_wght.ttf +0 -0
- package/src/hooks/api.tsx +0 -39
- package/src/hooks/auth.tsx +0 -397
- package/src/hooks/form.tsx +0 -11
- package/src/hooks/general.tsx +0 -110
- package/src/hooks/index.ts +0 -5
- package/src/hooks/router.tsx +0 -168
- package/src/images/svg/brain.svg +0 -1
- package/src/index.ts +0 -2
- package/src/middlewares/index.ts +0 -1
- package/src/middlewares/session.ts +0 -21
- package/src/scripts/freshDesk.js +0 -473
- package/src/scripts/index.ts +0 -1
- package/src/server.js +0 -187
- package/src/settings/custom.ts +0 -22
- package/src/settings/index.ts +0 -7
- package/src/settings/vite.ts +0 -26
- package/src/setupTests.ts +0 -2
- package/src/slices/createSlice.ts +0 -8
- package/src/slices/index.ts +0 -2
- package/src/slices/session.ts +0 -32
- package/src/theme/ThemedBox.tsx +0 -265
- package/src/theme/colors.ts +0 -57
- package/src/theme/components/MuiAccordion.tsx +0 -13
- package/src/theme/components/MuiAutocomplete.tsx +0 -11
- package/src/theme/components/MuiButton.ts +0 -70
- package/src/theme/components/MuiCardActions.tsx +0 -12
- package/src/theme/components/MuiCheckbox.ts +0 -12
- package/src/theme/components/MuiContainer.ts +0 -19
- package/src/theme/components/MuiDialog.tsx +0 -16
- package/src/theme/components/MuiFormControlLabel.ts +0 -18
- package/src/theme/components/MuiFormHelperText.ts +0 -12
- package/src/theme/components/MuiGrid2.ts +0 -16
- package/src/theme/components/MuiInputBase.ts +0 -14
- package/src/theme/components/MuiLink.ts +0 -41
- package/src/theme/components/MuiList.ts +0 -12
- package/src/theme/components/MuiListItemText.ts +0 -18
- package/src/theme/components/MuiMenu.ts +0 -14
- package/src/theme/components/MuiMenuItem.ts +0 -15
- package/src/theme/components/MuiSelect.ts +0 -16
- package/src/theme/components/MuiTab.ts +0 -29
- package/src/theme/components/MuiTable.ts +0 -29
- package/src/theme/components/MuiTableBody.ts +0 -15
- package/src/theme/components/MuiTableHead.ts +0 -26
- package/src/theme/components/MuiTabs.ts +0 -26
- package/src/theme/components/MuiTextField.ts +0 -86
- package/src/theme/components/MuiToolbar.ts +0 -11
- package/src/theme/components/MuiTypography.ts +0 -12
- package/src/theme/components/_components.ts +0 -95
- package/src/theme/components/index.ts +0 -57
- package/src/theme/index.ts +0 -25
- package/src/theme/palette.ts +0 -98
- package/src/theme/spacing.ts +0 -8
- package/src/theme/typography.ts +0 -101
- package/src/utils/api.test.ts +0 -19
- package/src/utils/api.tsx +0 -339
- package/src/utils/auth.ts +0 -78
- package/src/utils/form.test.ts +0 -50
- package/src/utils/form.ts +0 -193
- package/src/utils/general.test.ts +0 -55
- package/src/utils/router.test.ts +0 -156
- package/src/utils/router.ts +0 -67
- package/src/utils/schema.ts +0 -290
- package/src/utils/store.ts +0 -31
- package/src/utils/test.tsx +0 -82
- package/src/utils/theme.tsx +0 -83
- package/src/utils/window.ts +0 -11
- package/src/vite-env.d.ts +0 -1
- package/tsconfig.app.json +0 -4
- package/tsconfig.json +0 -7
- package/tsconfig.node.json +0 -4
- package/types/fixes.d.ts +0 -18
- package/vite.config.ts +0 -23
package/src/hooks/auth.tsx
DELETED
|
@@ -1,397 +0,0 @@
|
|
|
1
|
-
import * as yup from "yup"
|
|
2
|
-
import { type ReactNode, useCallback, useEffect, useState } from "react"
|
|
3
|
-
import Cookies from "js-cookie"
|
|
4
|
-
import type { TypedUseMutation } from "@reduxjs/toolkit/query/react"
|
|
5
|
-
import { createSearchParams } from "react-router-dom"
|
|
6
|
-
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
|
7
|
-
import { useSelector } from "react-redux"
|
|
8
|
-
|
|
9
|
-
import { type AuthFactor, type User } from "../api"
|
|
10
|
-
import {
|
|
11
|
-
type OAuth2CodeChallenge,
|
|
12
|
-
type OAuth2CodeChallengeLengths,
|
|
13
|
-
type OAuth2ReceiveCodeUrlSearchParams,
|
|
14
|
-
type OAuth2RequestCodeUrlSearchParams,
|
|
15
|
-
generateOAuth2CodeChallenge,
|
|
16
|
-
makeOAuth2StorageKey,
|
|
17
|
-
} from "../utils/auth"
|
|
18
|
-
import { useLocation, useNavigate, useSearchParams } from "./router"
|
|
19
|
-
import { type ExchangeOAuth2CodeArg } from "../api/endpoints/session"
|
|
20
|
-
import { SESSION_METADATA_COOKIE_NAME } from "../settings"
|
|
21
|
-
import { generateSecureRandomString } from "../utils/general"
|
|
22
|
-
import { selectIsLoggedIn } from "../slices/session"
|
|
23
|
-
|
|
24
|
-
// -----------------------------------------------------------------------------
|
|
25
|
-
// Session
|
|
26
|
-
// -----------------------------------------------------------------------------
|
|
27
|
-
|
|
28
|
-
export interface SessionMetadata {
|
|
29
|
-
user_id: User["id"]
|
|
30
|
-
user_type: "teacher" | "student" | "indy"
|
|
31
|
-
auth_factors: Array<AuthFactor["type"]>
|
|
32
|
-
otp_bypass_token_exists: boolean
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function useSessionMetadata<T = SessionMetadata>(
|
|
36
|
-
cookieName = SESSION_METADATA_COOKIE_NAME,
|
|
37
|
-
): T | undefined {
|
|
38
|
-
return useSelector(selectIsLoggedIn)
|
|
39
|
-
? (JSON.parse(Cookies.get(cookieName)!) as T)
|
|
40
|
-
: undefined
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* A utility function to predefine a useSessionMetadata hook.
|
|
45
|
-
* @param cookieName The name of the session metadata cookie.
|
|
46
|
-
* @returns An object containing the session metadata.
|
|
47
|
-
*/
|
|
48
|
-
useSessionMetadata.predefine = <SessionMetadata,>(
|
|
49
|
-
cookieName = SESSION_METADATA_COOKIE_NAME,
|
|
50
|
-
) => {
|
|
51
|
-
return () => useSessionMetadata<SessionMetadata>(cookieName)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export type UseSessionChildrenFunction<Required extends boolean> = (
|
|
55
|
-
metadata: Required extends true
|
|
56
|
-
? SessionMetadata
|
|
57
|
-
: SessionMetadata | undefined,
|
|
58
|
-
) => ReactNode
|
|
59
|
-
|
|
60
|
-
export type UseSessionChildren<
|
|
61
|
-
UserType extends SessionMetadata["user_type"] | undefined,
|
|
62
|
-
> =
|
|
63
|
-
| ReactNode
|
|
64
|
-
| (UserType extends undefined
|
|
65
|
-
? UseSessionChildrenFunction<false>
|
|
66
|
-
: UseSessionChildrenFunction<true>)
|
|
67
|
-
|
|
68
|
-
export type UseSessionOptions<
|
|
69
|
-
UserType extends SessionMetadata["user_type"] | undefined,
|
|
70
|
-
> = Partial<{
|
|
71
|
-
userType: UserType
|
|
72
|
-
next: boolean
|
|
73
|
-
}>
|
|
74
|
-
|
|
75
|
-
export function useSession<
|
|
76
|
-
UserType extends SessionMetadata["user_type"] | undefined = undefined,
|
|
77
|
-
>(
|
|
78
|
-
children: UseSessionChildren<UserType>,
|
|
79
|
-
options: UseSessionOptions<UserType> = {},
|
|
80
|
-
) {
|
|
81
|
-
const { userType, next = true } = options
|
|
82
|
-
|
|
83
|
-
const { pathname } = useLocation()
|
|
84
|
-
const navigate = useNavigate()
|
|
85
|
-
const sessionMetadata = useSessionMetadata()
|
|
86
|
-
|
|
87
|
-
const loginRequired =
|
|
88
|
-
userType && (!sessionMetadata || sessionMetadata.user_type !== userType)
|
|
89
|
-
|
|
90
|
-
useEffect(() => {
|
|
91
|
-
if (loginRequired) {
|
|
92
|
-
navigate({
|
|
93
|
-
pathname:
|
|
94
|
-
"/login" +
|
|
95
|
-
{
|
|
96
|
-
teacher: "/teacher",
|
|
97
|
-
student: "/student",
|
|
98
|
-
indy: "/independent",
|
|
99
|
-
}[userType],
|
|
100
|
-
search: next
|
|
101
|
-
? createSearchParams({ next: pathname }).toString()
|
|
102
|
-
: undefined,
|
|
103
|
-
})
|
|
104
|
-
}
|
|
105
|
-
}, [navigate, loginRequired, userType, next, pathname])
|
|
106
|
-
|
|
107
|
-
if (loginRequired) return <></>
|
|
108
|
-
|
|
109
|
-
if (typeof children === "function") {
|
|
110
|
-
return sessionMetadata
|
|
111
|
-
? (children as UseSessionChildrenFunction<true>)(sessionMetadata)
|
|
112
|
-
: (children as UseSessionChildrenFunction<false>)(sessionMetadata)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return children
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// -----------------------------------------------------------------------------
|
|
119
|
-
// OAuth2
|
|
120
|
-
// -----------------------------------------------------------------------------
|
|
121
|
-
|
|
122
|
-
export function useOAuth2State(
|
|
123
|
-
provider: string,
|
|
124
|
-
length: number = 32,
|
|
125
|
-
storageKey: string = "state",
|
|
126
|
-
): [string | undefined, () => void] {
|
|
127
|
-
const oAuth2StorageKey = makeOAuth2StorageKey(provider, storageKey)
|
|
128
|
-
const storageValue = sessionStorage.getItem(oAuth2StorageKey)
|
|
129
|
-
|
|
130
|
-
const [_state, _setState] = useState<string>()
|
|
131
|
-
|
|
132
|
-
useEffect(() => {
|
|
133
|
-
let state: string
|
|
134
|
-
if (storageValue && storageValue.length === length) {
|
|
135
|
-
state = storageValue
|
|
136
|
-
} else {
|
|
137
|
-
state = generateSecureRandomString(length)
|
|
138
|
-
sessionStorage.setItem(oAuth2StorageKey, state)
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
_setState(state)
|
|
142
|
-
}, [oAuth2StorageKey, storageValue, length])
|
|
143
|
-
|
|
144
|
-
const resetState = useCallback(() => {
|
|
145
|
-
sessionStorage.removeItem(oAuth2StorageKey)
|
|
146
|
-
_setState(undefined)
|
|
147
|
-
}, [oAuth2StorageKey])
|
|
148
|
-
|
|
149
|
-
return [_state, resetState]
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export function useOAuth2CodeChallenge(
|
|
153
|
-
provider: string,
|
|
154
|
-
length: OAuth2CodeChallengeLengths = 128,
|
|
155
|
-
storageKey: string = "codeChallenge",
|
|
156
|
-
): [OAuth2CodeChallenge | undefined, () => void] {
|
|
157
|
-
const oAuth2StorageKey = makeOAuth2StorageKey(provider, storageKey)
|
|
158
|
-
const storageValue = sessionStorage.getItem(oAuth2StorageKey)
|
|
159
|
-
|
|
160
|
-
const [_codeChallenge, _setCodeChallenge] = useState<OAuth2CodeChallenge>()
|
|
161
|
-
|
|
162
|
-
useEffect(() => {
|
|
163
|
-
let codeChallenge: OAuth2CodeChallenge | undefined
|
|
164
|
-
if (storageValue) {
|
|
165
|
-
const storageJsonValue: unknown = JSON.parse(storageValue)
|
|
166
|
-
if (
|
|
167
|
-
typeof storageJsonValue === "object" &&
|
|
168
|
-
storageJsonValue &&
|
|
169
|
-
"verifier" in storageJsonValue &&
|
|
170
|
-
typeof storageJsonValue.verifier == "string" &&
|
|
171
|
-
storageJsonValue.verifier.length === length &&
|
|
172
|
-
"challenge" in storageJsonValue &&
|
|
173
|
-
typeof storageJsonValue.challenge === "string" &&
|
|
174
|
-
"method" in storageJsonValue &&
|
|
175
|
-
storageJsonValue.method === "S256"
|
|
176
|
-
) {
|
|
177
|
-
codeChallenge = {
|
|
178
|
-
verifier: storageJsonValue.verifier,
|
|
179
|
-
challenge: storageJsonValue.challenge,
|
|
180
|
-
method: storageJsonValue.method,
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if (codeChallenge) _setCodeChallenge(codeChallenge)
|
|
186
|
-
else {
|
|
187
|
-
generateOAuth2CodeChallenge(length)
|
|
188
|
-
.then(codeChallenge => {
|
|
189
|
-
sessionStorage.setItem(
|
|
190
|
-
oAuth2StorageKey,
|
|
191
|
-
JSON.stringify(codeChallenge),
|
|
192
|
-
)
|
|
193
|
-
|
|
194
|
-
_setCodeChallenge(codeChallenge)
|
|
195
|
-
})
|
|
196
|
-
.catch(error => {
|
|
197
|
-
if (error) console.error(error)
|
|
198
|
-
})
|
|
199
|
-
}
|
|
200
|
-
}, [oAuth2StorageKey, storageValue, length])
|
|
201
|
-
|
|
202
|
-
const resetCodeChallenge = useCallback(() => {
|
|
203
|
-
sessionStorage.removeItem(oAuth2StorageKey)
|
|
204
|
-
_setCodeChallenge(undefined)
|
|
205
|
-
}, [oAuth2StorageKey])
|
|
206
|
-
|
|
207
|
-
return [_codeChallenge, resetCodeChallenge]
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
interface BaseUseOAuth2KwArgs<SessionMetadata> {
|
|
211
|
-
provider: string
|
|
212
|
-
authUri: string
|
|
213
|
-
clientId: string
|
|
214
|
-
redirectUri: string
|
|
215
|
-
scope: string
|
|
216
|
-
responseType?: "code"
|
|
217
|
-
accessType?: "offline"
|
|
218
|
-
prompt?: string
|
|
219
|
-
useLoginMutation: TypedUseMutation<
|
|
220
|
-
SessionMetadata,
|
|
221
|
-
ExchangeOAuth2CodeArg,
|
|
222
|
-
any
|
|
223
|
-
>
|
|
224
|
-
onCreateSession: (result: SessionMetadata) => void
|
|
225
|
-
onRetrieveSession: (metadata: SessionMetadata) => void
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
interface UseOAuth2KwArgs<SessionMetadata>
|
|
229
|
-
extends BaseUseOAuth2KwArgs<SessionMetadata> {
|
|
230
|
-
useSessionMetadata: () => SessionMetadata | undefined
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
export type OAuth2 = [string, OAuth2RequestCodeUrlSearchParams] | []
|
|
234
|
-
|
|
235
|
-
// https://datatracker.ietf.org/doc/html/rfc7636
|
|
236
|
-
function useOAuth2Internal<SessionMetadata>({
|
|
237
|
-
provider,
|
|
238
|
-
authUri,
|
|
239
|
-
clientId,
|
|
240
|
-
redirectUri,
|
|
241
|
-
scope,
|
|
242
|
-
responseType = "code",
|
|
243
|
-
accessType = "offline",
|
|
244
|
-
prompt,
|
|
245
|
-
useSessionMetadata,
|
|
246
|
-
useLoginMutation,
|
|
247
|
-
onCreateSession,
|
|
248
|
-
onRetrieveSession,
|
|
249
|
-
}: UseOAuth2KwArgs<SessionMetadata>): OAuth2 {
|
|
250
|
-
const [state, resetState] = useOAuth2State(provider)
|
|
251
|
-
const [
|
|
252
|
-
{
|
|
253
|
-
verifier: codeVerifier,
|
|
254
|
-
challenge: codeChallenge,
|
|
255
|
-
method: codeChallengeMethod,
|
|
256
|
-
} = {},
|
|
257
|
-
resetCodeChallenge,
|
|
258
|
-
] = useOAuth2CodeChallenge(provider)
|
|
259
|
-
const [
|
|
260
|
-
login,
|
|
261
|
-
{
|
|
262
|
-
originalArgs: loginArgs = {} as ExchangeOAuth2CodeArg,
|
|
263
|
-
isLoading: loginIsLoading,
|
|
264
|
-
isError: loginIsError,
|
|
265
|
-
},
|
|
266
|
-
] = useLoginMutation()
|
|
267
|
-
const sessionMetadata = useSessionMetadata()
|
|
268
|
-
const navigate = useNavigate()
|
|
269
|
-
const searchParams =
|
|
270
|
-
useSearchParams({ code: yup.string(), state: yup.string() }) || {}
|
|
271
|
-
const location = useLocation<OAuth2ReceiveCodeUrlSearchParams>()
|
|
272
|
-
|
|
273
|
-
const locationState = location.state || {}
|
|
274
|
-
|
|
275
|
-
useEffect(() => {
|
|
276
|
-
// If the the auth provider has redirected back to our site with the
|
|
277
|
-
// expected search params, we redirect to the current page to remove them.
|
|
278
|
-
if (searchParams.code && searchParams.state) {
|
|
279
|
-
navigate<OAuth2ReceiveCodeUrlSearchParams>(".", {
|
|
280
|
-
// Removes the URL containing the search params from the history stack.
|
|
281
|
-
replace: true,
|
|
282
|
-
// Ensure we don't break the auth flow by navigating to another page.
|
|
283
|
-
next: false,
|
|
284
|
-
// Store the search params in the page's state instead.
|
|
285
|
-
state: { code: searchParams.code, state: searchParams.state },
|
|
286
|
-
})
|
|
287
|
-
}
|
|
288
|
-
}, [searchParams.code, searchParams.state, navigate])
|
|
289
|
-
|
|
290
|
-
useEffect(() => {
|
|
291
|
-
// If we're already logged in, no need to log in again.
|
|
292
|
-
if (sessionMetadata) onRetrieveSession(sessionMetadata)
|
|
293
|
-
else if (
|
|
294
|
-
// If the state and code verifier have been generated...
|
|
295
|
-
state &&
|
|
296
|
-
codeVerifier &&
|
|
297
|
-
// ...and the page's state contains a code...
|
|
298
|
-
locationState.code &&
|
|
299
|
-
// ...and the page's state contains the stored state...
|
|
300
|
-
locationState.state === state &&
|
|
301
|
-
// ...and the login endpoint was not called with the current values or has
|
|
302
|
-
// not returned an error...
|
|
303
|
-
(loginArgs.code !== locationState.code ||
|
|
304
|
-
loginArgs.code_verifier !== codeVerifier ||
|
|
305
|
-
loginArgs.redirect_uri !== redirectUri ||
|
|
306
|
-
!loginIsError) &&
|
|
307
|
-
// ...and the login endpoint is not currently being called...
|
|
308
|
-
!loginIsLoading
|
|
309
|
-
) {
|
|
310
|
-
// ...call the login endpoint.
|
|
311
|
-
login({
|
|
312
|
-
code: locationState.code,
|
|
313
|
-
code_verifier: codeVerifier,
|
|
314
|
-
redirect_uri: redirectUri,
|
|
315
|
-
})
|
|
316
|
-
.unwrap()
|
|
317
|
-
.then(onCreateSession)
|
|
318
|
-
.catch(() => {
|
|
319
|
-
navigate(".", {
|
|
320
|
-
replace: true,
|
|
321
|
-
state: {
|
|
322
|
-
notifications: [
|
|
323
|
-
{
|
|
324
|
-
props: {
|
|
325
|
-
error: true,
|
|
326
|
-
children: "Failed to login. Please try again.",
|
|
327
|
-
},
|
|
328
|
-
},
|
|
329
|
-
],
|
|
330
|
-
},
|
|
331
|
-
})
|
|
332
|
-
})
|
|
333
|
-
.finally(() => {
|
|
334
|
-
resetState()
|
|
335
|
-
resetCodeChallenge()
|
|
336
|
-
})
|
|
337
|
-
}
|
|
338
|
-
}, [
|
|
339
|
-
navigate,
|
|
340
|
-
redirectUri,
|
|
341
|
-
// State
|
|
342
|
-
state,
|
|
343
|
-
locationState.state,
|
|
344
|
-
resetState,
|
|
345
|
-
// Code
|
|
346
|
-
codeVerifier,
|
|
347
|
-
locationState.code,
|
|
348
|
-
resetCodeChallenge,
|
|
349
|
-
// Login
|
|
350
|
-
login,
|
|
351
|
-
loginIsLoading,
|
|
352
|
-
loginIsError,
|
|
353
|
-
loginArgs.code,
|
|
354
|
-
loginArgs.code_verifier,
|
|
355
|
-
loginArgs.redirect_uri,
|
|
356
|
-
// Session
|
|
357
|
-
sessionMetadata,
|
|
358
|
-
onCreateSession,
|
|
359
|
-
onRetrieveSession,
|
|
360
|
-
])
|
|
361
|
-
|
|
362
|
-
if (state && codeChallenge && codeChallengeMethod) {
|
|
363
|
-
const urlSearchParams: OAuth2RequestCodeUrlSearchParams = {
|
|
364
|
-
client_id: clientId,
|
|
365
|
-
redirect_uri: redirectUri,
|
|
366
|
-
scope,
|
|
367
|
-
response_type: responseType,
|
|
368
|
-
access_type: accessType,
|
|
369
|
-
state,
|
|
370
|
-
code_challenge: codeChallenge,
|
|
371
|
-
code_challenge_method: codeChallengeMethod,
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
if (prompt) urlSearchParams["prompt"] = prompt
|
|
375
|
-
|
|
376
|
-
return [
|
|
377
|
-
authUri + "?" + new URLSearchParams(urlSearchParams).toString(),
|
|
378
|
-
urlSearchParams,
|
|
379
|
-
]
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
return []
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
export const useOAuth2: {
|
|
386
|
-
<SessionMetadata>(kwargs: UseOAuth2KwArgs<SessionMetadata>): OAuth2
|
|
387
|
-
(kwargs: BaseUseOAuth2KwArgs<SessionMetadata>): OAuth2
|
|
388
|
-
} = <_SessionMetadata,>(
|
|
389
|
-
kwargs:
|
|
390
|
-
| UseOAuth2KwArgs<_SessionMetadata>
|
|
391
|
-
| BaseUseOAuth2KwArgs<SessionMetadata>,
|
|
392
|
-
): OAuth2 => {
|
|
393
|
-
return useOAuth2Internal(
|
|
394
|
-
// @ts-expect-error value is assignable
|
|
395
|
-
"useSessionMetadata" in kwargs ? kwargs : { ...kwargs, useSessionMetadata },
|
|
396
|
-
)
|
|
397
|
-
}
|
package/src/hooks/form.tsx
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { useRef } from "react"
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Shorthand for a reference to a HTML input element since this is so common for
|
|
5
|
-
* forms.
|
|
6
|
-
*
|
|
7
|
-
* @returns Ref object to a HTML input element.
|
|
8
|
-
*/
|
|
9
|
-
export function useInputRef() {
|
|
10
|
-
return useRef<HTMLInputElement>(null)
|
|
11
|
-
}
|
package/src/hooks/general.tsx
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type DependencyList,
|
|
3
|
-
type Dispatch,
|
|
4
|
-
type SetStateAction,
|
|
5
|
-
useEffect,
|
|
6
|
-
useState,
|
|
7
|
-
} from "react"
|
|
8
|
-
|
|
9
|
-
export function useExternalScript<EventType extends keyof HTMLElementEventMap>({
|
|
10
|
-
props,
|
|
11
|
-
attrs,
|
|
12
|
-
eventTypes,
|
|
13
|
-
}: {
|
|
14
|
-
props: Partial<HTMLScriptElement> & { src: string }
|
|
15
|
-
attrs?: Record<string, string>
|
|
16
|
-
eventTypes?: EventType[]
|
|
17
|
-
}): EventType | undefined {
|
|
18
|
-
const [eventType, setEventType] = useState<EventType>()
|
|
19
|
-
|
|
20
|
-
useEffect(() => {
|
|
21
|
-
if (
|
|
22
|
-
document.querySelector<HTMLScriptElement>(`script[src="${props.src}"]`)
|
|
23
|
-
) {
|
|
24
|
-
throw Error("already exists")
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const script = document.createElement("script")
|
|
28
|
-
|
|
29
|
-
Object.entries(props).forEach(([key, value]) => {
|
|
30
|
-
// @ts-expect-error value is assignable
|
|
31
|
-
script[key] = value
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
if (attrs !== undefined) {
|
|
35
|
-
Object.entries(attrs).forEach(([key, value]) => {
|
|
36
|
-
script.setAttribute(key, value)
|
|
37
|
-
})
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function eventListener(event: Event): void {
|
|
41
|
-
setEventType(event.type as EventType)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
eventTypes?.forEach(eventType => {
|
|
45
|
-
script.addEventListener(eventType, eventListener)
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
document.head.appendChild(script)
|
|
49
|
-
|
|
50
|
-
return () => {
|
|
51
|
-
eventTypes?.forEach(eventType => {
|
|
52
|
-
script.removeEventListener(eventType, eventListener)
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
document.head.removeChild(script)
|
|
56
|
-
}
|
|
57
|
-
}, [eventTypes, attrs, props])
|
|
58
|
-
|
|
59
|
-
return eventType
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function useCountdown(
|
|
63
|
-
seconds: number,
|
|
64
|
-
interval: number = 1,
|
|
65
|
-
): [number, Dispatch<SetStateAction<number>>] {
|
|
66
|
-
if (seconds <= 0) throw Error("seconds must be > 0")
|
|
67
|
-
if (interval <= 0) throw Error("interval must be > 0")
|
|
68
|
-
|
|
69
|
-
const [_seconds, _setSeconds] = useState(seconds)
|
|
70
|
-
|
|
71
|
-
useEffect(() => {
|
|
72
|
-
const countdown = setInterval(() => {
|
|
73
|
-
_setSeconds(seconds => {
|
|
74
|
-
seconds = seconds - interval
|
|
75
|
-
return seconds < 0 ? 0 : seconds
|
|
76
|
-
})
|
|
77
|
-
}, interval * 1000)
|
|
78
|
-
|
|
79
|
-
return () => {
|
|
80
|
-
clearInterval(countdown)
|
|
81
|
-
}
|
|
82
|
-
}, [interval])
|
|
83
|
-
|
|
84
|
-
return [_seconds, _setSeconds]
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export function useEventListener<EventType extends keyof HTMLElementEventMap>(
|
|
88
|
-
element: HTMLElement,
|
|
89
|
-
type: EventType,
|
|
90
|
-
listener: (this: HTMLElement, ev: HTMLElementEventMap[EventType]) => any,
|
|
91
|
-
kwArgs: {
|
|
92
|
-
options?: boolean | AddEventListenerOptions
|
|
93
|
-
deps?: DependencyList
|
|
94
|
-
} = {},
|
|
95
|
-
): void {
|
|
96
|
-
const { options, deps = [] } = kwArgs
|
|
97
|
-
|
|
98
|
-
useEffect(
|
|
99
|
-
() => {
|
|
100
|
-
element.addEventListener(type, listener, options)
|
|
101
|
-
|
|
102
|
-
return () => {
|
|
103
|
-
element.removeEventListener(type, listener, options)
|
|
104
|
-
}
|
|
105
|
-
},
|
|
106
|
-
// TODO: simplify this hook.
|
|
107
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
108
|
-
deps,
|
|
109
|
-
)
|
|
110
|
-
}
|
package/src/hooks/index.ts
DELETED
package/src/hooks/router.tsx
DELETED
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type Location,
|
|
3
|
-
type Params,
|
|
4
|
-
type To,
|
|
5
|
-
type NavigateOptions as _NavigateOptions,
|
|
6
|
-
useLocation as _useLocation,
|
|
7
|
-
useNavigate as _useNavigate,
|
|
8
|
-
useParams as _useParams,
|
|
9
|
-
useSearchParams as _useSearchParams,
|
|
10
|
-
} from "react-router-dom"
|
|
11
|
-
import { type ObjectShape, object as objectSchema } from "yup"
|
|
12
|
-
import { type ReactNode, useEffect } from "react"
|
|
13
|
-
|
|
14
|
-
import {
|
|
15
|
-
type ObjectSchemaFromShape,
|
|
16
|
-
type TryValidateSyncOnErrorRT,
|
|
17
|
-
type TryValidateSyncOptions,
|
|
18
|
-
type TryValidateSyncRT,
|
|
19
|
-
tryValidateSync,
|
|
20
|
-
} from "../utils/schema"
|
|
21
|
-
import { type PageState } from "../components/page"
|
|
22
|
-
import { type ReadOnly } from "../utils/router"
|
|
23
|
-
|
|
24
|
-
export type NavigateOptions<
|
|
25
|
-
State extends Record<string, any> = Record<string, any>,
|
|
26
|
-
> = Omit<_NavigateOptions, "state"> & {
|
|
27
|
-
state?: State & Partial<PageState>
|
|
28
|
-
next?: boolean
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export type Navigate = {
|
|
32
|
-
<State extends Record<string, any> = Record<string, any>>(
|
|
33
|
-
to: To,
|
|
34
|
-
options?: NavigateOptions<State>,
|
|
35
|
-
): void
|
|
36
|
-
(delta: number): void
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function useNavigate(): Navigate {
|
|
40
|
-
const navigate = _useNavigate()
|
|
41
|
-
const searchParams = useSearchParams()
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
toOrDelta: To | number,
|
|
45
|
-
options: (NavigateOptions & { next?: boolean }) | undefined = undefined,
|
|
46
|
-
) => {
|
|
47
|
-
if (typeof toOrDelta === "number") navigate(toOrDelta)
|
|
48
|
-
else {
|
|
49
|
-
const { next = true, ..._options } = options || {}
|
|
50
|
-
|
|
51
|
-
navigate(
|
|
52
|
-
next && "next" in searchParams ? searchParams.next : toOrDelta,
|
|
53
|
-
_options,
|
|
54
|
-
)
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function useLocation<State = {}>() {
|
|
60
|
-
return _useLocation() as Location<null | Partial<PageState & State>>
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// -----------------------------------------------------------------------------
|
|
64
|
-
// Use Search Params
|
|
65
|
-
// -----------------------------------------------------------------------------
|
|
66
|
-
|
|
67
|
-
export function useSearchParams(): { [k: string]: string }
|
|
68
|
-
|
|
69
|
-
export function useSearchParams<
|
|
70
|
-
OnErrorRT extends TryValidateSyncOnErrorRT<ObjectSchemaFromShape<Shape>>,
|
|
71
|
-
Shape extends ObjectShape = {},
|
|
72
|
-
>(
|
|
73
|
-
shape: Shape,
|
|
74
|
-
validateOptions?: TryValidateSyncOptions<
|
|
75
|
-
ObjectSchemaFromShape<Shape>,
|
|
76
|
-
OnErrorRT
|
|
77
|
-
>,
|
|
78
|
-
): TryValidateSyncRT<ObjectSchemaFromShape<Shape>, OnErrorRT>
|
|
79
|
-
|
|
80
|
-
export function useSearchParams<
|
|
81
|
-
OnErrorRT extends TryValidateSyncOnErrorRT<ObjectSchemaFromShape<Shape>>,
|
|
82
|
-
Shape extends ObjectShape = {},
|
|
83
|
-
>(
|
|
84
|
-
shape?: Shape,
|
|
85
|
-
validateOptions?: TryValidateSyncOptions<
|
|
86
|
-
ObjectSchemaFromShape<Shape>,
|
|
87
|
-
OnErrorRT
|
|
88
|
-
>,
|
|
89
|
-
) {
|
|
90
|
-
const searchParams = Object.fromEntries(_useSearchParams()[0].entries())
|
|
91
|
-
if (!shape) return searchParams
|
|
92
|
-
|
|
93
|
-
return tryValidateSync(searchParams, objectSchema(shape), validateOptions)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// -----------------------------------------------------------------------------
|
|
97
|
-
// Use Params
|
|
98
|
-
// -----------------------------------------------------------------------------
|
|
99
|
-
|
|
100
|
-
export function useParams(): ReadOnly<Params<string>>
|
|
101
|
-
|
|
102
|
-
export function useParams<
|
|
103
|
-
OnErrorRT extends TryValidateSyncOnErrorRT<ObjectSchemaFromShape<Shape>>,
|
|
104
|
-
Shape extends ObjectShape = {},
|
|
105
|
-
>(
|
|
106
|
-
shape: Shape,
|
|
107
|
-
validateOptions?: TryValidateSyncOptions<
|
|
108
|
-
ObjectSchemaFromShape<Shape>,
|
|
109
|
-
OnErrorRT
|
|
110
|
-
>,
|
|
111
|
-
): TryValidateSyncRT<ObjectSchemaFromShape<Shape>, OnErrorRT>
|
|
112
|
-
|
|
113
|
-
export function useParams<
|
|
114
|
-
OnErrorRT extends TryValidateSyncOnErrorRT<ObjectSchemaFromShape<Shape>>,
|
|
115
|
-
Shape extends ObjectShape = {},
|
|
116
|
-
>(
|
|
117
|
-
shape?: Shape,
|
|
118
|
-
validateOptions?: TryValidateSyncOptions<
|
|
119
|
-
ObjectSchemaFromShape<Shape>,
|
|
120
|
-
OnErrorRT
|
|
121
|
-
>,
|
|
122
|
-
) {
|
|
123
|
-
const params = _useParams()
|
|
124
|
-
if (!shape) return params
|
|
125
|
-
|
|
126
|
-
return tryValidateSync(params, objectSchema(shape), validateOptions)
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export function useParamsRequired<
|
|
130
|
-
OnErrorRT extends TryValidateSyncOnErrorRT<ObjectSchemaFromShape<Shape>>,
|
|
131
|
-
Shape extends ObjectShape = {},
|
|
132
|
-
>({
|
|
133
|
-
shape,
|
|
134
|
-
children,
|
|
135
|
-
onValidationError,
|
|
136
|
-
onValidationSuccess = () => {},
|
|
137
|
-
validateOptions,
|
|
138
|
-
}: {
|
|
139
|
-
shape: Shape
|
|
140
|
-
children: (
|
|
141
|
-
data: NonNullable<
|
|
142
|
-
TryValidateSyncRT<ObjectSchemaFromShape<Shape>, OnErrorRT>
|
|
143
|
-
>,
|
|
144
|
-
) => ReactNode
|
|
145
|
-
onValidationError: (navigate: Navigate) => void
|
|
146
|
-
onValidationSuccess?: (
|
|
147
|
-
params: NonNullable<
|
|
148
|
-
TryValidateSyncRT<ObjectSchemaFromShape<Shape>, OnErrorRT>
|
|
149
|
-
>,
|
|
150
|
-
) => void
|
|
151
|
-
validateOptions?: TryValidateSyncOptions<
|
|
152
|
-
ObjectSchemaFromShape<Shape>,
|
|
153
|
-
OnErrorRT
|
|
154
|
-
>
|
|
155
|
-
}) {
|
|
156
|
-
const params = useParams(shape, validateOptions)
|
|
157
|
-
const navigate = useNavigate()
|
|
158
|
-
|
|
159
|
-
useEffect(
|
|
160
|
-
() => {
|
|
161
|
-
if (params) onValidationSuccess(params)
|
|
162
|
-
else onValidationError(navigate)
|
|
163
|
-
},
|
|
164
|
-
[], // eslint-disable-line react-hooks/exhaustive-deps
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
return params ? children(params) : <></>
|
|
168
|
-
}
|