goobs-frontend 0.122.2 → 0.122.4
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 +24 -24
- package/src/components/Card/index.tsx +16 -44
- package/src/components/DataGrid/MetricCard/index.tsx +9 -3
- package/src/components/DataGrid/Table/CreationRow/index.tsx +19 -0
- package/src/components/DataGrid/types/index.ts +2 -0
- package/src/components/Table/index.tsx +19 -162
- package/src/index.ts +5 -0
- package/src/theme/card.ts +14 -4
- package/src/theme/chip.ts +28 -2
- package/src/theme/index.ts +1 -0
- package/src/theme/table.ts +188 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "goobs-frontend",
|
|
3
|
-
"version": "0.122.
|
|
3
|
+
"version": "0.122.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A comprehensive React-based libary for building modern web applications",
|
|
6
6
|
"license": "MIT",
|
|
@@ -47,35 +47,35 @@
|
|
|
47
47
|
"zod-formik-adapter": "^1"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@babel/core": "^7.28
|
|
51
|
-
"@babel/generator": "^7.28
|
|
52
|
-
"@babel/parser": "^7.28
|
|
53
|
-
"@babel/traverse": "^7.28
|
|
54
|
-
"@babel/types": "^7.28
|
|
55
|
-
"@chromatic-com/storybook": "^4
|
|
50
|
+
"@babel/core": "^7.28",
|
|
51
|
+
"@babel/generator": "^7.28",
|
|
52
|
+
"@babel/parser": "^7.28",
|
|
53
|
+
"@babel/traverse": "^7.28",
|
|
54
|
+
"@babel/types": "^7.28",
|
|
55
|
+
"@chromatic-com/storybook": "^4",
|
|
56
56
|
"@next/eslint-plugin-next": "^15",
|
|
57
57
|
"@storybook/addon-onboarding": "^9",
|
|
58
58
|
"@storybook/nextjs": "^9",
|
|
59
59
|
"@storybook/react": "^9",
|
|
60
60
|
"@storybook/test": "^8",
|
|
61
61
|
"@types/babel__generator": "^7.27.0",
|
|
62
|
-
"@types/babel__traverse": "^7
|
|
63
|
-
"@types/react": "^19.1
|
|
64
|
-
"@types/react-dom": "^19.1
|
|
65
|
-
"@typescript-eslint/eslint-plugin": "^8
|
|
66
|
-
"@typescript-eslint/parser": "^8
|
|
67
|
-
"autoprefixer": "^10
|
|
68
|
-
"chromatic": "^13.1
|
|
69
|
-
"eslint": "^9
|
|
70
|
-
"eslint-config-next": "^15
|
|
71
|
-
"eslint-config-prettier": "^10
|
|
72
|
-
"eslint-plugin-prettier": "^5
|
|
73
|
-
"eslint-plugin-storybook": "^9
|
|
74
|
-
"eslint-plugin-tsc": "^2
|
|
75
|
-
"eslint-plugin-unused-imports": "^4
|
|
76
|
-
"prettier": "^3
|
|
77
|
-
"react": "^19
|
|
78
|
-
"react-dom": "^19
|
|
62
|
+
"@types/babel__traverse": "^7",
|
|
63
|
+
"@types/react": "^19.1",
|
|
64
|
+
"@types/react-dom": "^19.1",
|
|
65
|
+
"@typescript-eslint/eslint-plugin": "^8",
|
|
66
|
+
"@typescript-eslint/parser": "^8",
|
|
67
|
+
"autoprefixer": "^10",
|
|
68
|
+
"chromatic": "^13.1",
|
|
69
|
+
"eslint": "^9",
|
|
70
|
+
"eslint-config-next": "^15",
|
|
71
|
+
"eslint-config-prettier": "^10",
|
|
72
|
+
"eslint-plugin-prettier": "^5",
|
|
73
|
+
"eslint-plugin-storybook": "^9",
|
|
74
|
+
"eslint-plugin-tsc": "^2",
|
|
75
|
+
"eslint-plugin-unused-imports": "^4",
|
|
76
|
+
"prettier": "^3",
|
|
77
|
+
"react": "^19",
|
|
78
|
+
"react-dom": "^19",
|
|
79
79
|
"typescript": "^5"
|
|
80
80
|
},
|
|
81
81
|
"files": [
|
|
@@ -6,34 +6,12 @@
|
|
|
6
6
|
import React, { forwardRef, useState, useMemo } from 'react'
|
|
7
7
|
import { getCardStyles } from '../../theme/card'
|
|
8
8
|
import type { CardStyles } from '../../theme/card'
|
|
9
|
+
import { SACRED_GLYPHS, injectKeyframes } from '../../theme/shared'
|
|
9
10
|
|
|
10
11
|
// --------------------------------------------------------------------------
|
|
11
|
-
// SACRED GLYPHS CONSTANTS
|
|
12
|
+
// SACRED GLYPHS CONSTANTS (from shared)
|
|
12
13
|
// --------------------------------------------------------------------------
|
|
13
14
|
|
|
14
|
-
const SACRED_GLYPHS: string[] = [
|
|
15
|
-
'⧈',
|
|
16
|
-
'◊',
|
|
17
|
-
'✦',
|
|
18
|
-
'⟡',
|
|
19
|
-
'◈',
|
|
20
|
-
'⬟',
|
|
21
|
-
'◉',
|
|
22
|
-
'⬢',
|
|
23
|
-
'⟐',
|
|
24
|
-
'◆',
|
|
25
|
-
'⬝',
|
|
26
|
-
'⟢',
|
|
27
|
-
'◇',
|
|
28
|
-
'⬡',
|
|
29
|
-
'⬛',
|
|
30
|
-
'⟁',
|
|
31
|
-
'◊',
|
|
32
|
-
'⬜',
|
|
33
|
-
'⟐',
|
|
34
|
-
'◈',
|
|
35
|
-
]
|
|
36
|
-
|
|
37
15
|
// --------------------------------------------------------------------------
|
|
38
16
|
// CARD PROPS
|
|
39
17
|
// --------------------------------------------------------------------------
|
|
@@ -126,7 +104,7 @@ const SacredBackground: React.FC<{
|
|
|
126
104
|
height: '100%',
|
|
127
105
|
background:
|
|
128
106
|
'linear-gradient(90deg, transparent, rgba(255, 215, 0, 0.1), transparent)',
|
|
129
|
-
animation: '
|
|
107
|
+
animation: 'sacredShimmer 1.5s ease-in-out',
|
|
130
108
|
zIndex: 1,
|
|
131
109
|
}}
|
|
132
110
|
/>
|
|
@@ -175,7 +153,7 @@ const SacredBackgroundGlyphs: React.FC<{ isHovered: boolean }> = ({
|
|
|
175
153
|
transform: `rotate(${randoms[index]?.rotation ?? 0}deg)`,
|
|
176
154
|
userSelect: 'none',
|
|
177
155
|
transition: 'opacity 0.3s ease',
|
|
178
|
-
animation: `
|
|
156
|
+
animation: `sacredGlyphRotate ${randoms[index]?.duration ?? 60}s linear infinite`,
|
|
179
157
|
}}
|
|
180
158
|
>
|
|
181
159
|
{glyph}
|
|
@@ -195,6 +173,10 @@ export const Card = forwardRef<HTMLDivElement, CardProps>(
|
|
|
195
173
|
const isDisabled = styles?.disabled
|
|
196
174
|
const isSacredTheme = styles?.theme === 'sacred'
|
|
197
175
|
|
|
176
|
+
React.useEffect(() => {
|
|
177
|
+
injectKeyframes()
|
|
178
|
+
}, [])
|
|
179
|
+
|
|
198
180
|
const computedStyles = useMemo(
|
|
199
181
|
() => getCardStyles(styles, isHovered, isDisabled, elevation),
|
|
200
182
|
[styles, isHovered, isDisabled, elevation]
|
|
@@ -294,6 +276,13 @@ export const CardHeader = forwardRef<HTMLDivElement, CardHeaderProps>(
|
|
|
294
276
|
ref
|
|
295
277
|
) => {
|
|
296
278
|
const computedStyles = useMemo(() => getCardStyles(styles), [styles])
|
|
279
|
+
const themeName = styles?.theme || 'light'
|
|
280
|
+
const subtitleColor =
|
|
281
|
+
themeName === 'sacred'
|
|
282
|
+
? 'rgba(255, 215, 0, 0.75)'
|
|
283
|
+
: themeName === 'dark'
|
|
284
|
+
? 'rgba(248, 250, 252, 0.7)'
|
|
285
|
+
: 'rgba(0, 0, 0, 0.6)'
|
|
297
286
|
|
|
298
287
|
return (
|
|
299
288
|
<div
|
|
@@ -320,7 +309,7 @@ export const CardHeader = forwardRef<HTMLDivElement, CardHeaderProps>(
|
|
|
320
309
|
<div
|
|
321
310
|
style={{
|
|
322
311
|
fontSize: '0.875rem',
|
|
323
|
-
color:
|
|
312
|
+
color: subtitleColor,
|
|
324
313
|
lineHeight: 1.43,
|
|
325
314
|
}}
|
|
326
315
|
>
|
|
@@ -340,20 +329,3 @@ export const CardHeader = forwardRef<HTMLDivElement, CardHeaderProps>(
|
|
|
340
329
|
CardHeader.displayName = 'CardHeader'
|
|
341
330
|
|
|
342
331
|
export default Card
|
|
343
|
-
|
|
344
|
-
// Add keyframes for animations if needed
|
|
345
|
-
if (typeof document !== 'undefined') {
|
|
346
|
-
const styleSheet = document.createElement('style')
|
|
347
|
-
styleSheet.textContent = `
|
|
348
|
-
@keyframes rotateGlyph {
|
|
349
|
-
0% { transform: rotate(0deg); }
|
|
350
|
-
100% { transform: rotate(360deg); }
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
@keyframes shimmer {
|
|
354
|
-
0% { left: -100%; }
|
|
355
|
-
100% { left: 100%; }
|
|
356
|
-
}
|
|
357
|
-
`
|
|
358
|
-
document.head.appendChild(styleSheet)
|
|
359
|
-
}
|
|
@@ -211,7 +211,9 @@ export default function MetricCard({
|
|
|
211
211
|
const standardCardStyle: React.CSSProperties = {
|
|
212
212
|
height: '100%',
|
|
213
213
|
background: 'linear-gradient(135deg, #ffffff 0%, #f8fafc 100%)',
|
|
214
|
-
|
|
214
|
+
borderWidth: '2px',
|
|
215
|
+
borderStyle: 'solid',
|
|
216
|
+
borderColor: rgbaColor(0.2),
|
|
215
217
|
borderRadius: '12px',
|
|
216
218
|
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
|
|
217
219
|
cursor: 'pointer',
|
|
@@ -318,7 +320,9 @@ export default function MetricCard({
|
|
|
318
320
|
const sacredCardStyle: React.CSSProperties = {
|
|
319
321
|
height: '100%',
|
|
320
322
|
background: `linear-gradient(135deg, ${egyptianStyles.cardBackground} 0%, rgba(22, 33, 62, 0.95) 100%)`,
|
|
321
|
-
|
|
323
|
+
borderWidth: '2px',
|
|
324
|
+
borderStyle: 'solid',
|
|
325
|
+
borderColor: rgbaColor(0.5),
|
|
322
326
|
borderRadius: '12px',
|
|
323
327
|
position: 'relative',
|
|
324
328
|
overflow: 'hidden',
|
|
@@ -418,7 +422,9 @@ export default function MetricCard({
|
|
|
418
422
|
padding: '8px',
|
|
419
423
|
borderRadius: '8px',
|
|
420
424
|
backgroundColor: rgbaColor(0.15),
|
|
421
|
-
|
|
425
|
+
borderWidth: '1px',
|
|
426
|
+
borderStyle: 'solid',
|
|
427
|
+
borderColor: rgbaColor(0.3),
|
|
422
428
|
boxShadow: `0 0 10px ${rgbaColor(0.2)}`,
|
|
423
429
|
display: 'flex',
|
|
424
430
|
alignItems: 'center',
|
|
@@ -24,6 +24,7 @@ import VLANField from '../../../Field/IPAM/VLAN'
|
|
|
24
24
|
import CIDRField from '../../../Field/IPAM/CIDR'
|
|
25
25
|
import SupernetField from '../../../Field/IPAM/Supernet'
|
|
26
26
|
import MACAddressField from '../../../Field/IPAM/MACAddress'
|
|
27
|
+
import USDField from '../../../Field/USD'
|
|
27
28
|
|
|
28
29
|
interface CreationRowProps {
|
|
29
30
|
columns: ColumnDef[]
|
|
@@ -71,6 +72,24 @@ const CreationRow: React.FC<CreationRowProps> = ({
|
|
|
71
72
|
}
|
|
72
73
|
|
|
73
74
|
switch (fieldConfig.type) {
|
|
75
|
+
case 'currency':
|
|
76
|
+
case 'usd': {
|
|
77
|
+
return (
|
|
78
|
+
<USDField
|
|
79
|
+
initialValue={String(value ?? '')}
|
|
80
|
+
onChange={(newValue: string) =>
|
|
81
|
+
onCreationFieldChange?.(column.field, newValue)
|
|
82
|
+
}
|
|
83
|
+
{...(fieldConfig.placeholder
|
|
84
|
+
? { placeholder: fieldConfig.placeholder }
|
|
85
|
+
: {})}
|
|
86
|
+
{...(fieldConfig.helperText
|
|
87
|
+
? { helperText: fieldConfig.helperText }
|
|
88
|
+
: {})}
|
|
89
|
+
styles={fieldStyles}
|
|
90
|
+
/>
|
|
91
|
+
)
|
|
92
|
+
}
|
|
74
93
|
case 'text':
|
|
75
94
|
return (
|
|
76
95
|
<TextField
|
|
@@ -1,27 +1,10 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
3
|
import React from 'react'
|
|
4
|
+
import { getTableStyles } from '../../theme'
|
|
5
|
+
import type { TableStyles as ThemeTableStyles } from '../../theme'
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
const alpha = (color: string, opacity: number): string => {
|
|
7
|
-
if (color.startsWith('#')) {
|
|
8
|
-
const hex = color.slice(1)
|
|
9
|
-
const r = parseInt(hex.slice(0, 2), 16)
|
|
10
|
-
const g = parseInt(hex.slice(2, 4), 16)
|
|
11
|
-
const b = parseInt(hex.slice(4, 6), 16)
|
|
12
|
-
return `rgba(${r}, ${g}, ${b}, ${opacity})`
|
|
13
|
-
}
|
|
14
|
-
return color
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface TableStyles {
|
|
18
|
-
theme?: 'sacred' | 'light' | 'dark'
|
|
19
|
-
backgroundColor?: string
|
|
20
|
-
borderColor?: string
|
|
21
|
-
width?: string
|
|
22
|
-
maxWidth?: string
|
|
23
|
-
borderRadius?: string
|
|
24
|
-
}
|
|
7
|
+
export type TableStyles = ThemeTableStyles
|
|
25
8
|
|
|
26
9
|
export interface SimpleTableProps {
|
|
27
10
|
children: React.ReactNode
|
|
@@ -31,7 +14,6 @@ export interface SimpleTableProps {
|
|
|
31
14
|
export interface TableContainerProps {
|
|
32
15
|
children: React.ReactNode
|
|
33
16
|
styles?: TableStyles
|
|
34
|
-
sx?: React.CSSProperties
|
|
35
17
|
}
|
|
36
18
|
|
|
37
19
|
export interface TableHeadProps {
|
|
@@ -56,146 +38,28 @@ export interface TableCellProps {
|
|
|
56
38
|
styles?: TableStyles
|
|
57
39
|
}
|
|
58
40
|
|
|
59
|
-
const getTableTheme = (styles?: TableStyles) => {
|
|
60
|
-
const theme = styles?.theme || 'light'
|
|
61
|
-
const goldColor = '#FFD700'
|
|
62
|
-
|
|
63
|
-
switch (theme) {
|
|
64
|
-
case 'sacred':
|
|
65
|
-
return {
|
|
66
|
-
container: {
|
|
67
|
-
backgroundColor: alpha('#000000', 0.8),
|
|
68
|
-
borderColor: alpha(goldColor, 0.3),
|
|
69
|
-
borderRadius: '8px',
|
|
70
|
-
},
|
|
71
|
-
table: {
|
|
72
|
-
backgroundColor: 'transparent',
|
|
73
|
-
},
|
|
74
|
-
header: {
|
|
75
|
-
backgroundColor: alpha(goldColor, 0.1),
|
|
76
|
-
borderColor: alpha(goldColor, 0.3),
|
|
77
|
-
color: goldColor,
|
|
78
|
-
fontFamily: '"Cinzel", serif',
|
|
79
|
-
fontWeight: 700,
|
|
80
|
-
textTransform: 'uppercase' as const,
|
|
81
|
-
letterSpacing: '0.05em',
|
|
82
|
-
},
|
|
83
|
-
cell: {
|
|
84
|
-
borderColor: alpha(goldColor, 0.2),
|
|
85
|
-
color: alpha(goldColor, 0.9),
|
|
86
|
-
fontFamily: '"Merriweather", serif',
|
|
87
|
-
},
|
|
88
|
-
row: {
|
|
89
|
-
'&:hover': {
|
|
90
|
-
backgroundColor: alpha(goldColor, 0.05),
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
}
|
|
94
|
-
case 'dark':
|
|
95
|
-
return {
|
|
96
|
-
container: {
|
|
97
|
-
backgroundColor: '#1a1a1a',
|
|
98
|
-
borderColor: '#333333',
|
|
99
|
-
borderRadius: '4px',
|
|
100
|
-
},
|
|
101
|
-
table: {
|
|
102
|
-
backgroundColor: 'transparent',
|
|
103
|
-
},
|
|
104
|
-
header: {
|
|
105
|
-
backgroundColor: '#2a2a2a',
|
|
106
|
-
borderColor: '#444444',
|
|
107
|
-
color: '#ffffff',
|
|
108
|
-
fontWeight: 600,
|
|
109
|
-
},
|
|
110
|
-
cell: {
|
|
111
|
-
borderColor: '#333333',
|
|
112
|
-
color: '#ffffff',
|
|
113
|
-
},
|
|
114
|
-
row: {
|
|
115
|
-
'&:hover': {
|
|
116
|
-
backgroundColor: alpha('#ffffff', 0.05),
|
|
117
|
-
},
|
|
118
|
-
},
|
|
119
|
-
}
|
|
120
|
-
default: // light
|
|
121
|
-
return {
|
|
122
|
-
container: {
|
|
123
|
-
backgroundColor: '#ffffff',
|
|
124
|
-
borderColor: '#e0e0e0',
|
|
125
|
-
borderRadius: '4px',
|
|
126
|
-
},
|
|
127
|
-
table: {
|
|
128
|
-
backgroundColor: 'transparent',
|
|
129
|
-
},
|
|
130
|
-
header: {
|
|
131
|
-
backgroundColor: '#f5f5f5',
|
|
132
|
-
borderColor: '#e0e0e0',
|
|
133
|
-
color: '#333333',
|
|
134
|
-
fontWeight: 600,
|
|
135
|
-
},
|
|
136
|
-
cell: {
|
|
137
|
-
borderColor: '#e0e0e0',
|
|
138
|
-
color: '#333333',
|
|
139
|
-
},
|
|
140
|
-
row: {
|
|
141
|
-
'&:hover': {
|
|
142
|
-
backgroundColor: alpha('#000000', 0.05),
|
|
143
|
-
},
|
|
144
|
-
},
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
41
|
export const TableContainer: React.FC<TableContainerProps> = ({
|
|
150
42
|
children,
|
|
151
43
|
styles,
|
|
152
|
-
sx,
|
|
153
44
|
}) => {
|
|
154
|
-
const themeConfig =
|
|
155
|
-
|
|
156
|
-
const containerStyle: React.CSSProperties = {
|
|
157
|
-
...themeConfig.container,
|
|
158
|
-
border: `1px solid ${themeConfig.container.borderColor}`,
|
|
159
|
-
overflowX: 'auto',
|
|
160
|
-
width: styles?.width || '100%',
|
|
161
|
-
maxWidth: styles?.maxWidth || '100%',
|
|
162
|
-
...sx,
|
|
163
|
-
}
|
|
45
|
+
const themeConfig = getTableStyles(styles)
|
|
164
46
|
|
|
165
|
-
return <div style={
|
|
47
|
+
return <div style={themeConfig.container}>{children}</div>
|
|
166
48
|
}
|
|
167
49
|
|
|
168
50
|
export const Table: React.FC<SimpleTableProps> = ({ children, styles }) => {
|
|
169
|
-
const themeConfig =
|
|
170
|
-
|
|
171
|
-
const tableStyle: React.CSSProperties = {
|
|
172
|
-
...themeConfig.table,
|
|
173
|
-
width: '100%',
|
|
174
|
-
borderCollapse: 'collapse',
|
|
175
|
-
tableLayout: 'auto',
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
return <table style={tableStyle}>{children}</table>
|
|
51
|
+
const themeConfig = getTableStyles(styles)
|
|
52
|
+
return <table style={themeConfig.table}>{children}</table>
|
|
179
53
|
}
|
|
180
54
|
|
|
181
55
|
export const TableHead: React.FC<TableHeadProps> = ({ children, styles }) => {
|
|
182
|
-
const themeConfig =
|
|
183
|
-
|
|
184
|
-
const headStyle: React.CSSProperties = {
|
|
185
|
-
...themeConfig.header,
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return <thead style={headStyle}>{children}</thead>
|
|
56
|
+
const themeConfig = getTableStyles(styles)
|
|
57
|
+
return <thead style={themeConfig.header}>{children}</thead>
|
|
189
58
|
}
|
|
190
59
|
|
|
191
60
|
export const TableBody: React.FC<TableBodyProps> = ({ children, styles }) => {
|
|
192
|
-
const themeConfig =
|
|
193
|
-
|
|
194
|
-
const bodyStyle: React.CSSProperties = {
|
|
195
|
-
...themeConfig.table,
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
return <tbody style={bodyStyle}>{children}</tbody>
|
|
61
|
+
const themeConfig = getTableStyles(styles)
|
|
62
|
+
return <tbody style={themeConfig.table}>{children}</tbody>
|
|
199
63
|
}
|
|
200
64
|
|
|
201
65
|
export const TableRow: React.FC<TableRowProps> = ({
|
|
@@ -203,19 +67,15 @@ export const TableRow: React.FC<TableRowProps> = ({
|
|
|
203
67
|
hover = false,
|
|
204
68
|
styles,
|
|
205
69
|
}) => {
|
|
70
|
+
const themeConfig = getTableStyles(styles)
|
|
206
71
|
const rowStyle: React.CSSProperties = {
|
|
207
|
-
...
|
|
208
|
-
transition: 'background-color 0.2s ease',
|
|
209
|
-
}),
|
|
72
|
+
...themeConfig.row,
|
|
210
73
|
}
|
|
211
74
|
|
|
212
75
|
const handleMouseEnter = (e: React.MouseEvent<HTMLTableRowElement>) => {
|
|
213
|
-
if (hover
|
|
214
|
-
e.currentTarget.style.backgroundColor =
|
|
215
|
-
|
|
216
|
-
e.currentTarget.style.backgroundColor = alpha('#ffffff', 0.05)
|
|
217
|
-
} else if (hover) {
|
|
218
|
-
e.currentTarget.style.backgroundColor = alpha('#000000', 0.05)
|
|
76
|
+
if (hover) {
|
|
77
|
+
e.currentTarget.style.backgroundColor =
|
|
78
|
+
themeConfig.rowHoverBackgroundColor
|
|
219
79
|
}
|
|
220
80
|
}
|
|
221
81
|
|
|
@@ -241,18 +101,15 @@ export const TableCell: React.FC<TableCellProps> = ({
|
|
|
241
101
|
align = 'left',
|
|
242
102
|
styles,
|
|
243
103
|
}) => {
|
|
244
|
-
const themeConfig =
|
|
104
|
+
const themeConfig = getTableStyles(styles)
|
|
245
105
|
const isHeader =
|
|
246
106
|
React.isValidElement(children) &&
|
|
247
107
|
(children as React.ReactElement).type === 'th'
|
|
248
108
|
|
|
249
109
|
const cellStyle: React.CSSProperties = {
|
|
250
|
-
|
|
110
|
+
...themeConfig.cell,
|
|
251
111
|
textAlign: align,
|
|
252
|
-
borderBottom: `1px solid ${themeConfig.cell.borderColor}`,
|
|
253
|
-
color: themeConfig.cell.color,
|
|
254
|
-
fontFamily: themeConfig.cell.fontFamily,
|
|
255
|
-
verticalAlign: 'middle',
|
|
112
|
+
borderBottom: `1px solid ${themeConfig.cell.borderColor || 'transparent'}`,
|
|
256
113
|
...(isHeader && themeConfig.header),
|
|
257
114
|
}
|
|
258
115
|
|
package/src/index.ts
CHANGED
|
@@ -191,6 +191,10 @@ import type {
|
|
|
191
191
|
MetricCardData,
|
|
192
192
|
} from './components/DataGrid/types'
|
|
193
193
|
|
|
194
|
+
// DataGrid components
|
|
195
|
+
import MetricCard from './components/DataGrid/MetricCard'
|
|
196
|
+
import MetricSection from './components/DataGrid/MetricSection'
|
|
197
|
+
|
|
194
198
|
// Colors
|
|
195
199
|
import {
|
|
196
200
|
moss,
|
|
@@ -360,6 +364,7 @@ export { Fade }
|
|
|
360
364
|
export { Slide }
|
|
361
365
|
export { Zoom }
|
|
362
366
|
export { BigCalendar }
|
|
367
|
+
export { MetricCard, MetricSection }
|
|
363
368
|
|
|
364
369
|
// Export utilities
|
|
365
370
|
export { alpha, keyframes, css, commonKeyframes }
|
package/src/theme/card.ts
CHANGED
|
@@ -11,7 +11,9 @@ import { TRANSITIONS, SHADOWS } from './shared'
|
|
|
11
11
|
export interface CardTheme {
|
|
12
12
|
container: {
|
|
13
13
|
background: string
|
|
14
|
-
|
|
14
|
+
borderWidth?: string
|
|
15
|
+
borderStyle?: React.CSSProperties['borderStyle']
|
|
16
|
+
borderColor?: string
|
|
15
17
|
borderRadius: string
|
|
16
18
|
boxShadow: string
|
|
17
19
|
backdropFilter: string
|
|
@@ -86,6 +88,7 @@ export interface CardStyles {
|
|
|
86
88
|
borderColor?: string
|
|
87
89
|
borderRadius?: string
|
|
88
90
|
borderWidth?: string
|
|
91
|
+
borderStyle?: React.CSSProperties['borderStyle']
|
|
89
92
|
boxShadow?: string
|
|
90
93
|
backdropFilter?: string
|
|
91
94
|
backgroundImage?: string
|
|
@@ -136,7 +139,9 @@ export interface CardStyles {
|
|
|
136
139
|
const lightTheme: CardTheme = {
|
|
137
140
|
container: {
|
|
138
141
|
background: 'rgba(255, 255, 255, 0.95)',
|
|
139
|
-
|
|
142
|
+
borderWidth: '1px',
|
|
143
|
+
borderStyle: 'solid',
|
|
144
|
+
borderColor: 'rgba(226, 232, 240, 0.6)',
|
|
140
145
|
borderRadius: '8px',
|
|
141
146
|
boxShadow: SHADOWS.light.small,
|
|
142
147
|
backdropFilter: 'blur(8px)',
|
|
@@ -175,7 +180,9 @@ const lightTheme: CardTheme = {
|
|
|
175
180
|
const darkTheme: CardTheme = {
|
|
176
181
|
container: {
|
|
177
182
|
background: 'rgba(30, 41, 59, 0.95)',
|
|
178
|
-
|
|
183
|
+
borderWidth: '1px',
|
|
184
|
+
borderStyle: 'solid',
|
|
185
|
+
borderColor: 'rgba(71, 85, 105, 0.6)',
|
|
179
186
|
borderRadius: '8px',
|
|
180
187
|
boxShadow: SHADOWS.dark.small,
|
|
181
188
|
backdropFilter: 'blur(12px)',
|
|
@@ -219,7 +226,9 @@ const sacredTheme: CardTheme = {
|
|
|
219
226
|
rgba(26, 26, 26, 0.97) 50%,
|
|
220
227
|
rgba(10, 10, 10, 0.95) 100%
|
|
221
228
|
)`,
|
|
222
|
-
|
|
229
|
+
borderWidth: '2px',
|
|
230
|
+
borderStyle: 'solid',
|
|
231
|
+
borderColor: 'rgba(255, 215, 0, 0.4)',
|
|
223
232
|
borderRadius: '12px',
|
|
224
233
|
boxShadow: `${SHADOWS.sacred.small}, 0 8px 32px rgba(0, 0, 0, 0.3)`,
|
|
225
234
|
backdropFilter: 'blur(16px)',
|
|
@@ -337,6 +346,7 @@ export const getCardStyles = (
|
|
|
337
346
|
boxShadow,
|
|
338
347
|
...(styles?.backgroundColor && { backgroundColor: styles.backgroundColor }),
|
|
339
348
|
...(styles?.borderColor && { borderColor: styles.borderColor }),
|
|
349
|
+
...(styles?.borderWidth && { borderWidth: styles.borderWidth }),
|
|
340
350
|
...(styles?.borderRadius && { borderRadius: styles.borderRadius }),
|
|
341
351
|
...(styles?.boxShadow && { boxShadow: styles.boxShadow }),
|
|
342
352
|
...(styles?.color && { color: styles.color }),
|
package/src/theme/chip.ts
CHANGED
|
@@ -594,6 +594,27 @@ export const getChipStyles = (
|
|
|
594
594
|
) => {
|
|
595
595
|
const themeConfig = getChipTheme(styles)
|
|
596
596
|
|
|
597
|
+
const parseBorder = (border: string) => {
|
|
598
|
+
if (!border) {
|
|
599
|
+
return {
|
|
600
|
+
width: undefined as string | undefined,
|
|
601
|
+
style: undefined as string | undefined,
|
|
602
|
+
color: undefined as string | undefined,
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
const parts = border.trim().split(' ')
|
|
606
|
+
const width = parts[0]
|
|
607
|
+
const style = parts[1]
|
|
608
|
+
const color = parts.slice(2).join(' ')
|
|
609
|
+
return { width, style, color }
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
const {
|
|
613
|
+
width: baseBorderWidth,
|
|
614
|
+
style: baseBorderStyle,
|
|
615
|
+
color: baseBorderColor,
|
|
616
|
+
} = parseBorder(themeConfig.container.border)
|
|
617
|
+
|
|
597
618
|
const containerStyle: React.CSSProperties = {
|
|
598
619
|
display: 'flex',
|
|
599
620
|
alignItems: 'center',
|
|
@@ -601,7 +622,12 @@ export const getChipStyles = (
|
|
|
601
622
|
overflow: styles?.whiteSpace === 'normal' ? 'visible' : 'hidden',
|
|
602
623
|
transition: themeConfig.transition,
|
|
603
624
|
borderRadius: themeConfig.container.borderRadius,
|
|
604
|
-
|
|
625
|
+
borderWidth:
|
|
626
|
+
baseBorderStyle === 'none'
|
|
627
|
+
? 0
|
|
628
|
+
: (baseBorderWidth as unknown as number | string),
|
|
629
|
+
borderStyle: baseBorderStyle as any,
|
|
630
|
+
borderColor: baseBorderColor,
|
|
605
631
|
backgroundColor: themeConfig.container.background,
|
|
606
632
|
backdropFilter: themeConfig.container.backdropFilter,
|
|
607
633
|
boxShadow: themeConfig.container.boxShadow,
|
|
@@ -644,7 +670,7 @@ export const getChipStyles = (
|
|
|
644
670
|
}),
|
|
645
671
|
// Apply outline override
|
|
646
672
|
...(styles?.outline === false && {
|
|
647
|
-
|
|
673
|
+
borderWidth: 0,
|
|
648
674
|
boxShadow: 'none',
|
|
649
675
|
}),
|
|
650
676
|
}
|
package/src/theme/index.ts
CHANGED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
// --------------------------------------------------------------------------
|
|
2
|
+
// TABLE THEME SYSTEM
|
|
3
|
+
// --------------------------------------------------------------------------
|
|
4
|
+
import React from 'react'
|
|
5
|
+
import { alpha } from '../utils/alpha'
|
|
6
|
+
|
|
7
|
+
export interface TableTheme {
|
|
8
|
+
container: React.CSSProperties
|
|
9
|
+
table: React.CSSProperties
|
|
10
|
+
header: React.CSSProperties
|
|
11
|
+
cell: React.CSSProperties
|
|
12
|
+
row: React.CSSProperties
|
|
13
|
+
rowHoverBackgroundColor: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface TableStyles {
|
|
17
|
+
theme?: 'sacred' | 'light' | 'dark'
|
|
18
|
+
backgroundColor?: string
|
|
19
|
+
borderColor?: string
|
|
20
|
+
borderRadius?: string
|
|
21
|
+
width?: string
|
|
22
|
+
maxWidth?: string
|
|
23
|
+
color?: string
|
|
24
|
+
headerBackgroundColor?: string
|
|
25
|
+
headerColor?: string
|
|
26
|
+
fontFamily?: string
|
|
27
|
+
cellBorderColor?: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const goldColor = '#FFD700'
|
|
31
|
+
|
|
32
|
+
const lightTheme: TableTheme = {
|
|
33
|
+
container: {
|
|
34
|
+
backgroundColor: '#ffffff',
|
|
35
|
+
borderColor: '#e0e0e0',
|
|
36
|
+
borderRadius: '4px',
|
|
37
|
+
borderStyle: 'solid',
|
|
38
|
+
borderWidth: '1px',
|
|
39
|
+
overflowX: 'auto',
|
|
40
|
+
width: '100%',
|
|
41
|
+
maxWidth: '100%',
|
|
42
|
+
},
|
|
43
|
+
table: {
|
|
44
|
+
backgroundColor: 'transparent',
|
|
45
|
+
width: '100%',
|
|
46
|
+
borderCollapse: 'collapse',
|
|
47
|
+
tableLayout: 'auto',
|
|
48
|
+
},
|
|
49
|
+
header: {
|
|
50
|
+
backgroundColor: '#f5f5f5',
|
|
51
|
+
borderBottom: '1px solid #e0e0e0',
|
|
52
|
+
color: '#333333',
|
|
53
|
+
fontWeight: 600,
|
|
54
|
+
},
|
|
55
|
+
cell: {
|
|
56
|
+
borderColor: '#e0e0e0',
|
|
57
|
+
color: '#333333',
|
|
58
|
+
padding: '12px 16px',
|
|
59
|
+
verticalAlign: 'middle',
|
|
60
|
+
},
|
|
61
|
+
row: {
|
|
62
|
+
transition: 'background-color 0.2s ease',
|
|
63
|
+
},
|
|
64
|
+
rowHoverBackgroundColor: alpha('#000000', 0.05),
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const darkTheme: TableTheme = {
|
|
68
|
+
container: {
|
|
69
|
+
backgroundColor: '#1a1a1a',
|
|
70
|
+
borderColor: '#333333',
|
|
71
|
+
borderRadius: '4px',
|
|
72
|
+
borderStyle: 'solid',
|
|
73
|
+
borderWidth: '1px',
|
|
74
|
+
overflowX: 'auto',
|
|
75
|
+
width: '100%',
|
|
76
|
+
maxWidth: '100%',
|
|
77
|
+
},
|
|
78
|
+
table: {
|
|
79
|
+
backgroundColor: 'transparent',
|
|
80
|
+
width: '100%',
|
|
81
|
+
borderCollapse: 'collapse',
|
|
82
|
+
tableLayout: 'auto',
|
|
83
|
+
},
|
|
84
|
+
header: {
|
|
85
|
+
backgroundColor: '#2a2a2a',
|
|
86
|
+
borderBottom: '1px solid #444444',
|
|
87
|
+
color: '#ffffff',
|
|
88
|
+
fontWeight: 600,
|
|
89
|
+
},
|
|
90
|
+
cell: {
|
|
91
|
+
borderColor: '#333333',
|
|
92
|
+
color: '#ffffff',
|
|
93
|
+
padding: '12px 16px',
|
|
94
|
+
verticalAlign: 'middle',
|
|
95
|
+
},
|
|
96
|
+
row: {
|
|
97
|
+
transition: 'background-color 0.2s ease',
|
|
98
|
+
},
|
|
99
|
+
rowHoverBackgroundColor: alpha('#ffffff', 0.05),
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const sacredTheme: TableTheme = {
|
|
103
|
+
container: {
|
|
104
|
+
backgroundColor: alpha('#000000', 0.8),
|
|
105
|
+
borderColor: alpha(goldColor, 0.3),
|
|
106
|
+
borderRadius: '8px',
|
|
107
|
+
borderStyle: 'solid',
|
|
108
|
+
borderWidth: '1px',
|
|
109
|
+
overflowX: 'auto',
|
|
110
|
+
width: '100%',
|
|
111
|
+
maxWidth: '100%',
|
|
112
|
+
},
|
|
113
|
+
table: {
|
|
114
|
+
backgroundColor: 'transparent',
|
|
115
|
+
width: '100%',
|
|
116
|
+
borderCollapse: 'collapse',
|
|
117
|
+
tableLayout: 'auto',
|
|
118
|
+
},
|
|
119
|
+
header: {
|
|
120
|
+
backgroundColor: alpha(goldColor, 0.1),
|
|
121
|
+
borderBottom: `1px solid ${alpha(goldColor, 0.3)}`,
|
|
122
|
+
color: goldColor,
|
|
123
|
+
fontFamily: '"Cinzel", serif',
|
|
124
|
+
fontWeight: 700,
|
|
125
|
+
textTransform: 'uppercase',
|
|
126
|
+
letterSpacing: '0.05em',
|
|
127
|
+
},
|
|
128
|
+
cell: {
|
|
129
|
+
borderColor: alpha(goldColor, 0.2),
|
|
130
|
+
color: alpha(goldColor, 0.9),
|
|
131
|
+
fontFamily: '"Merriweather", serif',
|
|
132
|
+
padding: '12px 16px',
|
|
133
|
+
verticalAlign: 'middle',
|
|
134
|
+
},
|
|
135
|
+
row: {
|
|
136
|
+
transition: 'background-color 0.2s ease',
|
|
137
|
+
},
|
|
138
|
+
rowHoverBackgroundColor: alpha(goldColor, 0.05),
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export const tableThemes: Record<'light' | 'dark' | 'sacred', TableTheme> = {
|
|
142
|
+
light: lightTheme,
|
|
143
|
+
dark: darkTheme,
|
|
144
|
+
sacred: sacredTheme,
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export const getTableTheme = (styles?: TableStyles): TableTheme => {
|
|
148
|
+
const theme: 'light' | 'dark' | 'sacred' = styles?.theme || 'light'
|
|
149
|
+
const base = tableThemes[theme]
|
|
150
|
+
|
|
151
|
+
const container: React.CSSProperties = {
|
|
152
|
+
...base.container,
|
|
153
|
+
...(styles?.backgroundColor && { backgroundColor: styles.backgroundColor }),
|
|
154
|
+
...(styles?.borderColor && { borderColor: styles.borderColor }),
|
|
155
|
+
...(styles?.borderRadius && { borderRadius: styles.borderRadius }),
|
|
156
|
+
...(styles?.width && { width: styles.width }),
|
|
157
|
+
...(styles?.maxWidth && { maxWidth: styles.maxWidth }),
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const header: React.CSSProperties = {
|
|
161
|
+
...base.header,
|
|
162
|
+
...(styles?.headerBackgroundColor && {
|
|
163
|
+
backgroundColor: styles.headerBackgroundColor,
|
|
164
|
+
}),
|
|
165
|
+
...(styles?.headerColor && { color: styles.headerColor }),
|
|
166
|
+
...(styles?.fontFamily && { fontFamily: styles.fontFamily }),
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const cell: React.CSSProperties = {
|
|
170
|
+
...base.cell,
|
|
171
|
+
...(styles?.color && { color: styles.color }),
|
|
172
|
+
...(styles?.fontFamily && { fontFamily: styles.fontFamily }),
|
|
173
|
+
...(styles?.cellBorderColor && { borderColor: styles.cellBorderColor }),
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return {
|
|
177
|
+
container,
|
|
178
|
+
table: base.table,
|
|
179
|
+
header,
|
|
180
|
+
cell,
|
|
181
|
+
row: base.row,
|
|
182
|
+
rowHoverBackgroundColor: base.rowHoverBackgroundColor,
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export const getTableStyles = (styles?: TableStyles): TableTheme => {
|
|
187
|
+
return getTableTheme(styles)
|
|
188
|
+
}
|