goobs-frontend 0.7.68 → 0.7.70
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.70",
|
|
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'
|
|
@@ -53,6 +55,7 @@ import { Animation } from './components/Content/Structure/animations'
|
|
|
53
55
|
import { ExtendedButtonProps } from './components/Content/Structure/button/useButton'
|
|
54
56
|
import { ExtendedTypographyProps } from './components/Content/Structure/typography/useGridTypography'
|
|
55
57
|
import { ExtendedTextFieldProps } from './components/Content/Structure/textfield/useTextField'
|
|
58
|
+
import { ExtendedQRCodeProps } from './components/Content/Structure/qrcode/useQRCode'
|
|
56
59
|
|
|
57
60
|
// Colors
|
|
58
61
|
import {
|
|
@@ -183,6 +186,7 @@ export { CustomToolbar }
|
|
|
183
186
|
export { TransferList }
|
|
184
187
|
export { StyledTooltip }
|
|
185
188
|
export { formContainerStyle }
|
|
189
|
+
export { QRCodeComponent }
|
|
186
190
|
|
|
187
191
|
// New named exports
|
|
188
192
|
export { DateField }
|
|
@@ -215,6 +219,8 @@ export type { CustomStepperProps }
|
|
|
215
219
|
export type { ToolbarProps }
|
|
216
220
|
export type { TransferListProps }
|
|
217
221
|
export type { CustomTooltipProps }
|
|
222
|
+
export type { QRCodeProps }
|
|
223
|
+
export type { ExtendedQRCodeProps }
|
|
218
224
|
|
|
219
225
|
// Additional type exports for the newly declared types
|
|
220
226
|
export type { TypographyComponentProps }
|