UNPKG

goobs-frontend

Version:

A comprehensive React-based libary for building modern web applications

688 lines (656 loc) 21.7 kB
// -------------------------------------------------------------------------- // CONFIRMATION CODE INPUT THEME SYSTEM // -------------------------------------------------------------------------- import React from 'react' import { TRANSITIONS, SHADOWS } from './shared' export interface ConfirmationCodeInputTheme { container: { background: string border: string borderRadius: string boxShadow: string backdropFilter: string padding: string backgroundImage?: string } containerHover: { transform: string boxShadow: string borderColor?: string } successContainer: { background: string border: string borderRadius: string boxShadow: string backdropFilter: string padding: string backgroundImage?: string } successIcon: { fontSize: string color: string filter?: string animation?: string } successMessage: { fontSize: string lineHeight: string color: string fontFamily: string fontWeight: string | number letterSpacing: string textTransform: string textShadow?: string } input: { width: string height: string padding: string fontSize: string fontFamily: string fontWeight: string | number letterSpacing: string color: string backgroundColor: string borderColor: string borderRadius: string borderWidth: string textShadow?: string animation?: string } inputFocus: { borderColor: string borderWidth: string transform: string boxShadow: string } statusIndicator: { width: string height: string borderRadius: string backgroundColor: string animation?: string } statusIndicatorValid: { backgroundColor: string animation?: string } transition: string } export interface ConfirmationCodeInputStyles { // Theme selection theme?: 'light' | 'dark' | 'sacred' // Container styling backgroundColor?: string borderColor?: string borderRadius?: string borderWidth?: string boxShadow?: string backdropFilter?: string backgroundImage?: string padding?: string // Hover states hoverBackgroundColor?: string hoverBorderColor?: string hoverBoxShadow?: string hoverTransform?: string // Success container styling successBackgroundColor?: string successBorderColor?: string successBorderRadius?: string successBoxShadow?: string successBackdropFilter?: string successBackgroundImage?: string successPadding?: string // Success icon styling successIconFontSize?: string successIconColor?: string successIconFilter?: string successIconAnimation?: string // Success message styling successMessageFontSize?: string successMessageLineHeight?: string successMessageColor?: string successMessageFontFamily?: string successMessageFontWeight?: string | number successMessageLetterSpacing?: string successMessageTextTransform?: string successMessageTextShadow?: string // Input styling inputWidth?: string inputHeight?: string inputPadding?: string inputFontSize?: string inputFontFamily?: string inputFontWeight?: string | number inputLetterSpacing?: string inputColor?: string inputBackgroundColor?: string inputBorderColor?: string inputBorderRadius?: string inputBorderWidth?: string inputTextShadow?: string inputAnimation?: string // Input focus styling inputFocusBorderColor?: string inputFocusBorderWidth?: string inputFocusTransform?: string inputFocusBoxShadow?: string // Status indicator styling statusIndicatorWidth?: string statusIndicatorHeight?: string statusIndicatorBorderRadius?: string statusIndicatorBackgroundColor?: string statusIndicatorAnimation?: string statusIndicatorValidBackgroundColor?: string statusIndicatorValidAnimation?: string // Layout and spacing gap?: string inputGap?: string margin?: string marginTop?: string marginBottom?: string marginLeft?: string marginRight?: string // Transitions transitionDuration?: string transitionEasing?: string // States disabled?: boolean outline?: boolean // Dimensions width?: string maxWidth?: string minWidth?: string height?: string maxHeight?: string minHeight?: string } export const confirmationCodeInputThemes: Record< 'light' | 'dark' | 'sacred', ConfirmationCodeInputTheme > = { light: { container: { background: 'rgba(255, 255, 255, 0.95)', border: '1px solid rgba(226, 232, 240, 0.8)', borderRadius: '12px', boxShadow: SHADOWS.light.small, backdropFilter: 'blur(8px)', padding: '1.5rem', }, containerHover: { transform: 'translateY(-1px)', boxShadow: SHADOWS.light.medium, borderColor: 'rgba(59, 130, 246, 0.3)', }, successContainer: { background: 'rgba(240, 253, 244, 0.95)', border: '1px solid rgba(74, 222, 128, 0.4)', borderRadius: '12px', boxShadow: SHADOWS.light.small, backdropFilter: 'blur(8px)', padding: '1.5rem', }, successIcon: { fontSize: '3.75rem', color: 'rgb(34, 197, 94)', filter: 'drop-shadow(0 2px 4px rgba(34, 197, 94, 0.3))', }, successMessage: { fontSize: '1.5rem', lineHeight: '2rem', color: 'rgb(21, 128, 61)', fontFamily: '"Inter", sans-serif', fontWeight: '600', letterSpacing: '-0.025em', textTransform: 'none', }, input: { width: '3rem', height: '3.5rem', padding: '0', fontSize: '1.25rem', fontFamily: '"Inter", sans-serif', fontWeight: '500', letterSpacing: '0.05em', color: 'rgb(31, 41, 55)', backgroundColor: 'rgb(255, 255, 255)', borderColor: 'rgb(209, 213, 219)', borderRadius: '8px', borderWidth: '1px', }, inputFocus: { borderColor: 'rgb(59, 130, 246)', borderWidth: '2px', transform: 'scale(1.02)', boxShadow: '0 0 0 3px rgba(59, 130, 246, 0.1)', }, statusIndicator: { width: '1.25rem', height: '1.25rem', borderRadius: '50%', backgroundColor: 'rgb(239, 68, 68)', }, statusIndicatorValid: { backgroundColor: 'rgb(34, 197, 94)', }, transition: TRANSITIONS.medium, }, dark: { container: { background: 'rgba(31, 41, 55, 0.95)', border: '1px solid rgba(75, 85, 99, 0.8)', borderRadius: '12px', boxShadow: '0 2px 8px rgba(0, 0, 0, 0.3), 0 1px 4px rgba(0, 0, 0, 0.2)', backdropFilter: 'blur(8px)', padding: '1.5rem', }, containerHover: { transform: 'translateY(-1px)', boxShadow: '0 4px 12px rgba(0, 0, 0, 0.4), 0 2px 6px rgba(0, 0, 0, 0.3)', borderColor: 'rgba(96, 165, 250, 0.4)', }, successContainer: { background: 'rgba(20, 83, 45, 0.3)', border: '1px solid rgba(74, 222, 128, 0.4)', borderRadius: '12px', boxShadow: '0 2px 8px rgba(0, 0, 0, 0.3), 0 1px 4px rgba(0, 0, 0, 0.2)', backdropFilter: 'blur(8px)', padding: '1.5rem', }, successIcon: { fontSize: '3.75rem', color: 'rgb(187, 247, 208)', filter: 'drop-shadow(0 2px 4px rgba(187, 247, 208, 0.3))', }, successMessage: { fontSize: '1.5rem', lineHeight: '2rem', color: 'rgb(187, 247, 208)', fontFamily: '"Inter", sans-serif', fontWeight: '600', letterSpacing: '-0.025em', textTransform: 'none', }, input: { width: '3rem', height: '3.5rem', padding: '0', fontSize: '1.25rem', fontFamily: '"Inter", sans-serif', fontWeight: '500', letterSpacing: '0.05em', color: 'rgb(243, 244, 246)', backgroundColor: 'rgb(55, 65, 81)', borderColor: 'rgb(107, 114, 128)', borderRadius: '8px', borderWidth: '1px', }, inputFocus: { borderColor: 'rgb(96, 165, 250)', borderWidth: '2px', transform: 'scale(1.02)', boxShadow: '0 0 0 3px rgba(96, 165, 250, 0.1)', }, statusIndicator: { width: '1.25rem', height: '1.25rem', borderRadius: '50%', backgroundColor: 'rgb(248, 113, 113)', }, statusIndicatorValid: { backgroundColor: 'rgb(74, 222, 128)', }, transition: TRANSITIONS.medium, }, sacred: { container: { background: 'rgba(10, 10, 10, 0.95)', border: '2px solid rgba(255, 215, 0, 0.4)', borderRadius: '12px', boxShadow: SHADOWS.sacred.small, backdropFilter: 'blur(8px)', padding: '1.5rem', backgroundImage: ` radial-gradient(circle at top right, rgba(255, 215, 0, 0.05) 0%, transparent 50%), radial-gradient(circle at bottom left, rgba(255, 215, 0, 0.03) 0%, transparent 50%) `, }, containerHover: { transform: 'translateY(-2px)', boxShadow: SHADOWS.sacred.medium, borderColor: 'rgba(255, 215, 0, 0.6)', }, successContainer: { background: 'rgba(10, 10, 10, 0.95)', border: '2px solid rgba(255, 215, 0, 0.6)', borderRadius: '12px', boxShadow: SHADOWS.sacred.medium, backdropFilter: 'blur(8px)', padding: '1.5rem', backgroundImage: ` radial-gradient(circle at center, rgba(255, 215, 0, 0.1) 0%, transparent 50%), linear-gradient(135deg, rgba(255, 215, 0, 0.05) 0%, transparent 50%) `, }, successIcon: { fontSize: '3.75rem', color: '#FFD700', filter: 'drop-shadow(0 0 20px rgba(255, 215, 0, 0.8))', animation: 'sacred-pulse 1.5s infinite', }, successMessage: { fontSize: '1.5rem', lineHeight: '2rem', color: '#FFD700', fontFamily: '"Cinzel", serif', fontWeight: '600', letterSpacing: '0.1em', textTransform: 'uppercase', textShadow: '0 0 10px rgba(255, 215, 0, 0.7)', }, input: { width: '3rem', height: '3.5rem', padding: '0', fontSize: '1.25rem', fontFamily: 'monospace', fontWeight: '600', letterSpacing: '0.1em', color: '#FFD700', backgroundColor: 'rgba(26, 26, 26, 0.9)', borderColor: 'rgba(255, 215, 0, 0.5)', borderRadius: '8px', borderWidth: '1px', textShadow: '0 0 2px rgba(255, 215, 0, 0.5)', animation: 'sacred-input-glow 3s infinite alternate', }, inputFocus: { borderColor: '#FFD700', borderWidth: '2px', transform: 'scale(1.05)', boxShadow: '0 0 20px rgba(255, 215, 0, 0.6), inset 0 0 15px rgba(255, 215, 0, 0.3)', }, statusIndicator: { width: '1.25rem', height: '1.25rem', borderRadius: '50%', backgroundColor: 'rgba(255, 215, 0, 0.3)', }, statusIndicatorValid: { backgroundColor: '#FFD700', animation: 'sacred-status-glow 1.5s infinite alternate', }, transition: TRANSITIONS.slow, }, } // Helper function to get computed theme with custom style overrides export const getConfirmationCodeInputTheme = ( styles?: ConfirmationCodeInputStyles ): ConfirmationCodeInputTheme => { const theme = styles?.theme || 'light' const baseTheme = confirmationCodeInputThemes[theme] if (!styles) { return baseTheme } return { container: { background: styles.backgroundColor || baseTheme.container.background, border: styles.borderColor ? `${styles.borderWidth || '1px'} solid ${styles.borderColor}` : baseTheme.container.border, borderRadius: styles.borderRadius || baseTheme.container.borderRadius, boxShadow: styles.boxShadow || baseTheme.container.boxShadow, backdropFilter: styles.backdropFilter || baseTheme.container.backdropFilter, padding: styles.padding || baseTheme.container.padding, backgroundImage: styles.backgroundImage || baseTheme.container.backgroundImage, }, containerHover: { transform: styles.hoverTransform || baseTheme.containerHover.transform, boxShadow: styles.hoverBoxShadow || baseTheme.containerHover.boxShadow, borderColor: styles.hoverBorderColor || baseTheme.containerHover.borderColor, }, successContainer: { background: styles.successBackgroundColor || baseTheme.successContainer.background, border: styles.successBorderColor ? `${styles.borderWidth || '1px'} solid ${styles.successBorderColor}` : baseTheme.successContainer.border, borderRadius: styles.successBorderRadius || baseTheme.successContainer.borderRadius, boxShadow: styles.successBoxShadow || baseTheme.successContainer.boxShadow, backdropFilter: styles.successBackdropFilter || baseTheme.successContainer.backdropFilter, padding: styles.successPadding || baseTheme.successContainer.padding, backgroundImage: styles.successBackgroundImage || baseTheme.successContainer.backgroundImage, }, successIcon: { fontSize: styles.successIconFontSize || baseTheme.successIcon.fontSize, color: styles.successIconColor || baseTheme.successIcon.color, filter: styles.successIconFilter || baseTheme.successIcon.filter, animation: styles.successIconAnimation || baseTheme.successIcon.animation, }, successMessage: { fontSize: styles.successMessageFontSize || baseTheme.successMessage.fontSize, lineHeight: styles.successMessageLineHeight || baseTheme.successMessage.lineHeight, color: styles.successMessageColor || baseTheme.successMessage.color, fontFamily: styles.successMessageFontFamily || baseTheme.successMessage.fontFamily, fontWeight: styles.successMessageFontWeight || baseTheme.successMessage.fontWeight, letterSpacing: styles.successMessageLetterSpacing || baseTheme.successMessage.letterSpacing, textTransform: styles.successMessageTextTransform || baseTheme.successMessage.textTransform, textShadow: styles.successMessageTextShadow || baseTheme.successMessage.textShadow, }, input: { width: styles.inputWidth || baseTheme.input.width, height: styles.inputHeight || baseTheme.input.height, padding: styles.inputPadding || baseTheme.input.padding, fontSize: styles.inputFontSize || baseTheme.input.fontSize, fontFamily: styles.inputFontFamily || baseTheme.input.fontFamily, fontWeight: styles.inputFontWeight || baseTheme.input.fontWeight, letterSpacing: styles.inputLetterSpacing || baseTheme.input.letterSpacing, color: styles.inputColor || baseTheme.input.color, backgroundColor: styles.inputBackgroundColor || baseTheme.input.backgroundColor, borderColor: styles.inputBorderColor || baseTheme.input.borderColor, borderRadius: styles.inputBorderRadius || baseTheme.input.borderRadius, borderWidth: styles.inputBorderWidth || baseTheme.input.borderWidth, textShadow: styles.inputTextShadow || baseTheme.input.textShadow, animation: styles.inputAnimation || baseTheme.input.animation, }, inputFocus: { borderColor: styles.inputFocusBorderColor || baseTheme.inputFocus.borderColor, borderWidth: styles.inputFocusBorderWidth || baseTheme.inputFocus.borderWidth, transform: styles.inputFocusTransform || baseTheme.inputFocus.transform, boxShadow: styles.inputFocusBoxShadow || baseTheme.inputFocus.boxShadow, }, statusIndicator: { width: styles.statusIndicatorWidth || baseTheme.statusIndicator.width, height: styles.statusIndicatorHeight || baseTheme.statusIndicator.height, borderRadius: styles.statusIndicatorBorderRadius || baseTheme.statusIndicator.borderRadius, backgroundColor: styles.statusIndicatorBackgroundColor || baseTheme.statusIndicator.backgroundColor, animation: styles.statusIndicatorAnimation || baseTheme.statusIndicator.animation, }, statusIndicatorValid: { backgroundColor: styles.statusIndicatorValidBackgroundColor || baseTheme.statusIndicatorValid.backgroundColor, animation: styles.statusIndicatorValidAnimation || baseTheme.statusIndicatorValid.animation, }, transition: styles.transitionDuration ? `all ${styles.transitionDuration} ${styles.transitionEasing || 'cubic-bezier(0.4, 0, 0.2, 1)'}` : baseTheme.transition, } } // Main style generator function export const getConfirmationCodeInputStyles = ( styles?: ConfirmationCodeInputStyles, isHovered?: boolean, isValid?: boolean, isDisabled?: boolean ) => { const themeConfig = getConfirmationCodeInputTheme(styles) const containerStyle: React.CSSProperties = { display: 'flex', flexDirection: 'column', alignItems: 'center', position: 'relative', width: styles?.width || '100%', maxWidth: styles?.maxWidth, minWidth: styles?.minWidth, height: styles?.height, maxHeight: styles?.maxHeight, minHeight: styles?.minHeight, margin: styles?.margin, marginTop: styles?.marginTop, marginBottom: styles?.marginBottom, marginLeft: styles?.marginLeft, marginRight: styles?.marginRight, background: themeConfig.container.background, border: themeConfig.container.border, borderRadius: themeConfig.container.borderRadius, boxShadow: themeConfig.container.boxShadow, backdropFilter: themeConfig.container.backdropFilter, padding: themeConfig.container.padding, backgroundImage: themeConfig.container.backgroundImage, transition: themeConfig.transition, opacity: isDisabled ? 0.5 : 1, cursor: isDisabled ? 'not-allowed' : 'default', ...(isHovered && !isDisabled && { transform: themeConfig.containerHover.transform, boxShadow: themeConfig.containerHover.boxShadow, borderColor: themeConfig.containerHover.borderColor, }), } const successContainerStyle: React.CSSProperties = { display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '0.5rem', width: '100%', background: themeConfig.successContainer.background, border: themeConfig.successContainer.border, borderRadius: themeConfig.successContainer.borderRadius, boxShadow: themeConfig.successContainer.boxShadow, backdropFilter: themeConfig.successContainer.backdropFilter, padding: themeConfig.successContainer.padding, backgroundImage: themeConfig.successContainer.backgroundImage, transition: themeConfig.transition, } const successIconStyle: React.CSSProperties = { fontSize: themeConfig.successIcon.fontSize, color: themeConfig.successIcon.color, filter: themeConfig.successIcon.filter, animation: themeConfig.successIcon.animation, } const successMessageStyle: React.CSSProperties = { fontSize: themeConfig.successMessage.fontSize, lineHeight: themeConfig.successMessage.lineHeight, color: themeConfig.successMessage.color, fontFamily: themeConfig.successMessage.fontFamily, fontWeight: themeConfig.successMessage.fontWeight, letterSpacing: themeConfig.successMessage.letterSpacing, textTransform: themeConfig.successMessage.textTransform as any, textShadow: themeConfig.successMessage.textShadow, textAlign: 'center', margin: 0, } const inputStyle: React.CSSProperties = { width: themeConfig.input.width, height: themeConfig.input.height, padding: themeConfig.input.padding, fontSize: themeConfig.input.fontSize, fontFamily: themeConfig.input.fontFamily, fontWeight: themeConfig.input.fontWeight, letterSpacing: themeConfig.input.letterSpacing, color: themeConfig.input.color, backgroundColor: themeConfig.input.backgroundColor, border: `${themeConfig.input.borderWidth} solid ${themeConfig.input.borderColor}`, borderRadius: themeConfig.input.borderRadius, textShadow: themeConfig.input.textShadow, animation: themeConfig.input.animation, textAlign: 'center', outline: 'none', transition: themeConfig.transition, } const inputFocusStyle: React.CSSProperties = { borderColor: themeConfig.inputFocus.borderColor, borderWidth: themeConfig.inputFocus.borderWidth, transform: themeConfig.inputFocus.transform, boxShadow: themeConfig.inputFocus.boxShadow, } const statusIndicatorStyle: React.CSSProperties = { width: themeConfig.statusIndicator.width, height: themeConfig.statusIndicator.height, borderRadius: themeConfig.statusIndicator.borderRadius, backgroundColor: isValid ? themeConfig.statusIndicatorValid.backgroundColor : themeConfig.statusIndicator.backgroundColor, animation: isValid ? themeConfig.statusIndicatorValid.animation : themeConfig.statusIndicator.animation, transition: themeConfig.transition, } const mainContentStyle: React.CSSProperties = { display: 'flex', flexDirection: 'column', alignItems: 'center', width: '100%', gap: styles?.gap || '1.25rem', } const inputsRowStyle: React.CSSProperties = { display: 'flex', alignItems: 'center', gap: '1rem', } const inputGroupStyle: React.CSSProperties = { display: 'flex', gap: styles?.inputGap || '0.75rem', } const buttonContainerStyle: React.CSSProperties = { display: 'flex', gap: '0.5rem', width: '100%', } return { container: containerStyle, successContainer: successContainerStyle, successIcon: successIconStyle, successMessage: successMessageStyle, input: inputStyle, inputFocus: inputFocusStyle, statusIndicator: statusIndicatorStyle, mainContent: mainContentStyle, inputsRow: inputsRowStyle, inputGroup: inputGroupStyle, buttonContainer: buttonContainerStyle, } }