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 +3 -3
- package/src/components/Button/index.tsx +44 -27
- package/src/components/DataGrid/Footer/index.tsx +1 -0
- package/src/components/Form/DataGrid/index.tsx +2 -0
- package/src/components/Nav/HorizontalVariant/index.tsx +100 -74
- package/src/components/Nav/VerticalVariant/index.tsx +29 -3
- package/src/components/Nav/index.tsx +8 -0
- package/src/components/PricingTable/defaultconfig.tsx +9 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "goobs-frontend",
|
|
3
|
-
"version": "0.8.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
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',
|
|
@@ -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 = '
|
|
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
|
-
<
|
|
65
|
+
<AppBar
|
|
66
|
+
position="sticky"
|
|
67
67
|
sx={{
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
<
|
|
78
|
-
|
|
79
|
-
onChange={handleTabChange}
|
|
80
|
-
aria-label="nav tabs"
|
|
72
|
+
<Toolbar
|
|
73
|
+
disableGutters
|
|
81
74
|
sx={{
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
'
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
|
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={
|
|
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
|
|
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 {
|