@openedx/frontend-base 1.0.0-alpha.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 (356) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +112 -0
  3. package/config/babel/babel.config.js +28 -0
  4. package/config/config-helpers/createConfig.js +13 -0
  5. package/config/config-helpers/createLintConfig.js +16 -0
  6. package/config/config-helpers/getBaseConfig.js +12 -0
  7. package/config/defaultConfigPaths.js +35 -0
  8. package/config/eslint/base.eslint.config.js +113 -0
  9. package/config/index.js +12 -0
  10. package/config/jest/jest.config.js +30 -0
  11. package/config/tsconfig.json +32 -0
  12. package/config/types.js +25 -0
  13. package/config/webpack/common-config/all/getCodeRules.js +52 -0
  14. package/config/webpack/common-config/all/getFileLoaderRules.js +26 -0
  15. package/config/webpack/common-config/all/getIgnoreWarnings.js +14 -0
  16. package/config/webpack/common-config/all/getImageMinimizer.js +25 -0
  17. package/config/webpack/common-config/all/getStylesheetRule.js +112 -0
  18. package/config/webpack/common-config/dev/getDevServer.js +38 -0
  19. package/config/webpack/common-config/index.js +18 -0
  20. package/config/webpack/common-config/site/getHtmlWebpackPlugin.js +16 -0
  21. package/config/webpack/plugins/html-webpack-new-relic-plugin/HtmlWebpackNewRelicPlugin.js +91 -0
  22. package/config/webpack/plugins/html-webpack-new-relic-plugin/index.js +7 -0
  23. package/config/webpack/plugins/html-webpack-new-relic-plugin/test/fixtures/entry.js +3 -0
  24. package/config/webpack/plugins/paragon-webpack-plugin/ParagonWebpackPlugin.js +108 -0
  25. package/config/webpack/plugins/paragon-webpack-plugin/index.js +7 -0
  26. package/config/webpack/plugins/paragon-webpack-plugin/utils/assetUtils.js +64 -0
  27. package/config/webpack/plugins/paragon-webpack-plugin/utils/htmlUtils.js +53 -0
  28. package/config/webpack/plugins/paragon-webpack-plugin/utils/index.js +9 -0
  29. package/config/webpack/plugins/paragon-webpack-plugin/utils/paragonStylesheetUtils.js +114 -0
  30. package/config/webpack/plugins/paragon-webpack-plugin/utils/scriptUtils.js +146 -0
  31. package/config/webpack/plugins/paragon-webpack-plugin/utils/stylesheetUtils.js +126 -0
  32. package/config/webpack/plugins/paragon-webpack-plugin/utils/tagUtils.js +57 -0
  33. package/config/webpack/types.js +2 -0
  34. package/config/webpack/utils/getLocalAliases.js +65 -0
  35. package/config/webpack/utils/getPublicPath.js +6 -0
  36. package/config/webpack/utils/getResolvedSiteConfigPath.js +32 -0
  37. package/config/webpack/utils/paragonUtils.js +138 -0
  38. package/config/webpack/webpack.config.build.js +80 -0
  39. package/config/webpack/webpack.config.dev.js +76 -0
  40. package/config/webpack/webpack.config.dev.shell.js +110 -0
  41. package/eslint.config.js +18 -0
  42. package/frontend-base.d.ts +8 -0
  43. package/index.ts +7 -0
  44. package/jest.config.js +7 -0
  45. package/openedx-frontend-base.tgz +0 -0
  46. package/package.json +149 -0
  47. package/runtime/analytics/MockAnalyticsService.js +71 -0
  48. package/runtime/analytics/SegmentAnalyticsService.js +243 -0
  49. package/runtime/analytics/index.ts +12 -0
  50. package/runtime/analytics/interface.js +145 -0
  51. package/runtime/auth/AxiosCsrfTokenService.js +60 -0
  52. package/runtime/auth/AxiosJwtAuthService.js +363 -0
  53. package/runtime/auth/AxiosJwtTokenService.js +134 -0
  54. package/runtime/auth/LocalForageCache.js +76 -0
  55. package/runtime/auth/MockAuthService.js +278 -0
  56. package/runtime/auth/index.ts +19 -0
  57. package/runtime/auth/interceptors/createCsrfTokenProviderInterceptor.js +36 -0
  58. package/runtime/auth/interceptors/createJwtTokenProviderInterceptor.js +37 -0
  59. package/runtime/auth/interceptors/createProcessAxiosRequestErrorInterceptor.js +20 -0
  60. package/runtime/auth/interceptors/createRetryInterceptor.js +74 -0
  61. package/runtime/auth/interface.js +309 -0
  62. package/runtime/auth/utils.js +105 -0
  63. package/runtime/babel.config.js +3 -0
  64. package/runtime/config/index.ts +295 -0
  65. package/runtime/constants.ts +68 -0
  66. package/runtime/i18n/index.js +118 -0
  67. package/runtime/i18n/injectIntlWithShim.jsx +48 -0
  68. package/runtime/i18n/lib.ts +272 -0
  69. package/runtime/index.ts +134 -0
  70. package/runtime/initialize.js +352 -0
  71. package/runtime/jest.config.js +32 -0
  72. package/runtime/logging/MockLoggingService.js +31 -0
  73. package/runtime/logging/NewRelicLoggingService.js +184 -0
  74. package/runtime/logging/index.ts +9 -0
  75. package/runtime/logging/interface.js +109 -0
  76. package/runtime/logging/types.ts +4 -0
  77. package/runtime/react/AuthenticatedPageRoute.jsx +43 -0
  78. package/runtime/react/CombinedAppProvider.tsx +46 -0
  79. package/runtime/react/CurrentAppContext.tsx +25 -0
  80. package/runtime/react/CurrentAppProvider.tsx +46 -0
  81. package/runtime/react/Divider.tsx +5 -0
  82. package/runtime/react/ErrorBoundary.jsx +47 -0
  83. package/runtime/react/ErrorPage.jsx +72 -0
  84. package/runtime/react/LoginRedirect.jsx +16 -0
  85. package/runtime/react/PageWrap.jsx +24 -0
  86. package/runtime/react/SiteContext.tsx +32 -0
  87. package/runtime/react/SiteProvider.tsx +78 -0
  88. package/runtime/react/hooks.ts +106 -0
  89. package/runtime/react/index.ts +19 -0
  90. package/runtime/routing/index.ts +1 -0
  91. package/runtime/routing/utils.ts +34 -0
  92. package/runtime/scripts/GoogleAnalyticsLoader.ts +59 -0
  93. package/runtime/scripts/index.ts +1 -0
  94. package/runtime/setupTest.js +49 -0
  95. package/runtime/slots/Slot.tsx +32 -0
  96. package/runtime/slots/SlotContext.tsx +8 -0
  97. package/runtime/slots/hooks.ts +35 -0
  98. package/runtime/slots/index.ts +7 -0
  99. package/runtime/slots/layout/DefaultSlotLayout.tsx +9 -0
  100. package/runtime/slots/layout/hooks.ts +65 -0
  101. package/runtime/slots/layout/index.ts +5 -0
  102. package/runtime/slots/layout/types.ts +45 -0
  103. package/runtime/slots/layout/utils.ts +14 -0
  104. package/runtime/slots/types.ts +23 -0
  105. package/runtime/slots/utils.ts +59 -0
  106. package/runtime/slots/widget/WidgetContext.tsx +9 -0
  107. package/runtime/slots/widget/WidgetProvider.tsx +30 -0
  108. package/runtime/slots/widget/hooks.ts +105 -0
  109. package/runtime/slots/widget/iframe/IFrameContentWrapper.messages.tsx +16 -0
  110. package/runtime/slots/widget/iframe/IFrameContentWrapper.tsx +84 -0
  111. package/runtime/slots/widget/iframe/IFrameWidget.tsx +59 -0
  112. package/runtime/slots/widget/iframe/constants.ts +19 -0
  113. package/runtime/slots/widget/iframe/hooks.ts +179 -0
  114. package/runtime/slots/widget/iframe/index.ts +6 -0
  115. package/runtime/slots/widget/iframe/types.ts +7 -0
  116. package/runtime/slots/widget/index.ts +6 -0
  117. package/runtime/slots/widget/types.ts +134 -0
  118. package/runtime/slots/widget/utils.tsx +201 -0
  119. package/runtime/subscriptions.ts +60 -0
  120. package/runtime/testing/index.ts +9 -0
  121. package/runtime/testing/initializeMockApp.ts +81 -0
  122. package/runtime/testing/mockMessages.ts +23 -0
  123. package/runtime/utils.js +178 -0
  124. package/shell/DefaultLayout.tsx +18 -0
  125. package/shell/DefaultMain.tsx +7 -0
  126. package/shell/Logo.tsx +28 -0
  127. package/shell/Shell.messages.ts +61 -0
  128. package/shell/Shell.tsx +18 -0
  129. package/shell/app.scss +149 -0
  130. package/shell/app.ts +24 -0
  131. package/shell/babel.config.js +3 -0
  132. package/shell/dev/devFooter/app.tsx +43 -0
  133. package/shell/dev/devFooter/index.ts +1 -0
  134. package/shell/dev/devHeader/BarContext.tsx +13 -0
  135. package/shell/dev/devHeader/BarLink.tsx +16 -0
  136. package/shell/dev/devHeader/BarProvider.tsx +25 -0
  137. package/shell/dev/devHeader/CoursesLink.tsx +16 -0
  138. package/shell/dev/devHeader/FooContext.tsx +13 -0
  139. package/shell/dev/devHeader/FooLink.tsx +16 -0
  140. package/shell/dev/devHeader/FooProvider.tsx +25 -0
  141. package/shell/dev/devHeader/app.tsx +53 -0
  142. package/shell/dev/devHeader/index.ts +1 -0
  143. package/shell/dev/devHeader/providers.tsx +11 -0
  144. package/shell/dev/devHome/HomePage.tsx +28 -0
  145. package/shell/dev/devHome/app.ts +18 -0
  146. package/shell/dev/devHome/i18n/index.ts +27 -0
  147. package/shell/dev/devHome/index.ts +1 -0
  148. package/shell/dev/devHome/messages.ts +11 -0
  149. package/shell/dev/devUser/app.tsx +24 -0
  150. package/shell/dev/devUser/index.ts +1 -0
  151. package/shell/dev/index.ts +5 -0
  152. package/shell/dev/slotShowcase/HorizontalSlotLayout.tsx +11 -0
  153. package/shell/dev/slotShowcase/LayoutWithOptions.tsx +17 -0
  154. package/shell/dev/slotShowcase/SlotShowcasePage.tsx +66 -0
  155. package/shell/dev/slotShowcase/WidgetWithOptions.tsx +11 -0
  156. package/shell/dev/slotShowcase/app.tsx +373 -0
  157. package/shell/dev/slotShowcase/index.ts +1 -0
  158. package/shell/footer/CenterLinks.tsx +11 -0
  159. package/shell/footer/CopyrightNotice.tsx +36 -0
  160. package/shell/footer/Footer.tsx +34 -0
  161. package/shell/footer/LabeledLinkColumn.tsx +19 -0
  162. package/shell/footer/LanguageMenu.tsx +35 -0
  163. package/shell/footer/LanguageMenuItem.tsx +23 -0
  164. package/shell/footer/LeftLinks.tsx +11 -0
  165. package/shell/footer/LegalNotices.tsx +17 -0
  166. package/shell/footer/PoweredBy.tsx +17 -0
  167. package/shell/footer/RevealLinks.tsx +43 -0
  168. package/shell/footer/RightLinks.tsx +11 -0
  169. package/shell/footer/app.tsx +73 -0
  170. package/shell/footer/data/api.ts +48 -0
  171. package/shell/footer/index.ts +2 -0
  172. package/shell/header/AuthenticatedMenu.tsx +32 -0
  173. package/shell/header/Header.tsx +17 -0
  174. package/shell/header/anonymous-menu/AnonymousMenu.tsx +14 -0
  175. package/shell/header/anonymous-menu/LoginButton.tsx +14 -0
  176. package/shell/header/anonymous-menu/RegisterButton.tsx +15 -0
  177. package/shell/header/app.tsx +142 -0
  178. package/shell/header/desktop/DesktopLayout.tsx +22 -0
  179. package/shell/header/desktop/PrimaryNavLinks.tsx +10 -0
  180. package/shell/header/desktop/SecondaryNavLinks.tsx +10 -0
  181. package/shell/header/index.ts +2 -0
  182. package/shell/header/mobile/MobileLayout.tsx +47 -0
  183. package/shell/header/mobile/MobileNavLinks.tsx +10 -0
  184. package/shell/i18n/index.ts +25 -0
  185. package/shell/index.ts +7 -0
  186. package/shell/jest.config.js +30 -0
  187. package/shell/menus/LinkMenuItem.tsx +64 -0
  188. package/shell/menus/NavDropdownMenuSlot.tsx +29 -0
  189. package/shell/menus/ProfileLinkMenuItem.tsx +33 -0
  190. package/shell/menus/data/utils.ts +19 -0
  191. package/shell/public/index.html +10 -0
  192. package/shell/router/createRouter.ts +17 -0
  193. package/shell/router/getAppRoutes.ts +21 -0
  194. package/shell/setupTest.js +48 -0
  195. package/shell/site.config.dev.tsx +49 -0
  196. package/shell/site.tsx +41 -0
  197. package/test-site/app.d.ts +15 -0
  198. package/test-site/dist/176.436443549ebb858db483.js +2 -0
  199. package/test-site/dist/176.436443549ebb858db483.js.map +1 -0
  200. package/test-site/dist/362.536eff787d2380fe246c.js +2 -0
  201. package/test-site/dist/362.536eff787d2380fe246c.js.map +1 -0
  202. package/test-site/dist/653.486966b108d224551296.js +2 -0
  203. package/test-site/dist/653.486966b108d224551296.js.map +1 -0
  204. package/test-site/dist/74e025d3fe9a7b7f8503054e2563b353.jpg +0 -0
  205. package/test-site/dist/806.323cf6496ad0a7fe73a7.js +3 -0
  206. package/test-site/dist/806.323cf6496ad0a7fe73a7.js.LICENSE.txt +106 -0
  207. package/test-site/dist/806.323cf6496ad0a7fe73a7.js.map +1 -0
  208. package/test-site/dist/95ec738c0b7faac5b5c9126794446bbd.svg +4 -0
  209. package/test-site/dist/app.612058b36c74787759ac.css +61 -0
  210. package/test-site/dist/app.612058b36c74787759ac.css.map +1 -0
  211. package/test-site/dist/app.612058b36c74787759ac.js +2 -0
  212. package/test-site/dist/app.612058b36c74787759ac.js.map +1 -0
  213. package/test-site/dist/cb28cdb1468c915e27e5cec9af64f22f.svg +1 -0
  214. package/test-site/dist/index.html +1 -0
  215. package/test-site/dist/report.html +39 -0
  216. package/test-site/dist/runtime.c7aeaf7b967496cb076f.js +2 -0
  217. package/test-site/dist/runtime.c7aeaf7b967496cb076f.js.map +1 -0
  218. package/test-site/eslint.config.js +12 -0
  219. package/test-site/package-lock.json +19226 -0
  220. package/test-site/package.json +29 -0
  221. package/test-site/public/index.html +10 -0
  222. package/test-site/site.config.build.tsx +27 -0
  223. package/test-site/site.config.dev.tsx +27 -0
  224. package/test-site/src/authenticated-page/AuthenticatedPage.tsx +18 -0
  225. package/test-site/src/authenticated-page/i18n/index.ts +27 -0
  226. package/test-site/src/authenticated-page/index.tsx +28 -0
  227. package/test-site/src/example-page/ExamplePage.tsx +79 -0
  228. package/test-site/src/example-page/Image.tsx +11 -0
  229. package/test-site/src/example-page/ParagonPreview.jsx +66 -0
  230. package/test-site/src/example-page/apple.jpg +0 -0
  231. package/test-site/src/example-page/apple.svg +1 -0
  232. package/test-site/src/example-page/index.ts +16 -0
  233. package/test-site/src/i18n/README.md +3 -0
  234. package/test-site/src/i18n/messages/frontend-app-sample/ar.json +4 -0
  235. package/test-site/src/i18n/messages/frontend-app-sample/eo.json +1 -0
  236. package/test-site/src/i18n/messages/frontend-app-sample/es_419.json +4 -0
  237. package/test-site/src/i18n/messages/frontend-component-emptylangs/ar.json +1 -0
  238. package/test-site/src/i18n/messages/frontend-component-singlelang/ar.json +3 -0
  239. package/test-site/src/iframe-widget/IframeWidget.tsx +14 -0
  240. package/test-site/src/iframe-widget/index.ts +16 -0
  241. package/test-site/src/index.tsx +3 -0
  242. package/test-site/src/messages.js +11 -0
  243. package/test-site/src/site.scss +11 -0
  244. package/test-site/tsconfig.json +14 -0
  245. package/tools/babel/babel.config.js +27 -0
  246. package/tools/babel.config.js +3 -0
  247. package/tools/cli/README.md +29 -0
  248. package/tools/cli/commands/pack.ts +9 -0
  249. package/tools/cli/commands/release.ts +27 -0
  250. package/tools/cli/commands/serve.ts +43 -0
  251. package/tools/cli/intl-imports.ts +274 -0
  252. package/tools/cli/openedx.ts +101 -0
  253. package/tools/cli/transifex-utils.ts +75 -0
  254. package/tools/cli/utils/ensureConfigFilenameOption.ts +40 -0
  255. package/tools/cli/utils/formatter.ts +10 -0
  256. package/tools/cli/utils/getResolvedConfigPath.ts +23 -0
  257. package/tools/cli/utils/prettyPrintTitle.ts +15 -0
  258. package/tools/cli/utils/printUsage.ts +53 -0
  259. package/tools/config-helpers/createConfig.ts +8 -0
  260. package/tools/config-helpers/createLintConfig.ts +14 -0
  261. package/tools/config-helpers/getBaseConfig.ts +11 -0
  262. package/tools/defaultConfigPaths.ts +30 -0
  263. package/tools/dist/babel/babel.config.js +28 -0
  264. package/tools/dist/cli/commands/pack.js +14 -0
  265. package/tools/dist/cli/commands/release.js +28 -0
  266. package/tools/dist/cli/commands/serve.js +44 -0
  267. package/tools/dist/cli/intl-imports.js +233 -0
  268. package/tools/dist/cli/openedx.js +100 -0
  269. package/tools/dist/cli/transifex-utils.js +68 -0
  270. package/tools/dist/cli/utils/ensureConfigFilenameOption.js +42 -0
  271. package/tools/dist/cli/utils/formatter.js +10 -0
  272. package/tools/dist/cli/utils/getResolvedConfigPath.js +28 -0
  273. package/tools/dist/cli/utils/prettyPrintTitle.js +17 -0
  274. package/tools/dist/cli/utils/printUsage.js +48 -0
  275. package/tools/dist/config-helpers/createConfig.js +13 -0
  276. package/tools/dist/config-helpers/createLintConfig.js +16 -0
  277. package/tools/dist/config-helpers/getBaseConfig.js +12 -0
  278. package/tools/dist/defaultConfigPaths.js +35 -0
  279. package/tools/dist/eslint/base.eslint.config.js +113 -0
  280. package/tools/dist/eslint.config.js +11 -0
  281. package/tools/dist/index.js +12 -0
  282. package/tools/dist/jest/jest.config.js +30 -0
  283. package/tools/dist/jest.config.js +20 -0
  284. package/tools/dist/types.js +25 -0
  285. package/tools/dist/typescript/tsconfig.json +32 -0
  286. package/tools/dist/webpack/common-config/all/getCodeRules.js +52 -0
  287. package/tools/dist/webpack/common-config/all/getFileLoaderRules.js +26 -0
  288. package/tools/dist/webpack/common-config/all/getIgnoreWarnings.js +14 -0
  289. package/tools/dist/webpack/common-config/all/getImageMinimizer.js +25 -0
  290. package/tools/dist/webpack/common-config/all/getStylesheetRule.js +112 -0
  291. package/tools/dist/webpack/common-config/dev/getDevServer.js +38 -0
  292. package/tools/dist/webpack/common-config/index.js +18 -0
  293. package/tools/dist/webpack/common-config/site/getHtmlWebpackPlugin.js +16 -0
  294. package/tools/dist/webpack/plugins/html-webpack-new-relic-plugin/HtmlWebpackNewRelicPlugin.js +91 -0
  295. package/tools/dist/webpack/plugins/html-webpack-new-relic-plugin/index.js +7 -0
  296. package/tools/dist/webpack/plugins/html-webpack-new-relic-plugin/test/fixtures/entry.js +3 -0
  297. package/tools/dist/webpack/plugins/paragon-webpack-plugin/ParagonWebpackPlugin.js +108 -0
  298. package/tools/dist/webpack/plugins/paragon-webpack-plugin/index.js +7 -0
  299. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/assetUtils.js +64 -0
  300. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/htmlUtils.js +53 -0
  301. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/index.js +9 -0
  302. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/paragonStylesheetUtils.js +114 -0
  303. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/scriptUtils.js +146 -0
  304. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/stylesheetUtils.js +126 -0
  305. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/tagUtils.js +57 -0
  306. package/tools/dist/webpack/types.js +2 -0
  307. package/tools/dist/webpack/utils/getLocalAliases.js +65 -0
  308. package/tools/dist/webpack/utils/getPublicPath.js +6 -0
  309. package/tools/dist/webpack/utils/getResolvedSiteConfigPath.js +32 -0
  310. package/tools/dist/webpack/utils/paragonUtils.js +138 -0
  311. package/tools/dist/webpack/webpack.config.build.js +80 -0
  312. package/tools/dist/webpack/webpack.config.dev.js +76 -0
  313. package/tools/dist/webpack/webpack.config.dev.shell.js +110 -0
  314. package/tools/eslint/base.eslint.config.js +124 -0
  315. package/tools/eslint/modules.d.ts +5 -0
  316. package/tools/eslint.config.js +15 -0
  317. package/tools/index.ts +3 -0
  318. package/tools/jest/jest.config.js +30 -0
  319. package/tools/jest.config.js +19 -0
  320. package/tools/tsconfig.json +24 -0
  321. package/tools/types.ts +21 -0
  322. package/tools/typescript/tsconfig.json +32 -0
  323. package/tools/webpack/common-config/README.md +15 -0
  324. package/tools/webpack/common-config/all/getCodeRules.ts +51 -0
  325. package/tools/webpack/common-config/all/getFileLoaderRules.ts +23 -0
  326. package/tools/webpack/common-config/all/getIgnoreWarnings.ts +13 -0
  327. package/tools/webpack/common-config/all/getImageMinimizer.ts +26 -0
  328. package/tools/webpack/common-config/all/getStylesheetRule.ts +111 -0
  329. package/tools/webpack/common-config/dev/getDevServer.ts +35 -0
  330. package/tools/webpack/common-config/index.ts +6 -0
  331. package/tools/webpack/common-config/site/getHtmlWebpackPlugin.ts +11 -0
  332. package/tools/webpack/modules.d.ts +6 -0
  333. package/tools/webpack/plugins/html-webpack-new-relic-plugin/HtmlWebpackNewRelicPlugin.ts +102 -0
  334. package/tools/webpack/plugins/html-webpack-new-relic-plugin/LICENSE +21 -0
  335. package/tools/webpack/plugins/html-webpack-new-relic-plugin/README.md +7 -0
  336. package/tools/webpack/plugins/html-webpack-new-relic-plugin/index.js +3 -0
  337. package/tools/webpack/plugins/html-webpack-new-relic-plugin/test/fixtures/entry.js +1 -0
  338. package/tools/webpack/plugins/paragon-webpack-plugin/ParagonWebpackPlugin.ts +134 -0
  339. package/tools/webpack/plugins/paragon-webpack-plugin/index.ts +3 -0
  340. package/tools/webpack/plugins/paragon-webpack-plugin/utils/assetUtils.ts +71 -0
  341. package/tools/webpack/plugins/paragon-webpack-plugin/utils/htmlUtils.ts +72 -0
  342. package/tools/webpack/plugins/paragon-webpack-plugin/utils/index.ts +6 -0
  343. package/tools/webpack/plugins/paragon-webpack-plugin/utils/paragonStylesheetUtils.ts +131 -0
  344. package/tools/webpack/plugins/paragon-webpack-plugin/utils/scriptUtils.ts +144 -0
  345. package/tools/webpack/plugins/paragon-webpack-plugin/utils/stylesheetUtils.ts +106 -0
  346. package/tools/webpack/plugins/paragon-webpack-plugin/utils/tagUtils.ts +54 -0
  347. package/tools/webpack/types.ts +69 -0
  348. package/tools/webpack/utils/getLocalAliases.ts +65 -0
  349. package/tools/webpack/utils/getPublicPath.ts +3 -0
  350. package/tools/webpack/utils/getResolvedSiteConfigPath.ts +28 -0
  351. package/tools/webpack/utils/paragonUtils.ts +152 -0
  352. package/tools/webpack/webpack.config.build.ts +93 -0
  353. package/tools/webpack/webpack.config.dev.shell.ts +122 -0
  354. package/tools/webpack/webpack.config.dev.ts +90 -0
  355. package/tsconfig.json +23 -0
  356. package/types.ts +99 -0
@@ -0,0 +1,109 @@
1
+ /**
2
+ * #### Import members from **@openedx/frontend-base logging**
3
+ *
4
+ * Contains a shared interface for logging information. (The default implementation is in
5
+ * NewRelicLoggingService.js.) When in development mode, all messages will instead be sent to the console.
6
+ *
7
+ * The `initialize` function performs much of the logging configuration for you. If, however,
8
+ * you're not using the `initialize` function, logging (via New Relic) can be configured via:
9
+ *
10
+ * ```
11
+ * import { getSiteConfig, configureLogging, NewRelicLoggingService, logInfo, logError } from '@openedx/frontend-base';
12
+ *
13
+ * configureLogging(NewRelicLoggingService, {
14
+ * config: getSiteConfig(),
15
+ * });
16
+ *
17
+ * logInfo('Just so you know...');
18
+ * logInfo(new Error('Unimportant error'), { type: 'unimportant' });
19
+ * logError('Uhoh!');
20
+ * logError(new Error('Uhoh error!'));
21
+ * ```
22
+ *
23
+ * As shown in this example, logging depends on the configuration document.
24
+ *
25
+ * @module Logging
26
+ */
27
+
28
+ import PropTypes from 'prop-types';
29
+
30
+ const optionsShape = {
31
+ config: PropTypes.object.isRequired,
32
+ };
33
+
34
+ const serviceShape = {
35
+ logInfo: PropTypes.func.isRequired,
36
+ logError: PropTypes.func.isRequired,
37
+ };
38
+
39
+ let service = null;
40
+
41
+ /**
42
+ *
43
+ */
44
+ export function configureLogging(LoggingService, options) {
45
+ PropTypes.checkPropTypes(optionsShape, options, 'property', 'Logging');
46
+ service = new LoggingService(options);
47
+ PropTypes.checkPropTypes(serviceShape, service, 'property', 'LoggingService');
48
+ return service;
49
+ }
50
+
51
+ /**
52
+ * Logs a message to the 'info' log level. Can accept custom attributes as a property of the error
53
+ * object, or as an optional second parameter.
54
+ *
55
+ * @param {string|Error} infoStringOrErrorObject
56
+ * @param {Object} [customAttributes={}]
57
+ */
58
+ export function logInfo(infoStringOrErrorObject, customAttributes) {
59
+ return service.logInfo(infoStringOrErrorObject, customAttributes);
60
+ }
61
+
62
+ /**
63
+ * Logs a message to the 'error' log level. Can accept custom attributes as a property of the error
64
+ * object, or as an optional second parameter.
65
+ *
66
+ * @param {string|Error} errorStringOrObject
67
+ * @param {Object} [customAttributes={}]
68
+ */
69
+ export function logError(errorStringOrObject, customAttributes) {
70
+ return service.logError(errorStringOrObject, customAttributes);
71
+ }
72
+
73
+ /**
74
+ * Sets a custom attribute that will be included with all subsequent log messages.
75
+ *
76
+ * @param {string} name
77
+ * @param {string|number|null} value
78
+ */
79
+ export function setCustomAttribute(name, value) {
80
+ return service.setCustomAttribute(name, value);
81
+ }
82
+
83
+ /**
84
+ *
85
+ * @throws {Error} Thrown if the logging service has not yet been configured via {@link configureLogging}.
86
+ * @returns {LoggingService}
87
+ */
88
+ export function getLoggingService() {
89
+ if (!service) {
90
+ throw Error('You must first configure the logging service.');
91
+ }
92
+ return service;
93
+ }
94
+
95
+ /**
96
+ * Sets the configured logging service back to null.
97
+ *
98
+ */
99
+ export function resetLoggingService() {
100
+ service = null;
101
+ }
102
+
103
+ /**
104
+ * @name LoggingService
105
+ * @interface
106
+ * @memberof module:Logging
107
+ * @property {function} logError
108
+ * @property {function} logInfo
109
+ */
@@ -0,0 +1,4 @@
1
+ export interface LoggingService {
2
+ logError: (errorStringOrObject: string | Error, customAttributes: any) => void,
3
+ logInfo: (infoStringOrErrorObject: string | Error, customAttributes: any) => void,
4
+ }
@@ -0,0 +1,43 @@
1
+ import PropTypes from 'prop-types';
2
+
3
+ import { getLoginRedirectUrl } from '../auth';
4
+ import PageWrap from './PageWrap';
5
+ import { useAuthenticatedUser } from './hooks';
6
+
7
+ /**
8
+ * A react-router route that redirects to the login page when the route becomes active and the user
9
+ * is not authenticated. If the application has been initialized with `requireAuthenticatedUser`
10
+ * false, an authenticatedPageRoute can be used to protect a subset of the application's routes,
11
+ * rather than the entire application.
12
+ *
13
+ * It can optionally accept an override URL to redirect to instead of the login page.
14
+ *
15
+ * Like a `PageWrap`, also calls `sendPageEvent` when the route becomes active.
16
+ *
17
+ * @see PageWrap
18
+ * @see {@link module:frontend-base~sendPageEvent}
19
+ * @memberof module:React
20
+ * @param {Object} props
21
+ * @param {string} props.redirectUrl The URL anonymous users should be redirected to, rather than
22
+ * viewing the route's contents.
23
+ */
24
+ export default function AuthenticatedPageRoute({ redirectUrl = null, children }) {
25
+ const authenticatedUser = useAuthenticatedUser();
26
+ if (authenticatedUser === null) {
27
+ const destination = redirectUrl || getLoginRedirectUrl(global.location.href);
28
+ global.location.assign(destination);
29
+
30
+ return null;
31
+ }
32
+
33
+ return (
34
+ <PageWrap>
35
+ {children}
36
+ </PageWrap>
37
+ );
38
+ }
39
+
40
+ AuthenticatedPageRoute.propTypes = {
41
+ redirectUrl: PropTypes.string,
42
+ children: PropTypes.node.isRequired,
43
+ };
@@ -0,0 +1,46 @@
1
+ import { ReactNode } from 'react';
2
+ import { App, AppProvider } from '../../types';
3
+ import { getSiteConfig } from '../config';
4
+
5
+ const combineProviders = (providers: AppProvider[]): AppProvider => {
6
+ return providers.reduce(
7
+ (AccumulatedProviders, CurrentProvider) => {
8
+ // eslint-disable-next-line react/prop-types
9
+ const CombinedProvider: AppProvider = ({ children }) => (
10
+ <AccumulatedProviders>
11
+ <CurrentProvider>{children}</CurrentProvider>
12
+ </AccumulatedProviders>
13
+ );
14
+ return CombinedProvider;
15
+ },
16
+ ({ children }) => <>{children}</>,
17
+ );
18
+ };
19
+
20
+ interface CombinedAppProviderProps {
21
+ children: ReactNode,
22
+ }
23
+
24
+ export default function CombinedAppProvider({ children }: CombinedAppProviderProps) {
25
+ const { apps } = getSiteConfig();
26
+
27
+ let providers: AppProvider[] = [];
28
+
29
+ if (apps) {
30
+ apps.forEach(
31
+ (app: App) => {
32
+ if (Array.isArray(app.providers)) {
33
+ providers = providers.concat(app.providers);
34
+ }
35
+ }
36
+ );
37
+ }
38
+
39
+ const CombinedProviders = combineProviders(providers);
40
+
41
+ return (
42
+ <CombinedProviders>
43
+ {children}
44
+ </CombinedProviders>
45
+ );
46
+ };
@@ -0,0 +1,25 @@
1
+ import { createContext } from 'react';
2
+ import { AppConfig } from '../../types';
3
+
4
+ /**
5
+ * `CurrentAppContext` provides data from `App` in a way that React components can readily consume.
6
+ * if it's mutable data. `CurrentAppContext` contains the following data structure:
7
+ *
8
+ * ```
9
+ * {
10
+ * config: <THE App.config OBJECT>
11
+ * }
12
+ * ```
13
+ * If the `App.config` data changes, `CurrentAppContext` will be updated
14
+ * accordingly and pass those changes onto React components using the context.
15
+ *
16
+ * `CurrentAppContext` is used in a React application like any other `[React Context](https://reactjs.org/docs/context.html)
17
+ * @memberof module:React
18
+ */
19
+ const CurrentAppContext = createContext<{
20
+ appConfig: AppConfig,
21
+ }>({
22
+ appConfig: {},
23
+ });
24
+
25
+ export default CurrentAppContext;
@@ -0,0 +1,46 @@
1
+ import { ReactNode, useMemo, useState } from 'react';
2
+
3
+ import { getAppConfig } from '../config';
4
+ import { CONFIG_CHANGED } from '../constants';
5
+
6
+ import CurrentAppContext from './CurrentAppContext';
7
+ import { useSiteEvent } from './hooks';
8
+
9
+ interface CurrentAppProviderProps {
10
+ appId: string,
11
+ children: ReactNode,
12
+ }
13
+
14
+ /**
15
+ * A wrapper component for React-based micro-frontends to initialize a number of common data/
16
+ * context providers.
17
+ *
18
+ * ```
19
+ * <CurrentAppProvider appId="my.app">
20
+ * <HelloWorld />
21
+ * </CurrentAppProvider>
22
+ * ```
23
+ *
24
+ * This will provide the following to HelloWorld:
25
+ * - A `CurrentAppContext` provider for React context data.
26
+ *
27
+ * @param {Object} props
28
+ * @memberof module:React
29
+ */
30
+ export default function CurrentAppProvider({ appId, children }: CurrentAppProviderProps) {
31
+ const [appConfig, setAppConfig] = useState(getAppConfig(appId));
32
+
33
+ useSiteEvent(CONFIG_CHANGED, () => {
34
+ setAppConfig(getAppConfig(appId));
35
+ });
36
+
37
+ const appContextValue = useMemo(() => ({
38
+ appConfig,
39
+ }), [appConfig]);
40
+
41
+ return (
42
+ <CurrentAppContext.Provider value={appContextValue}>
43
+ {children}
44
+ </CurrentAppContext.Provider>
45
+ );
46
+ }
@@ -0,0 +1,5 @@
1
+ export default function Divider() {
2
+ return (
3
+ <hr className="w-100 my-2" />
4
+ );
5
+ }
@@ -0,0 +1,47 @@
1
+ import React, { Component } from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ import { logError } from '../logging';
5
+
6
+ import ErrorPage from './ErrorPage';
7
+
8
+ /**
9
+ * Error boundary component used to log caught errors and display the error page.
10
+ *
11
+ * @memberof module:React
12
+ * @extends {Component}
13
+ */
14
+ class ErrorBoundary extends Component {
15
+ constructor(props) {
16
+ super(props);
17
+ this.state = { hasError: false };
18
+ }
19
+
20
+ static getDerivedStateFromError() {
21
+ // Update state so the next render will show the fallback UI.
22
+ return { hasError: true };
23
+ }
24
+
25
+ componentDidCatch(error, info) {
26
+ logError(error, { stack: info.componentStack });
27
+ }
28
+
29
+ render() {
30
+ if (this.state.hasError) {
31
+ return this.props.fallbackComponent || <ErrorPage />;
32
+ }
33
+ return this.props.children;
34
+ }
35
+ }
36
+
37
+ ErrorBoundary.propTypes = {
38
+ children: PropTypes.node,
39
+ fallbackComponent: PropTypes.node,
40
+ };
41
+
42
+ ErrorBoundary.defaultProps = {
43
+ children: null,
44
+ fallbackComponent: undefined,
45
+ };
46
+
47
+ export default ErrorBoundary;
@@ -0,0 +1,72 @@
1
+ import React, { useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import {
4
+ Button, Container, Row, Col,
5
+ } from '@openedx/paragon';
6
+
7
+ import { useSiteEvent } from './hooks';
8
+ import {
9
+ FormattedMessage,
10
+ IntlProvider,
11
+ getMessages,
12
+ getLocale,
13
+ LOCALE_CHANGED,
14
+ } from '../i18n';
15
+
16
+ /**
17
+ * An error page that displays a generic message for unexpected errors. Also contains a "Try
18
+ * Again" button to refresh the page.
19
+ *
20
+ * @memberof module:React
21
+ * @extends {Component}
22
+ */
23
+ function ErrorPage({
24
+ message = null,
25
+ }) {
26
+ const [locale, setLocale] = useState(getLocale());
27
+
28
+ useSiteEvent(LOCALE_CHANGED, () => {
29
+ setLocale(getLocale());
30
+ });
31
+
32
+ /* istanbul ignore next */
33
+ const reload = () => {
34
+ global.location.reload();
35
+ };
36
+
37
+ return (
38
+ <IntlProvider locale={locale} messages={getMessages()}>
39
+ <Container fluid className="py-5 justify-content-center align-items-start text-center" data-testid="error-page">
40
+ <Row>
41
+ <Col>
42
+ <p className="text-muted">
43
+ <FormattedMessage
44
+ id="unexpected.error.message.text"
45
+ defaultMessage="An unexpected error occurred. Please click the button below to refresh the page."
46
+ description="error message when an unexpected error occurs"
47
+ />
48
+ </p>
49
+ {message && (
50
+ <div role="alert" className="my-4">
51
+ <p>{message}</p>
52
+ </div>
53
+ )}
54
+ <Button onClick={reload}>
55
+ <FormattedMessage
56
+ id="unexpected.error.button.text"
57
+ defaultMessage="Try again"
58
+ description="text for button that tries to reload the app by refreshing the page"
59
+ />
60
+ </Button>
61
+ </Col>
62
+ </Row>
63
+ </Container>
64
+ </IntlProvider>
65
+ );
66
+ }
67
+
68
+ ErrorPage.propTypes = {
69
+ message: PropTypes.string,
70
+ };
71
+
72
+ export default ErrorPage;
@@ -0,0 +1,16 @@
1
+ import { useEffect } from 'react';
2
+ import { redirectToLogin } from '../auth';
3
+
4
+ /**
5
+ * A React component that, when rendered, redirects to the login page as a side effect. Uses
6
+ * `redirectToLogin` to perform the redirect.
7
+ *
8
+ * @see {@link module:frontend-base~redirectToLogin}
9
+ * @memberof module:React
10
+ */
11
+ export default function LoginRedirect() {
12
+ useEffect(() => {
13
+ redirectToLogin(global.location.href);
14
+ }, []);
15
+ return null;
16
+ }
@@ -0,0 +1,24 @@
1
+ /* eslint-disable react/prop-types */
2
+ // eslint-disable-next-line no-unused-vars
3
+ import { useEffect } from 'react';
4
+ import { useLocation } from 'react-router-dom';
5
+
6
+ import { sendPageEvent } from '../analytics';
7
+
8
+ /**
9
+ * A Wrapper component that calls `sendPageEvent` when it becomes active.
10
+ *
11
+ * @see {@link module:frontend-base~sendPageEvent}
12
+ * @memberof module:React
13
+ * @param {Object} props
14
+ */
15
+ export default function PageWrap({ children }) {
16
+ const location = useLocation();
17
+
18
+ useEffect(() => {
19
+ sendPageEvent();
20
+ // eslint-disable-next-line react-hooks/exhaustive-deps
21
+ }, [location.pathname]);
22
+
23
+ return children;
24
+ }
@@ -0,0 +1,32 @@
1
+ import { createContext } from 'react';
2
+ import { SiteConfig, User } from '../../types';
3
+ import { getSiteConfig } from '../config';
4
+
5
+ /**
6
+ * `SiteContext` provides data from `App` in a way that React components can readily consume, even
7
+ * if it's mutable data. `SiteContext` contains the following data structure:
8
+ *
9
+ * ```
10
+ * {
11
+ * authenticatedUser
12
+ * siteConfig
13
+ * locale
14
+ * }
15
+ * ```
16
+ * If `authenticatedUser`, `siteConfig`, or `locale` data changes, `SiteContext` will be updated
17
+ * accordingly and pass those changes onto React components using the context.
18
+ *
19
+ * `SiteContext` is used in a React application like any other `[React Context](https://reactjs.org/docs/context.html)
20
+ * @memberof module:React
21
+ */
22
+ const SiteContext = createContext<{
23
+ authenticatedUser: User | null,
24
+ siteConfig: SiteConfig,
25
+ locale: string,
26
+ }>({
27
+ authenticatedUser: null,
28
+ siteConfig: getSiteConfig(),
29
+ locale: 'en',
30
+ });
31
+
32
+ export default SiteContext;
@@ -0,0 +1,78 @@
1
+ import { ReactNode, useMemo, useState } from 'react';
2
+
3
+ import { AUTHENTICATED_USER_CHANGED, getAuthenticatedUser } from '../auth';
4
+ import { getSiteConfig } from '../config';
5
+ import { CONFIG_CHANGED } from '../constants';
6
+ import {
7
+ getLocale,
8
+ getMessages,
9
+ IntlProvider,
10
+ LOCALE_CHANGED,
11
+ } from '../i18n';
12
+
13
+ import CombinedAppProvider from './CombinedAppProvider';
14
+ import ErrorBoundary from './ErrorBoundary';
15
+ import SiteContext from './SiteContext';
16
+ import { useSiteEvent } from './hooks';
17
+
18
+ interface SiteProviderProps {
19
+ children: ReactNode,
20
+ }
21
+
22
+ /**
23
+ * A wrapper component for React-based micro-frontends to initialize a number of common data/
24
+ * context providers.
25
+ *
26
+ * ```
27
+ * subscribe(SITE_READY, () => {
28
+ * ReactDOM.render(
29
+ * <SiteProvider>
30
+ * <HelloWorld />
31
+ * </SiteProvider>
32
+ * )
33
+ * });
34
+ * ```
35
+ *
36
+ * This will provide the following to HelloWorld:
37
+ * - An error boundary as described above.
38
+ * - An `SiteContext` provider for React context data.
39
+ * - IntlProvider for @edx/frontend-i18n internationalization
40
+ *
41
+ * @param {Object} props
42
+ * @memberof module:React
43
+ */
44
+ export default function SiteProvider({ children }: SiteProviderProps) {
45
+ const [siteConfig, setSiteConfig] = useState(getSiteConfig());
46
+ const [authenticatedUser, setAuthenticatedUser] = useState(getAuthenticatedUser());
47
+ const [locale, setLocale] = useState(getLocale());
48
+
49
+ useSiteEvent(AUTHENTICATED_USER_CHANGED, () => {
50
+ setAuthenticatedUser(getAuthenticatedUser());
51
+ });
52
+
53
+ useSiteEvent(CONFIG_CHANGED, () => {
54
+ setSiteConfig(getSiteConfig());
55
+ });
56
+
57
+ useSiteEvent(LOCALE_CHANGED, () => {
58
+ setLocale(getLocale());
59
+ });
60
+
61
+ const siteContextValue = useMemo(() => ({
62
+ authenticatedUser,
63
+ siteConfig,
64
+ locale
65
+ }), [authenticatedUser, siteConfig, locale]);
66
+
67
+ return (
68
+ <IntlProvider locale={locale} messages={getMessages()}>
69
+ <ErrorBoundary>
70
+ <SiteContext.Provider value={siteContextValue}>
71
+ <CombinedAppProvider>
72
+ {children}
73
+ </CombinedAppProvider>
74
+ </SiteContext.Provider>
75
+ </ErrorBoundary>
76
+ </IntlProvider>
77
+ );
78
+ }
@@ -0,0 +1,106 @@
1
+ import { useCallback, useContext, useEffect, useState } from 'react';
2
+ import { useMatches } from 'react-router';
3
+
4
+ import { sendTrackEvent } from '../analytics';
5
+ import { getActiveRoles, setActiveRouteRoles } from '../config';
6
+ import { ACTIVE_ROLES_CHANGED } from '../constants';
7
+ import { isRoleRouteObject } from '../routing';
8
+ import { subscribe, unsubscribe } from '../subscriptions';
9
+
10
+ import SiteContext from './SiteContext';
11
+ import CurrentAppContext from './CurrentAppContext';
12
+
13
+ /**
14
+ * A React hook that allows functional components to subscribe to application events. This should
15
+ * be used sparingly - for the most part, Context should be used higher-up in the application to
16
+ * provide necessary data to a given component, rather than utilizing a non-React-like Pub/Sub
17
+ * mechanism.
18
+ *
19
+ * @memberof module:React
20
+ * @param {string} type
21
+ * @param {function} callback
22
+ */
23
+ export const useSiteEvent = (type, callback) => {
24
+ useEffect(() => {
25
+ subscribe(type, callback);
26
+
27
+ return () => {
28
+ unsubscribe(type, callback);
29
+ };
30
+ }, [callback, type]);
31
+ };
32
+
33
+ /**
34
+ * A React hook that tracks user's preferred color scheme (light or dark) and sends respective
35
+ * event to the tracking service.
36
+ *
37
+ * @memberof module:React
38
+ */
39
+ export const useTrackColorSchemeChoice = () => {
40
+ useEffect(() => {
41
+ const trackColorSchemeChoice = ({ matches }) => {
42
+ const preferredColorScheme = matches ? 'dark' : 'light';
43
+ sendTrackEvent('openedx.ui.frontend-base.prefers-color-scheme.selected', { preferredColorScheme });
44
+ };
45
+ const colorSchemeQuery = window.matchMedia?.('(prefers-color-scheme: dark)');
46
+ if (colorSchemeQuery) {
47
+ // send user's initial choice
48
+ trackColorSchemeChoice(colorSchemeQuery);
49
+ colorSchemeQuery.addEventListener('change', trackColorSchemeChoice);
50
+ }
51
+ return () => {
52
+ if (colorSchemeQuery) {
53
+ colorSchemeQuery.removeEventListener('change', trackColorSchemeChoice);
54
+ }
55
+ };
56
+ }, []);
57
+ };
58
+
59
+ export function useAuthenticatedUser() {
60
+ const { authenticatedUser } = useContext(SiteContext);
61
+ return authenticatedUser;
62
+ }
63
+
64
+ export function useSiteConfig() {
65
+ const { siteConfig } = useContext(SiteContext);
66
+ return siteConfig;
67
+ }
68
+
69
+ export function useAppConfig() {
70
+ const { appConfig } = useContext(CurrentAppContext);
71
+ return appConfig;
72
+ }
73
+
74
+ export function useActiveRouteRoleWatcher() {
75
+ const matches = useMatches();
76
+
77
+ // We create this callback so we can use it right away to populate the default state value.
78
+ const findActiveRouteRoles = useCallback(() => {
79
+ // Starts with the widget roles and adds the others in.
80
+ const roles: string[] = [];
81
+
82
+ // Route roles
83
+ for (const match of matches) {
84
+ if (isRoleRouteObject(match)) {
85
+ if (!roles.includes(match.handle.role)) {
86
+ roles.push(match.handle.role);
87
+ }
88
+ }
89
+ }
90
+
91
+ return roles;
92
+ }, [matches]);
93
+
94
+ useEffect(() => {
95
+ setActiveRouteRoles(findActiveRouteRoles());
96
+ }, [matches, findActiveRouteRoles]);
97
+ }
98
+
99
+ export function useActiveRoles() {
100
+ const [roles, setRoles] = useState<string[]>(getActiveRoles());
101
+ useSiteEvent(ACTIVE_ROLES_CHANGED, () => {
102
+ setRoles(getActiveRoles());
103
+ });
104
+
105
+ return roles;
106
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * #### Import members from **@openedx/frontend-base** React
3
+ * The React module provides a variety of React components, hooks, and contexts for use in an
4
+ * application.
5
+ *
6
+ * @module React
7
+ */
8
+
9
+ export { default as CurrentAppContext } from './CurrentAppContext';
10
+ export { default as CurrentAppProvider } from './CurrentAppProvider';
11
+ export { default as SiteContext } from './SiteContext';
12
+ export { default as SiteProvider } from './SiteProvider';
13
+ export { default as AuthenticatedPageRoute } from './AuthenticatedPageRoute';
14
+ export { default as Divider } from './Divider';
15
+ export { default as ErrorBoundary } from './ErrorBoundary';
16
+ export { default as ErrorPage } from './ErrorPage';
17
+ export { useSiteEvent, useAuthenticatedUser, useSiteConfig, useAppConfig } from './hooks';
18
+ export { default as LoginRedirect } from './LoginRedirect';
19
+ export { default as PageWrap } from './PageWrap';
@@ -0,0 +1 @@
1
+ export * from './utils';