goobs-frontend 0.8.13 → 0.8.14

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.8.13",
3
+ "version": "0.8.14",
4
4
  "type": "module",
5
5
  "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.",
6
6
  "license": "MIT",
@@ -28,7 +28,7 @@
28
28
  "highlight.js": "^11.10.0",
29
29
  "jotai": "^2.10.3",
30
30
  "lodash": "^4.17.21",
31
- "next": "15.1.0",
31
+ "next": "15.1.2",
32
32
  "otplib": "^12.0.1",
33
33
  "react-datepicker": "^7.5.0",
34
34
  "react-qr-code": "^2.0.15",
@@ -45,7 +45,7 @@
45
45
  "@typescript-eslint/eslint-plugin": "^8.18.0",
46
46
  "@typescript-eslint/parser": "^8.18.0",
47
47
  "eslint": "^9.16.0",
48
- "eslint-config-next": "^15.1.0",
48
+ "eslint-config-next": "^15.1.2",
49
49
  "eslint-config-prettier": "^9.1.0",
50
50
  "eslint-plugin-prettier": "^5.2.1",
51
51
  "prettier": "^3.4.2",
@@ -29,35 +29,52 @@ const StyledButton = styled(Button, {
29
29
  backgroundcolor?: string
30
30
  iconlocation?: 'left' | 'right' | 'above'
31
31
  fontlocation?: 'left' | 'center' | 'right'
32
- }>(({ backgroundcolor, iconlocation, fontlocation }) => ({
33
- minWidth: 'auto',
34
- width: '100%',
35
- height: '40px',
36
- padding: '8px 16px',
37
- display: 'flex',
38
- flexDirection: iconlocation === 'above' ? 'column' : 'row',
39
- alignItems: 'center',
40
- justifyContent:
41
- fontlocation === 'left'
42
- ? 'flex-start'
43
- : fontlocation === 'right'
44
- ? 'flex-end'
45
- : 'center',
46
- gap: '8px',
47
- ...(backgroundcolor && {
48
- backgroundColor: backgroundcolor,
49
- '&:hover': {
32
+ }>(({ backgroundcolor, iconlocation, fontlocation }) => {
33
+ // Determine styles based on backgroundcolor
34
+ let backgroundStyles = {}
35
+ if (backgroundcolor && backgroundcolor !== 'none') {
36
+ backgroundStyles = {
50
37
  backgroundColor: backgroundcolor,
51
- opacity: 0.9,
38
+ '&:hover': {
39
+ backgroundColor: backgroundcolor,
40
+ opacity: 0.9,
41
+ },
42
+ }
43
+ } else if (backgroundcolor === 'none') {
44
+ // No background, behave like a text button
45
+ backgroundStyles = {
46
+ backgroundColor: 'transparent',
47
+ '&:hover': {
48
+ backgroundColor: 'transparent',
49
+ opacity: 0.9,
50
+ },
51
+ }
52
+ }
53
+
54
+ return {
55
+ minWidth: 'auto',
56
+ width: '100%',
57
+ height: '40px',
58
+ padding: '8px 16px',
59
+ display: 'flex',
60
+ flexDirection: iconlocation === 'above' ? 'column' : 'row',
61
+ alignItems: 'center',
62
+ justifyContent:
63
+ fontlocation === 'left'
64
+ ? 'flex-start'
65
+ : fontlocation === 'right'
66
+ ? 'flex-end'
67
+ : 'center',
68
+ gap: '8px',
69
+ ...backgroundStyles,
70
+ '& .MuiButton-startIcon': {
71
+ margin: 0,
52
72
  },
53
- }),
54
- '& .MuiButton-startIcon': {
55
- margin: 0,
56
- },
57
- '& .MuiButton-endIcon': {
58
- margin: 0,
59
- },
60
- }))
73
+ '& .MuiButton-endIcon': {
74
+ margin: 0,
75
+ },
76
+ }
77
+ })
61
78
 
62
79
  const StyledBox = styled(Box)({
63
80
  display: 'flex',
@@ -98,6 +98,7 @@ function CustomFooter({
98
98
  text="Manage Columns"
99
99
  fontvariant="merriparagraph"
100
100
  fontcolor="black"
101
+ backgroundcolor="none"
101
102
  icon={<ShowHideEyeIcon visible={true} />}
102
103
  iconcolor="black"
103
104
  iconlocation="left"
@@ -44,6 +44,7 @@ function FormDataGrid({ title, description, datagrid }: FormDataGridProps) {
44
44
  width: '100%',
45
45
  textAlign: 'left',
46
46
  fontFamily: 'Merriweather',
47
+ marginLeft: 2,
47
48
  fontSize: '1.5rem',
48
49
  fontWeight: 400,
49
50
  color: 'black',
@@ -57,6 +58,7 @@ function FormDataGrid({ title, description, datagrid }: FormDataGridProps) {
57
58
  textAlign: 'left',
58
59
  fontFamily: 'Merriweather',
59
60
  fontSize: '1.25rem',
61
+ marginLeft: 2,
60
62
  fontWeight: 400,
61
63
  color: 'black',
62
64
  }}
@@ -1,6 +1,6 @@
1
1
  'use client'
2
2
  import React, { useState, useEffect } from 'react'
3
- import { Box, Tabs, Tab } from '@mui/material'
3
+ import { AppBar, Toolbar, Box, Tabs, Tab } from '@mui/material'
4
4
  import { NavProps, SubNav, View } from '../index'
5
5
  import { usePathname } from 'next/navigation'
6
6
 
@@ -19,8 +19,7 @@ export interface HorizontalVariantProps {
19
19
 
20
20
  function HorizontalVariant({
21
21
  items,
22
- height = '80px',
23
- alignment = 'left',
22
+ height = '48px',
24
23
  navname = '',
25
24
  }: HorizontalVariantProps) {
26
25
  const [activeTabValues, setActiveTabValues] = useState<
@@ -63,83 +62,110 @@ function HorizontalVariant({
63
62
  }
64
63
 
65
64
  return (
66
- <Box
65
+ <AppBar
66
+ position="sticky"
67
67
  sx={{
68
- flexGrow: 1,
69
- bgcolor: 'black',
70
- display: 'flex',
71
- height: height,
72
- justifyContent: alignment,
73
- paddingLeft: '5px',
74
- paddingRight: '5px',
68
+ backgroundColor: 'black',
69
+ color: 'white',
75
70
  }}
76
71
  >
77
- <Tabs
78
- value={activeTabValues[navname]?.tabId || false}
79
- onChange={handleTabChange}
80
- aria-label="nav tabs"
72
+ <Toolbar
73
+ disableGutters
81
74
  sx={{
82
- height: height,
83
- '& .MuiTabs-flexContainer': {
84
- height: '100%',
85
- },
86
- '& .MuiTab-root': {
87
- height: '100%',
88
- minHeight: 'unset',
89
- },
75
+ paddingLeft: 0,
76
+ paddingRight: 0,
77
+ height: `${height} !important`,
78
+ minHeight: `${height} !important`,
79
+ borderTop: '1px solid white',
90
80
  }}
91
81
  >
92
- {items.map((item: NavProps | SubNav | View) => {
93
- if ('orientation' in item) {
94
- const tab = item as NavProps
95
- return (
96
- <Tab
97
- key={tab.title}
98
- value={tab.title || ''}
99
- label={tab.title || ''}
100
- onClick={() => handleTabClick(tab)}
101
- sx={{
102
- minHeight: 0,
103
- textTransform: 'none',
104
- border: 'none',
105
- boxSizing: 'border-box',
106
- backgroundColor: 'black',
107
- color: '#fff',
108
- fontWeight: 500,
109
- fontFamily: 'Merriweather',
110
- fontSize: 16,
111
- height: height,
112
- '&:hover': {
113
- backgroundColor: 'rgba(255, 255, 255, 0.1)',
114
- },
115
- '& .MuiTouchRipple-root': {
116
- color: '#fff',
117
- },
118
- '&.Mui-selected': {
119
- color: '#fff',
120
- backgroundColor: 'rgba(255, 255, 255, 0.2)',
121
- },
122
- '& .MuiSvgIcon-root': {
123
- color: '#fff',
124
- },
125
- ...(tab.hasleftborder === 'true' && {
126
- borderLeft: '1px solid white',
127
- }),
128
- ...(tab.hasrightborder === 'true' && {
129
- borderRight: '1px solid white',
130
- }),
131
- width: 'auto',
132
- justifyContent: 'center',
133
- alignItems: 'center',
134
- px: 4,
135
- }}
136
- />
137
- )
138
- }
139
- return null
140
- })}
141
- </Tabs>
142
- </Box>
82
+ <Box
83
+ sx={{
84
+ width: '100%',
85
+ display: 'flex',
86
+ flexDirection: 'row',
87
+ justifyContent: 'flex-start',
88
+ }}
89
+ >
90
+ <Box
91
+ sx={{
92
+ flexGrow: 1,
93
+ display: 'flex',
94
+ height: height,
95
+ justifyContent: 'flex-start',
96
+ paddingLeft: 0,
97
+ paddingRight: 0,
98
+ }}
99
+ >
100
+ <Tabs
101
+ value={activeTabValues[navname]?.tabId || false}
102
+ onChange={handleTabChange}
103
+ aria-label="nav tabs"
104
+ sx={{
105
+ height: height,
106
+ '& .MuiTabs-flexContainer': {
107
+ height: '100%',
108
+ },
109
+ '& .MuiTab-root': {
110
+ height: '100%',
111
+ minHeight: 'unset',
112
+ },
113
+ }}
114
+ >
115
+ {items.map((item: NavProps | SubNav | View) => {
116
+ if ('orientation' in item) {
117
+ const tab = item as NavProps
118
+ return (
119
+ <Tab
120
+ key={tab.title}
121
+ value={tab.title || ''}
122
+ label={tab.title || ''}
123
+ onClick={() => handleTabClick(tab)}
124
+ sx={{
125
+ minHeight: 0,
126
+ textTransform: 'none',
127
+ border: 'none',
128
+ boxSizing: 'border-box',
129
+ backgroundColor: 'black',
130
+ color: '#fff',
131
+ fontWeight: 500,
132
+ fontFamily: 'Merriweather',
133
+ fontSize: 16,
134
+ height: height,
135
+ '&:hover': {
136
+ backgroundColor: 'rgba(255, 255, 255, 0.1)',
137
+ },
138
+ '& .MuiTouchRipple-root': {
139
+ color: '#fff',
140
+ },
141
+ '&.Mui-selected': {
142
+ color: '#fff',
143
+ backgroundColor: 'rgba(255, 255, 255, 0.2)',
144
+ },
145
+ '& .MuiSvgIcon-root': {
146
+ color: '#fff',
147
+ },
148
+ ...(tab.hasleftborder === 'true' && {
149
+ borderLeft: '1px solid white',
150
+ }),
151
+ ...(tab.hasrightborder === 'true' && {
152
+ borderRight: '1px solid white',
153
+ }),
154
+ width: 'auto',
155
+ justifyContent: 'center',
156
+ alignItems: 'center',
157
+ px: 4,
158
+ }}
159
+ />
160
+ )
161
+ }
162
+ return null
163
+ })}
164
+ </Tabs>
165
+ </Box>
166
+ </Box>
167
+ </Toolbar>
168
+ </AppBar>
143
169
  )
144
170
  }
145
171
 
@@ -40,6 +40,8 @@ export interface VerticalVariantProps {
40
40
  onClose?: () => void
41
41
  variant?: 'temporary' | 'permanent'
42
42
  spacingfromtopofscreen?: string
43
+ marginabovetitle?: string
44
+ marginbelowtitle?: string
43
45
  }
44
46
 
45
47
  function VerticalVariant({
@@ -63,6 +65,8 @@ function VerticalVariant({
63
65
  onClose,
64
66
  variant = 'permanent',
65
67
  spacingfromtopofscreen = '0px',
68
+ marginabovetitle = '0px',
69
+ marginbelowtitle = '0px',
66
70
  }: VerticalVariantProps) {
67
71
  const router = useRouter()
68
72
  const [selectedNav, setSelectedNav] = useState<string | null>(null)
@@ -109,6 +113,7 @@ function VerticalVariant({
109
113
  activeAndHoverColor = semiTransparentWhite.main
110
114
  ) => {
111
115
  if ('title' in item && 'subnavs' in item) {
116
+ // This is a NavProps item (top-level nav)
112
117
  const nav = item as NavProps
113
118
  const isExpanded = expandedNavs.includes(nav.title ?? '')
114
119
  return (
@@ -191,9 +196,11 @@ function VerticalVariant({
191
196
  </MuiAccordion>
192
197
  )
193
198
  } else if ('title' in item && 'views' in item) {
199
+ // This is a SubNav item
194
200
  const subnav = item as SubNav
195
201
  const isExpanded = expandedSubnavs.includes(subnav.title ?? '')
196
- if (subnav.views?.length === 0) {
202
+ if (!subnav.views || subnav.views.length === 0) {
203
+ // SubNav with no views, just a route
197
204
  return (
198
205
  <Link
199
206
  key={subnav.title}
@@ -214,6 +221,15 @@ function VerticalVariant({
214
221
  backgroundColor: activeAndHoverColor,
215
222
  },
216
223
  }}
224
+ onClick={() => {
225
+ if (
226
+ subnav.trigger === 'route' &&
227
+ variant === 'temporary' &&
228
+ onClose
229
+ ) {
230
+ onClose()
231
+ }
232
+ }}
217
233
  >
218
234
  <Typography
219
235
  fontvariant="merrih6"
@@ -224,6 +240,7 @@ function VerticalVariant({
224
240
  </Link>
225
241
  )
226
242
  } else {
243
+ // SubNav with views
227
244
  return (
228
245
  <MuiAccordion
229
246
  key={subnav.title}
@@ -302,6 +319,7 @@ function VerticalVariant({
302
319
  )
303
320
  }
304
321
  } else if ('title' in item && 'route' in item) {
322
+ // This is a View item
305
323
  const view = item as View
306
324
  return (
307
325
  <Link
@@ -311,7 +329,15 @@ function VerticalVariant({
311
329
  color: 'white',
312
330
  }}
313
331
  href={view.route ?? ''}
314
- onClick={variant === 'temporary' ? onClose : undefined}
332
+ onClick={() => {
333
+ if (
334
+ view.trigger === 'route' &&
335
+ variant === 'temporary' &&
336
+ onClose
337
+ ) {
338
+ onClose()
339
+ }
340
+ }}
315
341
  >
316
342
  <MenuItem
317
343
  sx={{
@@ -351,7 +377,7 @@ function VerticalVariant({
351
377
  <>
352
378
  <Box px={`15px`}>
353
379
  {showTitle && (
354
- <Box pt="0px" pb="0px">
380
+ <Box mt={marginabovetitle} mb={marginbelowtitle}>
355
381
  <Link
356
382
  href={titleUrl || '/'}
357
383
  passHref
@@ -37,6 +37,8 @@ export interface NavProps {
37
37
  onClose?: () => void // Handler for closing mobile drawer
38
38
  variant?: 'temporary' | 'permanent' // Drawer variant for mobile/desktop
39
39
  spacingfromtopofscreen?: string // Spacing from top of screen
40
+ marginabovetitle?: string // Margin above the title in vertical variant
41
+ marginbelowtitle?: string // Margin below the title in vertical variant
40
42
  }
41
43
 
42
44
  /**
@@ -48,6 +50,7 @@ export type SubNav = {
48
50
  subtitle?: string // Subtitle for the sub-nav
49
51
  views?: View[] // Views within the sub-nav
50
52
  navname?: string // Name of the sub-nav
53
+ trigger?: 'route' | 'onClick' | 'routeonhorizontal' // Trigger type for the sub-nav
51
54
  }
52
55
 
53
56
  /**
@@ -58,6 +61,7 @@ export type View = {
58
61
  title?: string // Title of the view
59
62
  subtitle?: string // Subtitle for the view
60
63
  navname?: string // Name of the view
64
+ trigger?: 'route' | 'onClick' | 'routeonhorizontal' // Trigger type for the view
61
65
  }
62
66
 
63
67
  /**
@@ -85,6 +89,8 @@ function Nav({
85
89
  onClose,
86
90
  variant = 'permanent',
87
91
  spacingfromtopofscreen,
92
+ marginabovetitle = '0px',
93
+ marginbelowtitle = '0px',
88
94
  }: NavProps): JSX.Element {
89
95
  // State for expanded navigation items
90
96
  const [expandedNavs, setExpandedNavs] = useState<string[]>([])
@@ -132,6 +138,8 @@ function Nav({
132
138
  onClose={onClose}
133
139
  variant={variant}
134
140
  spacingfromtopofscreen={spacingfromtopofscreen}
141
+ marginabovetitle={marginabovetitle}
142
+ marginbelowtitle={marginbelowtitle}
135
143
  />
136
144
  )
137
145
  } else {
@@ -307,6 +307,15 @@ const defaultConfig: PricingProps = {
307
307
  row: 7,
308
308
  column: 1,
309
309
  mobilewidth: '100%',
310
+ margintop: {
311
+ xs: 2,
312
+ sm: 2,
313
+ md: 2,
314
+ ms: 2,
315
+ ml: 2,
316
+ lg: 2,
317
+ xl: 2,
318
+ },
310
319
  marginbottom: {
311
320
  xs: 1,
312
321
  sm: 1,