goobs-frontend
Version:
A comprehensive React-based libary for building modern web applications
486 lines (467 loc) • 13 kB
text/typescript
// --------------------------------------------------------------------------
// QRCODE THEME SYSTEM
// --------------------------------------------------------------------------
import React from 'react'
import { TRANSITIONS, SHADOWS } from './shared'
export interface QRCodeTheme {
container: React.CSSProperties
title: React.CSSProperties
qrCodeContainer: React.CSSProperties
infoText: React.CSSProperties
successContainer: React.CSSProperties
successIcon: React.CSSProperties
successMessage: React.CSSProperties
buttonContainer: React.CSSProperties
confirmationContainer: React.CSSProperties
errorContainer: React.CSSProperties
errorText: React.CSSProperties
glyph: React.CSSProperties
decorativeGlyphs: React.CSSProperties
decorativeGlyph: React.CSSProperties
transition: string
}
export interface QRCodeStyles {
// Theme selection
theme?: 'light' | 'dark' | 'sacred'
// Container styling
backgroundColor?: string
borderColor?: string
borderRadius?: string
borderWidth?: string
boxShadow?: string
padding?: string
// Text styling
titleColor?: string
titleFontSize?: string
titleFontWeight?: string | number
infoTextColor?: string
// QR Code container styling
qrBackgroundColor?: string
qrBorderColor?: string
qrBoxShadow?: string
// Success state styling
successIconColor?: string
successMessageColor?: string
// Error styling
errorTextColor?: string
// Layout and sizing
size?: number
maxWidth?: string
width?: string
minWidth?: string
height?: string
maxHeight?: string
minHeight?: string
// Transitions
transitionDuration?: string
transitionEasing?: string
// States
showGlyphs?: boolean
}
export const qrCodeThemes: Record<'light' | 'dark' | 'sacred', QRCodeTheme> = {
light: {
container: {
padding: '1.5rem',
display: 'inline-block',
maxWidth: '100%',
boxSizing: 'border-box',
borderRadius: '16px',
boxShadow: SHADOWS.light.medium,
backgroundColor: 'rgba(255, 255, 255, 0.95)',
border: '1px solid rgba(226, 232, 240, 0.8)',
position: 'relative',
overflow: 'hidden',
},
title: {
marginBottom: '1rem',
textAlign: 'center',
fontFamily: 'Merriweather, serif',
fontSize: '1.25rem',
color: 'rgb(17, 24, 39)',
fontWeight: '600',
},
qrCodeContainer: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
margin: '0 auto',
padding: '1rem',
backgroundColor: 'white',
borderRadius: '12px',
border: '1px solid rgba(226, 232, 240, 0.5)',
boxShadow: SHADOWS.light.small,
},
infoText: {
marginTop: '1rem',
textAlign: 'center',
fontFamily: 'Merriweather, serif',
color: 'rgb(55, 65, 81)',
},
successContainer: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: '1rem',
padding: '1.5rem',
width: '100%',
},
successIcon: {
width: '60px',
height: '60px',
color: '#22C55E',
},
successMessage: {
textAlign: 'center',
fontFamily: 'Merriweather, serif',
fontSize: '1.25rem',
color: 'rgb(17, 24, 39)',
fontWeight: '600',
},
buttonContainer: {
marginTop: '1.5rem',
display: 'flex',
justifyContent: 'center',
gap: '1rem',
},
confirmationContainer: {
marginTop: '1.5rem',
display: 'flex',
justifyContent: 'center',
},
errorContainer: {
padding: '1rem',
},
errorText: {
fontFamily: 'Merriweather, serif',
color: '#DC2626',
},
glyph: {
position: 'absolute',
top: '0.5rem',
right: '0.5rem',
fontSize: '1.25rem',
color: 'transparent',
animation: 'none',
display: 'none',
},
decorativeGlyphs: {
display: 'none',
justifyContent: 'center',
gap: '0.5rem',
marginTop: '1.5rem',
},
decorativeGlyph: {
color: 'transparent',
fontSize: '0.875rem',
animation: 'none',
},
transition: TRANSITIONS.medium,
},
dark: {
container: {
padding: '1.5rem',
display: 'inline-block',
maxWidth: '100%',
boxSizing: 'border-box',
borderRadius: '16px',
boxShadow: '0 8px 25px rgba(0, 0, 0, 0.3), 0 4px 10px rgba(0, 0, 0, 0.2)',
backgroundColor: 'rgba(31, 41, 55, 0.95)',
border: '1px solid rgba(75, 85, 99, 0.8)',
position: 'relative',
overflow: 'hidden',
},
title: {
marginBottom: '1rem',
textAlign: 'center',
fontFamily: 'Merriweather, serif',
fontSize: '1.25rem',
color: 'rgb(243, 244, 246)',
fontWeight: '600',
},
qrCodeContainer: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
margin: '0 auto',
padding: '1rem',
backgroundColor: 'white',
borderRadius: '12px',
border: '1px solid rgba(75, 85, 99, 0.5)',
boxShadow: '0 4px 6px rgba(0, 0, 0, 0.3)',
},
infoText: {
marginTop: '1rem',
textAlign: 'center',
fontFamily: 'Merriweather, serif',
color: 'rgb(209, 213, 219)',
},
successContainer: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: '1rem',
padding: '1.5rem',
width: '100%',
},
successIcon: {
width: '60px',
height: '60px',
color: '#22C55E',
},
successMessage: {
textAlign: 'center',
fontFamily: 'Merriweather, serif',
fontSize: '1.25rem',
color: 'rgb(243, 244, 246)',
fontWeight: '600',
},
buttonContainer: {
marginTop: '1.5rem',
display: 'flex',
justifyContent: 'center',
gap: '1rem',
},
confirmationContainer: {
marginTop: '1.5rem',
display: 'flex',
justifyContent: 'center',
},
errorContainer: {
padding: '1rem',
},
errorText: {
fontFamily: 'Merriweather, serif',
color: '#F87171',
},
glyph: {
position: 'absolute',
top: '0.5rem',
right: '0.5rem',
fontSize: '1.25rem',
color: 'transparent',
animation: 'none',
display: 'none',
},
decorativeGlyphs: {
display: 'none',
justifyContent: 'center',
gap: '0.5rem',
marginTop: '1.5rem',
},
decorativeGlyph: {
color: 'transparent',
fontSize: '0.875rem',
animation: 'none',
},
transition: TRANSITIONS.medium,
},
sacred: {
container: {
padding: '1.5rem',
display: 'inline-block',
maxWidth: '100%',
boxSizing: 'border-box',
borderRadius: '12px',
boxShadow: SHADOWS.sacred.large,
backgroundColor: 'rgba(10, 10, 10, 0.95)',
border: '2px solid rgba(255, 215, 0, 0.4)',
position: 'relative',
overflow: 'hidden',
animation: 'sacred-glow-pulse 2s infinite alternate',
},
title: {
marginBottom: '1rem',
textAlign: 'center',
fontFamily: 'Cinzel, serif',
fontSize: '1.25rem',
color: '#FFD700',
fontWeight: '600',
letterSpacing: '0.05em',
textShadow: '0 0 10px rgba(255, 215, 0, 0.5)',
},
qrCodeContainer: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
margin: '0 auto',
padding: '1rem',
backgroundColor: 'white',
borderRadius: '8px',
border: '2px solid rgba(255, 215, 0, 0.6)',
boxShadow: '0 0 20px rgba(255, 215, 0, 0.4)',
},
infoText: {
marginTop: '1rem',
textAlign: 'center',
fontFamily: 'Cinzel, serif',
color: 'rgba(255, 215, 0, 0.9)',
fontStyle: 'italic',
letterSpacing: '0.05em',
},
successContainer: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: '1rem',
padding: '1.5rem',
width: '100%',
position: 'relative',
},
successIcon: {
width: '60px',
height: '60px',
color: '#FFD700',
filter: 'drop-shadow(0 0 10px rgba(255, 215, 0, 0.6))',
animation: 'sacred-float 3s infinite ease-in-out',
},
successMessage: {
textAlign: 'center',
fontFamily: 'Cinzel, serif',
fontSize: '1.25rem',
color: '#FFD700',
fontWeight: '600',
textShadow: '0 0 10px rgba(255, 215, 0, 0.5)',
},
buttonContainer: {
marginTop: '1.5rem',
display: 'flex',
justifyContent: 'center',
gap: '1rem',
},
confirmationContainer: {
marginTop: '1.5rem',
display: 'flex',
justifyContent: 'center',
},
errorContainer: {
padding: '1rem',
},
errorText: {
fontFamily: 'Cinzel, serif',
color: '#FFD700',
},
glyph: {
position: 'absolute',
top: '0.5rem',
right: '0.5rem',
fontSize: '1.25rem',
color: 'rgba(255, 215, 0, 0.3)',
animation: 'glyph-rotate 10s linear infinite',
},
decorativeGlyphs: {
display: 'flex',
justifyContent: 'center',
gap: '0.5rem',
marginTop: '1.5rem',
},
decorativeGlyph: {
color: 'rgba(255, 215, 0, 0.4)',
fontSize: '0.875rem',
animation: 'float-glyph 3s infinite ease-in-out',
},
transition: TRANSITIONS.premium,
},
}
// Helper function to get computed theme with custom style overrides
export const getQRCodeTheme = (styles?: QRCodeStyles): QRCodeTheme => {
const theme = styles?.theme || 'light'
const baseTheme = qrCodeThemes[theme]
if (!styles) {
return baseTheme
}
return {
...baseTheme,
container: {
...baseTheme.container,
backgroundColor:
styles.backgroundColor || baseTheme.container.backgroundColor,
border: styles.borderColor
? `${styles.borderWidth || '1px'} solid ${styles.borderColor}`
: baseTheme.container.border,
borderRadius: styles.borderRadius || baseTheme.container.borderRadius,
boxShadow: styles.boxShadow || baseTheme.container.boxShadow,
padding: styles.padding || baseTheme.container.padding,
maxWidth: styles.maxWidth || baseTheme.container.maxWidth,
},
title: {
...baseTheme.title,
color: styles.titleColor || baseTheme.title.color,
fontSize: styles.titleFontSize || baseTheme.title.fontSize,
fontWeight: styles.titleFontWeight || baseTheme.title.fontWeight,
},
qrCodeContainer: {
...baseTheme.qrCodeContainer,
backgroundColor:
styles.qrBackgroundColor || baseTheme.qrCodeContainer.backgroundColor,
border: styles.qrBorderColor
? `1px solid ${styles.qrBorderColor}`
: baseTheme.qrCodeContainer.border,
boxShadow: styles.qrBoxShadow || baseTheme.qrCodeContainer.boxShadow,
},
infoText: {
...baseTheme.infoText,
color: styles.infoTextColor || baseTheme.infoText.color,
},
successIcon: {
...baseTheme.successIcon,
color: styles.successIconColor || baseTheme.successIcon.color,
},
successMessage: {
...baseTheme.successMessage,
color: styles.successMessageColor || baseTheme.successMessage.color,
},
errorText: {
...baseTheme.errorText,
color: styles.errorTextColor || baseTheme.errorText.color,
},
glyph: {
...baseTheme.glyph,
display: styles.showGlyphs ? 'block' : baseTheme.glyph.display,
},
decorativeGlyphs: {
...baseTheme.decorativeGlyphs,
display: styles.showGlyphs ? 'flex' : baseTheme.decorativeGlyphs.display,
},
transition: styles.transitionDuration
? `all ${styles.transitionDuration} ${styles.transitionEasing || 'cubic-bezier(0.4, 0, 0.2, 1)'}`
: baseTheme.transition,
}
}
// Main style generator function
export const getQRCodeStyles = (
styles?: QRCodeStyles,
responsiveSize?: number
) => {
const themeConfig = getQRCodeTheme(styles)
const size = responsiveSize || styles?.size || 256
const containerStyle: React.CSSProperties = {
...themeConfig.container,
width: styles?.width,
minWidth: styles?.minWidth,
height: styles?.height,
maxHeight: styles?.maxHeight,
minHeight: styles?.minHeight,
transition: themeConfig.transition,
}
const qrCodeContainerStyle: React.CSSProperties = {
...themeConfig.qrCodeContainer,
width: size,
height: size,
}
return {
container: containerStyle,
title: themeConfig.title,
qrCodeContainer: qrCodeContainerStyle,
infoText: themeConfig.infoText,
successContainer: themeConfig.successContainer,
successIcon: themeConfig.successIcon,
successMessage: themeConfig.successMessage,
buttonContainer: themeConfig.buttonContainer,
confirmationContainer: themeConfig.confirmationContainer,
errorContainer: themeConfig.errorContainer,
errorText: themeConfig.errorText,
glyph: themeConfig.glyph,
decorativeGlyphs: themeConfig.decorativeGlyphs,
decorativeGlyph: themeConfig.decorativeGlyph,
}
}