goobs-frontend 0.8.12 → 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/Grid/index.tsx +102 -23
- package/src/components/Nav/HorizontalVariant/index.tsx +100 -74
- package/src/components/Nav/VerticalVariant/index.tsx +32 -4
- package/src/components/Nav/index.tsx +11 -0
- package/src/components/PricingTable/defaultconfig.tsx +98 -9
- package/src/components/PricingTable/index.tsx +11 -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
|
}}
|
|
@@ -4,9 +4,6 @@ import React from 'react'
|
|
|
4
4
|
import Grid2, { Grid2Props } from '@mui/material/Grid2'
|
|
5
5
|
import { useMediaQuery } from '@mui/material'
|
|
6
6
|
|
|
7
|
-
// Remove all theme creation and usage
|
|
8
|
-
// We will manually define our media queries instead of using createTheme or ThemeProvider
|
|
9
|
-
|
|
10
7
|
type Alignment = 'left' | 'center' | 'right' | 'inherit' | 'justify'
|
|
11
8
|
type BorderProp = 'none' | 'solid'
|
|
12
9
|
type WrapProp = 'nowrap' | 'wrap'
|
|
@@ -24,16 +21,34 @@ interface ResponsiveObject<T> {
|
|
|
24
21
|
|
|
25
22
|
type ResponsiveValue<T> = T | ResponsiveObject<T>
|
|
26
23
|
|
|
24
|
+
type cellconfig = {
|
|
25
|
+
border?: BorderProp
|
|
26
|
+
minHeight?: string
|
|
27
|
+
maxHeight?: string
|
|
28
|
+
width?: string
|
|
29
|
+
mobilewidth?: string
|
|
30
|
+
tabletwidth?: string
|
|
31
|
+
computerwidth?: string
|
|
32
|
+
borderColor?: string
|
|
33
|
+
backgroundColor?: string
|
|
34
|
+
onClick?: () => void
|
|
35
|
+
wrap?: WrapProp
|
|
36
|
+
}
|
|
37
|
+
|
|
27
38
|
type columnconfig = {
|
|
28
39
|
row: number
|
|
29
40
|
column: number
|
|
30
41
|
gridname?: string
|
|
31
42
|
alignment?: Alignment
|
|
32
43
|
margintop?: ResponsiveValue<number>
|
|
33
|
-
columnwidth?: string
|
|
34
44
|
marginbottom?: ResponsiveValue<number>
|
|
35
45
|
marginright?: ResponsiveValue<number>
|
|
36
46
|
marginleft?: ResponsiveValue<number>
|
|
47
|
+
paddingtop?: ResponsiveValue<number>
|
|
48
|
+
paddingbottom?: ResponsiveValue<number>
|
|
49
|
+
paddingright?: ResponsiveValue<number>
|
|
50
|
+
paddingleft?: ResponsiveValue<number>
|
|
51
|
+
columnwidth?: string
|
|
37
52
|
component?: React.ReactNode
|
|
38
53
|
bordercolor?: string
|
|
39
54
|
cellconfig?: cellconfig
|
|
@@ -49,24 +64,14 @@ type gridconfig = {
|
|
|
49
64
|
marginbottom?: ResponsiveValue<number>
|
|
50
65
|
marginright?: ResponsiveValue<number>
|
|
51
66
|
marginleft?: ResponsiveValue<number>
|
|
67
|
+
paddingtop?: ResponsiveValue<number>
|
|
68
|
+
paddingbottom?: ResponsiveValue<number>
|
|
69
|
+
paddingright?: ResponsiveValue<number>
|
|
70
|
+
paddingleft?: ResponsiveValue<number>
|
|
52
71
|
gridwidth?: string
|
|
53
72
|
bordercolor?: string
|
|
54
73
|
}
|
|
55
74
|
|
|
56
|
-
type cellconfig = {
|
|
57
|
-
border?: BorderProp
|
|
58
|
-
minHeight?: string
|
|
59
|
-
maxHeight?: string
|
|
60
|
-
width?: string
|
|
61
|
-
mobilewidth?: string
|
|
62
|
-
tabletwidth?: string
|
|
63
|
-
computerwidth?: string
|
|
64
|
-
borderColor?: string
|
|
65
|
-
backgroundColor?: string
|
|
66
|
-
onClick?: () => void
|
|
67
|
-
wrap?: WrapProp
|
|
68
|
-
}
|
|
69
|
-
|
|
70
75
|
type CustomGridProps = Omit<Grid2Props, 'children'> & {
|
|
71
76
|
gridconfig?: gridconfig
|
|
72
77
|
columnconfig?: columnconfig[]
|
|
@@ -134,6 +139,41 @@ function CustomGrid({
|
|
|
134
139
|
? 'flex-end'
|
|
135
140
|
: 'center'
|
|
136
141
|
|
|
142
|
+
// Get responsive margin and padding values for the overall grid
|
|
143
|
+
const gridMarginTop = getResponsiveValue(
|
|
144
|
+
gridConfigValues?.margintop,
|
|
145
|
+
currentBreakpoint
|
|
146
|
+
)
|
|
147
|
+
const gridMarginBottom = getResponsiveValue(
|
|
148
|
+
gridConfigValues?.marginbottom,
|
|
149
|
+
currentBreakpoint
|
|
150
|
+
)
|
|
151
|
+
const gridMarginLeft = getResponsiveValue(
|
|
152
|
+
gridConfigValues?.marginleft,
|
|
153
|
+
currentBreakpoint
|
|
154
|
+
)
|
|
155
|
+
const gridMarginRight = getResponsiveValue(
|
|
156
|
+
gridConfigValues?.marginright,
|
|
157
|
+
currentBreakpoint
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
const gridPaddingTop = getResponsiveValue(
|
|
161
|
+
gridConfigValues?.paddingtop,
|
|
162
|
+
currentBreakpoint
|
|
163
|
+
)
|
|
164
|
+
const gridPaddingBottom = getResponsiveValue(
|
|
165
|
+
gridConfigValues?.paddingbottom,
|
|
166
|
+
currentBreakpoint
|
|
167
|
+
)
|
|
168
|
+
const gridPaddingLeft = getResponsiveValue(
|
|
169
|
+
gridConfigValues?.paddingleft,
|
|
170
|
+
currentBreakpoint
|
|
171
|
+
)
|
|
172
|
+
const gridPaddingRight = getResponsiveValue(
|
|
173
|
+
gridConfigValues?.paddingright,
|
|
174
|
+
currentBreakpoint
|
|
175
|
+
)
|
|
176
|
+
|
|
137
177
|
const rows = Math.max(...(columnconfig || []).map(c => c.row || 1))
|
|
138
178
|
|
|
139
179
|
return (
|
|
@@ -148,10 +188,16 @@ function CustomGrid({
|
|
|
148
188
|
padding: 0,
|
|
149
189
|
margin: 0,
|
|
150
190
|
gap: 0,
|
|
191
|
+
// Apply grid-level margins and paddings
|
|
192
|
+
marginTop: gridMarginTop ? `${gridMarginTop * 8}px` : 0,
|
|
193
|
+
marginBottom: gridMarginBottom ? `${gridMarginBottom * 8}px` : 0,
|
|
194
|
+
marginLeft: gridMarginLeft ? `${gridMarginLeft * 8}px` : 0,
|
|
195
|
+
marginRight: gridMarginRight ? `${gridMarginRight * 8}px` : 0,
|
|
196
|
+
paddingTop: gridPaddingTop ? `${gridPaddingTop * 8}px` : 0,
|
|
197
|
+
paddingBottom: gridPaddingBottom ? `${gridPaddingBottom * 8}px` : 0,
|
|
198
|
+
paddingLeft: gridPaddingLeft ? `${gridPaddingLeft * 8}px` : 0,
|
|
199
|
+
paddingRight: gridPaddingRight ? `${gridPaddingRight * 8}px` : 0,
|
|
151
200
|
// Remove or adjust the child selector that sets margin:0
|
|
152
|
-
// If we must not remove code, we can make it more specific so it doesn't override column margins.
|
|
153
|
-
// Change '& > *' to a more specific selector that doesn't conflict with column Grid2 items:
|
|
154
|
-
// For example, limit it to direct child elements that are not Grid2:
|
|
155
201
|
'& > *:not(.grid-column)': {
|
|
156
202
|
border: 'none !important',
|
|
157
203
|
padding: 0,
|
|
@@ -221,6 +267,7 @@ function CustomGrid({
|
|
|
221
267
|
? 'flex-end'
|
|
222
268
|
: 'center'
|
|
223
269
|
|
|
270
|
+
// Get responsive margin and padding values for the column
|
|
224
271
|
const marginTop = getResponsiveValue(
|
|
225
272
|
currentColumnConfig?.margintop,
|
|
226
273
|
currentBreakpoint
|
|
@@ -238,6 +285,23 @@ function CustomGrid({
|
|
|
238
285
|
currentBreakpoint
|
|
239
286
|
)
|
|
240
287
|
|
|
288
|
+
const paddingTop = getResponsiveValue(
|
|
289
|
+
currentColumnConfig?.paddingtop,
|
|
290
|
+
currentBreakpoint
|
|
291
|
+
)
|
|
292
|
+
const paddingBottom = getResponsiveValue(
|
|
293
|
+
currentColumnConfig?.paddingbottom,
|
|
294
|
+
currentBreakpoint
|
|
295
|
+
)
|
|
296
|
+
const paddingLeft = getResponsiveValue(
|
|
297
|
+
currentColumnConfig?.paddingleft,
|
|
298
|
+
currentBreakpoint
|
|
299
|
+
)
|
|
300
|
+
const paddingRight = getResponsiveValue(
|
|
301
|
+
currentColumnConfig?.paddingright,
|
|
302
|
+
currentBreakpoint
|
|
303
|
+
)
|
|
304
|
+
|
|
241
305
|
return (
|
|
242
306
|
<Grid2
|
|
243
307
|
key={`column-${columnIndex}`}
|
|
@@ -252,8 +316,8 @@ function CustomGrid({
|
|
|
252
316
|
flexShrink: hasFixedWidth ? 0 : 1,
|
|
253
317
|
flexBasis: hasFixedWidth ? columnWidth : 'auto',
|
|
254
318
|
height: 'fit-content',
|
|
255
|
-
|
|
256
|
-
//
|
|
319
|
+
|
|
320
|
+
// Apply margin
|
|
257
321
|
marginLeft: marginLeft
|
|
258
322
|
? `${marginLeft * 8}px !important`
|
|
259
323
|
: '0 !important',
|
|
@@ -266,6 +330,21 @@ function CustomGrid({
|
|
|
266
330
|
marginBottom: marginBottom
|
|
267
331
|
? `${marginBottom * 8}px !important`
|
|
268
332
|
: '0 !important',
|
|
333
|
+
|
|
334
|
+
// Apply padding
|
|
335
|
+
paddingLeft: paddingLeft
|
|
336
|
+
? `${paddingLeft * 8}px !important`
|
|
337
|
+
: '0 !important',
|
|
338
|
+
paddingRight: paddingRight
|
|
339
|
+
? `${paddingRight * 8}px !important`
|
|
340
|
+
: '0 !important',
|
|
341
|
+
paddingTop: paddingTop
|
|
342
|
+
? `${paddingTop * 8}px !important`
|
|
343
|
+
: '0 !important',
|
|
344
|
+
paddingBottom: paddingBottom
|
|
345
|
+
? `${paddingBottom * 8}px !important`
|
|
346
|
+
: '0 !important',
|
|
347
|
+
|
|
269
348
|
border: 'none',
|
|
270
349
|
backgroundColor: currentCellConfig?.backgroundColor,
|
|
271
350
|
minHeight: 'min-content',
|
|
@@ -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
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
'use client'
|
|
2
|
-
|
|
3
2
|
import React, { useState, useCallback } from 'react'
|
|
4
3
|
import {
|
|
5
4
|
Drawer,
|
|
@@ -40,6 +39,9 @@ export interface VerticalVariantProps {
|
|
|
40
39
|
mobileOpen?: boolean
|
|
41
40
|
onClose?: () => void
|
|
42
41
|
variant?: 'temporary' | 'permanent'
|
|
42
|
+
spacingfromtopofscreen?: string
|
|
43
|
+
marginabovetitle?: string
|
|
44
|
+
marginbelowtitle?: string
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
function VerticalVariant({
|
|
@@ -62,6 +64,9 @@ function VerticalVariant({
|
|
|
62
64
|
mobileOpen = false,
|
|
63
65
|
onClose,
|
|
64
66
|
variant = 'permanent',
|
|
67
|
+
spacingfromtopofscreen = '0px',
|
|
68
|
+
marginabovetitle = '0px',
|
|
69
|
+
marginbelowtitle = '0px',
|
|
65
70
|
}: VerticalVariantProps) {
|
|
66
71
|
const router = useRouter()
|
|
67
72
|
const [selectedNav, setSelectedNav] = useState<string | null>(null)
|
|
@@ -108,6 +113,7 @@ function VerticalVariant({
|
|
|
108
113
|
activeAndHoverColor = semiTransparentWhite.main
|
|
109
114
|
) => {
|
|
110
115
|
if ('title' in item && 'subnavs' in item) {
|
|
116
|
+
// This is a NavProps item (top-level nav)
|
|
111
117
|
const nav = item as NavProps
|
|
112
118
|
const isExpanded = expandedNavs.includes(nav.title ?? '')
|
|
113
119
|
return (
|
|
@@ -190,9 +196,11 @@ function VerticalVariant({
|
|
|
190
196
|
</MuiAccordion>
|
|
191
197
|
)
|
|
192
198
|
} else if ('title' in item && 'views' in item) {
|
|
199
|
+
// This is a SubNav item
|
|
193
200
|
const subnav = item as SubNav
|
|
194
201
|
const isExpanded = expandedSubnavs.includes(subnav.title ?? '')
|
|
195
|
-
if (subnav.views
|
|
202
|
+
if (!subnav.views || subnav.views.length === 0) {
|
|
203
|
+
// SubNav with no views, just a route
|
|
196
204
|
return (
|
|
197
205
|
<Link
|
|
198
206
|
key={subnav.title}
|
|
@@ -213,6 +221,15 @@ function VerticalVariant({
|
|
|
213
221
|
backgroundColor: activeAndHoverColor,
|
|
214
222
|
},
|
|
215
223
|
}}
|
|
224
|
+
onClick={() => {
|
|
225
|
+
if (
|
|
226
|
+
subnav.trigger === 'route' &&
|
|
227
|
+
variant === 'temporary' &&
|
|
228
|
+
onClose
|
|
229
|
+
) {
|
|
230
|
+
onClose()
|
|
231
|
+
}
|
|
232
|
+
}}
|
|
216
233
|
>
|
|
217
234
|
<Typography
|
|
218
235
|
fontvariant="merrih6"
|
|
@@ -223,6 +240,7 @@ function VerticalVariant({
|
|
|
223
240
|
</Link>
|
|
224
241
|
)
|
|
225
242
|
} else {
|
|
243
|
+
// SubNav with views
|
|
226
244
|
return (
|
|
227
245
|
<MuiAccordion
|
|
228
246
|
key={subnav.title}
|
|
@@ -301,6 +319,7 @@ function VerticalVariant({
|
|
|
301
319
|
)
|
|
302
320
|
}
|
|
303
321
|
} else if ('title' in item && 'route' in item) {
|
|
322
|
+
// This is a View item
|
|
304
323
|
const view = item as View
|
|
305
324
|
return (
|
|
306
325
|
<Link
|
|
@@ -310,7 +329,15 @@ function VerticalVariant({
|
|
|
310
329
|
color: 'white',
|
|
311
330
|
}}
|
|
312
331
|
href={view.route ?? ''}
|
|
313
|
-
onClick={
|
|
332
|
+
onClick={() => {
|
|
333
|
+
if (
|
|
334
|
+
view.trigger === 'route' &&
|
|
335
|
+
variant === 'temporary' &&
|
|
336
|
+
onClose
|
|
337
|
+
) {
|
|
338
|
+
onClose()
|
|
339
|
+
}
|
|
340
|
+
}}
|
|
314
341
|
>
|
|
315
342
|
<MenuItem
|
|
316
343
|
sx={{
|
|
@@ -350,7 +377,7 @@ function VerticalVariant({
|
|
|
350
377
|
<>
|
|
351
378
|
<Box px={`15px`}>
|
|
352
379
|
{showTitle && (
|
|
353
|
-
<Box
|
|
380
|
+
<Box mt={marginabovetitle} mb={marginbelowtitle}>
|
|
354
381
|
<Link
|
|
355
382
|
href={titleUrl || '/'}
|
|
356
383
|
passHref
|
|
@@ -432,6 +459,7 @@ function VerticalVariant({
|
|
|
432
459
|
backgroundColor: ocean.main,
|
|
433
460
|
pt: '17px',
|
|
434
461
|
boxSizing: 'border-box',
|
|
462
|
+
marginTop: spacingfromtopofscreen,
|
|
435
463
|
},
|
|
436
464
|
}}
|
|
437
465
|
>
|
|
@@ -36,6 +36,9 @@ export interface NavProps {
|
|
|
36
36
|
mobileOpen?: boolean // Controls mobile drawer open state
|
|
37
37
|
onClose?: () => void // Handler for closing mobile drawer
|
|
38
38
|
variant?: 'temporary' | 'permanent' // Drawer variant for mobile/desktop
|
|
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
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
/**
|
|
@@ -47,6 +50,7 @@ export type SubNav = {
|
|
|
47
50
|
subtitle?: string // Subtitle for the sub-nav
|
|
48
51
|
views?: View[] // Views within the sub-nav
|
|
49
52
|
navname?: string // Name of the sub-nav
|
|
53
|
+
trigger?: 'route' | 'onClick' | 'routeonhorizontal' // Trigger type for the sub-nav
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
/**
|
|
@@ -57,6 +61,7 @@ export type View = {
|
|
|
57
61
|
title?: string // Title of the view
|
|
58
62
|
subtitle?: string // Subtitle for the view
|
|
59
63
|
navname?: string // Name of the view
|
|
64
|
+
trigger?: 'route' | 'onClick' | 'routeonhorizontal' // Trigger type for the view
|
|
60
65
|
}
|
|
61
66
|
|
|
62
67
|
/**
|
|
@@ -83,6 +88,9 @@ function Nav({
|
|
|
83
88
|
mobileOpen = false,
|
|
84
89
|
onClose,
|
|
85
90
|
variant = 'permanent',
|
|
91
|
+
spacingfromtopofscreen,
|
|
92
|
+
marginabovetitle = '0px',
|
|
93
|
+
marginbelowtitle = '0px',
|
|
86
94
|
}: NavProps): JSX.Element {
|
|
87
95
|
// State for expanded navigation items
|
|
88
96
|
const [expandedNavs, setExpandedNavs] = useState<string[]>([])
|
|
@@ -129,6 +137,9 @@ function Nav({
|
|
|
129
137
|
mobileOpen={mobileOpen}
|
|
130
138
|
onClose={onClose}
|
|
131
139
|
variant={variant}
|
|
140
|
+
spacingfromtopofscreen={spacingfromtopofscreen}
|
|
141
|
+
marginabovetitle={marginabovetitle}
|
|
142
|
+
marginbelowtitle={marginbelowtitle}
|
|
132
143
|
/>
|
|
133
144
|
)
|
|
134
145
|
} else {
|
|
@@ -2,13 +2,16 @@ import { PricingProps } from './index'
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Default configuration for the PricingTable component
|
|
5
|
+
*
|
|
6
|
+
* All margin and padding values are now defined as ResponsiveObject<number> directly
|
|
7
|
+
* in the columnconfig, allowing you to edit each breakpoint value individually.
|
|
5
8
|
*/
|
|
9
|
+
|
|
6
10
|
const defaultConfig: PricingProps = {
|
|
7
11
|
// Configuration for the header grid
|
|
8
12
|
headerGridConfig: {
|
|
9
13
|
gridname: 'pricingtableheader',
|
|
10
14
|
alignment: 'center' as const,
|
|
11
|
-
margintop: 1,
|
|
12
15
|
gridwidth: '100%',
|
|
13
16
|
},
|
|
14
17
|
// Configuration for the table title
|
|
@@ -19,11 +22,27 @@ const defaultConfig: PricingProps = {
|
|
|
19
22
|
column: 1,
|
|
20
23
|
gridname: 'pricingtableheader',
|
|
21
24
|
alignment: 'left' as const,
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
paddingleft: {
|
|
26
|
+
xs: 2,
|
|
27
|
+
sm: 2,
|
|
28
|
+
md: 2,
|
|
29
|
+
ms: 2,
|
|
30
|
+
ml: 2,
|
|
31
|
+
lg: 2,
|
|
32
|
+
xl: 2,
|
|
33
|
+
},
|
|
34
|
+
paddingtop: {
|
|
35
|
+
xs: 1,
|
|
36
|
+
sm: 1,
|
|
37
|
+
md: 1,
|
|
38
|
+
ms: 1,
|
|
39
|
+
ml: 1,
|
|
40
|
+
lg: 1,
|
|
41
|
+
xl: 1,
|
|
42
|
+
},
|
|
24
43
|
mobilewidth: '100%',
|
|
25
44
|
tabletwidth: '100%',
|
|
26
|
-
computerwidth: '
|
|
45
|
+
computerwidth: '50%',
|
|
27
46
|
},
|
|
28
47
|
},
|
|
29
48
|
// Configuration for package columns
|
|
@@ -31,10 +50,46 @@ const defaultConfig: PricingProps = {
|
|
|
31
50
|
packagenames: ['ThothOS', 'ThothOS Pro', 'ThothOS Enterprise'],
|
|
32
51
|
columnconfig: {
|
|
33
52
|
row: 1,
|
|
34
|
-
column:
|
|
53
|
+
column: 1,
|
|
35
54
|
gridname: 'pricingtableheader',
|
|
36
55
|
alignment: 'center' as const,
|
|
37
|
-
|
|
56
|
+
paddingleft: {
|
|
57
|
+
xs: 2,
|
|
58
|
+
sm: 2,
|
|
59
|
+
md: 2,
|
|
60
|
+
ms: 2,
|
|
61
|
+
ml: 2,
|
|
62
|
+
lg: 2,
|
|
63
|
+
xl: 2,
|
|
64
|
+
},
|
|
65
|
+
paddingright: {
|
|
66
|
+
xs: 2,
|
|
67
|
+
sm: 2,
|
|
68
|
+
md: 2,
|
|
69
|
+
ms: 2,
|
|
70
|
+
ml: 2,
|
|
71
|
+
lg: 2,
|
|
72
|
+
xl: 2,
|
|
73
|
+
},
|
|
74
|
+
paddingtop: {
|
|
75
|
+
xs: 2.5,
|
|
76
|
+
sm: 2.5,
|
|
77
|
+
md: 2.5,
|
|
78
|
+
ms: 2.5,
|
|
79
|
+
ml: 2.5,
|
|
80
|
+
lg: 2.5,
|
|
81
|
+
xl: 2.5,
|
|
82
|
+
},
|
|
83
|
+
paddingbottom: {
|
|
84
|
+
xs: 1,
|
|
85
|
+
sm: 2,
|
|
86
|
+
md: 2,
|
|
87
|
+
ms: 2,
|
|
88
|
+
ml: 2,
|
|
89
|
+
lg: 2,
|
|
90
|
+
xl: 2,
|
|
91
|
+
},
|
|
92
|
+
mobilewidth: '100%',
|
|
38
93
|
tabletwidth: '48%',
|
|
39
94
|
computerwidth: '48%',
|
|
40
95
|
},
|
|
@@ -250,10 +305,44 @@ const defaultConfig: PricingProps = {
|
|
|
250
305
|
],
|
|
251
306
|
columnconfig: {
|
|
252
307
|
row: 7,
|
|
253
|
-
column:
|
|
308
|
+
column: 1,
|
|
254
309
|
mobilewidth: '100%',
|
|
255
|
-
|
|
256
|
-
|
|
310
|
+
margintop: {
|
|
311
|
+
xs: 2,
|
|
312
|
+
sm: 2,
|
|
313
|
+
md: 2,
|
|
314
|
+
ms: 2,
|
|
315
|
+
ml: 2,
|
|
316
|
+
lg: 2,
|
|
317
|
+
xl: 2,
|
|
318
|
+
},
|
|
319
|
+
marginbottom: {
|
|
320
|
+
xs: 1,
|
|
321
|
+
sm: 1,
|
|
322
|
+
md: 1,
|
|
323
|
+
ms: 1,
|
|
324
|
+
ml: 1,
|
|
325
|
+
lg: 1,
|
|
326
|
+
xl: 1,
|
|
327
|
+
},
|
|
328
|
+
marginright: {
|
|
329
|
+
xs: 1,
|
|
330
|
+
sm: 1,
|
|
331
|
+
md: 1,
|
|
332
|
+
ms: 1,
|
|
333
|
+
ml: 1,
|
|
334
|
+
lg: 1,
|
|
335
|
+
xl: 1,
|
|
336
|
+
},
|
|
337
|
+
marginleft: {
|
|
338
|
+
xs: 1,
|
|
339
|
+
sm: 1,
|
|
340
|
+
md: 1,
|
|
341
|
+
ms: 1,
|
|
342
|
+
ml: 1,
|
|
343
|
+
lg: 1,
|
|
344
|
+
xl: 1,
|
|
345
|
+
},
|
|
257
346
|
tabletwidth: '100%',
|
|
258
347
|
computerwidth: '48%',
|
|
259
348
|
gridname: 'pricingtablefeatures',
|
|
@@ -129,6 +129,9 @@ const PricingTable: React.FC<PricingProps> = props => {
|
|
|
129
129
|
if (config.packagecolumns && config.packagecolumns.columnconfig) {
|
|
130
130
|
headerColumnConfigs.push({
|
|
131
131
|
...config.packagecolumns.columnconfig,
|
|
132
|
+
// Add 5px margin above (margintop: 0.625) and to the right (marginright: 0.625)
|
|
133
|
+
margintop: 1,
|
|
134
|
+
marginright: 0.625,
|
|
132
135
|
component: (
|
|
133
136
|
<Dropdown
|
|
134
137
|
label="Packages"
|
|
@@ -138,6 +141,7 @@ const PricingTable: React.FC<PricingProps> = props => {
|
|
|
138
141
|
}))}
|
|
139
142
|
defaultValue={selectedPackage}
|
|
140
143
|
backgroundcolor={semiTransparentBlack.main}
|
|
144
|
+
shrunklabelposition="aboveNotch"
|
|
141
145
|
outlinecolor={black.main}
|
|
142
146
|
fontcolor={black.main}
|
|
143
147
|
shrunkfontcolor={black.main}
|
|
@@ -177,6 +181,8 @@ const PricingTable: React.FC<PricingProps> = props => {
|
|
|
177
181
|
if (feature.columnconfig) {
|
|
178
182
|
featureColumnConfigs.push({
|
|
179
183
|
...feature.columnconfig,
|
|
184
|
+
margintop: 1,
|
|
185
|
+
paddingleft: 2,
|
|
180
186
|
component: (
|
|
181
187
|
<Box display="flex" alignItems="center">
|
|
182
188
|
<Typography
|
|
@@ -207,6 +213,7 @@ const PricingTable: React.FC<PricingProps> = props => {
|
|
|
207
213
|
if (feature.tiedtopackage && feature.tiedtopackage.columnconfig) {
|
|
208
214
|
const tiedConfig: columnconfig = {
|
|
209
215
|
...feature.tiedtopackage.columnconfig,
|
|
216
|
+
margintop: 1,
|
|
210
217
|
cellconfig: {
|
|
211
218
|
minHeight: '40px',
|
|
212
219
|
},
|
|
@@ -225,6 +232,8 @@ const PricingTable: React.FC<PricingProps> = props => {
|
|
|
225
232
|
if (subFeature.columnconfig) {
|
|
226
233
|
featureColumnConfigs.push({
|
|
227
234
|
...subFeature.columnconfig,
|
|
235
|
+
margintop: 1,
|
|
236
|
+
paddingleft: 3,
|
|
228
237
|
component: (
|
|
229
238
|
<Box display="flex" alignItems="center">
|
|
230
239
|
<Typography
|
|
@@ -255,6 +264,7 @@ const PricingTable: React.FC<PricingProps> = props => {
|
|
|
255
264
|
if (subFeature.tiedtopackage && subFeature.tiedtopackage.columnconfig) {
|
|
256
265
|
const tiedConfig: columnconfig = {
|
|
257
266
|
...subFeature.tiedtopackage.columnconfig,
|
|
267
|
+
margintop: 1,
|
|
258
268
|
cellconfig: {
|
|
259
269
|
minHeight: '40px',
|
|
260
270
|
},
|
|
@@ -279,6 +289,7 @@ const PricingTable: React.FC<PricingProps> = props => {
|
|
|
279
289
|
|
|
280
290
|
featureColumnConfigs.push({
|
|
281
291
|
...config.buttoncolumns.columnconfig,
|
|
292
|
+
margintop: 1,
|
|
282
293
|
component: (
|
|
283
294
|
<CustomButton
|
|
284
295
|
variant="contained"
|