goobs-frontend 0.7.57 → 0.7.59
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 +14 -14
- package/src/components/Button/index.tsx +6 -65
- package/src/components/ConfirmationCodeInput/index.tsx +40 -5
- package/src/components/Content/Structure/styledcomponent/useStyledComponent.tsx +0 -6
- package/src/components/Form/Popup/index.tsx +143 -106
- package/src/components/StyledComponent/{adornments.tsx → adornment/index.tsx} +17 -12
- package/src/components/StyledComponent/helperfooter/useHelperFooter.tsx +225 -89
- package/src/components/StyledComponent/index.tsx +99 -182
- package/src/components/StyledComponent/useEffects/index.tsx +54 -0
- package/src/index.ts +1 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "goobs-frontend",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.59",
|
|
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",
|
|
@@ -25,29 +25,29 @@
|
|
|
25
25
|
"@emotion/cache": "^11.11.0",
|
|
26
26
|
"@emotion/react": "^11.11.4",
|
|
27
27
|
"@emotion/styled": "^11.11.5",
|
|
28
|
-
"@mui/icons-material": "^5.
|
|
29
|
-
"@mui/material": "^5.
|
|
30
|
-
"@types/lodash": "^4.17.
|
|
31
|
-
"goobs-cache": "^1.
|
|
32
|
-
"highlight.js": "^11.
|
|
28
|
+
"@mui/icons-material": "^5.16.0",
|
|
29
|
+
"@mui/material": "^5.16.0",
|
|
30
|
+
"@types/lodash": "^4.17.6",
|
|
31
|
+
"goobs-cache": "^1.3.1",
|
|
32
|
+
"highlight.js": "^11.10.0",
|
|
33
33
|
"lodash": "^4.17.21",
|
|
34
|
-
"next": "14.2.
|
|
34
|
+
"next": "14.2.5"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@next/eslint-plugin-next": "^14.2.
|
|
38
|
-
"@types/node": "^20.14.
|
|
39
|
-
"@types/react": "18.3.
|
|
37
|
+
"@next/eslint-plugin-next": "^14.2.5",
|
|
38
|
+
"@types/node": "^20.14.10",
|
|
39
|
+
"@types/react": "18.3.3",
|
|
40
40
|
"@types/react-dom": "^18.3.0",
|
|
41
|
-
"@typescript-eslint/eslint-plugin": "^7.
|
|
42
|
-
"@typescript-eslint/parser": "^7.
|
|
41
|
+
"@typescript-eslint/eslint-plugin": "^7.16.0",
|
|
42
|
+
"@typescript-eslint/parser": "^7.16.0",
|
|
43
43
|
"eslint": "^8.57.0",
|
|
44
|
-
"eslint-config-next": "^14.2.
|
|
44
|
+
"eslint-config-next": "^14.2.5",
|
|
45
45
|
"eslint-config-prettier": "^9.1.0",
|
|
46
46
|
"eslint-plugin-prettier": "^5.1.3",
|
|
47
47
|
"prettier": "^3.3.2",
|
|
48
48
|
"react": "^18.3.1",
|
|
49
49
|
"react-dom": "^18.3.1",
|
|
50
|
-
"typescript": "^5.5.
|
|
50
|
+
"typescript": "^5.5.3"
|
|
51
51
|
},
|
|
52
52
|
"files": [
|
|
53
53
|
"src"
|
|
@@ -7,46 +7,24 @@ import Typography from '../Typography'
|
|
|
7
7
|
import { get, JSONValue } from 'goobs-cache'
|
|
8
8
|
import { red } from '../../styles/palette'
|
|
9
9
|
|
|
10
|
-
/**
|
|
11
|
-
* Defines the possible alignment options for button content.
|
|
12
|
-
*/
|
|
13
10
|
export type ButtonAlignment = 'left' | 'center' | 'right'
|
|
14
11
|
|
|
15
|
-
/**
|
|
16
|
-
* Defines the structure of helper footer messages used for form validation.
|
|
17
|
-
*/
|
|
18
12
|
export interface HelperFooterMessage {
|
|
19
|
-
/** Indicates whether the message represents an error or success state */
|
|
20
13
|
status: 'error' | 'success'
|
|
21
|
-
/** The message to display in the status area */
|
|
22
14
|
statusMessage: string
|
|
23
|
-
/** The message to spread across multiple components */
|
|
24
15
|
spreadMessage: string
|
|
25
|
-
/** Priority of the spread message for determining which message to show */
|
|
26
16
|
spreadMessagePriority: number
|
|
27
|
-
/** The name of the form this message is associated with */
|
|
28
17
|
formname: string
|
|
29
|
-
/** Indicates if the field associated with this message is required */
|
|
30
18
|
required: boolean
|
|
31
19
|
}
|
|
32
20
|
|
|
33
|
-
/**
|
|
34
|
-
* Props for the CustomButton component.
|
|
35
|
-
* Extends ButtonProps from Material-UI, omitting 'color' and 'variant'.
|
|
36
|
-
*/
|
|
37
21
|
export interface CustomButtonProps
|
|
38
22
|
extends Omit<ButtonProps, 'color' | 'variant'> {
|
|
39
|
-
/** Text to display on the button */
|
|
40
23
|
text?: string
|
|
41
|
-
/** Background color of the button */
|
|
42
24
|
backgroundcolor?: string
|
|
43
|
-
/** Color of the button's outline */
|
|
44
25
|
outlinecolor?: string
|
|
45
|
-
/** Color of the button's text */
|
|
46
26
|
fontcolor?: string
|
|
47
|
-
/** Alignment of the button's text */
|
|
48
27
|
fontlocation?: ButtonAlignment
|
|
49
|
-
/** Typography variant for the button's text */
|
|
50
28
|
fontvariant?:
|
|
51
29
|
| 'arapeyh1'
|
|
52
30
|
| 'arapeyh2'
|
|
@@ -75,32 +53,18 @@ export interface CustomButtonProps
|
|
|
75
53
|
| 'merriparagraph'
|
|
76
54
|
| 'merrihelperheader'
|
|
77
55
|
| 'merrihelperfooter'
|
|
78
|
-
/** Icon to display on the button. Set to false to hide the icon */
|
|
79
56
|
icon?: React.ReactNode | false
|
|
80
|
-
/** Color of the icon */
|
|
81
57
|
iconcolor?: string
|
|
82
|
-
/** Size of the icon */
|
|
83
58
|
iconsize?: string
|
|
84
|
-
/** Position of the icon relative to the text */
|
|
85
59
|
iconlocation?: 'left' | 'top' | 'right'
|
|
86
|
-
/** Style variant of the button */
|
|
87
60
|
variant?: 'text' | 'outlined' | 'contained'
|
|
88
|
-
/** Function to call when the button is clicked */
|
|
89
61
|
onClick?: () => void
|
|
90
|
-
/** Helper footer message for form validation */
|
|
91
62
|
helperfooter?: HelperFooterMessage
|
|
92
|
-
/** Width of the button */
|
|
93
63
|
width?: string
|
|
94
|
-
/** Name of the form this button is associated with */
|
|
95
64
|
formname?: string
|
|
96
|
-
/** Name attribute for the button element */
|
|
97
65
|
name?: string
|
|
98
66
|
}
|
|
99
67
|
|
|
100
|
-
/**
|
|
101
|
-
* CustomButton component renders a customizable button with integrated form validation.
|
|
102
|
-
* It displays error messages based on helper footers and form validation status.
|
|
103
|
-
*/
|
|
104
68
|
const CustomButton: React.FC<CustomButtonProps> = props => {
|
|
105
69
|
const {
|
|
106
70
|
text,
|
|
@@ -121,24 +85,16 @@ const CustomButton: React.FC<CustomButtonProps> = props => {
|
|
|
121
85
|
width,
|
|
122
86
|
} = props
|
|
123
87
|
|
|
124
|
-
/** State for storing the current error message */
|
|
125
88
|
const [errorMessage, setErrorMessage] = useState<string | undefined>(
|
|
126
89
|
undefined
|
|
127
90
|
)
|
|
128
|
-
/** State for tracking whether the associated form is valid */
|
|
129
91
|
const [isFormValid, setIsFormValid] = useState<boolean>(true)
|
|
130
|
-
/** State for storing helper footer messages */
|
|
131
92
|
const [helperFooterValue, setHelperFooterValue] = useState<
|
|
132
93
|
Record<string, HelperFooterMessage>
|
|
133
94
|
>({})
|
|
134
95
|
|
|
135
|
-
/**
|
|
136
|
-
* Updates the form validation status and error message based on helper footers.
|
|
137
|
-
* This function filters relevant footers, checks for errors and empty required fields,
|
|
138
|
-
* and updates the error message and form validity accordingly.
|
|
139
|
-
*/
|
|
140
96
|
const updateFormValidation = useCallback(() => {
|
|
141
|
-
if (formname) {
|
|
97
|
+
if (formname && helperFooterValue) {
|
|
142
98
|
const relevantFooters = Object.values(helperFooterValue).filter(
|
|
143
99
|
footer => footer?.formname === formname
|
|
144
100
|
)
|
|
@@ -168,13 +124,12 @@ const CustomButton: React.FC<CustomButtonProps> = props => {
|
|
|
168
124
|
setErrorMessage(undefined)
|
|
169
125
|
setIsFormValid(true)
|
|
170
126
|
}
|
|
127
|
+
} else {
|
|
128
|
+
setErrorMessage(undefined)
|
|
129
|
+
setIsFormValid(true)
|
|
171
130
|
}
|
|
172
131
|
}, [formname, helperFooterValue])
|
|
173
132
|
|
|
174
|
-
/**
|
|
175
|
-
* Fetches helper footer data from the cache when formname changes.
|
|
176
|
-
* This effect runs whenever the formname prop changes.
|
|
177
|
-
*/
|
|
178
133
|
useEffect(() => {
|
|
179
134
|
const fetchHelperFooter = async () => {
|
|
180
135
|
const helperFooterResult = await get('helperFooter', 'client')
|
|
@@ -189,28 +144,18 @@ const CustomButton: React.FC<CustomButtonProps> = props => {
|
|
|
189
144
|
HelperFooterMessage
|
|
190
145
|
>
|
|
191
146
|
)
|
|
147
|
+
} else {
|
|
148
|
+
setHelperFooterValue({})
|
|
192
149
|
}
|
|
193
150
|
}
|
|
194
151
|
|
|
195
152
|
fetchHelperFooter()
|
|
196
153
|
}, [formname])
|
|
197
154
|
|
|
198
|
-
/**
|
|
199
|
-
* Triggers form validation whenever helperFooterValue changes.
|
|
200
|
-
* This effect ensures that the form validation is updated whenever
|
|
201
|
-
* the helper footer messages change.
|
|
202
|
-
*/
|
|
203
155
|
useEffect(() => {
|
|
204
156
|
updateFormValidation()
|
|
205
157
|
}, [updateFormValidation])
|
|
206
158
|
|
|
207
|
-
/**
|
|
208
|
-
* Renders the icon element based on the provided icon prop.
|
|
209
|
-
* If the icon prop is false, it returns null.
|
|
210
|
-
* If the icon is a valid React element, it clones it with the specified size.
|
|
211
|
-
* Otherwise, it renders a default StarIcon.
|
|
212
|
-
* @returns The rendered icon element or null.
|
|
213
|
-
*/
|
|
214
159
|
const renderIcon = () => {
|
|
215
160
|
if (icon === false) {
|
|
216
161
|
return null
|
|
@@ -223,10 +168,6 @@ const CustomButton: React.FC<CustomButtonProps> = props => {
|
|
|
223
168
|
return <StarIcon style={{ fontSize: iconsize }} />
|
|
224
169
|
}
|
|
225
170
|
|
|
226
|
-
/**
|
|
227
|
-
* Handles the button click event.
|
|
228
|
-
* If the form is valid and an onClick handler is provided, it calls the handler.
|
|
229
|
-
*/
|
|
230
171
|
const handleButtonClick = async () => {
|
|
231
172
|
if (!isFormValid) {
|
|
232
173
|
return
|
|
@@ -4,12 +4,16 @@ import { Input, Box } from '@mui/material'
|
|
|
4
4
|
import { useCodeConfirmation } from './utils/useCodeConfirmation'
|
|
5
5
|
import { columnconfig } from '../../components/Grid'
|
|
6
6
|
import { red, green } from '../../styles/palette'
|
|
7
|
+
import { set } from 'goobs-cache'
|
|
7
8
|
|
|
8
9
|
export interface ConfirmationCodeInputsProps {
|
|
9
10
|
identifier?: string
|
|
10
11
|
columnconfig?: columnconfig
|
|
11
12
|
isValid: boolean
|
|
12
13
|
codeLength?: number
|
|
14
|
+
'aria-label'?: string
|
|
15
|
+
'aria-required'?: boolean
|
|
16
|
+
'aria-invalid'?: boolean
|
|
13
17
|
}
|
|
14
18
|
|
|
15
19
|
/**
|
|
@@ -21,12 +25,17 @@ export interface ConfirmationCodeInputsProps {
|
|
|
21
25
|
const ConfirmationCodeInputs: React.FC<ConfirmationCodeInputsProps> = ({
|
|
22
26
|
codeLength = 6,
|
|
23
27
|
isValid,
|
|
28
|
+
'aria-label': ariaLabel,
|
|
29
|
+
'aria-required': ariaRequired,
|
|
30
|
+
'aria-invalid': ariaInvalid,
|
|
24
31
|
...props
|
|
25
32
|
}) => {
|
|
26
|
-
const { handleCodeChange, handleKeyDown } = useCodeConfirmation(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
33
|
+
const { handleCodeChange, handleKeyDown, combinedCode } = useCodeConfirmation(
|
|
34
|
+
{
|
|
35
|
+
codeLength,
|
|
36
|
+
isValid,
|
|
37
|
+
}
|
|
38
|
+
)
|
|
30
39
|
|
|
31
40
|
/**
|
|
32
41
|
* handleChange function is called when the value of an input field changes.
|
|
@@ -63,8 +72,29 @@ const ConfirmationCodeInputs: React.FC<ConfirmationCodeInputsProps> = ({
|
|
|
63
72
|
handleKeyDown(event, index)
|
|
64
73
|
}
|
|
65
74
|
|
|
75
|
+
/**
|
|
76
|
+
* useEffect hook is used to set the verification code into an atom using goobs-cache.
|
|
77
|
+
* It sets the code whenever the combinedCode changes and the code is valid.
|
|
78
|
+
*/
|
|
79
|
+
React.useEffect(() => {
|
|
80
|
+
if (isValid) {
|
|
81
|
+
set(
|
|
82
|
+
'verificationCode',
|
|
83
|
+
combinedCode,
|
|
84
|
+
new Date(Date.now() + 3600000),
|
|
85
|
+
'memory'
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
}, [combinedCode, isValid])
|
|
89
|
+
|
|
66
90
|
return (
|
|
67
|
-
<Box
|
|
91
|
+
<Box
|
|
92
|
+
display="flex"
|
|
93
|
+
flexDirection="row"
|
|
94
|
+
alignItems="center"
|
|
95
|
+
role="group"
|
|
96
|
+
aria-label={ariaLabel || 'Confirmation Code'}
|
|
97
|
+
>
|
|
68
98
|
<Box display="flex" gap={1}>
|
|
69
99
|
{Array.from({ length: codeLength }, (_, index) => (
|
|
70
100
|
<Input
|
|
@@ -72,6 +102,9 @@ const ConfirmationCodeInputs: React.FC<ConfirmationCodeInputsProps> = ({
|
|
|
72
102
|
name={`code${index + 1}`}
|
|
73
103
|
inputProps={{
|
|
74
104
|
maxLength: 1,
|
|
105
|
+
'aria-label': `Code Digit ${index + 1}`,
|
|
106
|
+
'aria-required': ariaRequired,
|
|
107
|
+
'aria-invalid': ariaInvalid,
|
|
75
108
|
}}
|
|
76
109
|
sx={{
|
|
77
110
|
border: '1px solid',
|
|
@@ -100,6 +133,8 @@ const ConfirmationCodeInputs: React.FC<ConfirmationCodeInputsProps> = ({
|
|
|
100
133
|
borderRadius="50%"
|
|
101
134
|
bgcolor={isValid ? green.main : red.main}
|
|
102
135
|
ml={2}
|
|
136
|
+
role="status"
|
|
137
|
+
aria-label={isValid ? 'Code is valid' : 'Code is invalid'}
|
|
103
138
|
/>
|
|
104
139
|
</Box>
|
|
105
140
|
)
|
|
@@ -42,9 +42,6 @@ const useStyledComponent = (grid: {
|
|
|
42
42
|
label,
|
|
43
43
|
shrunklabellocation,
|
|
44
44
|
value,
|
|
45
|
-
onChange,
|
|
46
|
-
defaultValue,
|
|
47
|
-
inputRef,
|
|
48
45
|
columnconfig: itemColumnConfig,
|
|
49
46
|
valuestatus,
|
|
50
47
|
cellconfig,
|
|
@@ -88,9 +85,6 @@ const useStyledComponent = (grid: {
|
|
|
88
85
|
label={label}
|
|
89
86
|
shrunklabellocation={shrunklabellocation}
|
|
90
87
|
value={value}
|
|
91
|
-
onChange={onChange}
|
|
92
|
-
defaultValue={defaultValue}
|
|
93
|
-
inputRef={inputRef}
|
|
94
88
|
valuestatus={valuestatus}
|
|
95
89
|
required={required}
|
|
96
90
|
{...restProps}
|
|
@@ -1,150 +1,187 @@
|
|
|
1
1
|
'use client'
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
import React, {
|
|
4
|
+
forwardRef,
|
|
5
|
+
useImperativeHandle,
|
|
6
|
+
useRef,
|
|
7
|
+
useMemo,
|
|
8
|
+
useCallback,
|
|
9
|
+
} from 'react'
|
|
3
10
|
import { Close } from '@mui/icons-material'
|
|
4
11
|
import { Dialog, IconButton, Box } from '@mui/material'
|
|
5
12
|
import ContentSection, { ContentSectionProps } from '../../Content'
|
|
6
13
|
import { formContainerStyle } from './../../../styles/Form'
|
|
7
14
|
import { ExtendedTypographyProps } from '../../Content/Structure/typography/useGridTypography'
|
|
8
|
-
import Typography from '../../Typography'
|
|
9
15
|
|
|
10
16
|
/**
|
|
11
17
|
* Props for the PopupForm component.
|
|
18
|
+
* @interface PopupFormProps
|
|
12
19
|
*/
|
|
13
20
|
export interface PopupFormProps {
|
|
14
|
-
/**
|
|
21
|
+
/** The title of the popup form */
|
|
15
22
|
title?: string
|
|
16
|
-
/**
|
|
23
|
+
/** The description of the popup form */
|
|
17
24
|
description?: string
|
|
18
|
-
/**
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
|
|
25
|
+
/** The grid configuration for the form content */
|
|
26
|
+
grids?: ContentSectionProps['grids']
|
|
27
|
+
/** Callback function to handle form submission */
|
|
28
|
+
onSubmit?: (event: React.FormEvent<HTMLFormElement>) => void
|
|
29
|
+
/** Custom content to render inside the form */
|
|
30
|
+
content?: React.ReactNode
|
|
31
|
+
/** The type of popup to render ('dialog' or 'modal') */
|
|
32
|
+
popupType: 'dialog' | 'modal'
|
|
33
|
+
/** Whether the popup is open (only applicable for 'dialog' type) */
|
|
34
|
+
open?: boolean
|
|
35
|
+
/** Callback function to handle closing the popup (only applicable for 'dialog' type) */
|
|
36
|
+
onClose?: () => void
|
|
26
37
|
}
|
|
27
38
|
|
|
28
39
|
/**
|
|
29
|
-
* PopupForm
|
|
30
|
-
*
|
|
31
|
-
*
|
|
40
|
+
* PopupForm Component
|
|
41
|
+
*
|
|
42
|
+
* A flexible popup form component that can be rendered as either a dialog or a modal.
|
|
43
|
+
* It supports custom content, grids, and header configuration.
|
|
32
44
|
*
|
|
33
|
-
* @
|
|
34
|
-
* @
|
|
35
|
-
*
|
|
45
|
+
* @component
|
|
46
|
+
* @example
|
|
47
|
+
* <PopupForm
|
|
48
|
+
* title="Login"
|
|
49
|
+
* description="Please enter your credentials"
|
|
50
|
+
* popupType="dialog"
|
|
51
|
+
* open={isOpen}
|
|
52
|
+
* onClose={handleClose}
|
|
53
|
+
* onSubmit={handleSubmit}
|
|
54
|
+
* content={<LoginForm />}
|
|
55
|
+
* />
|
|
36
56
|
*/
|
|
37
57
|
const PopupForm = forwardRef<HTMLFormElement, PopupFormProps>(
|
|
38
|
-
(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
58
|
+
(
|
|
59
|
+
{ title, description, grids, onSubmit, content, popupType, open, onClose },
|
|
60
|
+
ref
|
|
61
|
+
) => {
|
|
42
62
|
const internalFormRef = useRef<HTMLFormElement>(null)
|
|
43
63
|
|
|
64
|
+
// Expose the internal form ref to the parent component
|
|
44
65
|
useImperativeHandle(ref, () => internalFormRef.current as HTMLFormElement)
|
|
45
66
|
|
|
46
67
|
/**
|
|
47
|
-
*
|
|
48
|
-
* It includes the title and description as typography items.
|
|
68
|
+
* Memoized header grid configuration
|
|
49
69
|
*/
|
|
50
|
-
const headerGrid: ContentSectionProps['grids'][0] =
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
marginbottom: 1,
|
|
55
|
-
gridwidth: '100%',
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
typography: [
|
|
59
|
-
{
|
|
60
|
-
text: title,
|
|
61
|
-
fontvariant: 'merrih5',
|
|
62
|
-
fontcolor: 'black',
|
|
63
|
-
columnconfig: {
|
|
64
|
-
column: 1,
|
|
70
|
+
const headerGrid: ContentSectionProps['grids'][0] = useMemo(
|
|
71
|
+
() => ({
|
|
72
|
+
grid: {
|
|
73
|
+
gridconfig: {
|
|
65
74
|
gridname: 'formHeader',
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
marginbottom: 0.5,
|
|
75
|
+
marginbottom: 1,
|
|
76
|
+
gridwidth: '100%',
|
|
69
77
|
},
|
|
70
78
|
},
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
typography: [
|
|
80
|
+
{
|
|
81
|
+
text: title,
|
|
82
|
+
fontvariant: 'merrih5',
|
|
83
|
+
fontcolor: 'black',
|
|
84
|
+
columnconfig: {
|
|
85
|
+
row: 1,
|
|
86
|
+
column: 1,
|
|
87
|
+
gridname: 'formHeader',
|
|
88
|
+
columnwidth: '100%',
|
|
89
|
+
alignment: 'left',
|
|
90
|
+
marginbottom: 1.5,
|
|
91
|
+
},
|
|
79
92
|
},
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
93
|
+
{
|
|
94
|
+
text: description,
|
|
95
|
+
fontvariant: 'merriparagraph',
|
|
96
|
+
fontcolor: 'black',
|
|
97
|
+
columnconfig: {
|
|
98
|
+
row: 2,
|
|
99
|
+
column: 1,
|
|
100
|
+
alignment: 'left',
|
|
101
|
+
gridname: 'formHeader',
|
|
102
|
+
columnwidth: '100%',
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
] as ExtendedTypographyProps[],
|
|
106
|
+
}),
|
|
107
|
+
[title, description]
|
|
108
|
+
)
|
|
89
109
|
|
|
90
110
|
/**
|
|
91
|
-
*
|
|
92
|
-
* @param event - The form submission event
|
|
111
|
+
* Handle form submission
|
|
112
|
+
* @param {React.FormEvent<HTMLFormElement>} event - The form submission event
|
|
93
113
|
*/
|
|
94
|
-
const handleSubmit = (
|
|
95
|
-
event.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
setSubmittedData(data)
|
|
114
|
+
const handleSubmit = useCallback(
|
|
115
|
+
(event: React.FormEvent<HTMLFormElement>) => {
|
|
116
|
+
event.preventDefault()
|
|
117
|
+
if (onSubmit) {
|
|
118
|
+
onSubmit(event)
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
[onSubmit]
|
|
122
|
+
)
|
|
104
123
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
124
|
+
/**
|
|
125
|
+
* Memoized header render function
|
|
126
|
+
*/
|
|
127
|
+
const renderHeader = useMemo(
|
|
128
|
+
() => <ContentSection grids={[headerGrid]} />,
|
|
129
|
+
[headerGrid]
|
|
130
|
+
)
|
|
109
131
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
onClick={onClose}
|
|
116
|
-
sx={{
|
|
117
|
-
position: 'absolute',
|
|
118
|
-
right: 8,
|
|
119
|
-
top: 8,
|
|
120
|
-
color: theme => theme.palette.grey[500],
|
|
121
|
-
}}
|
|
122
|
-
>
|
|
123
|
-
<Close />
|
|
124
|
-
</IconButton>
|
|
125
|
-
{/* Form container */}
|
|
132
|
+
/**
|
|
133
|
+
* Memoized content render function
|
|
134
|
+
*/
|
|
135
|
+
const renderContent = useMemo(
|
|
136
|
+
() => (
|
|
126
137
|
<Box
|
|
127
138
|
// @ts-ignore
|
|
128
139
|
sx={formContainerStyle}
|
|
129
140
|
>
|
|
141
|
+
<Box mb={0}>{renderHeader}</Box>
|
|
130
142
|
<form onSubmit={handleSubmit} ref={internalFormRef}>
|
|
131
|
-
{
|
|
132
|
-
|
|
143
|
+
{React.isValidElement(content)
|
|
144
|
+
? React.cloneElement(content as React.ReactElement, {
|
|
145
|
+
onSubmit: handleSubmit,
|
|
146
|
+
})
|
|
147
|
+
: content || (grids && <ContentSection grids={grids} />)}
|
|
133
148
|
</form>
|
|
134
|
-
{/* Display submitted data */}
|
|
135
|
-
{Object.keys(submittedData).length > 0 && (
|
|
136
|
-
<Box mt={2}>
|
|
137
|
-
<Typography fontvariant="merrih6" text="Submitted Data:" />
|
|
138
|
-
{Object.entries(submittedData).map(([key, value]) => (
|
|
139
|
-
<Typography
|
|
140
|
-
key={key}
|
|
141
|
-
fontvariant="merriparagraph"
|
|
142
|
-
text={`${key}: ${value}`}
|
|
143
|
-
/>
|
|
144
|
-
))}
|
|
145
|
-
</Box>
|
|
146
|
-
)}
|
|
147
149
|
</Box>
|
|
150
|
+
),
|
|
151
|
+
[renderHeader, handleSubmit, content, grids]
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
if (popupType === 'modal') {
|
|
155
|
+
return (
|
|
156
|
+
<Dialog
|
|
157
|
+
open={true}
|
|
158
|
+
fullWidth
|
|
159
|
+
maxWidth="sm"
|
|
160
|
+
disableEscapeKeyDown
|
|
161
|
+
hideBackdrop
|
|
162
|
+
>
|
|
163
|
+
{renderContent}
|
|
164
|
+
</Dialog>
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return (
|
|
169
|
+
<Dialog open={open || false} onClose={onClose} fullWidth maxWidth="sm">
|
|
170
|
+
{onClose && (
|
|
171
|
+
<IconButton
|
|
172
|
+
size="small"
|
|
173
|
+
onClick={onClose}
|
|
174
|
+
sx={{
|
|
175
|
+
position: 'absolute',
|
|
176
|
+
right: 8,
|
|
177
|
+
top: 8,
|
|
178
|
+
color: theme => theme.palette.grey[500],
|
|
179
|
+
}}
|
|
180
|
+
>
|
|
181
|
+
<Close />
|
|
182
|
+
</IconButton>
|
|
183
|
+
)}
|
|
184
|
+
{renderContent}
|
|
148
185
|
</Dialog>
|
|
149
186
|
)
|
|
150
187
|
}
|
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
import React, { useState } from 'react'
|
|
2
2
|
import { InputAdornment, Button, Box } from '@mui/material'
|
|
3
|
-
import SearchIcon from '../../
|
|
4
|
-
import ShowHideEyeIcon from '../../
|
|
5
|
-
import DownArrowFilledIcon from '../../
|
|
6
|
-
|
|
3
|
+
import SearchIcon from '../../Icons/Search'
|
|
4
|
+
import ShowHideEyeIcon from '../../Icons/ShowHideEye'
|
|
5
|
+
import DownArrowFilledIcon from '../../Icons/DownArrowFilled'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Props interface for the Adornment components
|
|
9
|
+
*/
|
|
10
|
+
export interface AdornmentProps {
|
|
11
|
+
componentvariant: string
|
|
12
|
+
iconcolor?: string
|
|
13
|
+
passwordVisible?: boolean
|
|
14
|
+
marginRight?: number | string
|
|
15
|
+
handleIncrement?: () => void
|
|
16
|
+
handleDecrement?: () => void
|
|
17
|
+
}
|
|
7
18
|
|
|
8
19
|
/**
|
|
9
20
|
* StartAdornment component renders the start adornment for the input component.
|
|
10
21
|
* @param props The props for the StartAdornment component.
|
|
11
22
|
* @returns The start adornment component or null.
|
|
12
23
|
*/
|
|
13
|
-
const StartAdornment: React.FC<AdornmentProps> = props => {
|
|
24
|
+
export const StartAdornment: React.FC<AdornmentProps> = props => {
|
|
14
25
|
const { componentvariant, iconcolor } = props
|
|
15
26
|
// Render the search icon for the search bar variant
|
|
16
27
|
if (componentvariant === 'searchbar') {
|
|
@@ -28,26 +39,22 @@ const StartAdornment: React.FC<AdornmentProps> = props => {
|
|
|
28
39
|
* @param props The props for the EndAdornment component.
|
|
29
40
|
* @returns The end adornment component or null.
|
|
30
41
|
*/
|
|
31
|
-
const EndAdornment: React.FC<AdornmentProps> = props => {
|
|
42
|
+
export const EndAdornment: React.FC<AdornmentProps> = props => {
|
|
32
43
|
const {
|
|
33
44
|
componentvariant,
|
|
34
45
|
passwordVisible,
|
|
35
46
|
handleIncrement,
|
|
36
47
|
handleDecrement,
|
|
37
48
|
} = props
|
|
38
|
-
|
|
39
49
|
const [isPasswordVisible, setIsPasswordVisible] = useState(
|
|
40
50
|
passwordVisible || false
|
|
41
51
|
)
|
|
42
|
-
|
|
43
52
|
const adornmentStyle = {
|
|
44
53
|
cursor: 'pointer',
|
|
45
54
|
}
|
|
46
|
-
|
|
47
55
|
const togglePasswordVisibility = () => {
|
|
48
56
|
setIsPasswordVisible(!isPasswordVisible)
|
|
49
57
|
}
|
|
50
|
-
|
|
51
58
|
// Render the show/hide eye icon for the password variant
|
|
52
59
|
if (componentvariant === 'password') {
|
|
53
60
|
return (
|
|
@@ -118,5 +125,3 @@ const EndAdornment: React.FC<AdornmentProps> = props => {
|
|
|
118
125
|
}
|
|
119
126
|
return null
|
|
120
127
|
}
|
|
121
|
-
|
|
122
|
-
export { StartAdornment, EndAdornment }
|