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.
Files changed (364) hide show
  1. package/dist/Countdown-DFI1RljW.js +28 -0
  2. package/dist/Countdown-DFI1RljW.js.map +1 -0
  3. package/dist/Countdown-zY3nMzmi.cjs +2 -0
  4. package/dist/Countdown-zY3nMzmi.cjs.map +1 -0
  5. package/dist/Image-D5jC9UoX.js +21 -0
  6. package/dist/Image-D5jC9UoX.js.map +1 -0
  7. package/dist/Image-mgT45r_B.cjs +2 -0
  8. package/dist/Image-mgT45r_B.cjs.map +1 -0
  9. package/dist/LinkButton-BYFkvL_O.cjs +2 -0
  10. package/dist/LinkButton-BYFkvL_O.cjs.map +1 -0
  11. package/dist/LinkButton-oK0RThqn.js +12 -0
  12. package/dist/LinkButton-oK0RThqn.js.map +1 -0
  13. package/dist/Navigate-Dq47aqC8.js +25 -0
  14. package/dist/Navigate-Dq47aqC8.js.map +1 -0
  15. package/dist/Navigate-dQocLhzN.cjs +2 -0
  16. package/dist/Navigate-dQocLhzN.cjs.map +1 -0
  17. package/dist/api/endpoints/index.cjs.js +2 -0
  18. package/dist/api/endpoints/index.cjs.js.map +1 -0
  19. package/dist/api/endpoints/index.d.ts +81 -0
  20. package/dist/api/endpoints/index.es.js +78 -0
  21. package/dist/api/endpoints/index.es.js.map +1 -0
  22. package/dist/api/index.cjs.js +4 -0
  23. package/dist/api/index.cjs.js.map +1 -0
  24. package/dist/api/index.d.ts +77 -0
  25. package/dist/api/index.es.js +541 -0
  26. package/dist/api/index.es.js.map +1 -0
  27. package/dist/api-Cbyt3rw0.js +92 -0
  28. package/dist/api-Cbyt3rw0.js.map +1 -0
  29. package/dist/api-CnMfjRk3.cjs +2 -0
  30. package/dist/api-CnMfjRk3.cjs.map +1 -0
  31. package/dist/api-Cs4Y-WeI.js +20 -0
  32. package/dist/api-Cs4Y-WeI.js.map +1 -0
  33. package/dist/api-DIgp_6Vr.cjs +2 -0
  34. package/dist/api-DIgp_6Vr.cjs.map +1 -0
  35. package/dist/api.d.ts +123 -0
  36. package/dist/auth-BPfUPjmM.js +237 -0
  37. package/dist/auth-BPfUPjmM.js.map +1 -0
  38. package/dist/auth-Vf1MgMci.cjs +2 -0
  39. package/dist/auth-Vf1MgMci.cjs.map +1 -0
  40. package/dist/auth.d.ts +40 -0
  41. package/dist/components/form/index.cjs.js +2 -0
  42. package/dist/components/form/index.cjs.js.map +1 -0
  43. package/dist/components/form/index.d.ts +86 -0
  44. package/dist/components/form/index.es.js +18 -0
  45. package/dist/components/form/index.es.js.map +1 -0
  46. package/dist/components/index.cjs.js +11 -0
  47. package/dist/components/index.cjs.js.map +1 -0
  48. package/dist/components/index.d.ts +90 -0
  49. package/dist/components/index.es.js +383 -0
  50. package/dist/components/index.es.js.map +1 -0
  51. package/dist/components/page/index.cjs.js +2 -0
  52. package/dist/components/page/index.cjs.js.map +1 -0
  53. package/dist/components/page/index.d.ts +77 -0
  54. package/dist/components/page/index.es.js +9 -0
  55. package/dist/components/page/index.es.js.map +1 -0
  56. package/dist/components/router/index.cjs.js +2 -0
  57. package/dist/components/router/index.cjs.js.map +1 -0
  58. package/dist/components/router/index.d.ts +78 -0
  59. package/dist/components/router/index.es.js +11 -0
  60. package/dist/components/router/index.es.js.map +1 -0
  61. package/dist/components/table/index.cjs.js +2 -0
  62. package/dist/components/table/index.cjs.js.map +1 -0
  63. package/dist/components/table/index.d.ts +75 -0
  64. package/dist/components/table/index.es.js +9 -0
  65. package/dist/components/table/index.es.js.map +1 -0
  66. package/dist/en-gb-B_rK7Jx1.js +20 -0
  67. package/dist/en-gb-B_rK7Jx1.js.map +1 -0
  68. package/dist/en-gb-CpyEkKq3.cjs +2 -0
  69. package/dist/en-gb-CpyEkKq3.cjs.map +1 -0
  70. package/dist/features/index.cjs.js +2 -0
  71. package/dist/features/index.cjs.js.map +1 -0
  72. package/dist/features/index.d.ts +76 -0
  73. package/dist/features/index.es.js +47 -0
  74. package/dist/features/index.es.js.map +1 -0
  75. package/dist/form.d.ts +40 -0
  76. package/dist/general-BPbbmkeX.cjs +2 -0
  77. package/dist/general-BPbbmkeX.cjs.map +1 -0
  78. package/dist/general-CtTJPCJn.js +58 -0
  79. package/dist/general-CtTJPCJn.js.map +1 -0
  80. package/dist/general.d.ts +53 -0
  81. package/dist/hooks/index.cjs.js +2 -0
  82. package/dist/hooks/index.cjs.js.map +1 -0
  83. package/dist/hooks/index.d.ts +77 -0
  84. package/dist/hooks/index.es.js +25 -0
  85. package/dist/hooks/index.es.js.map +1 -0
  86. package/dist/index-2W--_sNE.js +30 -0
  87. package/dist/index-2W--_sNE.js.map +1 -0
  88. package/dist/index-BUMdUVBH.cjs +5 -0
  89. package/dist/index-BUMdUVBH.cjs.map +1 -0
  90. package/dist/index-B_Zy_zwA.cjs +2 -0
  91. package/dist/index-B_Zy_zwA.cjs.map +1 -0
  92. package/dist/index-BgsynEGX.cjs +2 -0
  93. package/dist/index-BgsynEGX.cjs.map +1 -0
  94. package/dist/index-CA-ugBSa.cjs +2 -0
  95. package/dist/index-CA-ugBSa.cjs.map +1 -0
  96. package/dist/index-CNtOlJ49.js +572 -0
  97. package/dist/index-CNtOlJ49.js.map +1 -0
  98. package/dist/index-DkM_cG3a.js +237 -0
  99. package/dist/index-DkM_cG3a.js.map +1 -0
  100. package/dist/index-Dqp7dpn3.js +1111 -0
  101. package/dist/index-Dqp7dpn3.js.map +1 -0
  102. package/dist/index.cjs.js +2 -0
  103. package/dist/index.cjs.js.map +1 -0
  104. package/dist/index.d.ts +78 -0
  105. package/dist/index.es.js +7 -0
  106. package/dist/index.es.js.map +1 -0
  107. package/dist/jsx-runtime-CeSfJrVB.cjs +31 -0
  108. package/dist/jsx-runtime-CeSfJrVB.cjs.map +1 -0
  109. package/dist/jsx-runtime-Dpn_P65e.js +634 -0
  110. package/dist/jsx-runtime-Dpn_P65e.js.map +1 -0
  111. package/dist/middlewares/index.cjs.js +2 -0
  112. package/dist/middlewares/index.cjs.js.map +1 -0
  113. package/dist/middlewares/index.d.ts +73 -0
  114. package/dist/middlewares/index.es.js +10 -0
  115. package/dist/middlewares/index.es.js.map +1 -0
  116. package/dist/palette-CE2mKYse.cjs +2 -0
  117. package/dist/palette-CE2mKYse.cjs.map +1 -0
  118. package/dist/palette-C_L0akN_.js +43 -0
  119. package/dist/palette-C_L0akN_.js.map +1 -0
  120. package/dist/router.d.ts +48 -0
  121. package/dist/rtk-query.modern-CjetfYPg.js +3038 -0
  122. package/dist/rtk-query.modern-CjetfYPg.js.map +1 -0
  123. package/dist/rtk-query.modern-PBCErCqb.cjs +15 -0
  124. package/dist/rtk-query.modern-PBCErCqb.cjs.map +1 -0
  125. package/dist/schema.d.ts +89 -0
  126. package/dist/schemas-BZbJpkD5.cjs +2 -0
  127. package/dist/schemas-BZbJpkD5.cjs.map +1 -0
  128. package/dist/schemas-DlOtf2vf.js +162 -0
  129. package/dist/schemas-DlOtf2vf.js.map +1 -0
  130. package/dist/server.cjs.js +6 -0
  131. package/dist/server.cjs.js.map +1 -0
  132. package/dist/server.d.ts +129 -0
  133. package/dist/server.es.js +127 -0
  134. package/dist/server.es.js.map +1 -0
  135. package/dist/session-CE2U7oL1.cjs +2 -0
  136. package/dist/session-CE2U7oL1.cjs.map +1 -0
  137. package/dist/session-CacrgFSv.cjs +2 -0
  138. package/dist/session-CacrgFSv.cjs.map +1 -0
  139. package/dist/session-D312kYKk.js +32 -0
  140. package/dist/session-D312kYKk.js.map +1 -0
  141. package/dist/session-oI-Ht2C8.js +30 -0
  142. package/dist/session-oI-Ht2C8.js.map +1 -0
  143. package/dist/settings/index.cjs.js +2 -0
  144. package/dist/settings/index.cjs.js.map +1 -0
  145. package/dist/settings/index.d.ts +76 -0
  146. package/dist/settings/index.es.js +17 -0
  147. package/dist/settings/index.es.js.map +1 -0
  148. package/dist/slices/index.cjs.js +2 -0
  149. package/dist/slices/index.cjs.js.map +1 -0
  150. package/dist/slices/index.d.ts +74 -0
  151. package/dist/slices/index.es.js +6 -0
  152. package/dist/slices/index.es.js.map +1 -0
  153. package/dist/store.d.ts +17 -0
  154. package/dist/style.css +1 -0
  155. package/dist/test.d.ts +75 -0
  156. package/dist/theme/components/index.cjs.js +2 -0
  157. package/dist/theme/components/index.cjs.js.map +1 -0
  158. package/dist/theme/components/index.d.ts +75 -0
  159. package/dist/theme/components/index.es.js +6 -0
  160. package/dist/theme/components/index.es.js.map +1 -0
  161. package/dist/theme/index.cjs.js +2 -0
  162. package/dist/theme/index.cjs.js.map +1 -0
  163. package/dist/theme/index.d.ts +79 -0
  164. package/dist/theme/index.es.js +222 -0
  165. package/dist/theme/index.es.js.map +1 -0
  166. package/dist/theme.d.ts +19 -0
  167. package/dist/urls-DtHr1d3H.js +14 -0
  168. package/dist/urls-DtHr1d3H.js.map +1 -0
  169. package/dist/urls-MaVXL_C2.cjs +2 -0
  170. package/dist/urls-MaVXL_C2.cjs.map +1 -0
  171. package/dist/utils/api.cjs.js +2 -0
  172. package/dist/utils/api.cjs.js.map +1 -0
  173. package/dist/utils/api.d.ts +144 -0
  174. package/dist/utils/api.es.js +16 -0
  175. package/dist/utils/api.es.js.map +1 -0
  176. package/dist/utils/auth.cjs.js +2 -0
  177. package/dist/utils/auth.cjs.js.map +1 -0
  178. package/dist/utils/auth.d.ts +100 -0
  179. package/dist/utils/auth.es.js +117 -0
  180. package/dist/utils/auth.es.js.map +1 -0
  181. package/dist/utils/form.cjs.js +2 -0
  182. package/dist/utils/form.cjs.js.map +1 -0
  183. package/dist/utils/form.d.ts +97 -0
  184. package/dist/utils/form.es.js +76 -0
  185. package/dist/utils/form.es.js.map +1 -0
  186. package/dist/utils/general.cjs.js +2 -0
  187. package/dist/utils/general.cjs.js.map +1 -0
  188. package/dist/utils/general.d.ts +102 -0
  189. package/{src/utils/general.ts → dist/utils/general.es.js} +87 -165
  190. package/dist/utils/general.es.js.map +1 -0
  191. package/dist/utils/router.cjs.js +2 -0
  192. package/dist/utils/router.cjs.js.map +1 -0
  193. package/dist/utils/router.d.ts +91 -0
  194. package/dist/utils/router.es.js +33 -0
  195. package/dist/utils/router.es.js.map +1 -0
  196. package/dist/utils/schema.cjs.js +2 -0
  197. package/dist/utils/schema.cjs.js.map +1 -0
  198. package/dist/utils/schema.d.ts +115 -0
  199. package/dist/utils/schema.es.js +123 -0
  200. package/dist/utils/schema.es.js.map +1 -0
  201. package/dist/utils/store.cjs.js +2 -0
  202. package/dist/utils/store.cjs.js.map +1 -0
  203. package/dist/utils/store.d.ts +82 -0
  204. package/dist/utils/store.es.js +20 -0
  205. package/dist/utils/store.es.js.map +1 -0
  206. package/dist/utils/test.cjs.js +2 -0
  207. package/dist/utils/test.cjs.js.map +1 -0
  208. package/dist/utils/test.d.ts +125 -0
  209. package/dist/utils/test.es.js +60 -0
  210. package/dist/utils/test.es.js.map +1 -0
  211. package/dist/utils/theme.cjs.js +2 -0
  212. package/dist/utils/theme.cjs.js.map +1 -0
  213. package/dist/utils/theme.d.ts +83 -0
  214. package/dist/utils/theme.es.js +12 -0
  215. package/dist/utils/theme.es.js.map +1 -0
  216. package/dist/utils/window.cjs.js +2 -0
  217. package/dist/utils/window.cjs.js.map +1 -0
  218. package/dist/utils/window.d.ts +74 -0
  219. package/dist/utils/window.es.js +11 -0
  220. package/dist/utils/window.es.js.map +1 -0
  221. package/dist/window.d.ts +5 -0
  222. package/package.json +142 -37
  223. package/.github/workflows/main.yml +0 -55
  224. package/.prettierignore +0 -1
  225. package/CHANGELOG.md +0 -2020
  226. package/CONTRIBUTING.md +0 -3
  227. package/eslint.config.js +0 -17
  228. package/src/api/createApi.ts +0 -91
  229. package/src/api/endpoints/authFactor.ts +0 -31
  230. package/src/api/endpoints/index.ts +0 -9
  231. package/src/api/endpoints/klass.ts +0 -87
  232. package/src/api/endpoints/school.ts +0 -34
  233. package/src/api/endpoints/session.ts +0 -47
  234. package/src/api/endpoints/user.ts +0 -70
  235. package/src/api/index.ts +0 -5
  236. package/src/api/models.ts +0 -145
  237. package/src/api/schemas.ts +0 -243
  238. package/src/api/tagTypes.ts +0 -12
  239. package/src/api/urls.ts +0 -13
  240. package/src/components/App.css +0 -38
  241. package/src/components/App.tsx +0 -152
  242. package/src/components/ClickableTooltip.tsx +0 -43
  243. package/src/components/CopyIconButton.test.tsx +0 -16
  244. package/src/components/CopyIconButton.tsx +0 -27
  245. package/src/components/Countdown.tsx +0 -42
  246. package/src/components/DownloadFileButton.tsx +0 -55
  247. package/src/components/ElevatedAppBar.tsx +0 -41
  248. package/src/components/Image.tsx +0 -41
  249. package/src/components/InputFileButton.tsx +0 -27
  250. package/src/components/ItemizedList.tsx +0 -61
  251. package/src/components/OrderedGrid.tsx +0 -92
  252. package/src/components/ScrollIntoViewLink.tsx +0 -22
  253. package/src/components/SyncError.tsx +0 -14
  254. package/src/components/TablePagination.tsx +0 -142
  255. package/src/components/YouTubeVideo.tsx +0 -26
  256. package/src/components/form/ApiAutocompleteField.tsx +0 -187
  257. package/src/components/form/AutocompleteField.tsx +0 -135
  258. package/src/components/form/CheckboxField.tsx +0 -86
  259. package/src/components/form/CountryField.tsx +0 -75
  260. package/src/components/form/DatePickerField.tsx +0 -126
  261. package/src/components/form/EmailField.tsx +0 -38
  262. package/src/components/form/FirstNameField.tsx +0 -40
  263. package/src/components/form/Form.tsx +0 -165
  264. package/src/components/form/OtpField.tsx +0 -28
  265. package/src/components/form/PasswordField.tsx +0 -71
  266. package/src/components/form/RepeatField.tsx +0 -123
  267. package/src/components/form/SubmitButton.tsx +0 -57
  268. package/src/components/form/TextField.tsx +0 -150
  269. package/src/components/form/UkCountyField.tsx +0 -68
  270. package/src/components/form/index.tsx +0 -35
  271. package/src/components/index.ts +0 -28
  272. package/src/components/page/Banner.tsx +0 -95
  273. package/src/components/page/Notification.tsx +0 -71
  274. package/src/components/page/Page.tsx +0 -73
  275. package/src/components/page/Section.tsx +0 -21
  276. package/src/components/page/TabBar.tsx +0 -131
  277. package/src/components/page/index.ts +0 -10
  278. package/src/components/router/Link.tsx +0 -23
  279. package/src/components/router/LinkButton.tsx +0 -22
  280. package/src/components/router/LinkIconButton.tsx +0 -22
  281. package/src/components/router/LinkListItem.tsx +0 -22
  282. package/src/components/router/LinkTab.tsx +0 -22
  283. package/src/components/router/Navigate.tsx +0 -33
  284. package/src/components/router/index.tsx +0 -9
  285. package/src/components/table/CellStack.tsx +0 -19
  286. package/src/components/table/Table.tsx +0 -55
  287. package/src/components/table/index.tsx +0 -8
  288. package/src/features/InactiveDialog.tsx +0 -40
  289. package/src/features/ScreenTimeDialog.tsx +0 -30
  290. package/src/features/index.ts +0 -4
  291. package/src/fonts/ttf/Inter-VariableFont_slnt,wght.ttf +0 -0
  292. package/src/fonts/ttf/SpaceGrotesk-VariableFont_wght.ttf +0 -0
  293. package/src/hooks/api.tsx +0 -39
  294. package/src/hooks/auth.tsx +0 -397
  295. package/src/hooks/form.tsx +0 -11
  296. package/src/hooks/general.tsx +0 -110
  297. package/src/hooks/index.ts +0 -5
  298. package/src/hooks/router.tsx +0 -168
  299. package/src/images/svg/brain.svg +0 -1
  300. package/src/index.ts +0 -2
  301. package/src/middlewares/index.ts +0 -1
  302. package/src/middlewares/session.ts +0 -21
  303. package/src/scripts/freshDesk.js +0 -473
  304. package/src/scripts/index.ts +0 -1
  305. package/src/server.js +0 -187
  306. package/src/settings/custom.ts +0 -22
  307. package/src/settings/index.ts +0 -7
  308. package/src/settings/vite.ts +0 -26
  309. package/src/setupTests.ts +0 -2
  310. package/src/slices/createSlice.ts +0 -8
  311. package/src/slices/index.ts +0 -2
  312. package/src/slices/session.ts +0 -32
  313. package/src/theme/ThemedBox.tsx +0 -265
  314. package/src/theme/colors.ts +0 -57
  315. package/src/theme/components/MuiAccordion.tsx +0 -13
  316. package/src/theme/components/MuiAutocomplete.tsx +0 -11
  317. package/src/theme/components/MuiButton.ts +0 -70
  318. package/src/theme/components/MuiCardActions.tsx +0 -12
  319. package/src/theme/components/MuiCheckbox.ts +0 -12
  320. package/src/theme/components/MuiContainer.ts +0 -19
  321. package/src/theme/components/MuiDialog.tsx +0 -16
  322. package/src/theme/components/MuiFormControlLabel.ts +0 -18
  323. package/src/theme/components/MuiFormHelperText.ts +0 -12
  324. package/src/theme/components/MuiGrid2.ts +0 -16
  325. package/src/theme/components/MuiInputBase.ts +0 -14
  326. package/src/theme/components/MuiLink.ts +0 -41
  327. package/src/theme/components/MuiList.ts +0 -12
  328. package/src/theme/components/MuiListItemText.ts +0 -18
  329. package/src/theme/components/MuiMenu.ts +0 -14
  330. package/src/theme/components/MuiMenuItem.ts +0 -15
  331. package/src/theme/components/MuiSelect.ts +0 -16
  332. package/src/theme/components/MuiTab.ts +0 -29
  333. package/src/theme/components/MuiTable.ts +0 -29
  334. package/src/theme/components/MuiTableBody.ts +0 -15
  335. package/src/theme/components/MuiTableHead.ts +0 -26
  336. package/src/theme/components/MuiTabs.ts +0 -26
  337. package/src/theme/components/MuiTextField.ts +0 -86
  338. package/src/theme/components/MuiToolbar.ts +0 -11
  339. package/src/theme/components/MuiTypography.ts +0 -12
  340. package/src/theme/components/_components.ts +0 -95
  341. package/src/theme/components/index.ts +0 -57
  342. package/src/theme/index.ts +0 -25
  343. package/src/theme/palette.ts +0 -98
  344. package/src/theme/spacing.ts +0 -8
  345. package/src/theme/typography.ts +0 -101
  346. package/src/utils/api.test.ts +0 -19
  347. package/src/utils/api.tsx +0 -339
  348. package/src/utils/auth.ts +0 -78
  349. package/src/utils/form.test.ts +0 -50
  350. package/src/utils/form.ts +0 -193
  351. package/src/utils/general.test.ts +0 -55
  352. package/src/utils/router.test.ts +0 -156
  353. package/src/utils/router.ts +0 -67
  354. package/src/utils/schema.ts +0 -290
  355. package/src/utils/store.ts +0 -31
  356. package/src/utils/test.tsx +0 -82
  357. package/src/utils/theme.tsx +0 -83
  358. package/src/utils/window.ts +0 -11
  359. package/src/vite-env.d.ts +0 -1
  360. package/tsconfig.app.json +0 -4
  361. package/tsconfig.json +0 -7
  362. package/tsconfig.node.json +0 -4
  363. package/types/fixes.d.ts +0 -18
  364. package/vite.config.ts +0 -23
@@ -0,0 +1,237 @@
1
+ import { j as S } from "./jsx-runtime-Dpn_P65e.js";
2
+ import * as j from "yup";
3
+ import { object as L } from "yup";
4
+ import { useEffect as g, useState as V, useCallback as J } from "react";
5
+ import q from "js-cookie";
6
+ import { useNavigate as k, useLocation as w, useSearchParams as z, useParams as B, createSearchParams as G } from "react-router-dom";
7
+ import { useSelector as H } from "react-redux";
8
+ import { SESSION_METADATA_COOKIE_NAME as K } from "./settings/index.es.js";
9
+ import { b as Q } from "./session-oI-Ht2C8.js";
10
+ import { makeOAuth2StorageKey as R, generateOAuth2CodeChallenge as W } from "./utils/auth.es.js";
11
+ import "@mui/material";
12
+ import { generateSecureRandomString as X } from "./utils/general.es.js";
13
+ import "@mui/icons-material";
14
+ import "./schemas-DlOtf2vf.js";
15
+ import "./urls-DtHr1d3H.js";
16
+ import { tryValidateSync as $ } from "./utils/schema.es.js";
17
+ import "./palette-C_L0akN_.js";
18
+ function C() {
19
+ const e = k(), s = T();
20
+ return (o, t = void 0) => {
21
+ if (typeof o == "number") e(o);
22
+ else {
23
+ const { next: a = !0, ...i } = t || {};
24
+ e(
25
+ a && "next" in s ? s.next : o,
26
+ i
27
+ );
28
+ }
29
+ };
30
+ }
31
+ function F() {
32
+ return w();
33
+ }
34
+ function T(e, s) {
35
+ const o = Object.fromEntries(z()[0].entries());
36
+ return e ? $(o, L(e), s) : o;
37
+ }
38
+ function Y(e, s) {
39
+ const o = B();
40
+ return e ? $(o, L(e), s) : o;
41
+ }
42
+ function Se({
43
+ shape: e,
44
+ children: s,
45
+ onValidationError: o,
46
+ onValidationSuccess: t = () => {
47
+ },
48
+ validateOptions: a
49
+ }) {
50
+ const i = Y(e, a), n = C();
51
+ return g(
52
+ () => {
53
+ i ? t(i) : o(n);
54
+ },
55
+ []
56
+ // eslint-disable-line react-hooks/exhaustive-deps
57
+ ), i ? s(i) : /* @__PURE__ */ S.jsx(S.Fragment, {});
58
+ }
59
+ function _(e = K) {
60
+ return H(Q) ? JSON.parse(q.get(e)) : void 0;
61
+ }
62
+ _.predefine = (e = K) => () => _(e);
63
+ function _e(e, s = {}) {
64
+ const { userType: o, next: t = !0 } = s, { pathname: a } = F(), i = C(), n = _(), c = o && (!n || n.user_type !== o);
65
+ return g(() => {
66
+ c && i({
67
+ pathname: "/login" + {
68
+ teacher: "/teacher",
69
+ student: "/student",
70
+ indy: "/independent"
71
+ }[o],
72
+ search: t ? G({ next: a }).toString() : void 0
73
+ });
74
+ }, [i, c, o, t, a]), c ? /* @__PURE__ */ S.jsx(S.Fragment, {}) : typeof e == "function" ? e(n) : e;
75
+ }
76
+ function Z(e, s = 32, o = "state") {
77
+ const t = R(e, o), a = sessionStorage.getItem(t), [i, n] = V();
78
+ g(() => {
79
+ let u;
80
+ a && a.length === s ? u = a : (u = X(s), sessionStorage.setItem(t, u)), n(u);
81
+ }, [t, a, s]);
82
+ const c = J(() => {
83
+ sessionStorage.removeItem(t), n(void 0);
84
+ }, [t]);
85
+ return [i, c];
86
+ }
87
+ function D(e, s = 128, o = "codeChallenge") {
88
+ const t = R(e, o), a = sessionStorage.getItem(t), [i, n] = V();
89
+ g(() => {
90
+ let u;
91
+ if (a) {
92
+ const r = JSON.parse(a);
93
+ typeof r == "object" && r && "verifier" in r && typeof r.verifier == "string" && r.verifier.length === s && "challenge" in r && typeof r.challenge == "string" && "method" in r && r.method === "S256" && (u = {
94
+ verifier: r.verifier,
95
+ challenge: r.challenge,
96
+ method: r.method
97
+ });
98
+ }
99
+ u ? n(u) : W(s).then((r) => {
100
+ sessionStorage.setItem(
101
+ t,
102
+ JSON.stringify(r)
103
+ ), n(r);
104
+ }).catch((r) => {
105
+ r && console.error(r);
106
+ });
107
+ }, [t, a, s]);
108
+ const c = J(() => {
109
+ sessionStorage.removeItem(t), n(void 0);
110
+ }, [t]);
111
+ return [i, c];
112
+ }
113
+ function U({
114
+ provider: e,
115
+ authUri: s,
116
+ clientId: o,
117
+ redirectUri: t,
118
+ scope: a,
119
+ responseType: i = "code",
120
+ accessType: n = "offline",
121
+ prompt: c,
122
+ useSessionMetadata: u,
123
+ useLoginMutation: r,
124
+ onCreateSession: A,
125
+ onRetrieveSession: P
126
+ }) {
127
+ const [d, I] = Z(e), [
128
+ {
129
+ verifier: h,
130
+ challenge: x,
131
+ method: O
132
+ } = {},
133
+ E
134
+ ] = D(e), [
135
+ M,
136
+ {
137
+ originalArgs: m = {},
138
+ isLoading: N,
139
+ isError: b
140
+ }
141
+ ] = r(), v = u(), p = C(), f = T({ code: j.string(), state: j.string() }) || {}, l = F().state || {};
142
+ if (g(() => {
143
+ f.code && f.state && p(".", {
144
+ // Removes the URL containing the search params from the history stack.
145
+ replace: !0,
146
+ // Ensure we don't break the auth flow by navigating to another page.
147
+ next: !1,
148
+ // Store the search params in the page's state instead.
149
+ state: { code: f.code, state: f.state }
150
+ });
151
+ }, [f.code, f.state, p]), g(() => {
152
+ v ? P(v) : (
153
+ // If the state and code verifier have been generated...
154
+ d && h && // ...and the page's state contains a code...
155
+ l.code && // ...and the page's state contains the stored state...
156
+ l.state === d && // ...and the login endpoint was not called with the current values or has
157
+ // not returned an error...
158
+ (m.code !== l.code || m.code_verifier !== h || m.redirect_uri !== t || !b) && // ...and the login endpoint is not currently being called...
159
+ !N && M({
160
+ code: l.code,
161
+ code_verifier: h,
162
+ redirect_uri: t
163
+ }).unwrap().then(A).catch(() => {
164
+ p(".", {
165
+ replace: !0,
166
+ state: {
167
+ notifications: [
168
+ {
169
+ props: {
170
+ error: !0,
171
+ children: "Failed to login. Please try again."
172
+ }
173
+ }
174
+ ]
175
+ }
176
+ });
177
+ }).finally(() => {
178
+ I(), E();
179
+ })
180
+ );
181
+ }, [
182
+ p,
183
+ t,
184
+ // State
185
+ d,
186
+ l.state,
187
+ I,
188
+ // Code
189
+ h,
190
+ l.code,
191
+ E,
192
+ // Login
193
+ M,
194
+ N,
195
+ b,
196
+ m.code,
197
+ m.code_verifier,
198
+ m.redirect_uri,
199
+ // Session
200
+ v,
201
+ A,
202
+ P
203
+ ]), d && x && O) {
204
+ const y = {
205
+ client_id: o,
206
+ redirect_uri: t,
207
+ scope: a,
208
+ response_type: i,
209
+ access_type: n,
210
+ state: d,
211
+ code_challenge: x,
212
+ code_challenge_method: O
213
+ };
214
+ return c && (y.prompt = c), [
215
+ s + "?" + new URLSearchParams(y).toString(),
216
+ y
217
+ ];
218
+ }
219
+ return [];
220
+ }
221
+ const ve = (e) => U(
222
+ // @ts-expect-error value is assignable
223
+ "useSessionMetadata" in e ? e : { ...e, useSessionMetadata: _ }
224
+ );
225
+ export {
226
+ _e as a,
227
+ Z as b,
228
+ D as c,
229
+ ve as d,
230
+ C as e,
231
+ F as f,
232
+ T as g,
233
+ Y as h,
234
+ Se as i,
235
+ _ as u
236
+ };
237
+ //# sourceMappingURL=auth-BPfUPjmM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-BPfUPjmM.js","sources":["../src/hooks/router.tsx","../src/hooks/auth.tsx"],"sourcesContent":["import {\n type Location,\n type Params,\n type To,\n type NavigateOptions as _NavigateOptions,\n useLocation as _useLocation,\n useNavigate as _useNavigate,\n useParams as _useParams,\n useSearchParams as _useSearchParams,\n} from \"react-router-dom\"\nimport { type ObjectShape, object as objectSchema } from \"yup\"\nimport { type ReactNode, useEffect } from \"react\"\n\nimport {\n type ObjectSchemaFromShape,\n type TryValidateSyncOnErrorRT,\n type TryValidateSyncOptions,\n type TryValidateSyncRT,\n tryValidateSync,\n} from \"../utils/schema\"\nimport { type PageState } from \"../components/page\"\nimport { type ReadOnly } from \"../utils/router\"\n\nexport type NavigateOptions<\n State extends Record<string, any> = Record<string, any>,\n> = Omit<_NavigateOptions, \"state\"> & {\n state?: State & Partial<PageState>\n next?: boolean\n}\n\nexport type Navigate = {\n <State extends Record<string, any> = Record<string, any>>(\n to: To,\n options?: NavigateOptions<State>,\n ): void\n (delta: number): void\n}\n\nexport function useNavigate(): Navigate {\n const navigate = _useNavigate()\n const searchParams = useSearchParams()\n\n return (\n toOrDelta: To | number,\n options: (NavigateOptions & { next?: boolean }) | undefined = undefined,\n ) => {\n if (typeof toOrDelta === \"number\") navigate(toOrDelta)\n else {\n const { next = true, ..._options } = options || {}\n\n navigate(\n next && \"next\" in searchParams ? searchParams.next : toOrDelta,\n _options,\n )\n }\n }\n}\n\nexport function useLocation<State = {}>() {\n return _useLocation() as Location<null | Partial<PageState & State>>\n}\n\n// -----------------------------------------------------------------------------\n// Use Search Params\n// -----------------------------------------------------------------------------\n\nexport function useSearchParams(): { [k: string]: string }\n\nexport function useSearchParams<\n OnErrorRT extends TryValidateSyncOnErrorRT<ObjectSchemaFromShape<Shape>>,\n Shape extends ObjectShape = {},\n>(\n shape: Shape,\n validateOptions?: TryValidateSyncOptions<\n ObjectSchemaFromShape<Shape>,\n OnErrorRT\n >,\n): TryValidateSyncRT<ObjectSchemaFromShape<Shape>, OnErrorRT>\n\nexport function useSearchParams<\n OnErrorRT extends TryValidateSyncOnErrorRT<ObjectSchemaFromShape<Shape>>,\n Shape extends ObjectShape = {},\n>(\n shape?: Shape,\n validateOptions?: TryValidateSyncOptions<\n ObjectSchemaFromShape<Shape>,\n OnErrorRT\n >,\n) {\n const searchParams = Object.fromEntries(_useSearchParams()[0].entries())\n if (!shape) return searchParams\n\n return tryValidateSync(searchParams, objectSchema(shape), validateOptions)\n}\n\n// -----------------------------------------------------------------------------\n// Use Params\n// -----------------------------------------------------------------------------\n\nexport function useParams(): ReadOnly<Params<string>>\n\nexport function useParams<\n OnErrorRT extends TryValidateSyncOnErrorRT<ObjectSchemaFromShape<Shape>>,\n Shape extends ObjectShape = {},\n>(\n shape: Shape,\n validateOptions?: TryValidateSyncOptions<\n ObjectSchemaFromShape<Shape>,\n OnErrorRT\n >,\n): TryValidateSyncRT<ObjectSchemaFromShape<Shape>, OnErrorRT>\n\nexport function useParams<\n OnErrorRT extends TryValidateSyncOnErrorRT<ObjectSchemaFromShape<Shape>>,\n Shape extends ObjectShape = {},\n>(\n shape?: Shape,\n validateOptions?: TryValidateSyncOptions<\n ObjectSchemaFromShape<Shape>,\n OnErrorRT\n >,\n) {\n const params = _useParams()\n if (!shape) return params\n\n return tryValidateSync(params, objectSchema(shape), validateOptions)\n}\n\nexport function useParamsRequired<\n OnErrorRT extends TryValidateSyncOnErrorRT<ObjectSchemaFromShape<Shape>>,\n Shape extends ObjectShape = {},\n>({\n shape,\n children,\n onValidationError,\n onValidationSuccess = () => {},\n validateOptions,\n}: {\n shape: Shape\n children: (\n data: NonNullable<\n TryValidateSyncRT<ObjectSchemaFromShape<Shape>, OnErrorRT>\n >,\n ) => ReactNode\n onValidationError: (navigate: Navigate) => void\n onValidationSuccess?: (\n params: NonNullable<\n TryValidateSyncRT<ObjectSchemaFromShape<Shape>, OnErrorRT>\n >,\n ) => void\n validateOptions?: TryValidateSyncOptions<\n ObjectSchemaFromShape<Shape>,\n OnErrorRT\n >\n}) {\n const params = useParams(shape, validateOptions)\n const navigate = useNavigate()\n\n useEffect(\n () => {\n if (params) onValidationSuccess(params)\n else onValidationError(navigate)\n },\n [], // eslint-disable-line react-hooks/exhaustive-deps\n )\n\n return params ? children(params) : <></>\n}\n","import * as yup from \"yup\"\nimport { type ReactNode, useCallback, useEffect, useState } from \"react\"\nimport Cookies from \"js-cookie\"\nimport type { TypedUseMutation } from \"@reduxjs/toolkit/query/react\"\nimport { createSearchParams } from \"react-router-dom\"\n// eslint-disable-next-line @typescript-eslint/no-restricted-imports\nimport { useSelector } from \"react-redux\"\n\nimport { type AuthFactor, type User } from \"../api\"\nimport {\n type OAuth2CodeChallenge,\n type OAuth2CodeChallengeLengths,\n type OAuth2ReceiveCodeUrlSearchParams,\n type OAuth2RequestCodeUrlSearchParams,\n generateOAuth2CodeChallenge,\n makeOAuth2StorageKey,\n} from \"../utils/auth\"\nimport { useLocation, useNavigate, useSearchParams } from \"./router\"\nimport { type ExchangeOAuth2CodeArg } from \"../api/endpoints/session\"\nimport { SESSION_METADATA_COOKIE_NAME } from \"../settings\"\nimport { generateSecureRandomString } from \"../utils/general\"\nimport { selectIsLoggedIn } from \"../slices/session\"\n\n// -----------------------------------------------------------------------------\n// Session\n// -----------------------------------------------------------------------------\n\nexport interface SessionMetadata {\n user_id: User[\"id\"]\n user_type: \"teacher\" | \"student\" | \"indy\"\n auth_factors: Array<AuthFactor[\"type\"]>\n otp_bypass_token_exists: boolean\n}\n\nexport function useSessionMetadata<T = SessionMetadata>(\n cookieName = SESSION_METADATA_COOKIE_NAME,\n): T | undefined {\n return useSelector(selectIsLoggedIn)\n ? (JSON.parse(Cookies.get(cookieName)!) as T)\n : undefined\n}\n\n/**\n * A utility function to predefine a useSessionMetadata hook.\n * @param cookieName The name of the session metadata cookie.\n * @returns An object containing the session metadata.\n */\nuseSessionMetadata.predefine = <SessionMetadata,>(\n cookieName = SESSION_METADATA_COOKIE_NAME,\n) => {\n return () => useSessionMetadata<SessionMetadata>(cookieName)\n}\n\nexport type UseSessionChildrenFunction<Required extends boolean> = (\n metadata: Required extends true\n ? SessionMetadata\n : SessionMetadata | undefined,\n) => ReactNode\n\nexport type UseSessionChildren<\n UserType extends SessionMetadata[\"user_type\"] | undefined,\n> =\n | ReactNode\n | (UserType extends undefined\n ? UseSessionChildrenFunction<false>\n : UseSessionChildrenFunction<true>)\n\nexport type UseSessionOptions<\n UserType extends SessionMetadata[\"user_type\"] | undefined,\n> = Partial<{\n userType: UserType\n next: boolean\n}>\n\nexport function useSession<\n UserType extends SessionMetadata[\"user_type\"] | undefined = undefined,\n>(\n children: UseSessionChildren<UserType>,\n options: UseSessionOptions<UserType> = {},\n) {\n const { userType, next = true } = options\n\n const { pathname } = useLocation()\n const navigate = useNavigate()\n const sessionMetadata = useSessionMetadata()\n\n const loginRequired =\n userType && (!sessionMetadata || sessionMetadata.user_type !== userType)\n\n useEffect(() => {\n if (loginRequired) {\n navigate({\n pathname:\n \"/login\" +\n {\n teacher: \"/teacher\",\n student: \"/student\",\n indy: \"/independent\",\n }[userType],\n search: next\n ? createSearchParams({ next: pathname }).toString()\n : undefined,\n })\n }\n }, [navigate, loginRequired, userType, next, pathname])\n\n if (loginRequired) return <></>\n\n if (typeof children === \"function\") {\n return sessionMetadata\n ? (children as UseSessionChildrenFunction<true>)(sessionMetadata)\n : (children as UseSessionChildrenFunction<false>)(sessionMetadata)\n }\n\n return children\n}\n\n// -----------------------------------------------------------------------------\n// OAuth2\n// -----------------------------------------------------------------------------\n\nexport function useOAuth2State(\n provider: string,\n length: number = 32,\n storageKey: string = \"state\",\n): [string | undefined, () => void] {\n const oAuth2StorageKey = makeOAuth2StorageKey(provider, storageKey)\n const storageValue = sessionStorage.getItem(oAuth2StorageKey)\n\n const [_state, _setState] = useState<string>()\n\n useEffect(() => {\n let state: string\n if (storageValue && storageValue.length === length) {\n state = storageValue\n } else {\n state = generateSecureRandomString(length)\n sessionStorage.setItem(oAuth2StorageKey, state)\n }\n\n _setState(state)\n }, [oAuth2StorageKey, storageValue, length])\n\n const resetState = useCallback(() => {\n sessionStorage.removeItem(oAuth2StorageKey)\n _setState(undefined)\n }, [oAuth2StorageKey])\n\n return [_state, resetState]\n}\n\nexport function useOAuth2CodeChallenge(\n provider: string,\n length: OAuth2CodeChallengeLengths = 128,\n storageKey: string = \"codeChallenge\",\n): [OAuth2CodeChallenge | undefined, () => void] {\n const oAuth2StorageKey = makeOAuth2StorageKey(provider, storageKey)\n const storageValue = sessionStorage.getItem(oAuth2StorageKey)\n\n const [_codeChallenge, _setCodeChallenge] = useState<OAuth2CodeChallenge>()\n\n useEffect(() => {\n let codeChallenge: OAuth2CodeChallenge | undefined\n if (storageValue) {\n const storageJsonValue: unknown = JSON.parse(storageValue)\n if (\n typeof storageJsonValue === \"object\" &&\n storageJsonValue &&\n \"verifier\" in storageJsonValue &&\n typeof storageJsonValue.verifier == \"string\" &&\n storageJsonValue.verifier.length === length &&\n \"challenge\" in storageJsonValue &&\n typeof storageJsonValue.challenge === \"string\" &&\n \"method\" in storageJsonValue &&\n storageJsonValue.method === \"S256\"\n ) {\n codeChallenge = {\n verifier: storageJsonValue.verifier,\n challenge: storageJsonValue.challenge,\n method: storageJsonValue.method,\n }\n }\n }\n\n if (codeChallenge) _setCodeChallenge(codeChallenge)\n else {\n generateOAuth2CodeChallenge(length)\n .then(codeChallenge => {\n sessionStorage.setItem(\n oAuth2StorageKey,\n JSON.stringify(codeChallenge),\n )\n\n _setCodeChallenge(codeChallenge)\n })\n .catch(error => {\n if (error) console.error(error)\n })\n }\n }, [oAuth2StorageKey, storageValue, length])\n\n const resetCodeChallenge = useCallback(() => {\n sessionStorage.removeItem(oAuth2StorageKey)\n _setCodeChallenge(undefined)\n }, [oAuth2StorageKey])\n\n return [_codeChallenge, resetCodeChallenge]\n}\n\ninterface BaseUseOAuth2KwArgs<SessionMetadata> {\n provider: string\n authUri: string\n clientId: string\n redirectUri: string\n scope: string\n responseType?: \"code\"\n accessType?: \"offline\"\n prompt?: string\n useLoginMutation: TypedUseMutation<\n SessionMetadata,\n ExchangeOAuth2CodeArg,\n any\n >\n onCreateSession: (result: SessionMetadata) => void\n onRetrieveSession: (metadata: SessionMetadata) => void\n}\n\ninterface UseOAuth2KwArgs<SessionMetadata>\n extends BaseUseOAuth2KwArgs<SessionMetadata> {\n useSessionMetadata: () => SessionMetadata | undefined\n}\n\nexport type OAuth2 = [string, OAuth2RequestCodeUrlSearchParams] | []\n\n// https://datatracker.ietf.org/doc/html/rfc7636\nfunction useOAuth2Internal<SessionMetadata>({\n provider,\n authUri,\n clientId,\n redirectUri,\n scope,\n responseType = \"code\",\n accessType = \"offline\",\n prompt,\n useSessionMetadata,\n useLoginMutation,\n onCreateSession,\n onRetrieveSession,\n}: UseOAuth2KwArgs<SessionMetadata>): OAuth2 {\n const [state, resetState] = useOAuth2State(provider)\n const [\n {\n verifier: codeVerifier,\n challenge: codeChallenge,\n method: codeChallengeMethod,\n } = {},\n resetCodeChallenge,\n ] = useOAuth2CodeChallenge(provider)\n const [\n login,\n {\n originalArgs: loginArgs = {} as ExchangeOAuth2CodeArg,\n isLoading: loginIsLoading,\n isError: loginIsError,\n },\n ] = useLoginMutation()\n const sessionMetadata = useSessionMetadata()\n const navigate = useNavigate()\n const searchParams =\n useSearchParams({ code: yup.string(), state: yup.string() }) || {}\n const location = useLocation<OAuth2ReceiveCodeUrlSearchParams>()\n\n const locationState = location.state || {}\n\n useEffect(() => {\n // If the the auth provider has redirected back to our site with the\n // expected search params, we redirect to the current page to remove them.\n if (searchParams.code && searchParams.state) {\n navigate<OAuth2ReceiveCodeUrlSearchParams>(\".\", {\n // Removes the URL containing the search params from the history stack.\n replace: true,\n // Ensure we don't break the auth flow by navigating to another page.\n next: false,\n // Store the search params in the page's state instead.\n state: { code: searchParams.code, state: searchParams.state },\n })\n }\n }, [searchParams.code, searchParams.state, navigate])\n\n useEffect(() => {\n // If we're already logged in, no need to log in again.\n if (sessionMetadata) onRetrieveSession(sessionMetadata)\n else if (\n // If the state and code verifier have been generated...\n state &&\n codeVerifier &&\n // ...and the page's state contains a code...\n locationState.code &&\n // ...and the page's state contains the stored state...\n locationState.state === state &&\n // ...and the login endpoint was not called with the current values or has\n // not returned an error...\n (loginArgs.code !== locationState.code ||\n loginArgs.code_verifier !== codeVerifier ||\n loginArgs.redirect_uri !== redirectUri ||\n !loginIsError) &&\n // ...and the login endpoint is not currently being called...\n !loginIsLoading\n ) {\n // ...call the login endpoint.\n login({\n code: locationState.code,\n code_verifier: codeVerifier,\n redirect_uri: redirectUri,\n })\n .unwrap()\n .then(onCreateSession)\n .catch(() => {\n navigate(\".\", {\n replace: true,\n state: {\n notifications: [\n {\n props: {\n error: true,\n children: \"Failed to login. Please try again.\",\n },\n },\n ],\n },\n })\n })\n .finally(() => {\n resetState()\n resetCodeChallenge()\n })\n }\n }, [\n navigate,\n redirectUri,\n // State\n state,\n locationState.state,\n resetState,\n // Code\n codeVerifier,\n locationState.code,\n resetCodeChallenge,\n // Login\n login,\n loginIsLoading,\n loginIsError,\n loginArgs.code,\n loginArgs.code_verifier,\n loginArgs.redirect_uri,\n // Session\n sessionMetadata,\n onCreateSession,\n onRetrieveSession,\n ])\n\n if (state && codeChallenge && codeChallengeMethod) {\n const urlSearchParams: OAuth2RequestCodeUrlSearchParams = {\n client_id: clientId,\n redirect_uri: redirectUri,\n scope,\n response_type: responseType,\n access_type: accessType,\n state,\n code_challenge: codeChallenge,\n code_challenge_method: codeChallengeMethod,\n }\n\n if (prompt) urlSearchParams[\"prompt\"] = prompt\n\n return [\n authUri + \"?\" + new URLSearchParams(urlSearchParams).toString(),\n urlSearchParams,\n ]\n }\n\n return []\n}\n\nexport const useOAuth2: {\n <SessionMetadata>(kwargs: UseOAuth2KwArgs<SessionMetadata>): OAuth2\n (kwargs: BaseUseOAuth2KwArgs<SessionMetadata>): OAuth2\n} = <_SessionMetadata,>(\n kwargs:\n | UseOAuth2KwArgs<_SessionMetadata>\n | BaseUseOAuth2KwArgs<SessionMetadata>,\n): OAuth2 => {\n return useOAuth2Internal(\n // @ts-expect-error value is assignable\n \"useSessionMetadata\" in kwargs ? kwargs : { ...kwargs, useSessionMetadata },\n )\n}\n"],"names":["useNavigate","navigate","_useNavigate","searchParams","useSearchParams","toOrDelta","options","next","_options","useLocation","_useLocation","shape","validateOptions","_useSearchParams","tryValidateSync","objectSchema","useParams","params","_useParams","useParamsRequired","children","onValidationError","onValidationSuccess","useEffect","jsx","Fragment","useSessionMetadata","cookieName","SESSION_METADATA_COOKIE_NAME","useSelector","selectIsLoggedIn","Cookies","useSession","userType","pathname","sessionMetadata","loginRequired","createSearchParams","useOAuth2State","provider","length","storageKey","oAuth2StorageKey","makeOAuth2StorageKey","storageValue","_state","_setState","useState","state","generateSecureRandomString","resetState","useCallback","useOAuth2CodeChallenge","_codeChallenge","_setCodeChallenge","codeChallenge","storageJsonValue","generateOAuth2CodeChallenge","error","resetCodeChallenge","useOAuth2Internal","authUri","clientId","redirectUri","scope","responseType","accessType","prompt","useLoginMutation","onCreateSession","onRetrieveSession","codeVerifier","codeChallengeMethod","login","loginArgs","loginIsLoading","loginIsError","yup","locationState","urlSearchParams","useOAuth2","kwargs"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";const y=require("./jsx-runtime-CeSfJrVB.cjs"),C=require("yup"),l=require("react"),w=require("js-cookie"),S=require("react-router-dom"),z=require("react-redux"),V=require("./settings/index.cjs.js"),B=require("./session-CE2U7oL1.cjs"),E=require("./utils/auth.cjs.js");require("@mui/material");const G=require("./utils/general.cjs.js");require("@mui/icons-material");require("./schemas-BZbJpkD5.cjs");require("./urls-MaVXL_C2.cjs");const k=require("./utils/schema.cjs.js");require("./palette-CE2mKYse.cjs");function H(e){const n=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const t in e)if(t!=="default"){const s=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(n,t,s.get?s:{enumerable:!0,get:()=>e[t]})}}return n.default=e,Object.freeze(n)}const T=H(C);function O(){const e=S.useNavigate(),n=x();return(t,s=void 0)=>{if(typeof t=="number")e(t);else{const{next:o=!0,...i}=s||{};e(o&&"next"in n?n.next:t,i)}}}function q(){return S.useLocation()}function x(e,n){const t=Object.fromEntries(S.useSearchParams()[0].entries());return e?k.tryValidateSync(t,C.object(e),n):t}function J(e,n){const t=S.useParams();return e?k.tryValidateSync(t,C.object(e),n):t}function Q({shape:e,children:n,onValidationError:t,onValidationSuccess:s=()=>{},validateOptions:o}){const i=J(e,o),a=O();return l.useEffect(()=>{i?s(i):t(a)},[]),i?n(i):y.jsxRuntimeExports.jsx(y.jsxRuntimeExports.Fragment,{})}function m(e=V.SESSION_METADATA_COOKIE_NAME){return z.useSelector(B.selectIsLoggedIn)?JSON.parse(w.get(e)):void 0}m.predefine=(e=V.SESSION_METADATA_COOKIE_NAME)=>()=>m(e);function W(e,n={}){const{userType:t,next:s=!0}=n,{pathname:o}=q(),i=O(),a=m(),c=t&&(!a||a.user_type!==t);return l.useEffect(()=>{c&&i({pathname:"/login"+{teacher:"/teacher",student:"/student",indy:"/independent"}[t],search:s?S.createSearchParams({next:o}).toString():void 0})},[i,c,t,s,o]),c?y.jsxRuntimeExports.jsx(y.jsxRuntimeExports.Fragment,{}):typeof e=="function"?e(a):e}function D(e,n=32,t="state"){const s=E.makeOAuth2StorageKey(e,t),o=sessionStorage.getItem(s),[i,a]=l.useState();l.useEffect(()=>{let u;o&&o.length===n?u=o:(u=G.generateSecureRandomString(n),sessionStorage.setItem(s,u)),a(u)},[s,o,n]);const c=l.useCallback(()=>{sessionStorage.removeItem(s),a(void 0)},[s]);return[i,c]}function F(e,n=128,t="codeChallenge"){const s=E.makeOAuth2StorageKey(e,t),o=sessionStorage.getItem(s),[i,a]=l.useState();l.useEffect(()=>{let u;if(o){const r=JSON.parse(o);typeof r=="object"&&r&&"verifier"in r&&typeof r.verifier=="string"&&r.verifier.length===n&&"challenge"in r&&typeof r.challenge=="string"&&"method"in r&&r.method==="S256"&&(u={verifier:r.verifier,challenge:r.challenge,method:r.method})}u?a(u):E.generateOAuth2CodeChallenge(n).then(r=>{sessionStorage.setItem(s,JSON.stringify(r)),a(r)}).catch(r=>{r&&console.error(r)})},[s,o,n]);const c=l.useCallback(()=>{sessionStorage.removeItem(s),a(void 0)},[s]);return[i,c]}function X({provider:e,authUri:n,clientId:t,redirectUri:s,scope:o,responseType:i="code",accessType:a="offline",prompt:c,useSessionMetadata:u,useLoginMutation:r,onCreateSession:P,onRetrieveSession:j}){const[h,I]=D(e),[{verifier:p,challenge:b,method:M}={},R]=F(e),[N,{originalArgs:f={},isLoading:L,isError:K}]=r(),v=u(),_=O(),g=x({code:T.string(),state:T.string()})||{},d=q().state||{};if(l.useEffect(()=>{g.code&&g.state&&_(".",{replace:!0,next:!1,state:{code:g.code,state:g.state}})},[g.code,g.state,_]),l.useEffect(()=>{v?j(v):h&&p&&d.code&&d.state===h&&(f.code!==d.code||f.code_verifier!==p||f.redirect_uri!==s||!K)&&!L&&N({code:d.code,code_verifier:p,redirect_uri:s}).unwrap().then(P).catch(()=>{_(".",{replace:!0,state:{notifications:[{props:{error:!0,children:"Failed to login. Please try again."}}]}})}).finally(()=>{I(),R()})},[_,s,h,d.state,I,p,d.code,R,N,L,K,f.code,f.code_verifier,f.redirect_uri,v,P,j]),h&&b&&M){const A={client_id:t,redirect_uri:s,scope:o,response_type:i,access_type:a,state:h,code_challenge:b,code_challenge_method:M};return c&&(A.prompt=c),[n+"?"+new URLSearchParams(A).toString(),A]}return[]}const Y=e=>X("useSessionMetadata"in e?e:{...e,useSessionMetadata:m});exports.useLocation=q;exports.useNavigate=O;exports.useOAuth2=Y;exports.useOAuth2CodeChallenge=F;exports.useOAuth2State=D;exports.useParams=J;exports.useParamsRequired=Q;exports.useSearchParams=x;exports.useSession=W;exports.useSessionMetadata=m;
2
+ //# sourceMappingURL=auth-Vf1MgMci.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-Vf1MgMci.cjs","sources":["../src/hooks/router.tsx","../src/hooks/auth.tsx"],"sourcesContent":["import {\n type Location,\n type Params,\n type To,\n type NavigateOptions as _NavigateOptions,\n useLocation as _useLocation,\n useNavigate as _useNavigate,\n useParams as _useParams,\n useSearchParams as _useSearchParams,\n} from \"react-router-dom\"\nimport { type ObjectShape, object as objectSchema } from \"yup\"\nimport { type ReactNode, useEffect } from \"react\"\n\nimport {\n type ObjectSchemaFromShape,\n type TryValidateSyncOnErrorRT,\n type TryValidateSyncOptions,\n type TryValidateSyncRT,\n tryValidateSync,\n} from \"../utils/schema\"\nimport { type PageState } from \"../components/page\"\nimport { type ReadOnly } from \"../utils/router\"\n\nexport type NavigateOptions<\n State extends Record<string, any> = Record<string, any>,\n> = Omit<_NavigateOptions, \"state\"> & {\n state?: State & Partial<PageState>\n next?: boolean\n}\n\nexport type Navigate = {\n <State extends Record<string, any> = Record<string, any>>(\n to: To,\n options?: NavigateOptions<State>,\n ): void\n (delta: number): void\n}\n\nexport function useNavigate(): Navigate {\n const navigate = _useNavigate()\n const searchParams = useSearchParams()\n\n return (\n toOrDelta: To | number,\n options: (NavigateOptions & { next?: boolean }) | undefined = undefined,\n ) => {\n if (typeof toOrDelta === \"number\") navigate(toOrDelta)\n else {\n const { next = true, ..._options } = options || {}\n\n navigate(\n next && \"next\" in searchParams ? searchParams.next : toOrDelta,\n _options,\n )\n }\n }\n}\n\nexport function useLocation<State = {}>() {\n return _useLocation() as Location<null | Partial<PageState & State>>\n}\n\n// -----------------------------------------------------------------------------\n// Use Search Params\n// -----------------------------------------------------------------------------\n\nexport function useSearchParams(): { [k: string]: string }\n\nexport function useSearchParams<\n OnErrorRT extends TryValidateSyncOnErrorRT<ObjectSchemaFromShape<Shape>>,\n Shape extends ObjectShape = {},\n>(\n shape: Shape,\n validateOptions?: TryValidateSyncOptions<\n ObjectSchemaFromShape<Shape>,\n OnErrorRT\n >,\n): TryValidateSyncRT<ObjectSchemaFromShape<Shape>, OnErrorRT>\n\nexport function useSearchParams<\n OnErrorRT extends TryValidateSyncOnErrorRT<ObjectSchemaFromShape<Shape>>,\n Shape extends ObjectShape = {},\n>(\n shape?: Shape,\n validateOptions?: TryValidateSyncOptions<\n ObjectSchemaFromShape<Shape>,\n OnErrorRT\n >,\n) {\n const searchParams = Object.fromEntries(_useSearchParams()[0].entries())\n if (!shape) return searchParams\n\n return tryValidateSync(searchParams, objectSchema(shape), validateOptions)\n}\n\n// -----------------------------------------------------------------------------\n// Use Params\n// -----------------------------------------------------------------------------\n\nexport function useParams(): ReadOnly<Params<string>>\n\nexport function useParams<\n OnErrorRT extends TryValidateSyncOnErrorRT<ObjectSchemaFromShape<Shape>>,\n Shape extends ObjectShape = {},\n>(\n shape: Shape,\n validateOptions?: TryValidateSyncOptions<\n ObjectSchemaFromShape<Shape>,\n OnErrorRT\n >,\n): TryValidateSyncRT<ObjectSchemaFromShape<Shape>, OnErrorRT>\n\nexport function useParams<\n OnErrorRT extends TryValidateSyncOnErrorRT<ObjectSchemaFromShape<Shape>>,\n Shape extends ObjectShape = {},\n>(\n shape?: Shape,\n validateOptions?: TryValidateSyncOptions<\n ObjectSchemaFromShape<Shape>,\n OnErrorRT\n >,\n) {\n const params = _useParams()\n if (!shape) return params\n\n return tryValidateSync(params, objectSchema(shape), validateOptions)\n}\n\nexport function useParamsRequired<\n OnErrorRT extends TryValidateSyncOnErrorRT<ObjectSchemaFromShape<Shape>>,\n Shape extends ObjectShape = {},\n>({\n shape,\n children,\n onValidationError,\n onValidationSuccess = () => {},\n validateOptions,\n}: {\n shape: Shape\n children: (\n data: NonNullable<\n TryValidateSyncRT<ObjectSchemaFromShape<Shape>, OnErrorRT>\n >,\n ) => ReactNode\n onValidationError: (navigate: Navigate) => void\n onValidationSuccess?: (\n params: NonNullable<\n TryValidateSyncRT<ObjectSchemaFromShape<Shape>, OnErrorRT>\n >,\n ) => void\n validateOptions?: TryValidateSyncOptions<\n ObjectSchemaFromShape<Shape>,\n OnErrorRT\n >\n}) {\n const params = useParams(shape, validateOptions)\n const navigate = useNavigate()\n\n useEffect(\n () => {\n if (params) onValidationSuccess(params)\n else onValidationError(navigate)\n },\n [], // eslint-disable-line react-hooks/exhaustive-deps\n )\n\n return params ? children(params) : <></>\n}\n","import * as yup from \"yup\"\nimport { type ReactNode, useCallback, useEffect, useState } from \"react\"\nimport Cookies from \"js-cookie\"\nimport type { TypedUseMutation } from \"@reduxjs/toolkit/query/react\"\nimport { createSearchParams } from \"react-router-dom\"\n// eslint-disable-next-line @typescript-eslint/no-restricted-imports\nimport { useSelector } from \"react-redux\"\n\nimport { type AuthFactor, type User } from \"../api\"\nimport {\n type OAuth2CodeChallenge,\n type OAuth2CodeChallengeLengths,\n type OAuth2ReceiveCodeUrlSearchParams,\n type OAuth2RequestCodeUrlSearchParams,\n generateOAuth2CodeChallenge,\n makeOAuth2StorageKey,\n} from \"../utils/auth\"\nimport { useLocation, useNavigate, useSearchParams } from \"./router\"\nimport { type ExchangeOAuth2CodeArg } from \"../api/endpoints/session\"\nimport { SESSION_METADATA_COOKIE_NAME } from \"../settings\"\nimport { generateSecureRandomString } from \"../utils/general\"\nimport { selectIsLoggedIn } from \"../slices/session\"\n\n// -----------------------------------------------------------------------------\n// Session\n// -----------------------------------------------------------------------------\n\nexport interface SessionMetadata {\n user_id: User[\"id\"]\n user_type: \"teacher\" | \"student\" | \"indy\"\n auth_factors: Array<AuthFactor[\"type\"]>\n otp_bypass_token_exists: boolean\n}\n\nexport function useSessionMetadata<T = SessionMetadata>(\n cookieName = SESSION_METADATA_COOKIE_NAME,\n): T | undefined {\n return useSelector(selectIsLoggedIn)\n ? (JSON.parse(Cookies.get(cookieName)!) as T)\n : undefined\n}\n\n/**\n * A utility function to predefine a useSessionMetadata hook.\n * @param cookieName The name of the session metadata cookie.\n * @returns An object containing the session metadata.\n */\nuseSessionMetadata.predefine = <SessionMetadata,>(\n cookieName = SESSION_METADATA_COOKIE_NAME,\n) => {\n return () => useSessionMetadata<SessionMetadata>(cookieName)\n}\n\nexport type UseSessionChildrenFunction<Required extends boolean> = (\n metadata: Required extends true\n ? SessionMetadata\n : SessionMetadata | undefined,\n) => ReactNode\n\nexport type UseSessionChildren<\n UserType extends SessionMetadata[\"user_type\"] | undefined,\n> =\n | ReactNode\n | (UserType extends undefined\n ? UseSessionChildrenFunction<false>\n : UseSessionChildrenFunction<true>)\n\nexport type UseSessionOptions<\n UserType extends SessionMetadata[\"user_type\"] | undefined,\n> = Partial<{\n userType: UserType\n next: boolean\n}>\n\nexport function useSession<\n UserType extends SessionMetadata[\"user_type\"] | undefined = undefined,\n>(\n children: UseSessionChildren<UserType>,\n options: UseSessionOptions<UserType> = {},\n) {\n const { userType, next = true } = options\n\n const { pathname } = useLocation()\n const navigate = useNavigate()\n const sessionMetadata = useSessionMetadata()\n\n const loginRequired =\n userType && (!sessionMetadata || sessionMetadata.user_type !== userType)\n\n useEffect(() => {\n if (loginRequired) {\n navigate({\n pathname:\n \"/login\" +\n {\n teacher: \"/teacher\",\n student: \"/student\",\n indy: \"/independent\",\n }[userType],\n search: next\n ? createSearchParams({ next: pathname }).toString()\n : undefined,\n })\n }\n }, [navigate, loginRequired, userType, next, pathname])\n\n if (loginRequired) return <></>\n\n if (typeof children === \"function\") {\n return sessionMetadata\n ? (children as UseSessionChildrenFunction<true>)(sessionMetadata)\n : (children as UseSessionChildrenFunction<false>)(sessionMetadata)\n }\n\n return children\n}\n\n// -----------------------------------------------------------------------------\n// OAuth2\n// -----------------------------------------------------------------------------\n\nexport function useOAuth2State(\n provider: string,\n length: number = 32,\n storageKey: string = \"state\",\n): [string | undefined, () => void] {\n const oAuth2StorageKey = makeOAuth2StorageKey(provider, storageKey)\n const storageValue = sessionStorage.getItem(oAuth2StorageKey)\n\n const [_state, _setState] = useState<string>()\n\n useEffect(() => {\n let state: string\n if (storageValue && storageValue.length === length) {\n state = storageValue\n } else {\n state = generateSecureRandomString(length)\n sessionStorage.setItem(oAuth2StorageKey, state)\n }\n\n _setState(state)\n }, [oAuth2StorageKey, storageValue, length])\n\n const resetState = useCallback(() => {\n sessionStorage.removeItem(oAuth2StorageKey)\n _setState(undefined)\n }, [oAuth2StorageKey])\n\n return [_state, resetState]\n}\n\nexport function useOAuth2CodeChallenge(\n provider: string,\n length: OAuth2CodeChallengeLengths = 128,\n storageKey: string = \"codeChallenge\",\n): [OAuth2CodeChallenge | undefined, () => void] {\n const oAuth2StorageKey = makeOAuth2StorageKey(provider, storageKey)\n const storageValue = sessionStorage.getItem(oAuth2StorageKey)\n\n const [_codeChallenge, _setCodeChallenge] = useState<OAuth2CodeChallenge>()\n\n useEffect(() => {\n let codeChallenge: OAuth2CodeChallenge | undefined\n if (storageValue) {\n const storageJsonValue: unknown = JSON.parse(storageValue)\n if (\n typeof storageJsonValue === \"object\" &&\n storageJsonValue &&\n \"verifier\" in storageJsonValue &&\n typeof storageJsonValue.verifier == \"string\" &&\n storageJsonValue.verifier.length === length &&\n \"challenge\" in storageJsonValue &&\n typeof storageJsonValue.challenge === \"string\" &&\n \"method\" in storageJsonValue &&\n storageJsonValue.method === \"S256\"\n ) {\n codeChallenge = {\n verifier: storageJsonValue.verifier,\n challenge: storageJsonValue.challenge,\n method: storageJsonValue.method,\n }\n }\n }\n\n if (codeChallenge) _setCodeChallenge(codeChallenge)\n else {\n generateOAuth2CodeChallenge(length)\n .then(codeChallenge => {\n sessionStorage.setItem(\n oAuth2StorageKey,\n JSON.stringify(codeChallenge),\n )\n\n _setCodeChallenge(codeChallenge)\n })\n .catch(error => {\n if (error) console.error(error)\n })\n }\n }, [oAuth2StorageKey, storageValue, length])\n\n const resetCodeChallenge = useCallback(() => {\n sessionStorage.removeItem(oAuth2StorageKey)\n _setCodeChallenge(undefined)\n }, [oAuth2StorageKey])\n\n return [_codeChallenge, resetCodeChallenge]\n}\n\ninterface BaseUseOAuth2KwArgs<SessionMetadata> {\n provider: string\n authUri: string\n clientId: string\n redirectUri: string\n scope: string\n responseType?: \"code\"\n accessType?: \"offline\"\n prompt?: string\n useLoginMutation: TypedUseMutation<\n SessionMetadata,\n ExchangeOAuth2CodeArg,\n any\n >\n onCreateSession: (result: SessionMetadata) => void\n onRetrieveSession: (metadata: SessionMetadata) => void\n}\n\ninterface UseOAuth2KwArgs<SessionMetadata>\n extends BaseUseOAuth2KwArgs<SessionMetadata> {\n useSessionMetadata: () => SessionMetadata | undefined\n}\n\nexport type OAuth2 = [string, OAuth2RequestCodeUrlSearchParams] | []\n\n// https://datatracker.ietf.org/doc/html/rfc7636\nfunction useOAuth2Internal<SessionMetadata>({\n provider,\n authUri,\n clientId,\n redirectUri,\n scope,\n responseType = \"code\",\n accessType = \"offline\",\n prompt,\n useSessionMetadata,\n useLoginMutation,\n onCreateSession,\n onRetrieveSession,\n}: UseOAuth2KwArgs<SessionMetadata>): OAuth2 {\n const [state, resetState] = useOAuth2State(provider)\n const [\n {\n verifier: codeVerifier,\n challenge: codeChallenge,\n method: codeChallengeMethod,\n } = {},\n resetCodeChallenge,\n ] = useOAuth2CodeChallenge(provider)\n const [\n login,\n {\n originalArgs: loginArgs = {} as ExchangeOAuth2CodeArg,\n isLoading: loginIsLoading,\n isError: loginIsError,\n },\n ] = useLoginMutation()\n const sessionMetadata = useSessionMetadata()\n const navigate = useNavigate()\n const searchParams =\n useSearchParams({ code: yup.string(), state: yup.string() }) || {}\n const location = useLocation<OAuth2ReceiveCodeUrlSearchParams>()\n\n const locationState = location.state || {}\n\n useEffect(() => {\n // If the the auth provider has redirected back to our site with the\n // expected search params, we redirect to the current page to remove them.\n if (searchParams.code && searchParams.state) {\n navigate<OAuth2ReceiveCodeUrlSearchParams>(\".\", {\n // Removes the URL containing the search params from the history stack.\n replace: true,\n // Ensure we don't break the auth flow by navigating to another page.\n next: false,\n // Store the search params in the page's state instead.\n state: { code: searchParams.code, state: searchParams.state },\n })\n }\n }, [searchParams.code, searchParams.state, navigate])\n\n useEffect(() => {\n // If we're already logged in, no need to log in again.\n if (sessionMetadata) onRetrieveSession(sessionMetadata)\n else if (\n // If the state and code verifier have been generated...\n state &&\n codeVerifier &&\n // ...and the page's state contains a code...\n locationState.code &&\n // ...and the page's state contains the stored state...\n locationState.state === state &&\n // ...and the login endpoint was not called with the current values or has\n // not returned an error...\n (loginArgs.code !== locationState.code ||\n loginArgs.code_verifier !== codeVerifier ||\n loginArgs.redirect_uri !== redirectUri ||\n !loginIsError) &&\n // ...and the login endpoint is not currently being called...\n !loginIsLoading\n ) {\n // ...call the login endpoint.\n login({\n code: locationState.code,\n code_verifier: codeVerifier,\n redirect_uri: redirectUri,\n })\n .unwrap()\n .then(onCreateSession)\n .catch(() => {\n navigate(\".\", {\n replace: true,\n state: {\n notifications: [\n {\n props: {\n error: true,\n children: \"Failed to login. Please try again.\",\n },\n },\n ],\n },\n })\n })\n .finally(() => {\n resetState()\n resetCodeChallenge()\n })\n }\n }, [\n navigate,\n redirectUri,\n // State\n state,\n locationState.state,\n resetState,\n // Code\n codeVerifier,\n locationState.code,\n resetCodeChallenge,\n // Login\n login,\n loginIsLoading,\n loginIsError,\n loginArgs.code,\n loginArgs.code_verifier,\n loginArgs.redirect_uri,\n // Session\n sessionMetadata,\n onCreateSession,\n onRetrieveSession,\n ])\n\n if (state && codeChallenge && codeChallengeMethod) {\n const urlSearchParams: OAuth2RequestCodeUrlSearchParams = {\n client_id: clientId,\n redirect_uri: redirectUri,\n scope,\n response_type: responseType,\n access_type: accessType,\n state,\n code_challenge: codeChallenge,\n code_challenge_method: codeChallengeMethod,\n }\n\n if (prompt) urlSearchParams[\"prompt\"] = prompt\n\n return [\n authUri + \"?\" + new URLSearchParams(urlSearchParams).toString(),\n urlSearchParams,\n ]\n }\n\n return []\n}\n\nexport const useOAuth2: {\n <SessionMetadata>(kwargs: UseOAuth2KwArgs<SessionMetadata>): OAuth2\n (kwargs: BaseUseOAuth2KwArgs<SessionMetadata>): OAuth2\n} = <_SessionMetadata,>(\n kwargs:\n | UseOAuth2KwArgs<_SessionMetadata>\n | BaseUseOAuth2KwArgs<SessionMetadata>,\n): OAuth2 => {\n return useOAuth2Internal(\n // @ts-expect-error value is assignable\n \"useSessionMetadata\" in kwargs ? kwargs : { ...kwargs, useSessionMetadata },\n )\n}\n"],"names":["useNavigate","navigate","_useNavigate","searchParams","useSearchParams","toOrDelta","options","next","_options","useLocation","_useLocation","shape","validateOptions","_useSearchParams","tryValidateSync","objectSchema","useParams","params","_useParams","useParamsRequired","children","onValidationError","onValidationSuccess","useEffect","jsx","Fragment","useSessionMetadata","cookieName","SESSION_METADATA_COOKIE_NAME","useSelector","selectIsLoggedIn","Cookies","useSession","userType","pathname","sessionMetadata","loginRequired","createSearchParams","useOAuth2State","provider","length","storageKey","oAuth2StorageKey","makeOAuth2StorageKey","storageValue","_state","_setState","useState","state","generateSecureRandomString","resetState","useCallback","useOAuth2CodeChallenge","_codeChallenge","_setCodeChallenge","codeChallenge","storageJsonValue","generateOAuth2CodeChallenge","error","resetCodeChallenge","useOAuth2Internal","authUri","clientId","redirectUri","scope","responseType","accessType","prompt","useLoginMutation","onCreateSession","onRetrieveSession","codeVerifier","codeChallengeMethod","login","loginArgs","loginIsLoading","loginIsError","yup","locationState","urlSearchParams","useOAuth2","kwargs"],"mappings":"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"}
package/dist/auth.d.ts ADDED
@@ -0,0 +1,40 @@
1
+ export declare function generateOAuth2CodeChallenge(length: OAuth2CodeChallengeLengths): Promise<OAuth2CodeChallenge>;
2
+
3
+ export declare function getCsrfCookie(): string | undefined;
4
+
5
+ export declare function logout(): void;
6
+
7
+ export declare function makeOAuth2StorageKey(provider: string, key: string): string;
8
+
9
+ export declare const OAUTH2_CODE_CHALLENGE_LENGTHS: readonly [43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128];
10
+
11
+ export declare const OAUTH2_CODE_CHALLENGE_METHODS: readonly ["S256"];
12
+
13
+ export declare type OAuth2CodeChallenge = {
14
+ verifier: string;
15
+ challenge: string;
16
+ method: OAuth2CodeChallengeMethods;
17
+ };
18
+
19
+ export declare type OAuth2CodeChallengeLengths = (typeof OAUTH2_CODE_CHALLENGE_LENGTHS)[number];
20
+
21
+ export declare type OAuth2CodeChallengeMethods = (typeof OAUTH2_CODE_CHALLENGE_METHODS)[number];
22
+
23
+ export declare type OAuth2ReceiveCodeUrlSearchParams = {
24
+ code: string;
25
+ state: string;
26
+ };
27
+
28
+ export declare type OAuth2RequestCodeUrlSearchParams = {
29
+ client_id: string;
30
+ redirect_uri: string;
31
+ scope: string;
32
+ response_type: string;
33
+ access_type: string;
34
+ prompt?: string;
35
+ state: string;
36
+ code_challenge: string;
37
+ code_challenge_method: string;
38
+ };
39
+
40
+ export { }
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../../index-BUMdUVBH.cjs");exports.ApiAutocompleteField=e.ApiAutocompleteField;exports.AutocompleteField=e.AutocompleteField;exports.CheckboxField=e.CheckboxField;exports.CountryField=e.CountryField;exports.DatePickerField=e.DatePickerField;exports.EmailField=e.EmailField;exports.FirstNameField=e.FirstNameField;exports.Form=e.Form;exports.OtpField=e.OtpField;exports.PasswordField=e.PasswordField;exports.RepeatField=e.RepeatField;exports.SubmitButton=e.SubmitButton;exports.TextField=e.TextField;exports.UkCountyField=e.UkCountyField;
2
+ //# sourceMappingURL=index.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,86 @@
1
+ export { default as ApiAutocompleteField, type ApiAutocompleteFieldProps, } from './ApiAutocompleteField';
2
+ export { default as AutocompleteField, type AutocompleteFieldProps, } from './AutocompleteField';
3
+ export { default as CheckboxField, type CheckboxFieldProps, } from './CheckboxField';
4
+ export { default as CountryField, type CountryFieldProps } from './CountryField';
5
+ export { default as DatePickerField, type DatePickerFieldProps, } from './DatePickerField';
6
+ export { default as EmailField, type EmailFieldProps } from './EmailField';
7
+ export { default as FirstNameField, type FirstNameFieldProps, } from './FirstNameField';
8
+ export { default as Form, type FormProps, type FormErrors } from './Form';
9
+ export { default as OtpField, type OtpFieldProps } from './OtpField';
10
+ export { default as PasswordField, type PasswordFieldProps, } from './PasswordField';
11
+ export { default as RepeatField, type RepeatFieldProps } from './RepeatField';
12
+ export { default as SubmitButton, type SubmitButtonProps } from './SubmitButton';
13
+ export { default as TextField, type TextFieldProps } from './TextField';
14
+ export { default as UkCountyField, type UkCountyFieldProps, } from './UkCountyField';
15
+
16
+
17
+ declare module "@mui/material/styles" {
18
+ interface CustomPaletteColors {
19
+ tertiary: PaletteColor;
20
+ white: PaletteColor;
21
+ black: PaletteColor;
22
+ teacher: PaletteColor;
23
+ student: PaletteColor;
24
+ indy: PaletteColor;
25
+ }
26
+ interface Palette extends CustomPaletteColors {
27
+ }
28
+ interface PaletteOptions extends CustomPaletteColors {
29
+ }
30
+ }
31
+
32
+
33
+ declare module "@mui/material" {
34
+ interface FabPropsColorOverrides extends PropsColorOverrides {
35
+ }
36
+ interface CardPropsColorOverrides extends PropsColorOverrides {
37
+ }
38
+ interface ChipPropsColorOverrides extends PropsColorOverrides {
39
+ }
40
+ interface IconPropsColorOverrides extends PropsColorOverrides {
41
+ }
42
+ interface AlertPropsColorOverrides extends PropsColorOverrides {
43
+ }
44
+ interface BadgePropsColorOverrides extends PropsColorOverrides {
45
+ }
46
+ interface RadioPropsColorOverrides extends PropsColorOverrides {
47
+ }
48
+ interface AppBarPropsColorOverrides extends PropsColorOverrides {
49
+ }
50
+ interface ButtonPropsColorOverrides extends PropsColorOverrides {
51
+ }
52
+ interface SliderPropsColorOverrides extends PropsColorOverrides {
53
+ }
54
+ interface SwitchPropsColorOverrides extends PropsColorOverrides {
55
+ }
56
+ interface SvgIconPropsColorOverrides extends PropsColorOverrides {
57
+ }
58
+ interface CheckboxPropsColorOverrides extends PropsColorOverrides {
59
+ }
60
+ interface FormLabelPropsColorOverrides extends PropsColorOverrides {
61
+ }
62
+ interface InputBasePropsColorOverrides extends PropsColorOverrides {
63
+ }
64
+ interface TextFieldPropsColorOverrides extends PropsColorOverrides {
65
+ }
66
+ interface IconButtonPropsColorOverrides extends PropsColorOverrides {
67
+ }
68
+ interface PaginationPropsColorOverrides extends PropsColorOverrides {
69
+ }
70
+ interface ButtonGroupPropsColorOverrides extends PropsColorOverrides {
71
+ }
72
+ interface FormControlPropsColorOverrides extends PropsColorOverrides {
73
+ }
74
+ interface ToggleButtonPropsColorOverrides extends PropsColorOverrides {
75
+ }
76
+ interface LinearProgressPropsColorOverrides extends PropsColorOverrides {
77
+ }
78
+ interface PaginationItemPropsColorOverrides extends PropsColorOverrides {
79
+ }
80
+ interface CircularProgressPropsColorOverrides extends PropsColorOverrides {
81
+ }
82
+ interface TabsPropsIndicatorColorOverrides extends PropsColorOverrides {
83
+ }
84
+ interface ToggleButtonGroupPropsColorOverrides extends PropsColorOverrides {
85
+ }
86
+ }
@@ -0,0 +1,18 @@
1
+ import { A as i, a as s, C as l, b as t, D as F, E as d, F as o, c as m, O as r, P as p, R as u, S as c, T as A, U as C } from "../../index-Dqp7dpn3.js";
2
+ export {
3
+ i as ApiAutocompleteField,
4
+ s as AutocompleteField,
5
+ l as CheckboxField,
6
+ t as CountryField,
7
+ F as DatePickerField,
8
+ d as EmailField,
9
+ o as FirstNameField,
10
+ m as Form,
11
+ r as OtpField,
12
+ p as PasswordField,
13
+ u as RepeatField,
14
+ c as SubmitButton,
15
+ A as TextField,
16
+ C as UkCountyField
17
+ };
18
+ //# sourceMappingURL=index.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.es.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -0,0 +1,11 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const C=require("../index-BUMdUVBH.cjs"),M=require("../index-BgsynEGX.cjs"),f=require("../Navigate-dQocLhzN.cjs"),U=require("../LinkButton-BYFkvL_O.cjs"),N=require("../index-CA-ugBSa.cjs"),r=require("../jsx-runtime-CeSfJrVB.cjs"),h=require("react-router-dom"),a=require("@mui/material"),j=require("react"),$=require("react-redux"),A=require("../Countdown-zY3nMzmi.cjs"),Y=require("../auth-Vf1MgMci.cjs"),D=require("../utils/general.cjs.js"),O=require("@mui/icons-material"),F=require("../Image-mgT45r_B.cjs"),B=require("../api-CnMfjRk3.cjs"),P=require("../api-DIgp_6Vr.cjs");function G(e){const n=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const t in e)if(t!=="default"){const s=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(n,t,s.get?s:{enumerable:!0,get:()=>e[t]})}}return n.default=e,Object.freeze(n)}const z=G(j);/**
2
+ * @remix-run/router v1.23.0
3
+ *
4
+ * Copyright (c) Remix Software Inc.
5
+ *
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE.md file in the root directory of this source tree.
8
+ *
9
+ * @license MIT
10
+ */var w;(function(e){e.Pop="POP",e.Push="PUSH",e.Replace="REPLACE"})(w||(w={}));var T;(function(e){e.data="data",e.deferred="deferred",e.redirect="redirect",e.error="error"})(T||(T={}));const S=["post","put","patch","delete"];new Set(S);const V=["get",...S];new Set(V);function H({basename:e,children:n,location:t="/",future:s}){typeof t=="string"&&(t=h.parsePath(t));let o=w.Pop,i={pathname:t.pathname||"/",search:t.search||"",hash:t.hash||"",state:t.state!=null?t.state:null,key:t.key||"default"},u=J();return z.createElement(h.Router,{basename:e,children:n,location:i,navigationType:o,navigator:u,future:s,static:!0})}function J(){return{createHref:X,encodeLocation:I,push(e){throw new Error(`You cannot use navigator.push() on the server because it is a stateless environment. This error was probably triggered when you did a \`navigate(${JSON.stringify(e)})\` somewhere in your app.`)},replace(e){throw new Error(`You cannot use navigator.replace() on the server because it is a stateless environment. This error was probably triggered when you did a \`navigate(${JSON.stringify(e)}, { replace: true })\` somewhere in your app.`)},go(e){throw new Error(`You cannot use navigator.go() on the server because it is a stateless environment. This error was probably triggered when you did a \`navigate(${e})\` somewhere in your app.`)},back(){throw new Error("You cannot use navigator.back() on the server because it is a stateless environment.")},forward(){throw new Error("You cannot use navigator.forward() on the server because it is a stateless environment.")}}}function X(e){return typeof e=="string"?e:h.createPath(e)}function I(e){let n=typeof e=="string"?e:h.createPath(e);n=n.replace(/ $/,"%20");let t=K.test(n)?new URL(n):new URL(n,"http://localhost");return{pathname:t.pathname,search:t.search,hash:t.hash}}const K=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,q=({path:e,routes:n,header:t=r.jsxRuntimeExports.jsx(r.jsxRuntimeExports.Fragment,{}),footer:s=r.jsxRuntimeExports.jsx(r.jsxRuntimeExports.Fragment,{}),headerExcludePaths:o=[],footerExcludePaths:i=[]})=>r.jsxRuntimeExports.jsxs(r.jsxRuntimeExports.Fragment,{children:[!o.includes(e)&&t,r.jsxRuntimeExports.jsx(h.Routes,{children:n}),!i.includes(e)&&s]}),Q=e=>{const{pathname:n}=Y.useLocation();return r.jsxRuntimeExports.jsx(q,{path:n,...e})},W=({path:e,theme:n,store:t,maxIdleSeconds:s=3600,maxTotalSeconds:o=3600,...i})=>r.jsxRuntimeExports.jsxs(a.ThemeProvider,{theme:n,children:[r.jsxRuntimeExports.jsx(a.CssBaseline,{}),r.jsxRuntimeExports.jsx($.Provider,{store:t,children:typeof window>"u"?r.jsxRuntimeExports.jsx(H,{location:e,children:r.jsxRuntimeExports.jsx(q,{path:e,...i})}):r.jsxRuntimeExports.jsx(h.BrowserRouter,{children:r.jsxRuntimeExports.jsx(Q,{...i})})})]}),Z=({open:e=!1,onClick:n,...t})=>{const[s,o]=j.useState(e);return j.useEffect(()=>{o(e)},[e]),r.jsxRuntimeExports.jsx(a.Tooltip,{open:s,onMouseOver:()=>{s||o(!0)},onMouseLeave:()=>{o(!1)},onClick:D.wrap({after:()=>{o(!s)}},n),...t})},ee=({content:e,children:n=r.jsxRuntimeExports.jsx(O.ContentCopy,{}),...t})=>r.jsxRuntimeExports.jsx(a.IconButton,{"data-testid":"copy-icon-button",onClick:()=>{navigator.clipboard.writeText(e)},...t,children:n}),te=({children:e="Download",endIcon:n=r.jsxRuntimeExports.jsx(O.Download,{}),file:t,...s})=>{let o,i;if("mimeType"in t){const{text:u,mimeType:x,name:c,charset:p="utf-8"}=t;let{extension:m}=t;m||(m="."+{plain:"txt",csv:"csv"}[x]),i={download:c+m,href:`data:text/${x};charset=${p},${encodeURIComponent(u)}`}}else o=URL.createObjectURL(t),i={href:o};return j.useEffect(()=>()=>{o&&URL.revokeObjectURL(o)},[o]),r.jsxRuntimeExports.jsx(a.Button,{endIcon:n,...s,...i,children:e})},ne=({containerProps:e,toolbarProps:n,elevation:t=4,children:s,...o})=>{const i=a.useScrollTrigger({disableHysteresis:!0,threshold:0});return j.cloneElement(r.jsxRuntimeExports.jsx(a.AppBar,{elevation:t,...o,children:r.jsxRuntimeExports.jsx(a.Container,{...e,children:r.jsxRuntimeExports.jsx(a.Toolbar,{...n,children:s})})}),{position:i?"fixed":"sticky"})},re=({children:e,inputProps:n,...t})=>r.jsxRuntimeExports.jsxs(a.Button,{component:"label",...t,children:[e,r.jsxRuntimeExports.jsx("input",{type:"file",hidden:!0,...n})]}),se=({styleType:e,listProps:n={},pl:t=4,children:s})=>{const{sx:o,...i}=n,u={display:"list-item"};return r.jsxRuntimeExports.jsx(a.List,{sx:{listStyleType:e,pl:t,".MuiListItem-root":u,".MuiListItemText-root":u,...o},...i,children:s})},oe=({rows:e,containerProps:n={},globalItemProps:t})=>{const s=Number(n.columns??12),o=x=>Math.floor(s/x),i=(x,c,p)=>Math.floor(c/o(p))*e.length+x,u=(x,c)=>{const p=e[0].length%o(c);return p!==0&&x===e[0].length-1?(s-p*c)/2:0};return r.jsxRuntimeExports.jsx(a.Unstable_Grid2,{container:!0,...n,children:e.map((x,c)=>x.map(({element:p,itemProps:m={}},l)=>r.jsxRuntimeExports.jsx(a.Unstable_Grid2,{order:{xs:i(c,l,t.xs),sm:i(c,l,t.sm),md:i(c,l,t.md),lg:i(c,l,t.lg),xl:i(c,l,t.xl)},xsOffset:u(l,t.xs),smOffset:u(l,t.sm),mdOffset:u(l,t.md),lgOffset:u(l,t.lg),xlOffset:u(l,t.xl),...t,...m,children:p},`${c}-${l}`)))})},ie=({elementId:e,options:n,...t})=>r.jsxRuntimeExports.jsx(a.Link,{...t,onClick:()=>{document.getElementById(e)?.scrollIntoView(n)}}),ae=({children:e,useLazyListQuery:n,preferCacheValue:t,filters:s,page:o=0,rowsPerPage:i=50,rowsPerPageOptions:u=[50,100,150],stackProps:x,onRowsPerPageChange:c,onPageChange:p,...m})=>{const[l,y]=n(),[{limit:g,page:b,offset:E},L]=P.usePagination({page:o,limit:i});j.useEffect(()=>{l({limit:g,offset:E,...s},t)},[l,g,E,...Object.values(s||{}),t]);const{count:k,max_limit:v}=y.data||{};return v&&(u=u.filter(d=>d<=v)),r.jsxRuntimeExports.jsxs(a.Stack,{...x,children:[B.handleResultState(y,({data:d})=>e(d,{limit:g,page:b,offset:E,count:k,maxLimit:v})),r.jsxRuntimeExports.jsx(a.TablePagination,{component:"div",count:k??0,rowsPerPage:g,onRowsPerPageChange:d=>{L({limit:parseInt(d.target.value),page:0}),c&&c(d)},page:b,onPageChange:(d,R)=>{L(({limit:_})=>({limit:_,page:R})),p&&p(d,R)},rowsPerPageOptions:u.sort((d,R)=>d-R),...m})]})},ue=({src:e,style:n={},...t})=>r.jsxRuntimeExports.jsx(a.Box,{component:"iframe",width:"100%",src:e,title:"YouTube video player",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen",style:{border:"0px",aspectRatio:"16 / 9",...n},...t});exports.forms=C.index;exports.pages=M.index;exports.Link=f.Link;exports.LinkIconButton=f.LinkIconButton;exports.LinkListItem=f.LinkListItem;exports.LinkTab=f.LinkTab;exports.Navigate=f.Navigate;exports.LinkButton=U.LinkButton;exports.tables=N.index;exports.Countdown=A.Countdown;exports.Image=F.Image;exports.SyncError=B.SyncError;exports.App=W;exports.ClickableTooltip=Z;exports.CopyIconButton=ee;exports.DownloadFileButton=te;exports.ElevatedAppBar=ne;exports.InputFileButton=re;exports.ItemizedList=se;exports.OrderedGrid=oe;exports.ScrollIntoViewLink=ie;exports.TablePagination=ae;exports.YouTubeVideo=ue;
11
+ //# sourceMappingURL=index.cjs.js.map