goobs-frontend 0.7.66 → 0.7.68

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 (39) hide show
  1. package/package.json +13 -16
  2. package/src/components/Button/index.tsx +95 -208
  3. package/src/components/ConfirmationCodeInput/index.tsx +4 -6
  4. package/src/components/Content/Structure/button/useButton.tsx +1 -35
  5. package/src/components/Content/Structure/datefield/useDateField.tsx +55 -0
  6. package/src/components/Content/Structure/dropdown/useDropdown.tsx +55 -0
  7. package/src/components/Content/Structure/incremementNumberField/useIncremementNumberField.tsx +65 -0
  8. package/src/components/Content/Structure/numberField/useNumberField.tsx +55 -0
  9. package/src/components/Content/Structure/passwordField/usePasswordField.tsx +57 -0
  10. package/src/components/Content/Structure/phoneNumber/usePhoneNumber.tsx +0 -0
  11. package/src/components/Content/Structure/searchbar/useSearchbar.tsx +55 -0
  12. package/src/components/Content/Structure/textfield/useTextField.tsx +84 -0
  13. package/src/components/Content/index.tsx +41 -7
  14. package/src/components/DateField/index.tsx +112 -0
  15. package/src/components/Dropdown/index.tsx +91 -0
  16. package/src/components/Form/Popup/index.tsx +1 -1
  17. package/src/components/IncrementNumberField/index.tsx +123 -0
  18. package/src/components/Nav/HorizontalVariant/index.tsx +18 -12
  19. package/src/components/Nav/VerticalVariant/index.tsx +14 -10
  20. package/src/components/NumberField/index.tsx +95 -0
  21. package/src/components/PasswordField/index.tsx +105 -0
  22. package/src/components/PhoneNumberField/index.tsx +102 -0
  23. package/src/components/PricingTable/index.tsx +10 -8
  24. package/src/components/Searchbar/index.tsx +77 -0
  25. package/src/components/TextField/index.tsx +130 -0
  26. package/src/components/Toolbar/index.tsx +11 -10
  27. package/src/index.ts +49 -8
  28. package/src/components/Button/hook/useHelperFooter.tsx +0 -224
  29. package/src/components/Content/Structure/styledcomponent/useStyledComponent.tsx +0 -104
  30. package/src/components/StyledComponent/adornment/index.tsx +0 -125
  31. package/src/components/StyledComponent/hooks/useDropdown.tsx +0 -146
  32. package/src/components/StyledComponent/hooks/useInputHelperFooter.tsx +0 -567
  33. package/src/components/StyledComponent/hooks/usePhoneNumber.tsx +0 -96
  34. package/src/components/StyledComponent/hooks/useRequiredFieldsValidator.tsx +0 -137
  35. package/src/components/StyledComponent/hooks/useSearchbar.tsx +0 -44
  36. package/src/components/StyledComponent/hooks/useSplitButton.tsx +0 -66
  37. package/src/components/StyledComponent/index.tsx +0 -426
  38. package/src/components/StyledComponent/useEffects/index.tsx +0 -49
  39. package/src/styles/StyledComponent/Label/index.ts +0 -76
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "goobs-frontend",
3
- "version": "0.7.66",
3
+ "version": "0.7.68",
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",
@@ -17,31 +17,28 @@
17
17
  "start": "next start",
18
18
  "lint": "next lint"
19
19
  },
20
- "peerDependencies": {
21
- "react": "^17.0.0 || ^18.0.0",
22
- "react-dom": "^17.0.0 || ^18.0.0"
23
- },
24
20
  "dependencies": {
25
21
  "@emotion/cache": "^11.13.1",
26
- "@emotion/react": "^11.13.0",
22
+ "@emotion/react": "^11.13.3",
27
23
  "@emotion/styled": "^11.13.0",
28
- "@mui/icons-material": "^5.16.6",
29
- "@mui/material": "^5.16.6",
24
+ "@mui/icons-material": "^5.16.7",
25
+ "@mui/material": "^5.16.7",
30
26
  "@types/lodash": "^4.17.7",
31
- "goobs-cache": "^1.6.4",
32
27
  "highlight.js": "^11.10.0",
28
+ "jotai": "^2.9.3",
33
29
  "lodash": "^4.17.21",
34
- "next": "14.2.5"
30
+ "next": "14.2.6",
31
+ "react-datepicker": "^7.3.0"
35
32
  },
36
33
  "devDependencies": {
37
- "@next/eslint-plugin-next": "^14.2.5",
38
- "@types/node": "^22.1.0",
39
- "@types/react": "18.3.3",
34
+ "@next/eslint-plugin-next": "^14.2.6",
35
+ "@types/node": "^22.5.0",
36
+ "@types/react": "18.3.4",
40
37
  "@types/react-dom": "^18.3.0",
41
- "@typescript-eslint/eslint-plugin": "^8.0.1",
42
- "@typescript-eslint/parser": "^8.0.1",
38
+ "@typescript-eslint/eslint-plugin": "^8.2.0",
39
+ "@typescript-eslint/parser": "^8.2.0",
43
40
  "eslint": "^8.57.0",
44
- "eslint-config-next": "^14.2.5",
41
+ "eslint-config-next": "^14.2.6",
45
42
  "eslint-config-prettier": "^9.1.0",
46
43
  "eslint-plugin-prettier": "^5.2.1",
47
44
  "prettier": "^3.3.3",
@@ -1,218 +1,99 @@
1
- import React, { useMemo, useCallback, useEffect, useState } from 'react'
1
+ 'use client'
2
+ import React from 'react'
2
3
  import { Button, Box, ButtonProps } from '@mui/material'
3
- import StarIcon from '@mui/icons-material/Star'
4
4
  import Typography from '../Typography'
5
- import { red } from '../../styles/palette'
6
- import useHelperFooter from './hook/useHelperFooter'
7
5
 
8
- export type ButtonAlignment = 'left' | 'center' | 'right'
9
-
10
- export interface CustomButtonProps
11
- extends Omit<ButtonProps, 'color' | 'variant'> {
6
+ export interface CustomButtonProps extends ButtonProps {
12
7
  text?: string
13
8
  backgroundcolor?: string
14
- outlinecolor?: string
15
9
  fontcolor?: string
16
- fontlocation?: ButtonAlignment
17
- fontvariant?:
18
- | 'arapeyh1'
19
- | 'arapeyh2'
20
- | 'arapeyh3'
21
- | 'arapeyh4'
22
- | 'arapeyh5'
23
- | 'arapeyh6'
24
- | 'arapeyparagraph'
25
- | 'arapeyhelperheader'
26
- | 'arapeyhelperfooter'
27
- | 'interh1'
28
- | 'interh2'
29
- | 'interh3'
30
- | 'interh4'
31
- | 'interh5'
32
- | 'interh6'
33
- | 'interparagraph'
34
- | 'interhelperheader'
35
- | 'interhelperfooter'
36
- | 'merrih1'
37
- | 'merrih2'
38
- | 'merrih3'
39
- | 'merrih4'
40
- | 'merrih5'
41
- | 'merrih6'
42
- | 'merriparagraph'
43
- | 'merrihelperheader'
44
- | 'merrihelperfooter'
45
- icon?: React.ReactNode | false
10
+ fontvariant?: 'merriparagraph' | 'merrihelperfooter'
11
+ width?: string
12
+ disableButton?: 'true' | 'false'
13
+ icon?: React.ReactNode
46
14
  iconcolor?: string
47
15
  iconsize?: string
48
- iconlocation?: 'left' | 'top' | 'right'
49
- variant?: 'text' | 'outlined' | 'contained'
50
- onClick?: () => void
51
- width?: string
52
- formname?: string
53
- name?: string
16
+ iconlocation?: 'left' | 'right' | 'above'
17
+ fontlocation?: 'left' | 'center' | 'right'
54
18
  }
55
19
 
56
20
  const CustomButton: React.FC<CustomButtonProps> = React.memo(
57
21
  props => {
22
+ console.log('[trace-button] CustomButton: Rendering component', { props })
58
23
  const {
59
24
  text,
60
25
  variant,
61
26
  fontvariant = 'merriparagraph',
62
- icon,
63
- iconlocation,
64
- iconsize,
65
- type,
66
27
  onClick,
67
28
  fontcolor,
68
- name,
69
- formname,
70
- outlinecolor,
71
29
  backgroundcolor,
72
- fontlocation,
73
- iconcolor,
74
30
  width,
31
+ disableButton,
32
+ icon,
33
+ iconcolor,
34
+ iconsize,
35
+ iconlocation = 'left',
36
+ fontlocation = 'center',
37
+ ...restProps
75
38
  } = props
76
39
 
77
- const [isFormFinished, setIsFormFinished] = useState<boolean>(false)
78
- const [isCheckingForm, setIsCheckingForm] = useState<boolean>(true)
79
-
80
- const {
81
- updateFormValidation,
82
- checkFormStatus,
83
- getEmptyRequiredFields,
84
- fetchHelperFooters,
85
- } = useHelperFooter(formname)
86
-
87
- const checkFormState = useCallback(async (): Promise<void> => {
88
- console.log('CustomButton: Checking form state...')
89
- setIsCheckingForm(true)
90
-
91
- const formStatus = await checkFormStatus()
92
- const emptyFields = await getEmptyRequiredFields()
93
- const helperFooters = await fetchHelperFooters()
94
-
95
- console.log('CustomButton: Form status:', formStatus)
96
- console.log('CustomButton: Empty fields:', emptyFields)
97
- console.log('CustomButton: Helper footers:', helperFooters)
98
-
99
- const newIsFormFinished =
100
- formStatus &&
101
- emptyFields.length === 0 &&
102
- (!helperFooters || Object.keys(helperFooters).length === 0)
103
-
104
- setIsFormFinished(newIsFormFinished)
105
- setIsCheckingForm(false)
106
-
107
- console.log(
108
- 'CustomButton: Form status changed. Is form finished:',
109
- newIsFormFinished
110
- )
111
- }, [checkFormStatus, getEmptyRequiredFields, fetchHelperFooters])
112
-
113
- useEffect(() => {
114
- console.log('CustomButton: Performing initial check')
115
- checkFormState()
116
- }, [checkFormState])
117
-
118
- const handleButtonClick = useCallback(
119
- async (event: React.MouseEvent<HTMLButtonElement>): Promise<void> => {
120
- event.preventDefault()
121
- console.log(
122
- 'CustomButton: Button clicked. Is form finished:',
123
- isFormFinished,
124
- 'Is checking form:',
125
- isCheckingForm
126
- )
127
- if (!isFormFinished || isCheckingForm) return
128
-
129
- const validationResult = await updateFormValidation()
130
- console.log('CustomButton: Validation result:', validationResult)
131
- if (validationResult && onClick) {
132
- onClick()
133
- }
134
- checkFormState()
135
- },
136
- [
137
- isFormFinished,
138
- isCheckingForm,
139
- updateFormValidation,
140
- onClick,
141
- checkFormState,
142
- ]
143
- )
144
-
145
- const renderIcon = useCallback((): React.ReactNode => {
146
- if (icon === false) {
147
- return null
148
- }
149
- if (React.isValidElement(icon)) {
150
- return React.cloneElement(icon as React.ReactElement, {
151
- style: { fontSize: iconsize },
40
+ const handleButtonClick = (
41
+ event: React.MouseEvent<HTMLButtonElement>
42
+ ): void => {
43
+ console.log('[trace-button] CustomButton: Button clicked')
44
+ event.preventDefault()
45
+ onClick?.(event)
46
+ }
47
+
48
+ const buttonStyle = {
49
+ backgroundColor: backgroundcolor,
50
+ width: width,
51
+ }
52
+
53
+ const isDisabled = disableButton === 'true'
54
+
55
+ const iconStyle = {
56
+ color: iconcolor,
57
+ fontSize: iconsize,
58
+ }
59
+
60
+ const IconComponent = icon
61
+ ? React.cloneElement(icon as React.ReactElement, {
62
+ style: { ...iconStyle, ...(icon as React.ReactElement).props.style },
152
63
  })
153
- }
154
- return <StarIcon style={{ fontSize: iconsize }} />
155
- }, [icon, iconsize])
156
-
157
- const buttonStyle = useMemo(
158
- () => ({
159
- minWidth: text ? 'auto' : 'fit-content',
160
- paddingLeft: text ? '8px' : '0',
161
- paddingRight: text ? '8px' : '0',
162
- justifyContent: fontlocation || 'center',
163
- backgroundColor: backgroundcolor,
164
- border: outlinecolor ? `1px solid ${outlinecolor}` : undefined,
165
- color: iconcolor,
166
- width: width,
167
- opacity: !isFormFinished || isCheckingForm ? 0.5 : 1,
168
- }),
169
- [
170
- text,
171
- fontlocation,
172
- backgroundcolor,
173
- outlinecolor,
174
- iconcolor,
175
- width,
176
- isFormFinished,
177
- isCheckingForm,
178
- ]
179
- )
180
-
181
- const buttonContent = useMemo(
182
- () => (
183
- <Box display="flex" alignItems="center">
184
- {iconlocation === 'left' && renderIcon()}
185
- {text && (
186
- <Typography
187
- fontvariant={fontvariant}
188
- fontcolor={fontcolor}
189
- text={text}
190
- />
191
- )}
192
- {iconlocation === 'right' && renderIcon()}
193
- </Box>
194
- ),
195
- [iconlocation, renderIcon, text, fontvariant, fontcolor]
196
- )
64
+ : null
197
65
 
198
- const messageComponent = useMemo(
199
- () =>
200
- !isFormFinished || isCheckingForm ? (
66
+ console.log('[trace-button] CustomButton: Rendering button', {
67
+ variant,
68
+ style: buttonStyle,
69
+ disableButton,
70
+ isDisabled,
71
+ })
72
+
73
+ const buttonContent = (
74
+ <>
75
+ {iconlocation === 'above' && IconComponent}
76
+ <Box
77
+ display="flex"
78
+ alignItems="center"
79
+ justifyContent={
80
+ fontlocation === 'left'
81
+ ? 'flex-start'
82
+ : fontlocation === 'right'
83
+ ? 'flex-end'
84
+ : 'center'
85
+ }
86
+ width="100%"
87
+ >
88
+ {iconlocation === 'left' && IconComponent}
201
89
  <Typography
202
- fontvariant="merrihelperfooter"
203
- fontcolor={red.main}
204
- text="Fill in required fields"
205
- marginTop={0.5}
206
- marginBottom={0}
207
- align="center"
208
- width="100%"
90
+ fontvariant={fontvariant}
91
+ fontcolor={isDisabled ? 'grey' : fontcolor}
92
+ text={text || ''}
209
93
  />
210
- ) : null,
211
- [isFormFinished, isCheckingForm]
212
- )
213
-
214
- console.log(
215
- `CustomButton: Rendering. Is form finished: ${isFormFinished} Is checking form: ${isCheckingForm}`
94
+ {iconlocation === 'right' && IconComponent}
95
+ </Box>
96
+ </>
216
97
  )
217
98
 
218
99
  return (
@@ -223,19 +104,23 @@ const CustomButton: React.FC<CustomButtonProps> = React.memo(
223
104
  width={width}
224
105
  >
225
106
  <Button
226
- disableElevation
107
+ {...restProps}
227
108
  variant={variant}
228
- startIcon={null}
229
- endIcon={null}
230
- type={type}
231
- name={name}
232
109
  onClick={handleButtonClick}
233
- style={buttonStyle}
234
- disabled={!isFormFinished || isCheckingForm}
110
+ style={{
111
+ ...buttonStyle,
112
+ flexDirection: iconlocation === 'above' ? 'column' : 'row',
113
+ justifyContent:
114
+ fontlocation === 'left'
115
+ ? 'flex-start'
116
+ : fontlocation === 'right'
117
+ ? 'flex-end'
118
+ : 'center',
119
+ }}
120
+ disabled={isDisabled}
235
121
  >
236
122
  {buttonContent}
237
123
  </Button>
238
- {messageComponent}
239
124
  </Box>
240
125
  )
241
126
  },
@@ -244,24 +129,26 @@ const CustomButton: React.FC<CustomButtonProps> = React.memo(
244
129
  prevProps.text === nextProps.text &&
245
130
  prevProps.variant === nextProps.variant &&
246
131
  prevProps.fontvariant === nextProps.fontvariant &&
247
- prevProps.icon === nextProps.icon &&
248
- prevProps.iconlocation === nextProps.iconlocation &&
249
- prevProps.iconsize === nextProps.iconsize &&
250
- prevProps.type === nextProps.type &&
251
132
  prevProps.onClick === nextProps.onClick &&
252
133
  prevProps.fontcolor === nextProps.fontcolor &&
253
- prevProps.name === nextProps.name &&
254
- prevProps.formname === nextProps.formname &&
255
- prevProps.outlinecolor === nextProps.outlinecolor &&
256
134
  prevProps.backgroundcolor === nextProps.backgroundcolor &&
257
- prevProps.fontlocation === nextProps.fontlocation &&
135
+ prevProps.width === nextProps.width &&
136
+ prevProps.disableButton === nextProps.disableButton &&
137
+ prevProps.icon === nextProps.icon &&
258
138
  prevProps.iconcolor === nextProps.iconcolor &&
259
- prevProps.width === nextProps.width
260
- console.log('CustomButton: Props changed:', !propsAreEqual)
139
+ prevProps.iconsize === nextProps.iconsize &&
140
+ prevProps.iconlocation === nextProps.iconlocation &&
141
+ prevProps.fontlocation === nextProps.fontlocation
142
+
143
+ console.log('[trace-button] CustomButton: Props comparison', {
144
+ propsAreEqual,
145
+ prevProps: Object.keys(prevProps),
146
+ nextProps: Object.keys(nextProps),
147
+ })
261
148
  return propsAreEqual
262
149
  }
263
150
  )
264
151
 
265
152
  CustomButton.displayName = 'CustomButton'
266
-
153
+ console.log('[trace-button] CustomButton: Component defined')
267
154
  export default CustomButton
@@ -1,10 +1,9 @@
1
1
  'use client'
2
- import React, { ChangeEvent, KeyboardEvent } from 'react'
2
+ import React, { ChangeEvent, KeyboardEvent, useState } from 'react'
3
3
  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 { session } from 'goobs-cache'
8
7
 
9
8
  export interface ConfirmationCodeInputsProps {
10
9
  identifier?: string
@@ -30,8 +29,7 @@ const ConfirmationCodeInputs: React.FC<ConfirmationCodeInputsProps> = ({
30
29
  'aria-invalid': ariaInvalid,
31
30
  ...props
32
31
  }) => {
33
- const verificationCodeAtom = session.atom<string>('')
34
- const [, setVerificationCode] = session.useAtom(verificationCodeAtom)
32
+ const [, setVerificationCode] = useState('')
35
33
 
36
34
  const { handleCodeChange, handleKeyDown, combinedCode } = useCodeConfirmation(
37
35
  {
@@ -76,14 +74,14 @@ const ConfirmationCodeInputs: React.FC<ConfirmationCodeInputsProps> = ({
76
74
  }
77
75
 
78
76
  /**
79
- * useEffect hook is used to set the verification code into the session atom using goobs-cache.
77
+ * useEffect hook is used to set the verification code into the state using useState.
80
78
  * It sets the code whenever the combinedCode changes and the code is valid.
81
79
  */
82
80
  React.useEffect(() => {
83
81
  if (isValid) {
84
82
  setVerificationCode(combinedCode)
85
83
  }
86
- }, [combinedCode, isValid, setVerificationCode])
84
+ }, [combinedCode, isValid])
87
85
 
88
86
  return (
89
87
  <Box
@@ -2,7 +2,6 @@
2
2
  import React from 'react'
3
3
  import CustomButton, { CustomButtonProps } from './../../../Button'
4
4
  import { columnconfig, cellconfig } from '../../../Grid'
5
- import { TypographyPropsVariantOverrides } from '@mui/material'
6
5
 
7
6
  export interface ExtendedButtonProps extends CustomButtonProps {
8
7
  columnconfig?: Partial<columnconfig>
@@ -19,20 +18,6 @@ const useButton = (grid: {
19
18
  index: number
20
19
  ): columnconfig => {
21
20
  const {
22
- text,
23
- name,
24
- backgroundcolor,
25
- outlinecolor,
26
- fontcolor,
27
- width,
28
- fontlocation,
29
- fontvariant,
30
- icon,
31
- iconcolor,
32
- iconsize,
33
- iconlocation,
34
- variant,
35
- onClick,
36
21
  columnconfig: itemColumnConfig,
37
22
  cellconfig,
38
23
  ...restProps
@@ -54,26 +39,7 @@ const useButton = (grid: {
54
39
  cellconfig: {
55
40
  ...cellconfig,
56
41
  },
57
- component: (
58
- <CustomButton
59
- key={`button-${index}`}
60
- text={text}
61
- name={name}
62
- backgroundcolor={backgroundcolor}
63
- outlinecolor={outlinecolor}
64
- fontcolor={fontcolor}
65
- width={width}
66
- fontlocation={fontlocation}
67
- fontvariant={fontvariant as keyof TypographyPropsVariantOverrides}
68
- icon={icon}
69
- iconcolor={iconcolor}
70
- iconsize={iconsize}
71
- iconlocation={iconlocation}
72
- variant={variant}
73
- onClick={onClick}
74
- {...restProps}
75
- />
76
- ),
42
+ component: <CustomButton key={`button-${index}`} {...restProps} />,
77
43
  }
78
44
 
79
45
  return mergedConfig
@@ -0,0 +1,55 @@
1
+ 'use client'
2
+ import React from 'react'
3
+ import DateField, { DateFieldProps } from './../../../DateField'
4
+ import { columnconfig, cellconfig } from '../../../Grid'
5
+
6
+ export interface ExtendedDateFieldProps extends DateFieldProps {
7
+ columnconfig?: Partial<columnconfig>
8
+ cellconfig?: cellconfig
9
+ }
10
+
11
+ const useDateField = (grid: {
12
+ datefield?: ExtendedDateFieldProps | ExtendedDateFieldProps[]
13
+ }) => {
14
+ if (!grid.datefield) return null
15
+
16
+ const renderDateField = (
17
+ dateFieldItem: ExtendedDateFieldProps,
18
+ index: number
19
+ ): columnconfig => {
20
+ const {
21
+ columnconfig: itemColumnConfig,
22
+ cellconfig,
23
+ ...restProps
24
+ } = dateFieldItem
25
+
26
+ if (
27
+ !itemColumnConfig ||
28
+ typeof itemColumnConfig !== 'object' ||
29
+ typeof itemColumnConfig.row !== 'number' ||
30
+ typeof itemColumnConfig.column !== 'number'
31
+ ) {
32
+ throw new Error(
33
+ 'columnconfig must be an object with row and column as numbers'
34
+ )
35
+ }
36
+
37
+ const mergedConfig: columnconfig = {
38
+ ...(itemColumnConfig as columnconfig),
39
+ cellconfig: {
40
+ ...cellconfig,
41
+ },
42
+ component: <DateField key={`datefield-${index}`} {...restProps} />,
43
+ }
44
+
45
+ return mergedConfig
46
+ }
47
+
48
+ if (Array.isArray(grid.datefield)) {
49
+ return grid.datefield.map(renderDateField)
50
+ } else {
51
+ return [renderDateField(grid.datefield, 0)]
52
+ }
53
+ }
54
+
55
+ export default useDateField
@@ -0,0 +1,55 @@
1
+ 'use client'
2
+ import React from 'react'
3
+ import Dropdown, { DropdownProps } from './../../../Dropdown'
4
+ import { columnconfig, cellconfig } from '../../../Grid'
5
+
6
+ export interface ExtendedDropdownProps extends DropdownProps {
7
+ columnconfig?: Partial<columnconfig>
8
+ cellconfig?: cellconfig
9
+ }
10
+
11
+ const useDropdown = (grid: {
12
+ dropdown?: ExtendedDropdownProps | ExtendedDropdownProps[]
13
+ }) => {
14
+ if (!grid.dropdown) return null
15
+
16
+ const renderDropdown = (
17
+ dropdownItem: ExtendedDropdownProps,
18
+ index: number
19
+ ): columnconfig => {
20
+ const {
21
+ columnconfig: itemColumnConfig,
22
+ cellconfig,
23
+ ...restProps
24
+ } = dropdownItem
25
+
26
+ if (
27
+ !itemColumnConfig ||
28
+ typeof itemColumnConfig !== 'object' ||
29
+ typeof itemColumnConfig.row !== 'number' ||
30
+ typeof itemColumnConfig.column !== 'number'
31
+ ) {
32
+ throw new Error(
33
+ 'columnconfig must be an object with row and column as numbers'
34
+ )
35
+ }
36
+
37
+ const mergedConfig: columnconfig = {
38
+ ...(itemColumnConfig as columnconfig),
39
+ cellconfig: {
40
+ ...cellconfig,
41
+ },
42
+ component: <Dropdown key={`dropdown-${index}`} {...restProps} />,
43
+ }
44
+
45
+ return mergedConfig
46
+ }
47
+
48
+ if (Array.isArray(grid.dropdown)) {
49
+ return grid.dropdown.map(renderDropdown)
50
+ } else {
51
+ return [renderDropdown(grid.dropdown, 0)]
52
+ }
53
+ }
54
+
55
+ export default useDropdown
@@ -0,0 +1,65 @@
1
+ 'use client'
2
+ import React from 'react'
3
+ import IncrementNumberField, {
4
+ IncrementNumberFieldProps,
5
+ } from './../../../IncrementNumberField'
6
+ import { columnconfig, cellconfig } from '../../../Grid'
7
+
8
+ export interface ExtendedIncrementNumberFieldProps
9
+ extends IncrementNumberFieldProps {
10
+ columnconfig?: Partial<columnconfig>
11
+ cellconfig?: cellconfig
12
+ }
13
+
14
+ const useIncrementNumberField = (grid: {
15
+ incrementNumberField?:
16
+ | ExtendedIncrementNumberFieldProps
17
+ | ExtendedIncrementNumberFieldProps[]
18
+ }) => {
19
+ if (!grid.incrementNumberField) return null
20
+
21
+ const renderIncrementNumberField = (
22
+ incrementNumberFieldItem: ExtendedIncrementNumberFieldProps,
23
+ index: number
24
+ ): columnconfig => {
25
+ const {
26
+ columnconfig: itemColumnConfig,
27
+ cellconfig,
28
+ ...restProps
29
+ } = incrementNumberFieldItem
30
+
31
+ if (
32
+ !itemColumnConfig ||
33
+ typeof itemColumnConfig !== 'object' ||
34
+ typeof itemColumnConfig.row !== 'number' ||
35
+ typeof itemColumnConfig.column !== 'number'
36
+ ) {
37
+ throw new Error(
38
+ 'columnconfig must be an object with row and column as numbers'
39
+ )
40
+ }
41
+
42
+ const mergedConfig: columnconfig = {
43
+ ...(itemColumnConfig as columnconfig),
44
+ cellconfig: {
45
+ ...cellconfig,
46
+ },
47
+ component: (
48
+ <IncrementNumberField
49
+ key={`increment-number-field-${index}`}
50
+ {...restProps}
51
+ />
52
+ ),
53
+ }
54
+
55
+ return mergedConfig
56
+ }
57
+
58
+ if (Array.isArray(grid.incrementNumberField)) {
59
+ return grid.incrementNumberField.map(renderIncrementNumberField)
60
+ } else {
61
+ return [renderIncrementNumberField(grid.incrementNumberField, 0)]
62
+ }
63
+ }
64
+
65
+ export default useIncrementNumberField