goobs-frontend 0.7.68 → 0.7.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "goobs-frontend",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.69",
|
|
4
4
|
"description": "A comprehensive React-based UI library built on Material-UI, offering a wide range of customizable components including grids, typography, buttons, cards, forms, navigation, pricing tables, steppers, tooltips, accordions, and more. Designed for building responsive and consistent user interfaces with advanced features like form validation, theming, and code syntax highlighting.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"jotai": "^2.9.3",
|
|
29
29
|
"lodash": "^4.17.21",
|
|
30
30
|
"next": "14.2.6",
|
|
31
|
-
"react-datepicker": "^7.3.0"
|
|
31
|
+
"react-datepicker": "^7.3.0",
|
|
32
|
+
"react-qr-code": "^2.0.15"
|
|
32
33
|
},
|
|
33
34
|
"devDependencies": {
|
|
34
35
|
"@next/eslint-plugin-next": "^14.2.6",
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import QRCodeComponent, { QRCodeProps } from '../../../../components/QRCode'
|
|
3
|
+
import { columnconfig, cellconfig } from '../../../Grid'
|
|
4
|
+
|
|
5
|
+
type ExtendedColumnConfig = Omit<columnconfig, 'component'> & {
|
|
6
|
+
component?: columnconfig['component']
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface ExtendedQRCodeProps extends Omit<QRCodeProps, 'sx'> {
|
|
10
|
+
columnconfig?: ExtendedColumnConfig
|
|
11
|
+
cellconfig?: cellconfig
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const useQRCode = (grid: {
|
|
15
|
+
qrcode?: ExtendedQRCodeProps | ExtendedQRCodeProps[]
|
|
16
|
+
}): columnconfig | columnconfig[] | null => {
|
|
17
|
+
if (!grid.qrcode) return null
|
|
18
|
+
|
|
19
|
+
const renderQRCode = (
|
|
20
|
+
component: ExtendedQRCodeProps,
|
|
21
|
+
index: number
|
|
22
|
+
): columnconfig => {
|
|
23
|
+
const {
|
|
24
|
+
value,
|
|
25
|
+
size,
|
|
26
|
+
title,
|
|
27
|
+
columnconfig: itemColumnConfig,
|
|
28
|
+
cellconfig,
|
|
29
|
+
...restProps
|
|
30
|
+
} = component
|
|
31
|
+
|
|
32
|
+
if (
|
|
33
|
+
!itemColumnConfig ||
|
|
34
|
+
typeof itemColumnConfig !== 'object' ||
|
|
35
|
+
typeof itemColumnConfig.row !== 'number' ||
|
|
36
|
+
typeof itemColumnConfig.column !== 'number'
|
|
37
|
+
) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
'columnconfig must be an object with row and column as numbers'
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const mergedConfig: columnconfig = {
|
|
44
|
+
...itemColumnConfig,
|
|
45
|
+
cellconfig: {
|
|
46
|
+
...cellconfig,
|
|
47
|
+
},
|
|
48
|
+
component: (
|
|
49
|
+
<QRCodeComponent
|
|
50
|
+
key={`qrcode-${index}`}
|
|
51
|
+
value={value}
|
|
52
|
+
size={size}
|
|
53
|
+
title={title}
|
|
54
|
+
{...restProps}
|
|
55
|
+
/>
|
|
56
|
+
),
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return mergedConfig
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (Array.isArray(grid.qrcode)) {
|
|
63
|
+
return grid.qrcode.map(renderQRCode)
|
|
64
|
+
} else {
|
|
65
|
+
return renderQRCode(grid.qrcode, 0)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export default useQRCode
|
|
@@ -56,6 +56,7 @@ import useNumberField, {
|
|
|
56
56
|
import usePasswordField, {
|
|
57
57
|
ExtendedPasswordFieldProps,
|
|
58
58
|
} from './Structure/passwordField/usePasswordField'
|
|
59
|
+
import useQRCode, { ExtendedQRCodeProps } from './Structure/qrcode/useQRCode'
|
|
59
60
|
|
|
60
61
|
/**
|
|
61
62
|
* Props for the ContentSection component.
|
|
@@ -88,6 +89,7 @@ export interface ContentSectionProps {
|
|
|
88
89
|
searchbar?: ExtendedSearchbarProps | ExtendedSearchbarProps[]
|
|
89
90
|
numberField?: ExtendedNumberFieldProps | ExtendedNumberFieldProps[]
|
|
90
91
|
passwordField?: ExtendedPasswordFieldProps | ExtendedPasswordFieldProps[]
|
|
92
|
+
qrcode?: ExtendedQRCodeProps | ExtendedQRCodeProps[]
|
|
91
93
|
}>
|
|
92
94
|
width?: number
|
|
93
95
|
}
|
|
@@ -137,6 +139,7 @@ const RenderContent: React.FC<
|
|
|
137
139
|
addToColumnConfigs(useSearchbar(props))
|
|
138
140
|
addToColumnConfigs(useNumberField({ numberField: props.numberField }))
|
|
139
141
|
addToColumnConfigs(usePasswordField({ passwordField: props.passwordField }))
|
|
142
|
+
addToColumnConfigs(useQRCode({ qrcode: props.qrcode }))
|
|
140
143
|
|
|
141
144
|
const updatedGridConfig: gridconfig = {
|
|
142
145
|
...grid.gridconfig,
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import React, { useMemo } from 'react'
|
|
2
|
+
import QRCode from 'react-qr-code'
|
|
3
|
+
import { Box, Typography, Paper, Theme, CircularProgress } from '@mui/material'
|
|
4
|
+
import { SxProps } from '@mui/system'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Props for the QRCodeComponent
|
|
8
|
+
* @typedef {Object} QRCodeProps
|
|
9
|
+
* @property {string} value - The value to be encoded in the QR code
|
|
10
|
+
* @property {number} [size] - The size of the QR code in pixels
|
|
11
|
+
* @property {string} [title] - An optional title to display above the QR code
|
|
12
|
+
* @property {SxProps<Theme>} [sx] - Custom styles to apply to the component
|
|
13
|
+
*/
|
|
14
|
+
export interface QRCodeProps {
|
|
15
|
+
value: string
|
|
16
|
+
size?: number
|
|
17
|
+
title?: string
|
|
18
|
+
sx?: SxProps<Theme>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A component that displays a QR code with Material-UI styling
|
|
23
|
+
* @param {QRCodeProps} props - The props for the component
|
|
24
|
+
* @returns {React.ReactElement} The rendered QR code component
|
|
25
|
+
*/
|
|
26
|
+
const QRCodeComponent: React.FC<QRCodeProps> = React.memo(
|
|
27
|
+
({ value, size = 256, title, sx }) => {
|
|
28
|
+
// Validate the QR code value
|
|
29
|
+
const isValidValue = useMemo(() => {
|
|
30
|
+
if (!value) return false
|
|
31
|
+
try {
|
|
32
|
+
// Check if the value is a valid URL
|
|
33
|
+
new URL(value)
|
|
34
|
+
return true
|
|
35
|
+
} catch {
|
|
36
|
+
// If not a URL, check if it's a non-empty string
|
|
37
|
+
return typeof value === 'string' && value.trim().length > 0
|
|
38
|
+
}
|
|
39
|
+
}, [value])
|
|
40
|
+
|
|
41
|
+
// Calculate responsive size
|
|
42
|
+
const responsiveSize = useMemo(() => {
|
|
43
|
+
return Math.min(size, window.innerWidth - 32) // 32px for padding
|
|
44
|
+
}, [size])
|
|
45
|
+
|
|
46
|
+
if (!isValidValue) {
|
|
47
|
+
return (
|
|
48
|
+
<Box sx={{ ...sx, p: 2 }} role="alert">
|
|
49
|
+
<Typography color="error">
|
|
50
|
+
Error: Invalid or empty QR code value
|
|
51
|
+
</Typography>
|
|
52
|
+
</Box>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<Paper
|
|
58
|
+
elevation={3}
|
|
59
|
+
sx={{
|
|
60
|
+
...sx,
|
|
61
|
+
p: 3,
|
|
62
|
+
display: 'inline-block',
|
|
63
|
+
maxWidth: '100%',
|
|
64
|
+
boxSizing: 'border-box',
|
|
65
|
+
}}
|
|
66
|
+
>
|
|
67
|
+
{title && (
|
|
68
|
+
<Typography variant="h6" gutterBottom align="center">
|
|
69
|
+
{title}
|
|
70
|
+
</Typography>
|
|
71
|
+
)}
|
|
72
|
+
<Box
|
|
73
|
+
sx={{
|
|
74
|
+
display: 'flex',
|
|
75
|
+
justifyContent: 'center',
|
|
76
|
+
alignItems: 'center',
|
|
77
|
+
width: responsiveSize,
|
|
78
|
+
height: responsiveSize,
|
|
79
|
+
margin: 'auto',
|
|
80
|
+
}}
|
|
81
|
+
>
|
|
82
|
+
<React.Suspense
|
|
83
|
+
fallback={
|
|
84
|
+
<CircularProgress
|
|
85
|
+
size={responsiveSize / 4}
|
|
86
|
+
aria-label="Loading QR Code"
|
|
87
|
+
/>
|
|
88
|
+
}
|
|
89
|
+
>
|
|
90
|
+
<QRCode
|
|
91
|
+
value={value}
|
|
92
|
+
size={responsiveSize}
|
|
93
|
+
style={{ height: 'auto', maxWidth: '100%', width: '100%' }}
|
|
94
|
+
aria-label={`QR Code for ${title || value}`}
|
|
95
|
+
/>
|
|
96
|
+
</React.Suspense>
|
|
97
|
+
</Box>
|
|
98
|
+
</Paper>
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
QRCodeComponent.displayName = 'QRCodeComponent'
|
|
104
|
+
|
|
105
|
+
export default QRCodeComponent
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
1
3
|
// Components
|
|
2
4
|
import CustomButton from './components/Button'
|
|
3
5
|
import CustomGrid, {
|
|
@@ -34,7 +36,7 @@ import { CustomStepper, CustomStepperProps } from './components/Stepper'
|
|
|
34
36
|
import CustomToolbar, { ToolbarProps } from './components/Toolbar'
|
|
35
37
|
import TransferList, { TransferListProps } from './components/TransferList'
|
|
36
38
|
import StyledTooltip, { CustomTooltipProps } from './components/Tooltip'
|
|
37
|
-
import
|
|
39
|
+
import QRCodeComponent, { QRCodeProps } from './components/QRCode'
|
|
38
40
|
|
|
39
41
|
// New imports
|
|
40
42
|
import DateField from './components/DateField'
|
|
@@ -183,6 +185,7 @@ export { CustomToolbar }
|
|
|
183
185
|
export { TransferList }
|
|
184
186
|
export { StyledTooltip }
|
|
185
187
|
export { formContainerStyle }
|
|
188
|
+
export { QRCodeComponent }
|
|
186
189
|
|
|
187
190
|
// New named exports
|
|
188
191
|
export { DateField }
|
|
@@ -215,6 +218,7 @@ export type { CustomStepperProps }
|
|
|
215
218
|
export type { ToolbarProps }
|
|
216
219
|
export type { TransferListProps }
|
|
217
220
|
export type { CustomTooltipProps }
|
|
221
|
+
export type { QRCodeProps }
|
|
218
222
|
|
|
219
223
|
// Additional type exports for the newly declared types
|
|
220
224
|
export type { TypographyComponentProps }
|