@rakeyshgidwani/roger-ui-bank-theme-stan-design 0.1.7 → 0.1.8

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/src/setupTests.ts DELETED
@@ -1,124 +0,0 @@
1
- import '@testing-library/jest-dom';
2
-
3
- // Mock localStorage for Jest environment
4
- const localStorageMock = {
5
- getItem: jest.fn(),
6
- setItem: jest.fn(),
7
- removeItem: jest.fn(),
8
- clear: jest.fn(),
9
- length: 0,
10
- key: jest.fn(),
11
- };
12
-
13
- Object.defineProperty(window, 'localStorage', {
14
- value: localStorageMock,
15
- writable: true,
16
- });
17
-
18
- // Mock sessionStorage for Jest environment
19
- const sessionStorageMock = {
20
- getItem: jest.fn(),
21
- setItem: jest.fn(),
22
- removeItem: jest.fn(),
23
- clear: jest.fn(),
24
- length: 0,
25
- key: jest.fn(),
26
- };
27
-
28
- Object.defineProperty(window, 'sessionStorage', {
29
- value: sessionStorageMock,
30
- writable: true,
31
- });
32
-
33
- // Mock performance API for Jest environment
34
- Object.defineProperty(window, 'performance', {
35
- value: {
36
- now: jest.fn(() => Date.now()),
37
- memory: {
38
- usedJSHeapSize: 1000000,
39
- totalJSHeapSize: 2000000,
40
- jsHeapSizeLimit: 3000000,
41
- },
42
- },
43
- writable: true,
44
- });
45
-
46
- // Mock ResizeObserver for Jest environment
47
- global.ResizeObserver = jest.fn().mockImplementation(() => ({
48
- observe: jest.fn(),
49
- unobserve: jest.fn(),
50
- disconnect: jest.fn(),
51
- }));
52
-
53
- // Mock IntersectionObserver for Jest environment
54
- global.IntersectionObserver = jest.fn().mockImplementation(() => ({
55
- observe: jest.fn(),
56
- unobserve: jest.fn(),
57
- disconnect: jest.fn(),
58
- }));
59
-
60
- // Mock React 18 createRoot for Jest environment
61
- const mockCreateRoot = jest.fn(() => ({
62
- render: jest.fn(),
63
- unmount: jest.fn(),
64
- }));
65
-
66
- Object.defineProperty(window, 'createRoot', {
67
- value: mockCreateRoot,
68
- writable: true,
69
- });
70
-
71
- // Suppress console warnings for expected test behavior
72
- const originalWarn = console.warn;
73
- const originalError = console.error;
74
-
75
- beforeAll(() => {
76
- // Suppress specific warnings that are expected in tests
77
- console.warn = jest.fn((...args) => {
78
- const message = args[0];
79
- if (
80
- typeof message === 'string' && (
81
- message.includes('Failed to read theme from storage') ||
82
- message.includes('Failed to store theme preference') ||
83
- message.includes('Failed to read system theme preference from storage')
84
- )
85
- ) {
86
- return; // Suppress expected storage warnings
87
- }
88
- originalWarn(...args);
89
- });
90
-
91
- // Suppress specific errors that are expected in tests
92
- console.error = jest.fn((...args) => {
93
- const message = args[0];
94
- if (
95
- typeof message === 'string' && (
96
- message.includes('Warning: An update to ThemeProvider inside a test was not wrapped in act') ||
97
- message.includes('createRoot') ||
98
- message.includes('Target container is not a DOM element')
99
- )
100
- ) {
101
- return; // Suppress expected React act warnings and createRoot errors
102
- }
103
- originalError(...args);
104
- });
105
- });
106
-
107
- afterAll(() => {
108
- // Restore original console methods
109
- console.warn = originalWarn;
110
- console.error = originalError;
111
- });
112
-
113
- // Reset mocks before each test
114
- beforeEach(() => {
115
- localStorageMock.getItem.mockClear();
116
- localStorageMock.setItem.mockClear();
117
- localStorageMock.removeItem.mockClear();
118
- localStorageMock.clear.mockClear();
119
-
120
- sessionStorageMock.getItem.mockClear();
121
- sessionStorageMock.setItem.mockClear();
122
- sessionStorageMock.removeItem.mockClear();
123
- sessionStorageMock.clear.mockClear();
124
- });
@@ -1,39 +0,0 @@
1
- # Storybook Stories
2
-
3
- This directory contains all the Storybook stories for the Roger UI Bank design system.
4
-
5
- ## Structure
6
-
7
- - `components/` - Component stories organized by category
8
- - `ui/` - Basic UI component stories
9
- - `layouts/` - Layout component stories
10
- - `feedback/` - Feedback component stories
11
- - `navigation/` - Navigation component stories
12
- - `overlay/` - Overlay component stories
13
- - `data-display/` - Data display component stories
14
- - `themes/` - Theme documentation and examples
15
- - `decorators/` - Story decorators for common functionality
16
-
17
- ## Usage
18
-
19
- 1. Start Storybook: `npm run storybook`
20
- 2. Navigate to http://localhost:6006
21
- 3. Use the theme switcher in the toolbar to see different themes
22
- 4. Explore component variations and documentation
23
-
24
- ## Adding New Stories
25
-
26
- 1. Create a new story file in the appropriate category
27
- 2. Import the component and create stories
28
- 3. Add theme decorator for multi-theme support
29
- 4. Include comprehensive documentation
30
- 5. Test with all available themes
31
-
32
- ## Theme Support
33
-
34
- All components support three themes:
35
- - **Stan Design** - Modern, professional design
36
- - **Enterprise** - Corporate, business-focused design
37
- - **Harvey Creative** - Creative, vibrant design
38
-
39
- Use the theme decorator to ensure proper theme integration in your stories.
@@ -1,143 +0,0 @@
1
- import React, { useEffect, useState } from 'react';
2
- import { useTheme } from '../../themes';
3
-
4
- /**
5
- * Theme Debugger Component for Storybook
6
- * Shows current theme state and CSS variables for debugging
7
- */
8
- export const ThemeDebugger: React.FC = () => {
9
- const { currentTheme, currentThemeConfig, availableThemes } = useTheme();
10
- const [cssVariables, setCssVariables] = useState<Record<string, string>>({});
11
- const [isVisible, setIsVisible] = useState(false);
12
-
13
- // Extract CSS variables from document root
14
- useEffect(() => {
15
- const extractCSSVariables = () => {
16
- const root = document.documentElement;
17
- const variables: Record<string, string> = {};
18
-
19
- // Get all CSS custom properties
20
- const styles = getComputedStyle(root);
21
-
22
- // Method 1: Try to get all CSS properties
23
- try {
24
- for (let i = 0; i < styles.length; i++) {
25
- const property = styles[i];
26
- if (property.startsWith('--cs-')) {
27
- variables[property] = styles.getPropertyValue(property);
28
- }
29
- }
30
- } catch (error) {
31
- console.warn('Could not iterate through styles:', error);
32
- }
33
-
34
- // Method 2: Try to get specific known CSS variables
35
- const knownVariables = [
36
- '--cs-primary-500', '--cs-secondary-500', '--cs-success', '--cs-warning', '--cs-error', '--cs-info',
37
- '--cs-text-primary', '--cs-text-secondary', '--cs-surface-bg', '--cs-border',
38
- '--cs-fonts-primary-family', '--cs-fonts-primary-sizes-md', '--cs-spacing-4'
39
- ];
40
-
41
- knownVariables.forEach(varName => {
42
- try {
43
- const value = styles.getPropertyValue(varName);
44
- if (value && value.trim() !== '') {
45
- variables[varName] = value;
46
- }
47
- } catch (error) {
48
- // Variable doesn't exist
49
- }
50
- });
51
-
52
- // Method 3: Check if variables are set via inline styles
53
- const inlineVars = root.style.cssText.match(/--cs-[^:]+:[^;]+/g) || [];
54
- inlineVars.forEach(varDeclaration => {
55
- const [name, value] = varDeclaration.split(':');
56
- if (name && value) {
57
- variables[name.trim()] = value.trim();
58
- }
59
- });
60
-
61
- console.log('Extracted CSS variables:', variables);
62
- setCssVariables(variables);
63
- };
64
-
65
- extractCSSVariables();
66
-
67
- // Listen for theme changes
68
- const handleThemeChange = () => {
69
- setTimeout(extractCSSVariables, 200); // Increased delay to ensure CSS is updated
70
- };
71
-
72
- window.addEventListener('themeChange', handleThemeChange);
73
-
74
- // Also check periodically for changes
75
- const interval = setInterval(extractCSSVariables, 1000);
76
-
77
- return () => {
78
- window.removeEventListener('themeChange', handleThemeChange);
79
- clearInterval(interval);
80
- };
81
- }, [currentTheme]);
82
-
83
- if (!isVisible) {
84
- return (
85
- <button
86
- onClick={() => setIsVisible(true)}
87
- className="fixed bottom-4 right-4 bg-blue-600 text-white px-3 py-2 rounded-lg text-sm z-50"
88
- >
89
- 🐛 Debug Theme
90
- </button>
91
- );
92
- }
93
-
94
- return (
95
- <div className="fixed bottom-4 right-4 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-lg p-4 max-w-md max-h-96 overflow-auto shadow-lg z-50">
96
- <div className="flex items-center justify-between mb-3">
97
- <h3 className="font-semibold text-gray-900 dark:text-white">Theme Debugger</h3>
98
- <button
99
- onClick={() => setIsVisible(false)}
100
- className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200"
101
- >
102
-
103
- </button>
104
- </div>
105
-
106
- <div className="space-y-3 text-sm">
107
- <div>
108
- <strong>Current Theme:</strong> {currentTheme}
109
- </div>
110
-
111
- <div>
112
- <strong>Available Themes:</strong> {availableThemes.join(', ')}
113
- </div>
114
-
115
- {currentThemeConfig && (
116
- <div>
117
- <strong>Theme Config:</strong>
118
- <pre className="mt-1 p-2 bg-gray-100 dark:bg-gray-700 rounded text-xs overflow-auto max-h-20">
119
- {JSON.stringify({
120
- name: currentThemeConfig.meta?.name,
121
- description: currentThemeConfig.meta?.description,
122
- category: currentThemeConfig.meta?.category,
123
- primaryColor: currentThemeConfig.colors?.primary?.[500],
124
- fontFamily: currentThemeConfig.fonts?.primary?.family
125
- }, null, 2)}
126
- </pre>
127
- </div>
128
- )}
129
-
130
- <div>
131
- <strong>CSS Variables ({Object.keys(cssVariables).length}):</strong>
132
- <div className="mt-1 max-h-32 overflow-auto">
133
- {Object.entries(cssVariables).map(([variable, value]) => (
134
- <div key={variable} className="text-xs font-mono">
135
- <span className="text-blue-600">{variable}:</span> {value}
136
- </div>
137
- ))}
138
- </div>
139
- </div>
140
- </div>
141
- </div>
142
- );
143
- };
@@ -1,29 +0,0 @@
1
- // Stories index file
2
- // Export all story-related utilities and decorators
3
-
4
-
5
-
6
- // Theme stories
7
- export * from './themes/theme-showcase.stories';
8
- export * from './themes/theme-documentation.stories';
9
-
10
- // Core UI Component Stories
11
- export * from './components/ui/button.stories';
12
- export * from './components/ui/card.stories';
13
- export * from './components/ui/input.stories';
14
- export * from './components/ui/mobile-input.stories';
15
- export * from './components/ui/checkbox.stories';
16
- export * from './components/ui/badge.stories';
17
- export * from './components/ui/label.stories';
18
-
19
- // Theme System Component Stories
20
-
21
- export * from './components/ui/theme-preview.stories';
22
- export * from './components/ui/color-preview.stories';
23
- export * from './components/ui/font-preview.stories';
24
-
25
- // Theme utilities
26
-
27
-
28
- // This file will be expanded as we add more stories
29
- // and utilities for the design system
@@ -1,51 +0,0 @@
1
- /* Storybook Theme CSS Imports - Stan Design Only */
2
- /* This file ensures Stan Design theme styles are available in Storybook */
3
-
4
- /* Import Stan Design theme styles directly (bypassing theme index to avoid Harvey theme) */
5
- @import '../styles/themes/stan-design.css';
6
-
7
- /* Import additional theme-related styles (excluding theme.css to avoid Harvey import) */
8
- @import '../styles/base/fonts.css';
9
-
10
- /* Ensure Stan Design theme variables are available in Storybook iframe */
11
- :root {
12
- /* Stan Design theme variables for Storybook */
13
- --cs-theme-active: 'stan-design';
14
- --cs-theme-available: 'stan-design';
15
- }
16
-
17
- /* Apply Stan Design theme globally to all Storybook content */
18
- body {
19
- background-color: var(--cs-colors-surface-background, #f8fafc);
20
- color: var(--cs-colors-text-primary, #0f172a);
21
- }
22
-
23
- /* Ensure all stories inherit the Stan Design theme */
24
- #storybook-panel-root,
25
- #storybook-preview-wrapper,
26
- #storybook-preview-iframe {
27
- background-color: var(--cs-colors-surface-background, #f8fafc) !important;
28
- }
29
-
30
- /* Dark mode overrides for Storybook */
31
- .dark body {
32
- background-color: var(--cs-colors-surface-background, #0f172a) !important;
33
- color: var(--cs-colors-text-primary, #f8fafc) !important;
34
- }
35
-
36
- .dark #storybook-panel-root,
37
- .dark #storybook-preview-wrapper,
38
- .dark #storybook-preview-iframe {
39
- background-color: var(--cs-colors-surface-background, #0f172a) !important;
40
- }
41
-
42
- /* Stan Design theme overrides for Storybook */
43
- [data-theme="stan-design"] {
44
- /* Stan Design theme specific styles */
45
- }
46
-
47
- /* Storybook-specific theme indicator */
48
- [data-storybook-theme="stan-design"] {
49
- /* Visual indicator that Stan Design theme is active in Storybook */
50
- position: relative;
51
- }
@@ -1,7 +0,0 @@
1
- // Test utilities for theme-aware testing
2
- export * from './theme-testing';
3
-
4
- // Re-export common testing utilities
5
- export { render, screen, fireEvent, waitFor, act } from '@testing-library/react';
6
- export { userEvent } from '@testing-library/user-event';
7
- export type { RenderResult, RenderOptions } from '@testing-library/react';
@@ -1,219 +0,0 @@
1
- import React from 'react';
2
- import { render, RenderOptions, RenderResult } from '@testing-library/react';
3
- import { ThemeProvider } from '../themes/ThemeProvider';
4
- import { defaultThemes } from '../themes/base-themes';
5
- import type { MultiThemeConfig } from '../themes/types';
6
-
7
- // Mock window.matchMedia for Jest environment
8
- Object.defineProperty(window, 'matchMedia', {
9
- writable: true,
10
- value: jest.fn().mockImplementation(query => ({
11
- matches: false,
12
- media: query,
13
- onchange: null,
14
- addListener: jest.fn(), // deprecated
15
- removeListener: jest.fn(), // deprecated
16
- addEventListener: jest.fn(),
17
- removeEventListener: jest.fn(),
18
- dispatchEvent: jest.fn(),
19
- })),
20
- });
21
-
22
- // Test utilities for theme-aware component testing
23
-
24
- export interface ThemeTestingOptions extends Omit<RenderOptions, 'wrapper'> {
25
- theme?: string;
26
- themes?: Record<string, MultiThemeConfig>;
27
- persistTheme?: boolean;
28
- }
29
-
30
- /**
31
- * Renders a component wrapped with ThemeProvider for testing
32
- */
33
- export const renderWithTheme = (
34
- component: React.ReactElement,
35
- options: ThemeTestingOptions = {}
36
- ): RenderResult => {
37
- const {
38
- theme = 'stan-design',
39
- themes = defaultThemes,
40
- persistTheme = false,
41
- ...renderOptions
42
- } = options;
43
-
44
- const ThemeWrapper = ({ children }: { children: React.ReactNode }) => (
45
- <ThemeProvider
46
- defaultTheme={theme}
47
- themes={themes}
48
- persistTheme={persistTheme}
49
- >
50
- {children}
51
- </ThemeProvider>
52
- );
53
-
54
- return render(component, {
55
- wrapper: ThemeWrapper,
56
- ...renderOptions,
57
- });
58
- };
59
-
60
- /**
61
- * Renders a component in all available themes for comprehensive testing
62
- */
63
- export const renderWithAllThemes = (
64
- component: React.ReactElement,
65
- options: Omit<ThemeTestingOptions, 'theme'> = {}
66
- ): Record<string, RenderResult> => {
67
- const { themes = defaultThemes, ...renderOptions } = options;
68
- const results: Record<string, RenderResult> = {};
69
-
70
- Object.keys(themes).forEach(themeName => {
71
- // Create a unique container for each theme to avoid conflicts
72
- const container = document.createElement('div');
73
- container.id = `theme-test-${themeName}`;
74
- document.body.appendChild(container);
75
-
76
- results[themeName] = render(component, {
77
- container,
78
- wrapper: ({ children }) => (
79
- <ThemeProvider
80
- defaultTheme={themeName}
81
- themes={themes}
82
- persistTheme={false}
83
- >
84
- {children}
85
- </ThemeProvider>
86
- ),
87
- ...renderOptions,
88
- });
89
- });
90
-
91
- return results;
92
- };
93
-
94
- /**
95
- * Cleanup function to remove theme test containers
96
- */
97
- export const cleanupThemeTests = (): void => {
98
- const containers = document.querySelectorAll('[id^="theme-test-"]');
99
- containers.forEach(container => {
100
- container.remove();
101
- });
102
- };
103
-
104
- /**
105
- * Test helper to switch themes during testing
106
- */
107
- export const createThemeSwitcher = (initialTheme: string = 'stan-design') => {
108
- let currentTheme = initialTheme;
109
-
110
- return {
111
- getCurrentTheme: () => currentTheme,
112
- switchTo: (newTheme: string) => {
113
- currentTheme = newTheme;
114
- return currentTheme;
115
- },
116
- renderWithCurrentTheme: (component: React.ReactElement, options: Omit<ThemeTestingOptions, 'theme'> = {}) => {
117
- return renderWithTheme(component, { theme: currentTheme, ...options });
118
- }
119
- };
120
- };
121
-
122
- /**
123
- * Helper to test theme-specific styles and properties
124
- */
125
- export const getThemeStyles = (themeName: string, themes = defaultThemes) => {
126
- const theme = themes[themeName];
127
- if (!theme) {
128
- throw new Error(`Theme '${themeName}' not found in provided themes`);
129
- }
130
- return theme;
131
- };
132
-
133
- /**
134
- * Helper to test CSS custom properties applied by themes
135
- */
136
- export const getThemeCSSVariables = (element: Element): Record<string, string> => {
137
- const computedStyle = window.getComputedStyle(element);
138
- const cssVariables: Record<string, string> = {};
139
-
140
- // Get all CSS custom properties (variables starting with --)
141
- for (let i = 0; i < computedStyle.length; i++) {
142
- const property = computedStyle[i];
143
- if (property.startsWith('--')) {
144
- cssVariables[property] = computedStyle.getPropertyValue(property).trim();
145
- }
146
- }
147
-
148
- return cssVariables;
149
- };
150
-
151
- /**
152
- * Helper to wait for theme transitions to complete
153
- */
154
- export const waitForThemeTransition = async (duration: number = 300): Promise<void> => {
155
- return new Promise(resolve => {
156
- setTimeout(resolve, duration);
157
- });
158
- };
159
-
160
- /**
161
- * Mock localStorage for theme persistence testing
162
- */
163
- export const createThemeStorageMock = () => {
164
- const storage: Record<string, string> = {};
165
-
166
- return {
167
- getItem: jest.fn((key: string) => storage[key] || null),
168
- setItem: jest.fn((key: string, value: string) => {
169
- storage[key] = value;
170
- }),
171
- removeItem: jest.fn((key: string) => {
172
- delete storage[key];
173
- }),
174
- clear: jest.fn(() => {
175
- Object.keys(storage).forEach(key => delete storage[key]);
176
- }),
177
- get storage() {
178
- return { ...storage };
179
- }
180
- };
181
- };
182
-
183
- /**
184
- * Mock matchMedia for responsive and system theme testing
185
- */
186
- export const createMatchMediaMock = (matches: boolean = false) => {
187
- return jest.fn().mockImplementation((query: string) => ({
188
- matches,
189
- media: query,
190
- onchange: null,
191
- addListener: jest.fn(),
192
- removeListener: jest.fn(),
193
- addEventListener: jest.fn(),
194
- removeEventListener: jest.fn(),
195
- dispatchEvent: jest.fn(),
196
- }));
197
- };
198
-
199
- /**
200
- * Test themes for consistent testing across all theme tests
201
- */
202
- export const getTestThemes = () => Object.keys(defaultThemes);
203
-
204
- /**
205
- * Helper to test theme contrast and accessibility
206
- */
207
- export const getThemeContrastInfo = (themeName: string, themes = defaultThemes) => {
208
- const theme = themes[themeName];
209
- if (!theme) {
210
- throw new Error(`Theme '${themeName}' not found`);
211
- }
212
-
213
- return {
214
- primaryColor: theme.colors.primary[500],
215
- backgroundColor: theme.colors.text.primary,
216
- textColor: theme.colors.text.primary,
217
- borderColor: theme.colors.surface.border,
218
- };
219
- };