@rebasepro/firebase 0.0.1-canary.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 (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +4 -0
  3. package/dist/components/FirebaseLoginView.d.ts +72 -0
  4. package/dist/components/RebaseFirebaseApp.d.ts +19 -0
  5. package/dist/components/RebaseFirebaseAppProps.d.ts +144 -0
  6. package/dist/components/index.d.ts +3 -0
  7. package/dist/components/social_icons.d.ts +6 -0
  8. package/dist/hooks/index.d.ts +7 -0
  9. package/dist/hooks/useAppCheck.d.ts +20 -0
  10. package/dist/hooks/useFirebaseAuthController.d.ts +15 -0
  11. package/dist/hooks/useFirebaseRealTimeDBDelegate.d.ts +5 -0
  12. package/dist/hooks/useFirebaseStorageSource.d.ts +14 -0
  13. package/dist/hooks/useFirestoreDataSource.d.ts +56 -0
  14. package/dist/hooks/useInitialiseFirebase.d.ts +34 -0
  15. package/dist/hooks/useRecaptcha.d.ts +8 -0
  16. package/dist/index.d.ts +4 -0
  17. package/dist/index.es.js +2715 -0
  18. package/dist/index.es.js.map +1 -0
  19. package/dist/index.umd.js +2703 -0
  20. package/dist/index.umd.js.map +1 -0
  21. package/dist/social_icons.d.ts +6 -0
  22. package/dist/types/appcheck.d.ts +10 -0
  23. package/dist/types/auth.d.ts +41 -0
  24. package/dist/types/index.d.ts +3 -0
  25. package/dist/types/text_search.d.ts +39 -0
  26. package/dist/utils/algolia.d.ts +14 -0
  27. package/dist/utils/collections_firestore.d.ts +5 -0
  28. package/dist/utils/database.d.ts +2 -0
  29. package/dist/utils/index.d.ts +7 -0
  30. package/dist/utils/local_text_search_controller.d.ts +2 -0
  31. package/dist/utils/pinecone.d.ts +24 -0
  32. package/dist/utils/rebase_search_controller.d.ts +73 -0
  33. package/dist/utils/text_search_controller.d.ts +13 -0
  34. package/package.json +67 -0
  35. package/src/components/FirebaseLoginView.tsx +702 -0
  36. package/src/components/RebaseFirebaseApp.tsx +266 -0
  37. package/src/components/RebaseFirebaseAppProps.tsx +190 -0
  38. package/src/components/index.ts +3 -0
  39. package/src/components/social_icons.tsx +135 -0
  40. package/src/hooks/index.ts +7 -0
  41. package/src/hooks/useAppCheck.ts +101 -0
  42. package/src/hooks/useFirebaseAuthController.ts +334 -0
  43. package/src/hooks/useFirebaseRealTimeDBDelegate.ts +278 -0
  44. package/src/hooks/useFirebaseStorageSource.ts +209 -0
  45. package/src/hooks/useFirestoreDataSource.ts +796 -0
  46. package/src/hooks/useInitialiseFirebase.ts +132 -0
  47. package/src/hooks/useRecaptcha.tsx +28 -0
  48. package/src/index.ts +4 -0
  49. package/src/social_icons.tsx +135 -0
  50. package/src/types/appcheck.ts +11 -0
  51. package/src/types/auth.tsx +74 -0
  52. package/src/types/index.ts +3 -0
  53. package/src/types/text_search.ts +42 -0
  54. package/src/utils/algolia.ts +30 -0
  55. package/src/utils/collections_firestore.ts +154 -0
  56. package/src/utils/database.ts +39 -0
  57. package/src/utils/index.ts +7 -0
  58. package/src/utils/local_text_search_controller.ts +143 -0
  59. package/src/utils/pinecone.ts +75 -0
  60. package/src/utils/rebase_search_controller.ts +356 -0
  61. package/src/utils/text_search_controller.ts +34 -0
@@ -0,0 +1,266 @@
1
+ import React from "react";
2
+ import { GoogleAuthProvider } from "@firebase/auth";
3
+
4
+ import {
5
+ AppBar,
6
+ CircularProgressCenter,
7
+ Drawer,
8
+ Rebase,
9
+ RebaseRoute,
10
+ ModeControllerProvider,
11
+ PropertyConfig,
12
+ Scaffold,
13
+ SideDialogs,
14
+ SnackbarProvider,
15
+ useBrowserTitleAndIcon,
16
+ useBuildLocalConfigurationPersistence,
17
+ useBuildModeController,
18
+ useBuildAdminModeController,
19
+ AdminModeControllerProvider,
20
+ useBuildCollectionRegistryController,
21
+ useBuildCMSUrlController,
22
+ useBuildNavigationStateController,
23
+ useValidateAuthenticator
24
+ } from "@rebasepro/core";
25
+ import { Route, Routes, Outlet } from "react-router-dom";
26
+
27
+ import { RebaseFirebaseAppProps } from "./RebaseFirebaseAppProps";
28
+ import { FirebaseLoginView } from "./FirebaseLoginView";
29
+ import {
30
+ useAppCheck,
31
+ useFirebaseAuthController,
32
+ useFirebaseStorageSource,
33
+ useFirestoreDataSource,
34
+ useInitialiseFirebase,
35
+ } from "../hooks";
36
+ import { CenteredView } from "@rebasepro/ui";
37
+ import { FirebaseAuthController } from "../types";
38
+
39
+ const DEFAULT_SIGN_IN_OPTIONS = [
40
+ GoogleAuthProvider.PROVIDER_ID
41
+ ];
42
+
43
+ /**
44
+ * This is the default implementation of a Rebase app using the Firebase services
45
+ * as a backend.
46
+ * You can use this component as a full app, by specifying collections and
47
+ * entity collections.
48
+ *
49
+ * This component is in charge of initialising Firebase, with the given
50
+ * configuration object.
51
+ *
52
+ * If you are building a larger app and need finer control, you can use
53
+ * {@link Rebase}, {@link Scaffold}, {@link SideDialogs}
54
+ * and {@link NavigationRoutes} instead.
55
+ *
56
+ * @param props
57
+
58
+ * @category Firebase
59
+ */
60
+ export function RebaseFirebaseApp({
61
+ name,
62
+ logo,
63
+ logoDark,
64
+ authenticator,
65
+ collections,
66
+ views,
67
+ adminViews,
68
+ textSearchControllerBuilder,
69
+ allowSkipLogin,
70
+ signInOptions = DEFAULT_SIGN_IN_OPTIONS,
71
+ firebaseConfig,
72
+ onFirebaseInit,
73
+ appCheckOptions,
74
+ dateTimeFormat,
75
+ locale,
76
+ basePath,
77
+ baseCollectionPath,
78
+ onAnalyticsEvent,
79
+ propertyConfigs: propertyConfigsProp,
80
+ plugins,
81
+ autoOpenDrawer,
82
+ firestoreIndexesBuilder,
83
+ components,
84
+ localTextSearchEnabled = false,
85
+ userManagement
86
+ }: RebaseFirebaseAppProps) {
87
+
88
+ /**
89
+ * Update the browser title and icon
90
+ */
91
+ useBrowserTitleAndIcon(name, logo);
92
+
93
+ const propertyConfigs: Record<string, PropertyConfig> = (propertyConfigsProp ?? [])
94
+ .map(pc => ({
95
+ [pc.key]: pc
96
+ }))
97
+ .reduce((a, b) => ({ ...a, ...b }), {});
98
+
99
+ const {
100
+ firebaseApp,
101
+ firebaseConfigLoading,
102
+ configError
103
+ } = useInitialiseFirebase({
104
+ onFirebaseInit,
105
+ firebaseConfig
106
+ });
107
+
108
+ /**
109
+ * Controller used to manage the dark or light color mode
110
+ */
111
+ const modeController = useBuildModeController();
112
+ const adminModeController = useBuildAdminModeController();
113
+
114
+ const {
115
+ loading,
116
+ appCheckVerified,
117
+ error
118
+ } = useAppCheck({
119
+ firebaseApp,
120
+ options: appCheckOptions
121
+ });
122
+
123
+ /**
124
+ * Controller for managing authentication
125
+ */
126
+ const authController: FirebaseAuthController = useFirebaseAuthController({
127
+ firebaseApp,
128
+ signInOptions
129
+ });
130
+
131
+ /**
132
+ * Controller for saving some user preferences locally.
133
+ */
134
+ const userConfigPersistence = useBuildLocalConfigurationPersistence();
135
+
136
+ const firestoreDelegate = useFirestoreDataSource({
137
+ firebaseApp,
138
+ textSearchControllerBuilder: textSearchControllerBuilder,
139
+ firestoreIndexesBuilder: firestoreIndexesBuilder,
140
+ localTextSearchEnabled
141
+ })
142
+
143
+ /**
144
+ * Controller used for saving and fetching files in storage
145
+ */
146
+ const storageSource = useFirebaseStorageSource({
147
+ firebaseApp
148
+ });
149
+
150
+ /**
151
+ * Validate authenticator
152
+ */
153
+ const {
154
+ authLoading,
155
+ canAccessMainView,
156
+ notAllowedError
157
+ } = useValidateAuthenticator({
158
+ authController,
159
+ authenticator,
160
+ dataSource: firestoreDelegate,
161
+ storageSource
162
+ });
163
+
164
+ const collectionRegistryController = useBuildCollectionRegistryController({
165
+ userConfigPersistence
166
+ });
167
+
168
+ const cmsUrlController = useBuildCMSUrlController({
169
+ basePath: basePath ?? "/",
170
+ baseCollectionPath: baseCollectionPath ?? "/c",
171
+ collectionRegistryController
172
+ });
173
+
174
+ const navigationStateController = useBuildNavigationStateController({
175
+ collections,
176
+ views,
177
+ adminViews,
178
+ authController,
179
+ dataSource: firestoreDelegate,
180
+ plugins,
181
+ collectionRegistryController,
182
+ cmsUrlController,
183
+ adminMode: adminModeController.mode,
184
+ userManagement: userManagement as any
185
+ });
186
+
187
+ if (firebaseConfigLoading || !firebaseApp || loading) {
188
+ return <>
189
+ <CircularProgressCenter />
190
+ </>;
191
+ }
192
+
193
+ if (configError) {
194
+ return <CenteredView>{configError}</CenteredView>;
195
+ }
196
+
197
+ return (
198
+ <SnackbarProvider>
199
+ <ModeControllerProvider value={modeController}>
200
+ <AdminModeControllerProvider value={adminModeController}>
201
+
202
+ <Rebase
203
+ authController={authController}
204
+ collectionRegistryController={collectionRegistryController}
205
+ cmsUrlController={cmsUrlController}
206
+ navigationStateController={navigationStateController}
207
+ userConfigPersistence={userConfigPersistence}
208
+ dateTimeFormat={dateTimeFormat}
209
+ dataSource={firestoreDelegate}
210
+ storageSource={storageSource}
211
+ userManagement={userManagement}
212
+ entityLinkBuilder={({ entity }) => `https://console.firebase.google.com/project/${firebaseApp.options.projectId}/firestore/data/${entity.path}/${entity.id}`}
213
+ locale={locale}
214
+ onAnalyticsEvent={onAnalyticsEvent}
215
+ plugins={plugins}
216
+ propertyConfigs={propertyConfigs}>
217
+ {({
218
+ context,
219
+ loading
220
+ }) => {
221
+
222
+ let component;
223
+ if (loading || authLoading) {
224
+ component = <CircularProgressCenter size={"large"} />;
225
+ } else {
226
+ const usedLogo = modeController.mode === "dark" && logoDark ? logoDark : logo;
227
+ if (!canAccessMainView) {
228
+ const LoginViewUsed = components?.LoginView ?? FirebaseLoginView;
229
+ component = (
230
+ <LoginViewUsed
231
+ logo={usedLogo}
232
+ allowSkipLogin={allowSkipLogin}
233
+ signInOptions={signInOptions ?? DEFAULT_SIGN_IN_OPTIONS}
234
+ firebaseApp={firebaseApp}
235
+ authController={authController}
236
+ notAllowedError={notAllowedError} />
237
+ );
238
+ } else {
239
+ component = (
240
+ <Routes>
241
+ <Route element={
242
+ <Scaffold
243
+ logo={usedLogo}
244
+ autoOpenDrawer={autoOpenDrawer}>
245
+ <AppBar title={name} logo={usedLogo} />
246
+ <Drawer />
247
+ <Outlet />
248
+ <SideDialogs />
249
+ </Scaffold>
250
+ }>
251
+ {components?.HomePage && <Route path="/" element={<components.HomePage />} />}
252
+ <Route path="/c/*" element={<RebaseRoute />} />
253
+ </Route>
254
+ </Routes>
255
+ );
256
+ }
257
+ }
258
+
259
+ return component;
260
+ }}
261
+ </Rebase>
262
+ </AdminModeControllerProvider>
263
+ </ModeControllerProvider>
264
+ </SnackbarProvider>
265
+ );
266
+ }
@@ -0,0 +1,190 @@
1
+ import React from "react";
2
+
3
+ import {
4
+ Authenticator,
5
+ CMSAnalyticsEvent,
6
+ CMSView,
7
+ CMSViewsBuilder,
8
+ EntityCollection,
9
+ EntityCollectionsBuilder,
10
+ RebasePlugin,
11
+ Locale,
12
+ PropertyConfig
13
+ } from "@rebasepro/core";
14
+ import { UserManagementDelegate } from "@rebasepro/types";
15
+ import { FirebaseApp } from "@firebase/app";
16
+ import { FirebaseLoginViewProps } from "./FirebaseLoginView";
17
+ import {
18
+ AppCheckOptions,
19
+ FirebaseSignInOption,
20
+ FirebaseSignInProvider,
21
+ FirebaseUserWrapper,
22
+ FirestoreTextSearchControllerBuilder
23
+ } from "../types";
24
+ import { FirestoreIndexesBuilder } from "../hooks";
25
+
26
+ /**
27
+ * Main entry point that defines the CMS configuration
28
+ * @category Firebase
29
+ */
30
+ export type RebaseFirebaseAppProps = {
31
+
32
+ /**
33
+ * Name of the app, displayed as the main title and in the tab title
34
+ */
35
+ name: string;
36
+
37
+ /**
38
+ * Logo to be displayed in the drawer of the CMS.
39
+ * If not specified, the Rebase logo will be used
40
+ */
41
+ logo?: string;
42
+
43
+ /**
44
+ * Logo used in dark mode. If not specified, `logo` will always be used.
45
+ */
46
+ logoDark?: string;
47
+
48
+ /**
49
+ * List of the mapped collections in the CMS.
50
+ * Each entry relates to a collection in the root database.
51
+ * Each of the navigation entries in this field
52
+ * generates an entry in the main menu.
53
+ */
54
+ collections?: EntityCollection[] | EntityCollectionsBuilder;
55
+
56
+ /**
57
+ * Custom additional views created by the developer, added to the main
58
+ * navigation
59
+ */
60
+ views?: CMSView[] | CMSViewsBuilder;
61
+
62
+ /**
63
+ * Custom additional views created by the developer, added to the admin
64
+ * navigation
65
+ */
66
+ adminViews?: CMSView[] | CMSViewsBuilder;
67
+
68
+ /**
69
+ * Record of custom form fields to be used in the CMS.
70
+ * You can use the key to reference the custom field in
71
+ * the `propertyConfig` prop of a property in a collection.
72
+ */
73
+ propertyConfigs?: PropertyConfig[];
74
+
75
+ /**
76
+ * Do the users need to log in to access the CMS.
77
+ * You can specify an Authenticator function to discriminate which users can
78
+ * access the CMS or not.
79
+ * If not specified, authentication is enabled but no user restrictions
80
+ * apply
81
+ */
82
+ authenticator?: boolean | Authenticator<FirebaseUserWrapper>;
83
+
84
+ /**
85
+ * List of sign in options that will be displayed in the login
86
+ * view if `authentication` is enabled. You can pass Firebase providers strings,
87
+ * such as `firebase.auth.GoogleAuthProvider.PROVIDER_ID` or include additional
88
+ * config such as scopes or custom parameters
89
+ * {@link FirebaseSignInOption}
90
+ * Defaults to Google sign in only.
91
+ */
92
+ signInOptions?: Array<FirebaseSignInProvider | FirebaseSignInOption>;
93
+
94
+ /**
95
+ * If authentication is enabled, allow the user to access the content
96
+ * without login.
97
+ */
98
+ allowSkipLogin?: boolean;
99
+
100
+ /**
101
+ * Firebase configuration of the project. If you afe deploying the app to
102
+ * Firebase hosting, you don't need to specify this value
103
+ */
104
+ firebaseConfig?: Record<string, unknown>;
105
+
106
+ /**
107
+ * Optional callback after Firebase has been initialised. Useful for
108
+ * using the local emulator or retrieving the used configuration.
109
+ * @param config
110
+ */
111
+ onFirebaseInit?: (config: object, app: FirebaseApp) => void;
112
+
113
+ /**
114
+ * Use this to enable Firebase App Check
115
+ */
116
+ appCheckOptions?: AppCheckOptions;
117
+
118
+ /**
119
+ * Format of the dates in the CMS.
120
+ * Defaults to 'MMMM dd, yyyy, HH:mm:ss'
121
+ */
122
+ dateTimeFormat?: string;
123
+
124
+ /**
125
+ * Locale of the CMS, currently only affecting dates
126
+ */
127
+ locale?: Locale;
128
+
129
+ /**
130
+ * Use this controller to return text search results as document ids, that
131
+ * get then fetched from Firestore.
132
+ *
133
+ */
134
+ textSearchControllerBuilder?: FirestoreTextSearchControllerBuilder;
135
+
136
+ /**
137
+ * Default path under the navigation routes of the CMS will be created
138
+ */
139
+ basePath?: string;
140
+
141
+ /**
142
+ * Default path under the collection routes of the CMS will be created
143
+ */
144
+ baseCollectionPath?: string;
145
+
146
+ /**
147
+ * Callback used to get analytics events from the CMS
148
+ */
149
+ onAnalyticsEvent?: (event: CMSAnalyticsEvent, data?: object) => void;
150
+
151
+ /**
152
+ * Use plugins to modify the behaviour of the CMS.
153
+ * Currently, in ALPHA, and likely subject to change.
154
+ */
155
+ plugins?: RebasePlugin[];
156
+
157
+ /**
158
+ * Open the drawer on hover. Defaults to `false`
159
+ */
160
+ autoOpenDrawer?: boolean;
161
+
162
+ /**
163
+ * Use this builder to indicate which indexes are available in your
164
+ * Firestore database. This is used to allow filtering and sorting
165
+ * for multiple fields in the CMS.
166
+ */
167
+ firestoreIndexesBuilder?: FirestoreIndexesBuilder;
168
+
169
+ localTextSearchEnabled?: boolean;
170
+
171
+ components?: ComponentsRegistry;
172
+
173
+ /**
174
+ * Delegate for user and role management. Provides the admin views if specified.
175
+ */
176
+ userManagement?: UserManagementDelegate;
177
+
178
+ };
179
+
180
+ export type ComponentsRegistry = {
181
+ /**
182
+ * Component to be used to render the login view
183
+ */
184
+ LoginView?: React.ComponentType<FirebaseLoginViewProps>;
185
+
186
+ /**
187
+ * Component to be used to render the home page
188
+ */
189
+ HomePage?: React.ComponentType;
190
+ };
@@ -0,0 +1,3 @@
1
+ export * from "./RebaseFirebaseApp";
2
+ export * from "./RebaseFirebaseAppProps";
3
+ export * from "./FirebaseLoginView";
@@ -0,0 +1,135 @@
1
+ export const googleIcon = (mode: "light" | "dark") => <>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ viewBox="0 0 64 64"
5
+ width={32}
6
+ height={32}
7
+ >
8
+ <linearGradient
9
+ id="95yY7w43Oj6n2vH63j6HJb"
10
+ x1="29.401"
11
+ x2="29.401"
12
+ y1="4.064"
13
+ y2="106.734"
14
+ gradientTransform="matrix(1 0 0 -1 0 66)"
15
+ gradientUnits="userSpaceOnUse"
16
+ >
17
+ <stop offset="0" stopColor="#ff5840"/>
18
+ <stop offset=".007" stopColor="#ff5840"/>
19
+ <stop offset=".989" stopColor="#fa528c"/>
20
+ <stop offset="1" stopColor="#fa528c"/>
21
+ </linearGradient>
22
+ <path
23
+ fill="url(#95yY7w43Oj6n2vH63j6HJb)"
24
+ d="M47.46,15.5l-1.37,1.48c-1.34,1.44-3.5,1.67-5.15,0.6c-2.71-1.75-6.43-3.13-11-2.37 c-4.94,0.83-9.17,3.85-11.64, 7.97l-8.03-6.08C14.99,9.82,23.2,5,32.5,5c5,0,9.94,1.56,14.27,4.46 C48.81,10.83,49.13,13.71,47.46,15.5z"
25
+ />
26
+ <linearGradient
27
+ id="95yY7w43Oj6n2vH63j6HJc"
28
+ x1="12.148"
29
+ x2="12.148"
30
+ y1=".872"
31
+ y2="47.812"
32
+ gradientTransform="matrix(1 0 0 -1 0 66)"
33
+ gradientUnits="userSpaceOnUse"
34
+ >
35
+ <stop offset="0" stopColor="#feaa53"/>
36
+ <stop offset=".612" stopColor="#ffcd49"/>
37
+ <stop offset="1" stopColor="#ffde44"/>
38
+ </linearGradient>
39
+ <path
40
+ fill="url(#95yY7w43Oj6n2vH63j6HJc)"
41
+ d="M16.01,30.91c-0.09,2.47,0.37,4.83,1.27,6.96l-8.21,6.05c-1.35-2.51-2.3-5.28-2.75-8.22 c-1.06-6.88,0.54-13.38, 3.95-18.6l8.03,6.08C16.93,25.47,16.1,28.11,16.01,30.91z"
42
+ />
43
+ <linearGradient
44
+ id="95yY7w43Oj6n2vH63j6HJd"
45
+ x1="29.76"
46
+ x2="29.76"
47
+ y1="32.149"
48
+ y2="-6.939"
49
+ gradientTransform="matrix(1 0 0 -1 0 66)"
50
+ gradientUnits="userSpaceOnUse"
51
+ >
52
+ <stop offset="0" stopColor="#42d778"/>
53
+ <stop offset=".428" stopColor="#3dca76"/>
54
+ <stop offset="1" stopColor="#34b171"/>
55
+ </linearGradient>
56
+ <path
57
+ fill="url(#95yY7w43Oj6n2vH63j6HJd)"
58
+ d="M50.45,51.28c-4.55,4.07-10.61,6.57-17.36,6.71C22.91,58.2,13.66,52.53,9.07,43.92l8.21-6.05 C19.78,43.81, 25.67,48,32.5,48c3.94,0,7.52-1.28,10.33-3.44L50.45,51.28z"
59
+ />
60
+ <linearGradient
61
+ id="95yY7w43Oj6n2vH63j6HJe"
62
+ x1="46"
63
+ x2="46"
64
+ y1="3.638"
65
+ y2="35.593"
66
+ gradientTransform="matrix(1 0 0 -1 0 66)"
67
+ gradientUnits="userSpaceOnUse"
68
+ >
69
+ <stop offset="0" stopColor="#155cde"/>
70
+ <stop offset=".278" stopColor="#1f7fe5"/>
71
+ <stop offset=".569" stopColor="#279ceb"/>
72
+ <stop offset=".82" stopColor="#2cafef"/>
73
+ <stop offset="1" stopColor="#2eb5f0"/>
74
+ </linearGradient>
75
+ <path
76
+ fill="url(#95yY7w43Oj6n2vH63j6HJe)"
77
+ d="M59,31.97c0.01,7.73-3.26,14.58-8.55,19.31l-7.62-6.72c2.1-1.61,3.77-3.71,4.84-6.15
78
+ c0.29-0.66-0.2-1.41-0.92-1.41H37c-2.21,0-4-1.79-4-4v-2c0-2.21,1.79-4,4-4h17C56.75,27,59,29.22,59,31.97z"
79
+ />
80
+ </svg>
81
+ </>;
82
+
83
+ export const appleIcon = (mode: "light" | "dark") => <svg width={32} height={32}
84
+ viewBox="0 0 56 56"
85
+ style={{ transform: "scale(2.8)" }}
86
+ version="1.1"
87
+ xmlns="http://www.w3.org/2000/svg">
88
+ <g stroke={mode === "light" ? "#424245" : "white"} strokeWidth="0.5"
89
+ fillRule="evenodd">
90
+ <path
91
+ d="M28.2226562,20.3846154 C29.0546875,20.3846154 30.0976562,19.8048315 30.71875,19.0317864 C31.28125,18.3312142 31.6914062,17.352829 31.6914062,16.3744437 C31.6914062,16.2415766 31.6796875,16.1087095 31.65625,16 C30.7304687,16.0362365 29.6171875,16.640178 28.9492187,17.4494596 C28.421875,18.06548 27.9414062,19.0317864 27.9414062,20.0222505 C27.9414062,20.1671964 27.9648438,20.3121424 27.9765625,20.3604577 C28.0351562,20.3725366 28.1289062,20.3846154 28.2226562,20.3846154 Z M25.2929688,35 C26.4296875,35 26.9335938,34.214876 28.3515625,34.214876 C29.7929688,34.214876 30.109375,34.9758423 31.375,34.9758423 C32.6171875,34.9758423 33.4492188,33.792117 34.234375,32.6325493 C35.1132812,31.3038779 35.4765625,29.9993643 35.5,29.9389701 C35.4179688,29.9148125 33.0390625,28.9122695 33.0390625,26.0979021 C33.0390625,23.6579784 34.9140625,22.5588048 35.0195312,22.474253 C33.7773438,20.6382708 31.890625,20.5899555 31.375,20.5899555 C29.9804688,20.5899555 28.84375,21.4596313 28.1289062,21.4596313 C27.3554688,21.4596313 26.3359375,20.6382708 25.1289062,20.6382708 C22.8320312,20.6382708 20.5,22.5950413 20.5,26.2911634 C20.5,28.5861411 21.3671875,31.013986 22.4335938,32.5842339 C23.3476562,33.9129053 24.1445312,35 25.2929688,35 Z"
92
+ fill={mode === "light" ? "#424245" : "white"} fillRule="nonzero"/>
93
+ </g>
94
+ </svg>;
95
+
96
+ export const githubIcon = (mode: "light" | "dark") => <svg
97
+ fill={mode === "light" ? "#1c1e21" : "white"}
98
+ role="img"
99
+ viewBox="0 0 24 24"
100
+ width={28}
101
+ height={28}
102
+ xmlns="http://www.w3.org/2000/svg">
103
+ <path
104
+ d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
105
+ </svg>;
106
+
107
+
108
+ export const facebookIcon = (mode: "light" | "dark") => <svg
109
+ xmlns="http://www.w3.org/2000/svg"
110
+ width={28} height={28}
111
+ viewBox="0 0 90 90">
112
+ <g>
113
+ <path
114
+ d="M90,15.001C90,7.119,82.884,0,75,0H15C7.116,0,0,7.119,0,15.001v59.998 C0,82.881,7.116,90,15.001,90H45V56H34V41h11v-5.844C45,25.077,52.568,16,61.875,16H74v15H61.875C60.548,31,59,32.611,59,35.024V41 h15v15H59v34h16c7.884,0,15-7.119,15-15.001V15.001z"
115
+ fill={mode === "light" ? "#39569c" : "white"}/>
116
+ </g>
117
+ </svg>;
118
+
119
+ export const microsoftIcon = (mode: "light" | "dark") => <svg
120
+ xmlns="http://www.w3.org/2000/svg" width={28} height={28}
121
+ viewBox="0 0 480 480">
122
+ <g>
123
+ <path
124
+ d="M0.176,224L0.001,67.963l192-26.072V224H0.176z M224.001,37.241L479.937,0v224H224.001V37.241z M479.999,256l-0.062,224 l-255.936-36.008V256H479.999z M192.001,439.918L0.157,413.621L0.147,256h191.854V439.918z"
125
+ fill={mode === "light" ? "#00a2ed" : "white"}/>
126
+ </g>
127
+ </svg>;
128
+
129
+ export const twitterIcon = (mode: "light" | "dark") => <svg
130
+ xmlns="http://www.w3.org/2000/svg" width={28} height={28}
131
+ viewBox="0 0 24 24">
132
+ <path fill={mode === "light" ? "#00acee" : "white"}
133
+ d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z"/>
134
+ </svg>;
135
+
@@ -0,0 +1,7 @@
1
+ export * from "./useFirebaseAuthController";
2
+ export * from "./useFirebaseStorageSource";
3
+ export * from "./useInitialiseFirebase";
4
+ export * from "./useAppCheck";
5
+ export * from "./useFirestoreDataSource";
6
+ export * from "./useFirebaseRealTimeDBDelegate";
7
+ export * from "./useRecaptcha";