goobs-frontend 0.7.66 → 0.7.67

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.66",
3
+ "version": "0.7.67",
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,7 @@
28
28
  "@mui/icons-material": "^5.16.6",
29
29
  "@mui/material": "^5.16.6",
30
30
  "@types/lodash": "^4.17.7",
31
- "goobs-cache": "^1.6.4",
31
+ "goobs-cache": "^1.7.0",
32
32
  "highlight.js": "^11.10.0",
33
33
  "lodash": "^4.17.21",
34
34
  "next": "14.2.5"
package/src/app/_app.tsx CHANGED
@@ -1,8 +1,8 @@
1
- import React from 'react'
2
- import type { AppProps } from 'next/app'
3
-
4
- const MyApp = ({ Component, pageProps }: AppProps) => {
5
- return <Component {...pageProps} />
6
- }
7
-
8
- export default MyApp
1
+ import React from 'react'
2
+ import type { AppProps } from 'next/app'
3
+
4
+ const MyApp = ({ Component, pageProps }: AppProps) => {
5
+ return <Component {...pageProps} />
6
+ }
7
+
8
+ export default MyApp
@@ -16,79 +16,77 @@ const useHelperFooter = (initialFormname?: string) => {
16
16
  initialFormname
17
17
  )
18
18
 
19
- const helperFooterAtom = session.atom<Record<
20
- string,
21
- HelperFooterMessage
22
- > | null>(null)
23
- const currentErrorIndexAtom = session.atom<number>(0)
19
+ const helperFooterAtom = useMemo(
20
+ () => session.atom<Record<string, HelperFooterMessage> | null>(null),
21
+ []
22
+ )
23
+ const currentErrorIndexAtom = useMemo(() => session.atom<number>(0), [])
24
+
25
+ const [helperFooters, setHelperFooters] = session.useAtom(helperFooterAtom)
26
+ const [currentErrorIndex, setCurrentErrorIndex] = session.useAtom(
27
+ currentErrorIndexAtom
28
+ )
29
+ const [helperFooterResult] = session.useAtom(
30
+ useMemo(
31
+ () => session.atom(`helperfooter:${initialFormname}`),
32
+ [initialFormname]
33
+ )
34
+ )
24
35
 
25
- const fetchHelperFooters = useCallback(async (): Promise<Record<
36
+ const fetchHelperFooters = useCallback((): Record<
26
37
  string,
27
38
  HelperFooterMessage
28
- > | null> => {
39
+ > | null => {
29
40
  console.log('useHelperFooter: fetchHelperFooters called')
30
41
  if (!initialFormname) {
31
42
  console.log('useHelperFooter: No formname provided, returning null')
32
43
  return null
33
44
  }
34
45
 
35
- const [helperFooters, setHelperFooters] = session.useAtom(helperFooterAtom)
36
-
37
- if (helperFooters === null) {
38
- const [helperFooterResult] = session.useAtom(
39
- session.atom(`helperfooter:${initialFormname}`)
40
- )
41
- console.log('useHelperFooter: helperFooterResult:', helperFooterResult)
42
-
43
- if (
44
- helperFooterResult &&
45
- typeof helperFooterResult === 'object' &&
46
- helperFooterResult !== null
47
- ) {
48
- const fetchedHelperFooters: Record<string, HelperFooterMessage> = {}
49
-
50
- for (const [key, value] of Object.entries(helperFooterResult)) {
51
- if (
52
- typeof value === 'object' &&
53
- value !== null &&
54
- 'status' in value &&
55
- 'statusMessage' in value &&
56
- 'spreadMessage' in value &&
57
- 'spreadMessagePriority' in value &&
58
- 'required' in value &&
59
- 'hasInput' in value
60
- ) {
61
- fetchedHelperFooters[key] = {
62
- status: value.status as 'error' | 'success' | 'emptyAndRequired',
63
- statusMessage: String(value.statusMessage),
64
- spreadMessage: String(value.spreadMessage),
65
- spreadMessagePriority: Number(value.spreadMessagePriority),
66
- required: Boolean(value.required),
67
- hasInput: Boolean(value.hasInput),
68
- }
46
+ if (
47
+ helperFooters === null &&
48
+ helperFooterResult &&
49
+ typeof helperFooterResult === 'object' &&
50
+ helperFooterResult !== null
51
+ ) {
52
+ const fetchedHelperFooters: Record<string, HelperFooterMessage> = {}
53
+
54
+ for (const [key, value] of Object.entries(helperFooterResult)) {
55
+ if (
56
+ typeof value === 'object' &&
57
+ value !== null &&
58
+ 'status' in value &&
59
+ 'statusMessage' in value &&
60
+ 'spreadMessage' in value &&
61
+ 'spreadMessagePriority' in value &&
62
+ 'required' in value &&
63
+ 'hasInput' in value
64
+ ) {
65
+ fetchedHelperFooters[key] = {
66
+ status: value.status as 'error' | 'success' | 'emptyAndRequired',
67
+ statusMessage: String(value.statusMessage),
68
+ spreadMessage: String(value.spreadMessage),
69
+ spreadMessagePriority: Number(value.spreadMessagePriority),
70
+ required: Boolean(value.required),
71
+ hasInput: Boolean(value.hasInput),
69
72
  }
70
73
  }
71
-
72
- console.log(
73
- 'useHelperFooter: Fetched helper footers:',
74
- fetchedHelperFooters
75
- )
76
- setHelperFooters(fetchedHelperFooters)
77
- return fetchedHelperFooters
78
74
  }
79
75
 
80
76
  console.log(
81
- 'useHelperFooter: Invalid helper footer result, returning null'
77
+ 'useHelperFooter: Fetched helper footers:',
78
+ fetchedHelperFooters
82
79
  )
83
- return null
80
+ setHelperFooters(fetchedHelperFooters)
81
+ return fetchedHelperFooters
84
82
  }
85
83
 
86
84
  return helperFooters
87
- }, [initialFormname, helperFooterAtom])
85
+ }, [helperFooters, helperFooterResult, initialFormname, setHelperFooters])
88
86
 
89
- const updateFormValidation = useCallback(async (): Promise<boolean> => {
87
+ const updateFormValidation = useCallback((): boolean => {
90
88
  console.log('useHelperFooter: updateFormValidation called')
91
- const fetchedHelperFooters = await fetchHelperFooters()
89
+ const fetchedHelperFooters = fetchHelperFooters()
92
90
 
93
91
  if (fetchedHelperFooters) {
94
92
  const errorFooters = Object.values(fetchedHelperFooters).filter(
@@ -100,7 +98,6 @@ const useHelperFooter = (initialFormname?: string) => {
100
98
  console.log('useHelperFooter: Error footers:', errorFooters)
101
99
 
102
100
  if (errorFooters.length === 0) {
103
- const [, setCurrentErrorIndex] = session.useAtom(currentErrorIndexAtom)
104
101
  setCurrentErrorIndex(0)
105
102
  console.log('useHelperFooter: No errors found, returning true')
106
103
  return true
@@ -110,9 +107,6 @@ const useHelperFooter = (initialFormname?: string) => {
110
107
  (a, b) => a.spreadMessagePriority - b.spreadMessagePriority
111
108
  )
112
109
 
113
- const [currentErrorIndex, setCurrentErrorIndex] = session.useAtom(
114
- currentErrorIndexAtom
115
- )
116
110
  if (currentErrorIndex >= errorFooters.length) {
117
111
  setCurrentErrorIndex(0)
118
112
  }
@@ -123,11 +117,11 @@ const useHelperFooter = (initialFormname?: string) => {
123
117
 
124
118
  console.log('useHelperFooter: No helper footers, returning true')
125
119
  return true
126
- }, [fetchHelperFooters, currentErrorIndexAtom])
120
+ }, [fetchHelperFooters, currentErrorIndex, setCurrentErrorIndex])
127
121
 
128
- const checkFormStatus = useCallback(async () => {
122
+ const checkFormStatus = useCallback(() => {
129
123
  console.log('useHelperFooter: checkFormStatus called')
130
- const fetchedHelperFooters = await fetchHelperFooters()
124
+ const fetchedHelperFooters = fetchHelperFooters()
131
125
  const status = fetchedHelperFooters
132
126
  ? Object.values(fetchedHelperFooters).every(
133
127
  value => !value.required || (value.required && value.hasInput)
@@ -137,9 +131,9 @@ const useHelperFooter = (initialFormname?: string) => {
137
131
  return status
138
132
  }, [fetchHelperFooters])
139
133
 
140
- const getEmptyRequiredFields = useCallback(async () => {
134
+ const getEmptyRequiredFields = useCallback(() => {
141
135
  console.log('useHelperFooter: getEmptyRequiredFields called')
142
- const fetchedHelperFooters = await fetchHelperFooters()
136
+ const fetchedHelperFooters = fetchHelperFooters()
143
137
  if (!fetchedHelperFooters) return []
144
138
  const emptyFields = Object.entries(fetchedHelperFooters)
145
139
  .filter(([, value]) => value.required && !value.hasInput)
@@ -148,9 +142,9 @@ const useHelperFooter = (initialFormname?: string) => {
148
142
  return emptyFields
149
143
  }, [fetchHelperFooters])
150
144
 
151
- const getCurrentErrorMessage = useCallback(async () => {
145
+ const getCurrentErrorMessage = useCallback(() => {
152
146
  console.log('useHelperFooter: getCurrentErrorMessage called')
153
- const fetchedHelperFooters = await fetchHelperFooters()
147
+ const fetchedHelperFooters = fetchHelperFooters()
154
148
  if (!fetchedHelperFooters) return undefined
155
149
  const errorFooters = Object.values(fetchedHelperFooters).filter(
156
150
  footer =>
@@ -158,14 +152,13 @@ const useHelperFooter = (initialFormname?: string) => {
158
152
  footer.required
159
153
  )
160
154
  if (errorFooters.length === 0) return undefined
161
- const [currentErrorIndex] = session.useAtom(currentErrorIndexAtom)
162
155
  const message = errorFooters[currentErrorIndex]?.spreadMessage
163
156
  console.log('useHelperFooter: Current error message:', message)
164
157
  return message
165
- }, [fetchHelperFooters, currentErrorIndexAtom])
158
+ }, [fetchHelperFooters, currentErrorIndex])
166
159
 
167
- const isFormValid = useCallback(async () => {
168
- const fetchedHelperFooters = await fetchHelperFooters()
160
+ const isFormValid = useCallback(() => {
161
+ const fetchedHelperFooters = fetchHelperFooters()
169
162
  if (!fetchedHelperFooters) return true
170
163
  const valid = Object.values(fetchedHelperFooters).every(
171
164
  footer =>
@@ -175,9 +168,9 @@ const useHelperFooter = (initialFormname?: string) => {
175
168
  return valid
176
169
  }, [fetchHelperFooters])
177
170
 
178
- const nextError = useCallback(async () => {
171
+ const nextError = useCallback(() => {
179
172
  console.log('useHelperFooter: nextError called')
180
- const fetchedHelperFooters = await fetchHelperFooters()
173
+ const fetchedHelperFooters = fetchHelperFooters()
181
174
  if (!fetchedHelperFooters) return
182
175
  const errorFooters = Object.values(fetchedHelperFooters).filter(
183
176
  footer =>
@@ -185,16 +178,13 @@ const useHelperFooter = (initialFormname?: string) => {
185
178
  footer.required
186
179
  )
187
180
  if (errorFooters.length > 0) {
188
- const [currentErrorIndex, setCurrentErrorIndex] = session.useAtom(
189
- currentErrorIndexAtom
190
- )
191
- setCurrentErrorIndex((currentErrorIndex + 1) % errorFooters.length)
181
+ setCurrentErrorIndex(prevIndex => (prevIndex + 1) % errorFooters.length)
192
182
  console.log(
193
183
  'useHelperFooter: New error index:',
194
184
  (currentErrorIndex + 1) % errorFooters.length
195
185
  )
196
186
  }
197
- }, [fetchHelperFooters, currentErrorIndexAtom])
187
+ }, [fetchHelperFooters, currentErrorIndex, setCurrentErrorIndex])
198
188
 
199
189
  const result = useMemo(
200
190
  () => ({
@@ -1,4 +1,4 @@
1
- import React, { useMemo, useCallback, useEffect, useState } from 'react'
1
+ import React, { useMemo, useCallback, useState } from 'react'
2
2
  import { Button, Box, ButtonProps } from '@mui/material'
3
3
  import StarIcon from '@mui/icons-material/Star'
4
4
  import Typography from '../Typography'
@@ -74,9 +74,6 @@ const CustomButton: React.FC<CustomButtonProps> = React.memo(
74
74
  width,
75
75
  } = props
76
76
 
77
- const [isFormFinished, setIsFormFinished] = useState<boolean>(false)
78
- const [isCheckingForm, setIsCheckingForm] = useState<boolean>(true)
79
-
80
77
  const {
81
78
  updateFormValidation,
82
79
  checkFormStatus,
@@ -84,6 +81,9 @@ const CustomButton: React.FC<CustomButtonProps> = React.memo(
84
81
  fetchHelperFooters,
85
82
  } = useHelperFooter(formname)
86
83
 
84
+ const [isFormFinished, setIsFormFinished] = useState(false)
85
+ const [isCheckingForm, setIsCheckingForm] = useState(true)
86
+
87
87
  const checkFormState = useCallback(async (): Promise<void> => {
88
88
  console.log('CustomButton: Checking form state...')
89
89
  setIsCheckingForm(true)
@@ -110,11 +110,6 @@ const CustomButton: React.FC<CustomButtonProps> = React.memo(
110
110
  )
111
111
  }, [checkFormStatus, getEmptyRequiredFields, fetchHelperFooters])
112
112
 
113
- useEffect(() => {
114
- console.log('CustomButton: Performing initial check')
115
- checkFormState()
116
- }, [checkFormState])
117
-
118
113
  const handleButtonClick = useCallback(
119
114
  async (event: React.MouseEvent<HTMLButtonElement>): Promise<void> => {
120
115
  event.preventDefault()
@@ -1,4 +1,6 @@
1
- import { useState, useEffect, useCallback } from 'react'
1
+ 'use client'
2
+
3
+ import { useState, useCallback } from 'react'
2
4
  import { StyledComponentProps } from '..'
3
5
  import { styled, Menu, MenuItem } from '@mui/material'
4
6
  import React from 'react'
@@ -29,41 +31,26 @@ export const useDropdown = (
29
31
  inputBoxRef: React.RefObject<HTMLDivElement>,
30
32
  onOptionSelect?: (option: string) => void
31
33
  ) => {
34
+ const { componentvariant, options, value, defaultOption } = props
35
+
32
36
  /** State to control if the dropdown is open */
33
37
  const [isDropdownOpen, setIsDropdownOpen] = useState(false)
34
38
  /** State to store the anchor element for the dropdown */
35
39
  const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null)
36
40
  /** State to store the filtered options */
37
- const [filteredOptions, setFilteredOptions] = useState<string[]>([])
41
+ const [filteredOptions, setFilteredOptions] = useState<string[]>(
42
+ componentvariant === 'dropdown' && options ? [...options] : []
43
+ )
38
44
  /** State to store the currently selected option */
39
- const [selectedOption, setSelectedOption] = useState('')
45
+ const [selectedOption, setSelectedOption] = useState(() => {
46
+ if (value !== undefined) return value
47
+ if (defaultOption !== undefined) return defaultOption
48
+ if (options && options.length > 0) return options[0]
49
+ return ''
50
+ })
40
51
  /** State to track if the dropdown is focused */
41
52
  const [isDropdownFocused, setIsDropdownFocused] = useState(false)
42
53
 
43
- const { componentvariant, options, value, defaultOption } = props
44
-
45
- /**
46
- * Effect to set filtered options when component variant is dropdown and options are provided
47
- */
48
- useEffect(() => {
49
- if (componentvariant === 'dropdown' && options) {
50
- setFilteredOptions([...options])
51
- }
52
- }, [componentvariant, options])
53
-
54
- /**
55
- * Effect to set the selected option based on value, defaultOption, or first option
56
- */
57
- useEffect(() => {
58
- if (value !== undefined) {
59
- setSelectedOption(value)
60
- } else if (defaultOption !== undefined) {
61
- setSelectedOption(defaultOption)
62
- } else if (options && options.length > 0) {
63
- setSelectedOption(options[0])
64
- }
65
- }, [value, defaultOption, options])
66
-
67
54
  /**
68
55
  * Handle click on the dropdown to open/close it
69
56
  */
@@ -102,6 +89,22 @@ export const useDropdown = (
102
89
  [componentvariant]
103
90
  )
104
91
 
92
+ /**
93
+ * Update filtered options and selected option when props change
94
+ */
95
+ const updateDropdownState = useCallback(() => {
96
+ if (componentvariant === 'dropdown' && options) {
97
+ setFilteredOptions([...options])
98
+ }
99
+ if (value !== undefined) {
100
+ setSelectedOption(value)
101
+ } else if (defaultOption !== undefined) {
102
+ setSelectedOption(defaultOption)
103
+ } else if (options && options.length > 0) {
104
+ setSelectedOption(options[0])
105
+ }
106
+ }, [componentvariant, options, value, defaultOption])
107
+
105
108
  /**
106
109
  * Render the dropdown menu
107
110
  */
@@ -142,5 +145,6 @@ export const useDropdown = (
142
145
  handleOptionSelect,
143
146
  isDropdownFocused,
144
147
  handleInputFocus,
148
+ updateDropdownState,
145
149
  }
146
150
  }