goobs-frontend 0.9.12 → 0.9.13

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.
@@ -0,0 +1,23 @@
1
+ 'use client'
2
+
3
+ import React from 'react'
4
+ import { Provider, createStore } from 'jotai'
5
+ import { columnsAtom } from './atom'
6
+
7
+ // Create a custom store
8
+ export const store = createStore()
9
+
10
+ // Initialize the store with our atoms to ensure they're properly registered
11
+ store.set(columnsAtom, [])
12
+
13
+ /**
14
+ * A Jotai Provider component that uses a custom store to prevent
15
+ * "multiple instances" error in Next.js applications.
16
+ */
17
+ export function JotaiProvider({
18
+ children,
19
+ }: {
20
+ children: React.ReactNode
21
+ }): React.ReactElement {
22
+ return <Provider store={store}>{children}</Provider>
23
+ }
@@ -1,8 +1,9 @@
1
- import React, { useMemo } from 'react'
1
+ import React, { useMemo, useEffect } from 'react'
2
2
  import QRCode from 'react-qr-code'
3
- import { Box, Typography, Paper, Theme, CircularProgress } from '@mui/material'
3
+ import { Box, Paper } from '@mui/material'
4
4
  import { SxProps } from '@mui/system'
5
5
  import { authenticator } from 'otplib'
6
+ import Typography from '../Typography'
6
7
 
7
8
  /**
8
9
  * Props for the QRCodeComponent
@@ -11,7 +12,7 @@ import { authenticator } from 'otplib'
11
12
  * @property {string} appName - The name of the application for MFA
12
13
  * @property {number} [size] - The size of the QR code in pixels
13
14
  * @property {string} [title] - An optional title to display above the QR code
14
- * @property {SxProps<Theme>} [sx] - Custom styles to apply to the component
15
+ * @property {SxProps} [sx] - Custom styles to apply to the component
15
16
  * @property {(secret: string) => void} [onSecretGenerated] - Callback function to receive the generated secret
16
17
  */
17
18
  export interface QRCodeProps {
@@ -19,7 +20,7 @@ export interface QRCodeProps {
19
20
  appName: string
20
21
  size?: number
21
22
  title?: string
22
- sx?: SxProps<Theme>
23
+ sx?: SxProps
23
24
  onSecretGenerated?: (secret: string) => void
24
25
  }
25
26
 
@@ -38,11 +39,15 @@ const QRCodeComponent: React.FC<QRCodeProps> = React.memo(
38
39
  encodeURIComponent(appName),
39
40
  generatedSecret
40
41
  )
41
- if (onSecretGenerated) {
42
- onSecretGenerated(generatedSecret)
43
- }
44
42
  return { secret: generatedSecret, otpAuth: otpAuthUrl }
45
- }, [username, appName, onSecretGenerated])
43
+ }, [username, appName])
44
+
45
+ // Move the callback to useEffect to avoid state updates during render
46
+ useEffect(() => {
47
+ if (onSecretGenerated && secret) {
48
+ onSecretGenerated(secret)
49
+ }
50
+ }, [secret, onSecretGenerated])
46
51
 
47
52
  // Calculate responsive size
48
53
  const responsiveSize = useMemo(() => {
@@ -52,9 +57,11 @@ const QRCodeComponent: React.FC<QRCodeProps> = React.memo(
52
57
  if (!otpAuth) {
53
58
  return (
54
59
  <Box sx={{ ...sx, p: 2 }} role="alert">
55
- <Typography color="error">
56
- Error: Failed to generate QR code
57
- </Typography>
60
+ <Typography
61
+ text="Error: Failed to generate QR code"
62
+ fontcolor="error"
63
+ fontvariant="merriparagraph"
64
+ />
58
65
  </Box>
59
66
  )
60
67
  }
@@ -63,17 +70,20 @@ const QRCodeComponent: React.FC<QRCodeProps> = React.memo(
63
70
  <Paper
64
71
  elevation={3}
65
72
  sx={{
66
- ...sx,
67
73
  p: 3,
68
74
  display: 'inline-block',
69
75
  maxWidth: '100%',
70
76
  boxSizing: 'border-box',
77
+ ...sx,
71
78
  }}
72
79
  >
73
80
  {title && (
74
- <Typography variant="h6" gutterBottom align="center">
75
- {title}
76
- </Typography>
81
+ <Typography
82
+ text={title}
83
+ fontvariant="merrih5"
84
+ align="center"
85
+ gutterBottom
86
+ />
77
87
  )}
78
88
  <Box
79
89
  sx={{
@@ -85,25 +95,13 @@ const QRCodeComponent: React.FC<QRCodeProps> = React.memo(
85
95
  margin: 'auto',
86
96
  }}
87
97
  >
88
- <React.Suspense
89
- fallback={
90
- <CircularProgress
91
- size={responsiveSize / 4}
92
- aria-label="Loading QR Code"
93
- />
94
- }
95
- >
96
- <QRCode
97
- value={otpAuth}
98
- size={responsiveSize}
99
- style={{ height: 'auto', maxWidth: '100%', width: '100%' }}
100
- aria-label={`QR Code for ${title || 'MFA Setup'}`}
101
- />
102
- </React.Suspense>
98
+ <QRCode
99
+ value={otpAuth}
100
+ size={responsiveSize}
101
+ style={{ height: 'auto', maxWidth: '100%', width: '100%' }}
102
+ aria-label={`QR Code for ${title || 'MFA Setup'}`}
103
+ />
103
104
  </Box>
104
- <Typography variant="body2" align="center" sx={{ mt: 2 }}>
105
- Secret: {secret}
106
- </Typography>
107
105
  </Paper>
108
106
  )
109
107
  }