@asafarim/react-themes 1.0.0
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/LICENSE +21 -0
- package/README.md +291 -0
- package/dist/index.d.mts +241 -0
- package/dist/index.d.ts +241 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +18 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +87 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Ali SAFARI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
# @asafarim/react-themes
|
|
2
|
+
|
|
3
|
+
A comprehensive theme management system for React applications with automatic dark/light mode detection, custom theme creation, and smooth transitions.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## ✨ Features
|
|
10
|
+
|
|
11
|
+
- 🌓 **Auto Dark/Light Mode**: Automatic system preference detection
|
|
12
|
+
- 🎨 **Custom Themes**: Create and apply custom themes easily
|
|
13
|
+
- ⚡ **TypeScript Ready**: Full TypeScript support with type definitions
|
|
14
|
+
- 🔄 **Smooth Transitions**: Beautiful transitions between theme changes
|
|
15
|
+
- 💾 **Persistence**: Automatically save user preferences to localStorage
|
|
16
|
+
- 🎯 **CSS Variables**: Automatic CSS variable injection for styling
|
|
17
|
+
- 🔧 **Flexible API**: Easy to integrate with existing projects
|
|
18
|
+
- ♿ **Accessible**: Built with accessibility in mind
|
|
19
|
+
|
|
20
|
+
## 📦 Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install @asafarim/react-themes
|
|
24
|
+
# or
|
|
25
|
+
yarn add @asafarim/react-themes
|
|
26
|
+
# or
|
|
27
|
+
pnpm add @asafarim/react-themes
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## 🚀 Quick Start
|
|
31
|
+
|
|
32
|
+
### 1. Wrap your app with ThemeProvider
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
import React from 'react';
|
|
36
|
+
import { ThemeProvider } from '@asafarim/react-themes';
|
|
37
|
+
import '@asafarim/react-themes/styles.css'; // Optional base styles
|
|
38
|
+
|
|
39
|
+
function App() {
|
|
40
|
+
return (
|
|
41
|
+
<ThemeProvider defaultMode="auto" persistMode={true}>
|
|
42
|
+
<YourAppContent />
|
|
43
|
+
</ThemeProvider>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 2. Use the theme in your components
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
import React from 'react';
|
|
52
|
+
import { useTheme, ThemeToggle } from '@asafarim/react-themes';
|
|
53
|
+
|
|
54
|
+
function MyComponent() {
|
|
55
|
+
const { mode, currentTheme, toggleMode } = useTheme();
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<div>
|
|
59
|
+
<h1>Current mode: {mode}</h1>
|
|
60
|
+
<ThemeToggle />
|
|
61
|
+
{/* Your component content */}
|
|
62
|
+
</div>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 📖 API Reference
|
|
68
|
+
|
|
69
|
+
### ThemeProvider
|
|
70
|
+
|
|
71
|
+
The main provider component that manages theme state and applies CSS variables.
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
interface ThemeProviderProps {
|
|
75
|
+
children: ReactNode;
|
|
76
|
+
defaultMode?: 'light' | 'dark' | 'auto';
|
|
77
|
+
defaultTheme?: string;
|
|
78
|
+
persistMode?: boolean;
|
|
79
|
+
storageKey?: string;
|
|
80
|
+
customThemes?: Record<string, Theme>;
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Props:**
|
|
85
|
+
- `defaultMode`: Initial theme mode (default: 'auto')
|
|
86
|
+
- `defaultTheme`: Default theme name (default: 'default')
|
|
87
|
+
- `persistMode`: Save theme preference to localStorage (default: true)
|
|
88
|
+
- `storageKey`: localStorage key for persistence (default: 'asafarim-theme-mode')
|
|
89
|
+
- `customThemes`: Additional custom themes
|
|
90
|
+
|
|
91
|
+
### useTheme Hook
|
|
92
|
+
|
|
93
|
+
Access theme state and controls.
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
const {
|
|
97
|
+
currentTheme, // Current active theme object
|
|
98
|
+
mode, // Current mode: 'light' | 'dark' | 'auto'
|
|
99
|
+
setMode, // Function to change mode
|
|
100
|
+
setTheme, // Function to change theme
|
|
101
|
+
themes, // Available themes
|
|
102
|
+
toggleMode // Function to cycle through modes
|
|
103
|
+
} = useTheme();
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### useThemeToggle Hook
|
|
107
|
+
|
|
108
|
+
Simplified hook for theme toggling functionality.
|
|
109
|
+
|
|
110
|
+
```tsx
|
|
111
|
+
const {
|
|
112
|
+
mode, // Current mode
|
|
113
|
+
setMode, // Set specific mode
|
|
114
|
+
toggleMode, // Toggle between modes
|
|
115
|
+
isDark, // Boolean: is dark mode
|
|
116
|
+
isLight, // Boolean: is light mode
|
|
117
|
+
isAuto // Boolean: is auto mode
|
|
118
|
+
} = useThemeToggle();
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Components
|
|
122
|
+
|
|
123
|
+
#### ThemeToggle
|
|
124
|
+
|
|
125
|
+
A pre-built theme toggle button.
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
<ThemeToggle
|
|
129
|
+
size="md" // 'sm' | 'md' | 'lg'
|
|
130
|
+
showLabels={false} // Show text labels
|
|
131
|
+
className="custom-class"
|
|
132
|
+
style={{ margin: '10px' }}
|
|
133
|
+
/>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### ThemeSelector
|
|
137
|
+
|
|
138
|
+
A dropdown selector for theme modes.
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
<ThemeSelector
|
|
142
|
+
showLabels={true}
|
|
143
|
+
className="custom-class"
|
|
144
|
+
options={[
|
|
145
|
+
{ mode: 'light', label: 'Light', icon: '☀️' },
|
|
146
|
+
{ mode: 'dark', label: 'Dark', icon: '🌙' },
|
|
147
|
+
{ mode: 'auto', label: 'Auto', icon: '🌓' }
|
|
148
|
+
]}
|
|
149
|
+
/>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## 🎨 Custom Themes
|
|
153
|
+
|
|
154
|
+
### Creating Custom Themes
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
import { createTheme, lightTheme } from '@asafarim/react-themes';
|
|
158
|
+
|
|
159
|
+
const myCustomTheme = createTheme(lightTheme, {
|
|
160
|
+
name: 'my-theme',
|
|
161
|
+
colors: {
|
|
162
|
+
primary: '#ff6b6b',
|
|
163
|
+
primaryHover: '#ff5252',
|
|
164
|
+
background: '#f8f9fa',
|
|
165
|
+
text: '#212529'
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// Use with provider
|
|
170
|
+
<ThemeProvider customThemes={{ 'my-theme': myCustomTheme }}>
|
|
171
|
+
<App />
|
|
172
|
+
</ThemeProvider>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Using CSS Variables
|
|
176
|
+
|
|
177
|
+
The package automatically injects CSS variables that you can use in your styles:
|
|
178
|
+
|
|
179
|
+
```css
|
|
180
|
+
.my-component {
|
|
181
|
+
background-color: var(--theme-color-background);
|
|
182
|
+
color: var(--theme-color-text);
|
|
183
|
+
border: 1px solid var(--theme-color-border);
|
|
184
|
+
border-radius: var(--theme-radius-md);
|
|
185
|
+
padding: var(--theme-spacing-md);
|
|
186
|
+
transition: all var(--theme-transition-normal);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.my-button {
|
|
190
|
+
background-color: var(--theme-color-primary);
|
|
191
|
+
color: white;
|
|
192
|
+
font-size: var(--theme-font-size-sm);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.my-button:hover {
|
|
196
|
+
background-color: var(--theme-color-primary-hover);
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## 🎯 Integration with @asafarim/dd-menu
|
|
201
|
+
|
|
202
|
+
This package works seamlessly with `@asafarim/dd-menu`:
|
|
203
|
+
|
|
204
|
+
```tsx
|
|
205
|
+
import { DDMenu } from '@asafarim/dd-menu';
|
|
206
|
+
import { useTheme } from '@asafarim/react-themes';
|
|
207
|
+
|
|
208
|
+
function NavMenu() {
|
|
209
|
+
const { mode } = useTheme();
|
|
210
|
+
|
|
211
|
+
return (
|
|
212
|
+
<DDMenu
|
|
213
|
+
items={menuItems}
|
|
214
|
+
theme={mode} // Pass current theme mode
|
|
215
|
+
variant="navbar"
|
|
216
|
+
/>
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## 🔧 Advanced Usage
|
|
222
|
+
|
|
223
|
+
### Custom Theme Structure
|
|
224
|
+
|
|
225
|
+
```tsx
|
|
226
|
+
interface Theme {
|
|
227
|
+
name: string;
|
|
228
|
+
mode: 'light' | 'dark' | 'auto';
|
|
229
|
+
colors: {
|
|
230
|
+
background: string;
|
|
231
|
+
backgroundSecondary: string;
|
|
232
|
+
text: string;
|
|
233
|
+
textSecondary: string;
|
|
234
|
+
primary: string;
|
|
235
|
+
primaryHover: string;
|
|
236
|
+
border: string;
|
|
237
|
+
// ... more colors
|
|
238
|
+
};
|
|
239
|
+
spacing: {
|
|
240
|
+
xs: string;
|
|
241
|
+
sm: string;
|
|
242
|
+
md: string;
|
|
243
|
+
lg: string;
|
|
244
|
+
// ... more spacing
|
|
245
|
+
};
|
|
246
|
+
// ... typography, radius, transitions, zIndex
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Programmatic Theme Application
|
|
251
|
+
|
|
252
|
+
```tsx
|
|
253
|
+
import { applyTheme } from '@asafarim/react-themes';
|
|
254
|
+
|
|
255
|
+
// Apply theme manually
|
|
256
|
+
applyTheme(customTheme, 'dark');
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## 🌍 Browser Support
|
|
260
|
+
|
|
261
|
+
- Modern browsers with CSS custom properties support
|
|
262
|
+
- Chrome 49+
|
|
263
|
+
- Firefox 31+
|
|
264
|
+
- Safari 9.1+
|
|
265
|
+
- Edge 16+
|
|
266
|
+
|
|
267
|
+
## 🤝 Contributing
|
|
268
|
+
|
|
269
|
+
Contributions are welcome! Please read our contributing guidelines and submit a pull request.
|
|
270
|
+
|
|
271
|
+
## 📄 License
|
|
272
|
+
|
|
273
|
+
MIT License - see the [LICENSE](LICENSE) file for details.
|
|
274
|
+
|
|
275
|
+
## 🔗 Related Packages
|
|
276
|
+
|
|
277
|
+
- [`@asafarim/dd-menu`](https://www.npmjs.com/package/@asafarim/dd-menu) - Elegant dropdown menu component
|
|
278
|
+
|
|
279
|
+
## 📝 Changelog
|
|
280
|
+
|
|
281
|
+
### 1.0.0
|
|
282
|
+
- Initial release
|
|
283
|
+
- Theme provider with auto mode detection
|
|
284
|
+
- CSS variable injection
|
|
285
|
+
- Built-in components (ThemeToggle, ThemeSelector)
|
|
286
|
+
- TypeScript support
|
|
287
|
+
- localStorage persistence
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
Made with ❤️ by [ASafariM](https://github.com/AliSafari-IT)
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import * as React$1 from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
type ThemeMode = 'light' | 'dark' | 'auto';
|
|
5
|
+
interface ThemeColors {
|
|
6
|
+
background: string;
|
|
7
|
+
backgroundSecondary: string;
|
|
8
|
+
backgroundTertiary: string;
|
|
9
|
+
text: string;
|
|
10
|
+
textSecondary: string;
|
|
11
|
+
textMuted: string;
|
|
12
|
+
border: string;
|
|
13
|
+
borderLight: string;
|
|
14
|
+
borderHover: string;
|
|
15
|
+
primary: string;
|
|
16
|
+
primaryHover: string;
|
|
17
|
+
primaryActive: string;
|
|
18
|
+
success: string;
|
|
19
|
+
warning: string;
|
|
20
|
+
error: string;
|
|
21
|
+
info: string;
|
|
22
|
+
hover: string;
|
|
23
|
+
active: string;
|
|
24
|
+
focus: string;
|
|
25
|
+
shadow: string;
|
|
26
|
+
shadowMd: string;
|
|
27
|
+
shadowLg: string;
|
|
28
|
+
}
|
|
29
|
+
interface ThemeSpacing {
|
|
30
|
+
xs: string;
|
|
31
|
+
sm: string;
|
|
32
|
+
md: string;
|
|
33
|
+
lg: string;
|
|
34
|
+
xl: string;
|
|
35
|
+
'2xl': string;
|
|
36
|
+
'3xl': string;
|
|
37
|
+
'4xl': string;
|
|
38
|
+
}
|
|
39
|
+
interface ThemeRadius {
|
|
40
|
+
none: string;
|
|
41
|
+
sm: string;
|
|
42
|
+
md: string;
|
|
43
|
+
lg: string;
|
|
44
|
+
xl: string;
|
|
45
|
+
'2xl': string;
|
|
46
|
+
full: string;
|
|
47
|
+
}
|
|
48
|
+
interface ThemeTypography {
|
|
49
|
+
fontFamily: {
|
|
50
|
+
sans: string;
|
|
51
|
+
serif: string;
|
|
52
|
+
mono: string;
|
|
53
|
+
};
|
|
54
|
+
fontSize: {
|
|
55
|
+
xs: string;
|
|
56
|
+
sm: string;
|
|
57
|
+
base: string;
|
|
58
|
+
lg: string;
|
|
59
|
+
xl: string;
|
|
60
|
+
'2xl': string;
|
|
61
|
+
'3xl': string;
|
|
62
|
+
'4xl': string;
|
|
63
|
+
'5xl': string;
|
|
64
|
+
};
|
|
65
|
+
fontWeight: {
|
|
66
|
+
light: string;
|
|
67
|
+
normal: string;
|
|
68
|
+
medium: string;
|
|
69
|
+
semibold: string;
|
|
70
|
+
bold: string;
|
|
71
|
+
};
|
|
72
|
+
lineHeight: {
|
|
73
|
+
tight: string;
|
|
74
|
+
normal: string;
|
|
75
|
+
relaxed: string;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
interface ThemeTransitions {
|
|
79
|
+
fast: string;
|
|
80
|
+
normal: string;
|
|
81
|
+
slow: string;
|
|
82
|
+
bounce: string;
|
|
83
|
+
}
|
|
84
|
+
interface Theme {
|
|
85
|
+
name: string;
|
|
86
|
+
mode: ThemeMode;
|
|
87
|
+
colors: ThemeColors;
|
|
88
|
+
spacing: ThemeSpacing;
|
|
89
|
+
radius: ThemeRadius;
|
|
90
|
+
typography: ThemeTypography;
|
|
91
|
+
transitions: ThemeTransitions;
|
|
92
|
+
zIndex: {
|
|
93
|
+
dropdown: number;
|
|
94
|
+
modal: number;
|
|
95
|
+
tooltip: number;
|
|
96
|
+
overlay: number;
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
interface ThemeContextValue {
|
|
100
|
+
theme: Theme;
|
|
101
|
+
mode: ThemeMode;
|
|
102
|
+
setMode: (mode: ThemeMode) => void;
|
|
103
|
+
toggleMode: () => void;
|
|
104
|
+
isDark: boolean;
|
|
105
|
+
isLight: boolean;
|
|
106
|
+
isAuto: boolean;
|
|
107
|
+
systemPrefersDark: boolean;
|
|
108
|
+
applyTheme: (customTheme: Partial<Theme>) => void;
|
|
109
|
+
resetTheme: () => void;
|
|
110
|
+
}
|
|
111
|
+
interface ThemeProviderProps$1 {
|
|
112
|
+
children: React.ReactNode;
|
|
113
|
+
defaultMode?: ThemeMode;
|
|
114
|
+
customTheme?: Partial<Theme>;
|
|
115
|
+
storageKey?: string;
|
|
116
|
+
enableTransitions?: boolean;
|
|
117
|
+
className?: string;
|
|
118
|
+
style?: React.CSSProperties;
|
|
119
|
+
}
|
|
120
|
+
interface UseThemeOptions {
|
|
121
|
+
defaultMode?: ThemeMode;
|
|
122
|
+
storageKey?: string;
|
|
123
|
+
}
|
|
124
|
+
interface ThemeConfig {
|
|
125
|
+
defaultMode?: ThemeMode;
|
|
126
|
+
defaultTheme?: string;
|
|
127
|
+
persistMode?: boolean;
|
|
128
|
+
storageKey?: string;
|
|
129
|
+
enableTransitions?: boolean;
|
|
130
|
+
customThemes?: Record<string, Theme>;
|
|
131
|
+
}
|
|
132
|
+
interface ThemeVariables {
|
|
133
|
+
colors: Record<keyof ThemeColors, string>;
|
|
134
|
+
spacing: Record<keyof ThemeSpacing, string>;
|
|
135
|
+
radius: Record<keyof ThemeRadius, string>;
|
|
136
|
+
typography: {
|
|
137
|
+
fontFamily: Record<keyof ThemeTypography['fontFamily'], string>;
|
|
138
|
+
fontSize: Record<keyof ThemeTypography['fontSize'], string>;
|
|
139
|
+
fontWeight: Record<keyof ThemeTypography['fontWeight'], string>;
|
|
140
|
+
lineHeight: Record<keyof ThemeTypography['lineHeight'], string>;
|
|
141
|
+
};
|
|
142
|
+
transitions: Record<keyof ThemeTransitions, string>;
|
|
143
|
+
zIndex: Record<keyof Theme['zIndex'], string>;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
declare const lightTheme: Theme;
|
|
147
|
+
declare const darkTheme: Theme;
|
|
148
|
+
declare const defaultTheme: Theme;
|
|
149
|
+
declare const themes: {
|
|
150
|
+
light: Theme;
|
|
151
|
+
dark: Theme;
|
|
152
|
+
};
|
|
153
|
+
declare const defaultThemes: {
|
|
154
|
+
default: Theme;
|
|
155
|
+
light: Theme;
|
|
156
|
+
dark: Theme;
|
|
157
|
+
};
|
|
158
|
+
declare function mergeTheme(baseTheme: Theme, customTheme: Partial<Theme>): Theme;
|
|
159
|
+
|
|
160
|
+
interface ThemeContextType {
|
|
161
|
+
currentTheme: Theme;
|
|
162
|
+
mode: ThemeMode;
|
|
163
|
+
setMode: (mode: ThemeMode) => void;
|
|
164
|
+
setTheme: (theme: Theme) => void;
|
|
165
|
+
themes: Record<string, Theme>;
|
|
166
|
+
toggleMode: () => void;
|
|
167
|
+
}
|
|
168
|
+
interface ThemeProviderProps {
|
|
169
|
+
children: ReactNode;
|
|
170
|
+
config?: ThemeConfig;
|
|
171
|
+
defaultMode?: ThemeMode;
|
|
172
|
+
defaultTheme?: string;
|
|
173
|
+
persistMode?: boolean;
|
|
174
|
+
storageKey?: string;
|
|
175
|
+
customThemes?: Record<string, Theme>;
|
|
176
|
+
}
|
|
177
|
+
declare const ThemeProvider: React$1.FC<ThemeProviderProps>;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Hook to access theme context
|
|
181
|
+
*/
|
|
182
|
+
declare function useTheme(): ThemeContextType;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Hook that provides theme toggle functionality
|
|
186
|
+
*/
|
|
187
|
+
declare function useThemeToggle(): {
|
|
188
|
+
mode: ThemeMode;
|
|
189
|
+
setMode: (mode: ThemeMode) => void;
|
|
190
|
+
toggleMode: () => void;
|
|
191
|
+
isDark: boolean;
|
|
192
|
+
isLight: boolean;
|
|
193
|
+
isAuto: boolean;
|
|
194
|
+
effectiveMode: "light" | "dark";
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
interface ThemeToggleProps {
|
|
198
|
+
className?: string;
|
|
199
|
+
style?: React$1.CSSProperties;
|
|
200
|
+
showLabels?: boolean;
|
|
201
|
+
size?: 'sm' | 'md' | 'lg';
|
|
202
|
+
}
|
|
203
|
+
declare const ThemeToggle: React$1.FC<ThemeToggleProps>;
|
|
204
|
+
|
|
205
|
+
interface ThemeSelectorProps {
|
|
206
|
+
className?: string;
|
|
207
|
+
style?: React$1.CSSProperties;
|
|
208
|
+
showLabels?: boolean;
|
|
209
|
+
options?: Array<{
|
|
210
|
+
mode: ThemeMode;
|
|
211
|
+
label: string;
|
|
212
|
+
icon?: string;
|
|
213
|
+
}>;
|
|
214
|
+
}
|
|
215
|
+
declare const ThemeSelector: React$1.FC<ThemeSelectorProps>;
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Creates a new theme by merging a base theme with custom properties
|
|
219
|
+
*/
|
|
220
|
+
declare function createTheme(baseTheme: Theme, customTheme: Partial<Theme>): Theme;
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Applies theme CSS variables to the document root
|
|
224
|
+
*/
|
|
225
|
+
declare function applyTheme(theme: Theme, mode: ThemeMode): void;
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Merges multiple themes into a single theme
|
|
229
|
+
* Later themes in the array take precedence over earlier ones
|
|
230
|
+
*/
|
|
231
|
+
declare function mergeThemes(...themes: Array<Theme | Partial<Theme>>): Theme;
|
|
232
|
+
/**
|
|
233
|
+
* Merges theme colors only
|
|
234
|
+
*/
|
|
235
|
+
declare function mergeThemeColors(baseColors: Theme['colors'], ...colorSets: Array<Partial<Theme['colors']>>): Theme['colors'];
|
|
236
|
+
/**
|
|
237
|
+
* Deep merge utility for complex theme objects
|
|
238
|
+
*/
|
|
239
|
+
declare function deepMergeThemes(target: Theme, ...sources: Array<Partial<Theme>>): Theme;
|
|
240
|
+
|
|
241
|
+
export { type Theme, type ThemeColors, type ThemeConfig, type ThemeContextType, type ThemeContextValue, type ThemeMode, ThemeProvider, type ThemeProviderProps$1 as ThemeProviderProps, type ThemeRadius, ThemeSelector, type ThemeSpacing, ThemeToggle, type ThemeTransitions, type ThemeTypography, type ThemeVariables, type UseThemeOptions, applyTheme, createTheme, darkTheme, deepMergeThemes, ThemeProvider as default, defaultTheme, defaultThemes, lightTheme, mergeTheme, mergeThemeColors, mergeThemes, themes, useTheme, useThemeToggle };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import * as React$1 from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
type ThemeMode = 'light' | 'dark' | 'auto';
|
|
5
|
+
interface ThemeColors {
|
|
6
|
+
background: string;
|
|
7
|
+
backgroundSecondary: string;
|
|
8
|
+
backgroundTertiary: string;
|
|
9
|
+
text: string;
|
|
10
|
+
textSecondary: string;
|
|
11
|
+
textMuted: string;
|
|
12
|
+
border: string;
|
|
13
|
+
borderLight: string;
|
|
14
|
+
borderHover: string;
|
|
15
|
+
primary: string;
|
|
16
|
+
primaryHover: string;
|
|
17
|
+
primaryActive: string;
|
|
18
|
+
success: string;
|
|
19
|
+
warning: string;
|
|
20
|
+
error: string;
|
|
21
|
+
info: string;
|
|
22
|
+
hover: string;
|
|
23
|
+
active: string;
|
|
24
|
+
focus: string;
|
|
25
|
+
shadow: string;
|
|
26
|
+
shadowMd: string;
|
|
27
|
+
shadowLg: string;
|
|
28
|
+
}
|
|
29
|
+
interface ThemeSpacing {
|
|
30
|
+
xs: string;
|
|
31
|
+
sm: string;
|
|
32
|
+
md: string;
|
|
33
|
+
lg: string;
|
|
34
|
+
xl: string;
|
|
35
|
+
'2xl': string;
|
|
36
|
+
'3xl': string;
|
|
37
|
+
'4xl': string;
|
|
38
|
+
}
|
|
39
|
+
interface ThemeRadius {
|
|
40
|
+
none: string;
|
|
41
|
+
sm: string;
|
|
42
|
+
md: string;
|
|
43
|
+
lg: string;
|
|
44
|
+
xl: string;
|
|
45
|
+
'2xl': string;
|
|
46
|
+
full: string;
|
|
47
|
+
}
|
|
48
|
+
interface ThemeTypography {
|
|
49
|
+
fontFamily: {
|
|
50
|
+
sans: string;
|
|
51
|
+
serif: string;
|
|
52
|
+
mono: string;
|
|
53
|
+
};
|
|
54
|
+
fontSize: {
|
|
55
|
+
xs: string;
|
|
56
|
+
sm: string;
|
|
57
|
+
base: string;
|
|
58
|
+
lg: string;
|
|
59
|
+
xl: string;
|
|
60
|
+
'2xl': string;
|
|
61
|
+
'3xl': string;
|
|
62
|
+
'4xl': string;
|
|
63
|
+
'5xl': string;
|
|
64
|
+
};
|
|
65
|
+
fontWeight: {
|
|
66
|
+
light: string;
|
|
67
|
+
normal: string;
|
|
68
|
+
medium: string;
|
|
69
|
+
semibold: string;
|
|
70
|
+
bold: string;
|
|
71
|
+
};
|
|
72
|
+
lineHeight: {
|
|
73
|
+
tight: string;
|
|
74
|
+
normal: string;
|
|
75
|
+
relaxed: string;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
interface ThemeTransitions {
|
|
79
|
+
fast: string;
|
|
80
|
+
normal: string;
|
|
81
|
+
slow: string;
|
|
82
|
+
bounce: string;
|
|
83
|
+
}
|
|
84
|
+
interface Theme {
|
|
85
|
+
name: string;
|
|
86
|
+
mode: ThemeMode;
|
|
87
|
+
colors: ThemeColors;
|
|
88
|
+
spacing: ThemeSpacing;
|
|
89
|
+
radius: ThemeRadius;
|
|
90
|
+
typography: ThemeTypography;
|
|
91
|
+
transitions: ThemeTransitions;
|
|
92
|
+
zIndex: {
|
|
93
|
+
dropdown: number;
|
|
94
|
+
modal: number;
|
|
95
|
+
tooltip: number;
|
|
96
|
+
overlay: number;
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
interface ThemeContextValue {
|
|
100
|
+
theme: Theme;
|
|
101
|
+
mode: ThemeMode;
|
|
102
|
+
setMode: (mode: ThemeMode) => void;
|
|
103
|
+
toggleMode: () => void;
|
|
104
|
+
isDark: boolean;
|
|
105
|
+
isLight: boolean;
|
|
106
|
+
isAuto: boolean;
|
|
107
|
+
systemPrefersDark: boolean;
|
|
108
|
+
applyTheme: (customTheme: Partial<Theme>) => void;
|
|
109
|
+
resetTheme: () => void;
|
|
110
|
+
}
|
|
111
|
+
interface ThemeProviderProps$1 {
|
|
112
|
+
children: React.ReactNode;
|
|
113
|
+
defaultMode?: ThemeMode;
|
|
114
|
+
customTheme?: Partial<Theme>;
|
|
115
|
+
storageKey?: string;
|
|
116
|
+
enableTransitions?: boolean;
|
|
117
|
+
className?: string;
|
|
118
|
+
style?: React.CSSProperties;
|
|
119
|
+
}
|
|
120
|
+
interface UseThemeOptions {
|
|
121
|
+
defaultMode?: ThemeMode;
|
|
122
|
+
storageKey?: string;
|
|
123
|
+
}
|
|
124
|
+
interface ThemeConfig {
|
|
125
|
+
defaultMode?: ThemeMode;
|
|
126
|
+
defaultTheme?: string;
|
|
127
|
+
persistMode?: boolean;
|
|
128
|
+
storageKey?: string;
|
|
129
|
+
enableTransitions?: boolean;
|
|
130
|
+
customThemes?: Record<string, Theme>;
|
|
131
|
+
}
|
|
132
|
+
interface ThemeVariables {
|
|
133
|
+
colors: Record<keyof ThemeColors, string>;
|
|
134
|
+
spacing: Record<keyof ThemeSpacing, string>;
|
|
135
|
+
radius: Record<keyof ThemeRadius, string>;
|
|
136
|
+
typography: {
|
|
137
|
+
fontFamily: Record<keyof ThemeTypography['fontFamily'], string>;
|
|
138
|
+
fontSize: Record<keyof ThemeTypography['fontSize'], string>;
|
|
139
|
+
fontWeight: Record<keyof ThemeTypography['fontWeight'], string>;
|
|
140
|
+
lineHeight: Record<keyof ThemeTypography['lineHeight'], string>;
|
|
141
|
+
};
|
|
142
|
+
transitions: Record<keyof ThemeTransitions, string>;
|
|
143
|
+
zIndex: Record<keyof Theme['zIndex'], string>;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
declare const lightTheme: Theme;
|
|
147
|
+
declare const darkTheme: Theme;
|
|
148
|
+
declare const defaultTheme: Theme;
|
|
149
|
+
declare const themes: {
|
|
150
|
+
light: Theme;
|
|
151
|
+
dark: Theme;
|
|
152
|
+
};
|
|
153
|
+
declare const defaultThemes: {
|
|
154
|
+
default: Theme;
|
|
155
|
+
light: Theme;
|
|
156
|
+
dark: Theme;
|
|
157
|
+
};
|
|
158
|
+
declare function mergeTheme(baseTheme: Theme, customTheme: Partial<Theme>): Theme;
|
|
159
|
+
|
|
160
|
+
interface ThemeContextType {
|
|
161
|
+
currentTheme: Theme;
|
|
162
|
+
mode: ThemeMode;
|
|
163
|
+
setMode: (mode: ThemeMode) => void;
|
|
164
|
+
setTheme: (theme: Theme) => void;
|
|
165
|
+
themes: Record<string, Theme>;
|
|
166
|
+
toggleMode: () => void;
|
|
167
|
+
}
|
|
168
|
+
interface ThemeProviderProps {
|
|
169
|
+
children: ReactNode;
|
|
170
|
+
config?: ThemeConfig;
|
|
171
|
+
defaultMode?: ThemeMode;
|
|
172
|
+
defaultTheme?: string;
|
|
173
|
+
persistMode?: boolean;
|
|
174
|
+
storageKey?: string;
|
|
175
|
+
customThemes?: Record<string, Theme>;
|
|
176
|
+
}
|
|
177
|
+
declare const ThemeProvider: React$1.FC<ThemeProviderProps>;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Hook to access theme context
|
|
181
|
+
*/
|
|
182
|
+
declare function useTheme(): ThemeContextType;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Hook that provides theme toggle functionality
|
|
186
|
+
*/
|
|
187
|
+
declare function useThemeToggle(): {
|
|
188
|
+
mode: ThemeMode;
|
|
189
|
+
setMode: (mode: ThemeMode) => void;
|
|
190
|
+
toggleMode: () => void;
|
|
191
|
+
isDark: boolean;
|
|
192
|
+
isLight: boolean;
|
|
193
|
+
isAuto: boolean;
|
|
194
|
+
effectiveMode: "light" | "dark";
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
interface ThemeToggleProps {
|
|
198
|
+
className?: string;
|
|
199
|
+
style?: React$1.CSSProperties;
|
|
200
|
+
showLabels?: boolean;
|
|
201
|
+
size?: 'sm' | 'md' | 'lg';
|
|
202
|
+
}
|
|
203
|
+
declare const ThemeToggle: React$1.FC<ThemeToggleProps>;
|
|
204
|
+
|
|
205
|
+
interface ThemeSelectorProps {
|
|
206
|
+
className?: string;
|
|
207
|
+
style?: React$1.CSSProperties;
|
|
208
|
+
showLabels?: boolean;
|
|
209
|
+
options?: Array<{
|
|
210
|
+
mode: ThemeMode;
|
|
211
|
+
label: string;
|
|
212
|
+
icon?: string;
|
|
213
|
+
}>;
|
|
214
|
+
}
|
|
215
|
+
declare const ThemeSelector: React$1.FC<ThemeSelectorProps>;
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Creates a new theme by merging a base theme with custom properties
|
|
219
|
+
*/
|
|
220
|
+
declare function createTheme(baseTheme: Theme, customTheme: Partial<Theme>): Theme;
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Applies theme CSS variables to the document root
|
|
224
|
+
*/
|
|
225
|
+
declare function applyTheme(theme: Theme, mode: ThemeMode): void;
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Merges multiple themes into a single theme
|
|
229
|
+
* Later themes in the array take precedence over earlier ones
|
|
230
|
+
*/
|
|
231
|
+
declare function mergeThemes(...themes: Array<Theme | Partial<Theme>>): Theme;
|
|
232
|
+
/**
|
|
233
|
+
* Merges theme colors only
|
|
234
|
+
*/
|
|
235
|
+
declare function mergeThemeColors(baseColors: Theme['colors'], ...colorSets: Array<Partial<Theme['colors']>>): Theme['colors'];
|
|
236
|
+
/**
|
|
237
|
+
* Deep merge utility for complex theme objects
|
|
238
|
+
*/
|
|
239
|
+
declare function deepMergeThemes(target: Theme, ...sources: Array<Partial<Theme>>): Theme;
|
|
240
|
+
|
|
241
|
+
export { type Theme, type ThemeColors, type ThemeConfig, type ThemeContextType, type ThemeContextValue, type ThemeMode, ThemeProvider, type ThemeProviderProps$1 as ThemeProviderProps, type ThemeRadius, ThemeSelector, type ThemeSpacing, ThemeToggle, type ThemeTransitions, type ThemeTypography, type ThemeVariables, type UseThemeOptions, applyTheme, createTheme, darkTheme, deepMergeThemes, ThemeProvider as default, defaultTheme, defaultThemes, lightTheme, mergeTheme, mergeThemeColors, mergeThemes, themes, useTheme, useThemeToggle };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";var b=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var Q=Object.prototype.hasOwnProperty;var U=(e,t)=>{for(var a in t)b(e,a,{get:t[a],enumerable:!0})},Z=(e,t,a,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of G(t))!Q.call(e,o)&&o!==a&&b(e,o,{get:()=>t[o],enumerable:!(r=B(t,o))||r.enumerable});return e};var q=e=>Z(b({},"__esModule",{value:!0}),e);var te={};U(te,{ThemeProvider:()=>v,ThemeSelector:()=>I,ThemeToggle:()=>A,applyTheme:()=>f,createTheme:()=>H,darkTheme:()=>k,deepMergeThemes:()=>R,default:()=>v,defaultTheme:()=>X,defaultThemes:()=>w,lightTheme:()=>h,mergeTheme:()=>_,mergeThemeColors:()=>L,mergeThemes:()=>N,themes:()=>Y,useTheme:()=>c,useThemeToggle:()=>E});module.exports=q(te);var J={background:"#ffffff",backgroundSecondary:"#f8fafc",backgroundTertiary:"#f1f5f9",text:"#0f172a",textSecondary:"#475569",textMuted:"#64748b",border:"#e2e8f0",borderLight:"#f1f5f9",borderHover:"#cbd5e1",primary:"#3b82f6",primaryHover:"#2563eb",primaryActive:"#1d4ed8",success:"#10b981",warning:"#f59e0b",error:"#ef4444",info:"#06b6d4",hover:"#f8fafc",active:"#f1f5f9",focus:"rgba(59, 130, 246, 0.1)",shadow:"0 1px 2px 0 rgba(0, 0, 0, 0.05)",shadowMd:"0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",shadowLg:"0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)"},K={background:"#0f172a",backgroundSecondary:"#1e293b",backgroundTertiary:"#334155",text:"#f8fafc",textSecondary:"#cbd5e1",textMuted:"#94a3b8",border:"#334155",borderLight:"#475569",borderHover:"#64748b",primary:"#60a5fa",primaryHover:"#3b82f6",primaryActive:"#2563eb",success:"#34d399",warning:"#fbbf24",error:"#f87171",info:"#22d3ee",hover:"#1e293b",active:"#334155",focus:"rgba(96, 165, 250, 0.1)",shadow:"0 1px 2px 0 rgba(0, 0, 0, 0.3)",shadowMd:"0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.3)",shadowLg:"0 10px 15px -3px rgba(0, 0, 0, 0.4), 0 4px 6px -2px rgba(0, 0, 0, 0.3)"},S={spacing:{xs:"0.25rem",sm:"0.5rem",md:"0.75rem",lg:"1rem",xl:"1.25rem","2xl":"1.5rem","3xl":"2rem","4xl":"3rem"},radius:{none:"0",sm:"0.25rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem",full:"9999px"},typography:{fontFamily:{sans:'ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif',serif:'ui-serif, Georgia, Cambria, "Times New Roman", Times, serif',mono:'ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo, monospace'},fontSize:{xs:"0.75rem",sm:"0.875rem",base:"1rem",lg:"1.125rem",xl:"1.25rem","2xl":"1.5rem","3xl":"1.875rem","4xl":"2.25rem","5xl":"3rem"},fontWeight:{light:"300",normal:"400",medium:"500",semibold:"600",bold:"700"},lineHeight:{tight:"1.25",normal:"1.5",relaxed:"1.75"}},transitions:{fast:"all 0.1s ease",normal:"all 0.2s ease",slow:"all 0.3s ease",bounce:"all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55)"},zIndex:{dropdown:1e3,modal:1050,tooltip:1100,overlay:1200}},h={name:"light",mode:"light",colors:J,...S},k={name:"dark",mode:"dark",colors:K,...S},X=h,Y={light:h,dark:k},w={default:h,light:h,dark:k};function _(e,t){return{...e,...t,colors:{...e.colors,...t.colors},spacing:{...e.spacing,...t.spacing},radius:{...e.radius,...t.radius},typography:{...e.typography,...t.typography,fontFamily:{...e.typography.fontFamily,...t.typography?.fontFamily},fontSize:{...e.typography.fontSize,...t.typography?.fontSize},fontWeight:{...e.typography.fontWeight,...t.typography?.fontWeight},lineHeight:{...e.typography.lineHeight,...t.typography?.lineHeight}},transitions:{...e.transitions,...t.transitions},zIndex:{...e.zIndex,...t.zIndex}}}var d=require("react");function f(e,t){if(typeof document>"u")return;let a=document.documentElement,r=t;t==="auto"&&(r=window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"),a.setAttribute("data-theme",e.name),a.setAttribute("data-theme-mode",r),Object.entries(e.colors).forEach(([o,n])=>{a.style.setProperty(`--theme-color-${P(o)}`,n)}),Object.entries(e.spacing).forEach(([o,n])=>{a.style.setProperty(`--theme-spacing-${o}`,n)}),Object.entries(e.radius).forEach(([o,n])=>{a.style.setProperty(`--theme-radius-${o}`,n)}),Object.entries(e.typography.fontFamily).forEach(([o,n])=>{a.style.setProperty(`--theme-font-family-${o}`,n)}),Object.entries(e.typography.fontSize).forEach(([o,n])=>{a.style.setProperty(`--theme-font-size-${o}`,n)}),Object.entries(e.typography.fontWeight).forEach(([o,n])=>{a.style.setProperty(`--theme-font-weight-${o}`,n)}),Object.entries(e.typography.lineHeight).forEach(([o,n])=>{a.style.setProperty(`--theme-line-height-${o}`,n)}),Object.entries(e.transitions).forEach(([o,n])=>{a.style.setProperty(`--theme-transition-${o}`,n)}),Object.entries(e.zIndex).forEach(([o,n])=>{a.style.setProperty(`--theme-z-index-${P(o)}`,n.toString())}),document.body.className=document.body.className.replace(/theme-\w+/g,""),document.body.classList.add(`theme-${e.name}`,`theme-${r}`)}function P(e){return e.replace(/[A-Z]/g,t=>`-${t.toLowerCase()}`)}var $=require("react/jsx-runtime"),z=(0,d.createContext)(void 0),v=({children:e,defaultMode:t="auto",defaultTheme:a="default",persistMode:r=!0,storageKey:o="asafarim-theme-mode",customThemes:n={}})=>{let l={...w,...n},i=()=>{if(!r||typeof window>"u")return t;try{let s=localStorage.getItem(o);if(s&&["light","dark","auto"].includes(s))return s}catch(s){console.warn("Failed to read theme mode from localStorage:",s)}return t},[m,p]=(0,d.useState)(i),[y,W]=(0,d.useState)(a),j=()=>m==="auto"?typeof window<"u"&&window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":m,C=()=>{let s=j();return y!=="default"&&y in l?l[y]:s==="dark"?l.dark:l.light},x=C(),T=s=>{if(p(s),r&&typeof window<"u")try{localStorage.setItem(o,s)}catch(u){console.warn("Failed to save theme mode to localStorage:",u)}},O=()=>{if(m==="auto"){let s=window.matchMedia("(prefers-color-scheme: dark)").matches;T(s?"light":"dark")}else T(m==="light"?"dark":"light")},D=s=>{W(s.name)};(0,d.useEffect)(()=>{f(x,m)},[x,m,y]),(0,d.useEffect)(()=>{if(m!=="auto")return;let s=window.matchMedia("(prefers-color-scheme: dark)"),u=()=>{f(C(),m)};return s.addEventListener("change",u),()=>s.removeEventListener("change",u)},[m]);let V={currentTheme:x,mode:m,setMode:T,setTheme:D,themes:l,toggleMode:O};return(0,$.jsx)(z.Provider,{value:V,children:e})},F=()=>{let e=(0,d.useContext)(z);if(e===void 0)throw new Error("useThemeContext must be used within a ThemeProvider");return e};function c(){return F()}function E(){let{mode:e,setMode:t,toggleMode:a}=c(),o=e==="auto"?typeof window<"u"&&window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":e;return{mode:e,setMode:t,toggleMode:a,isDark:o==="dark",isLight:o==="light",isAuto:e==="auto",effectiveMode:o}}var g=require("react/jsx-runtime"),A=({className:e="",style:t={},showLabels:a=!1,size:r="md"})=>{let{mode:o,toggleMode:n}=c(),i=`
|
|
2
|
+
${{sm:"w-8 h-8 text-sm",md:"w-10 h-10 text-base",lg:"w-12 h-12 text-lg"}[r]}
|
|
3
|
+
inline-flex items-center justify-center
|
|
4
|
+
rounded-md border border-gray-300
|
|
5
|
+
bg-white hover:bg-gray-50
|
|
6
|
+
dark:bg-gray-800 dark:border-gray-600 dark:hover:bg-gray-700
|
|
7
|
+
focus:outline-none focus:ring-2 focus:ring-blue-500
|
|
8
|
+
transition-all duration-200
|
|
9
|
+
${e}
|
|
10
|
+
`.trim(),m=()=>{switch(o){case"light":return"\u2600\uFE0F";case"dark":return"\u{1F319}";case"auto":default:return"\u{1F313}"}},p=()=>{switch(o){case"light":return"Light";case"dark":return"Dark";case"auto":default:return"Auto"}};return(0,g.jsxs)("button",{onClick:n,className:i,style:t,title:`Current theme: ${p()}. Click to toggle.`,"aria-label":`Switch theme. Current: ${p()}`,children:[(0,g.jsx)("span",{role:"img","aria-hidden":"true",children:m()}),a&&(0,g.jsx)("span",{className:"ml-2 text-sm font-medium",children:p()})]})};var M=require("react/jsx-runtime"),I=({className:e="",style:t={},showLabels:a=!0,options:r=[{mode:"light",label:"Light",icon:"\u2600\uFE0F"},{mode:"dark",label:"Dark",icon:"\u{1F319}"},{mode:"auto",label:"Auto",icon:"\u{1F313}"}]})=>{let{mode:o,setMode:n}=c(),l=`
|
|
11
|
+
px-3 py-2 border border-gray-300 rounded-md
|
|
12
|
+
bg-white dark:bg-gray-800 dark:border-gray-600
|
|
13
|
+
text-gray-900 dark:text-gray-100
|
|
14
|
+
focus:outline-none focus:ring-2 focus:ring-blue-500
|
|
15
|
+
transition-all duration-200
|
|
16
|
+
${e}
|
|
17
|
+
`.trim();return(0,M.jsx)("select",{value:o,onChange:i=>n(i.target.value),className:l,style:t,"aria-label":"Select theme mode",children:r.map(i=>(0,M.jsx)("option",{value:i.mode,children:a?`${i.icon?i.icon+" ":""}${i.label}`:i.icon||i.label},i.mode))})};function H(e,t){return{...e,...t,name:t.name||`${e.name}-custom`,colors:{...e.colors,...t.colors},spacing:{...e.spacing,...t.spacing},radius:{...e.radius,...t.radius},typography:{...e.typography,...t.typography,fontFamily:{...e.typography.fontFamily,...t.typography?.fontFamily},fontSize:{...e.typography.fontSize,...t.typography?.fontSize},fontWeight:{...e.typography.fontWeight,...t.typography?.fontWeight},lineHeight:{...e.typography.lineHeight,...t.typography?.lineHeight}},transitions:{...e.transitions,...t.transitions},zIndex:{...e.zIndex,...t.zIndex}}}function N(...e){if(e.length===0)throw new Error("At least one theme must be provided to mergeThemes");let[t,...a]=e;if(!ee(t))throw new Error("First theme must be a complete theme object");return a.reduce((r,o)=>({...r,...o,name:o.name||r.name,mode:o.mode||r.mode,colors:{...r.colors,...o.colors},spacing:{...r.spacing,...o.spacing},radius:{...r.radius,...o.radius},typography:{...r.typography,...o.typography,fontFamily:{...r.typography.fontFamily,...o.typography?.fontFamily},fontSize:{...r.typography.fontSize,...o.typography?.fontSize},fontWeight:{...r.typography.fontWeight,...o.typography?.fontWeight},lineHeight:{...r.typography.lineHeight,...o.typography?.lineHeight}},transitions:{...r.transitions,...o.transitions},zIndex:{...r.zIndex,...o.zIndex}}),t)}function ee(e){return!!(e&&typeof e=="object"&&"name"in e&&"mode"in e&&"colors"in e&&"spacing"in e&&"radius"in e&&"typography"in e&&"transitions"in e&&"zIndex"in e)}function L(e,...t){return t.reduce((a,r)=>({...a,...r}),e)}function R(e,...t){return t.reduce((a,r)=>{let o={...a};for(let n in r){let l=r[n],i=a[n];l&&typeof l=="object"&&!Array.isArray(l)&&i&&typeof i=="object"?o[n]={...i,...l}:l!==void 0&&(o[n]=l)}return o},e)}0&&(module.exports={ThemeProvider,ThemeSelector,ThemeToggle,applyTheme,createTheme,darkTheme,deepMergeThemes,defaultTheme,defaultThemes,lightTheme,mergeTheme,mergeThemeColors,mergeThemes,themes,useTheme,useThemeToggle});
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/themes.ts","../src/components/ThemeProvider.tsx","../src/utils/applyTheme.ts","../src/hooks/useTheme.ts","../src/hooks/useThemeToggle.ts","../src/components/ThemeToggle.tsx","../src/components/ThemeSelector.tsx","../src/utils/createTheme.ts","../src/utils/mergeThemes.ts"],"sourcesContent":["// @asafarim/react-themes - A comprehensive theme management system for React apps\r\n// Export all types and interfaces\r\nexport * from './types';\r\n\r\n// Export all themes and utilities\r\nexport * from './themes';\r\n\r\n// Export main components and hooks\r\nexport { ThemeProvider } from './components/ThemeProvider';\r\nexport type { ThemeContextType } from './components/ThemeProvider';\r\nexport { useTheme } from './hooks/useTheme';\r\nexport { useThemeToggle } from './hooks/useThemeToggle';\r\nexport { ThemeToggle } from './components/ThemeToggle';\r\nexport { ThemeSelector } from './components/ThemeSelector';\r\n\r\n// Export theme utilities\r\nexport { createTheme } from './utils/createTheme';\r\nexport { applyTheme } from './utils/applyTheme';\r\nexport { mergeThemes, mergeThemeColors, deepMergeThemes } from './utils/mergeThemes';\r\n\r\n// Default export for convenience\r\nexport { ThemeProvider as default } from './components/ThemeProvider';\r\n","import type { Theme, ThemeColors } from './types';\r\n\r\n// Light theme colors\r\nconst lightColors: ThemeColors = {\r\n // Background colors\r\n background: '#ffffff',\r\n backgroundSecondary: '#f8fafc',\r\n backgroundTertiary: '#f1f5f9',\r\n \r\n // Text colors\r\n text: '#0f172a',\r\n textSecondary: '#475569',\r\n textMuted: '#64748b',\r\n \r\n // Border colors\r\n border: '#e2e8f0',\r\n borderLight: '#f1f5f9',\r\n borderHover: '#cbd5e1',\r\n \r\n // Accent colors\r\n primary: '#3b82f6',\r\n primaryHover: '#2563eb',\r\n primaryActive: '#1d4ed8',\r\n \r\n // Status colors\r\n success: '#10b981',\r\n warning: '#f59e0b',\r\n error: '#ef4444',\r\n info: '#06b6d4',\r\n \r\n // Interactive states\r\n hover: '#f8fafc',\r\n active: '#f1f5f9',\r\n focus: 'rgba(59, 130, 246, 0.1)',\r\n \r\n // Shadows\r\n shadow: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',\r\n shadowMd: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',\r\n shadowLg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',\r\n};\r\n\r\n// Dark theme colors\r\nconst darkColors: ThemeColors = {\r\n // Background colors\r\n background: '#0f172a',\r\n backgroundSecondary: '#1e293b',\r\n backgroundTertiary: '#334155',\r\n \r\n // Text colors\r\n text: '#f8fafc',\r\n textSecondary: '#cbd5e1',\r\n textMuted: '#94a3b8',\r\n \r\n // Border colors\r\n border: '#334155',\r\n borderLight: '#475569',\r\n borderHover: '#64748b',\r\n \r\n // Accent colors\r\n primary: '#60a5fa',\r\n primaryHover: '#3b82f6',\r\n primaryActive: '#2563eb',\r\n \r\n // Status colors\r\n success: '#34d399',\r\n warning: '#fbbf24',\r\n error: '#f87171',\r\n info: '#22d3ee',\r\n \r\n // Interactive states\r\n hover: '#1e293b',\r\n active: '#334155',\r\n focus: 'rgba(96, 165, 250, 0.1)',\r\n \r\n // Shadows\r\n shadow: '0 1px 2px 0 rgba(0, 0, 0, 0.3)',\r\n shadowMd: '0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.3)',\r\n shadowLg: '0 10px 15px -3px rgba(0, 0, 0, 0.4), 0 4px 6px -2px rgba(0, 0, 0, 0.3)',\r\n};\r\n\r\n// Base theme structure\r\nconst baseTheme = {\r\n spacing: {\r\n xs: '0.25rem',\r\n sm: '0.5rem',\r\n md: '0.75rem',\r\n lg: '1rem',\r\n xl: '1.25rem',\r\n '2xl': '1.5rem',\r\n '3xl': '2rem',\r\n '4xl': '3rem',\r\n },\r\n radius: {\r\n none: '0',\r\n sm: '0.25rem',\r\n md: '0.375rem',\r\n lg: '0.5rem',\r\n xl: '0.75rem',\r\n '2xl': '1rem',\r\n full: '9999px',\r\n },\r\n typography: {\r\n fontFamily: {\r\n sans: 'ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif',\r\n serif: 'ui-serif, Georgia, Cambria, \"Times New Roman\", Times, serif',\r\n mono: 'ui-monospace, SFMono-Regular, \"SF Mono\", Consolas, \"Liberation Mono\", Menlo, monospace',\r\n },\r\n fontSize: {\r\n xs: '0.75rem',\r\n sm: '0.875rem',\r\n base: '1rem',\r\n lg: '1.125rem',\r\n xl: '1.25rem',\r\n '2xl': '1.5rem',\r\n '3xl': '1.875rem',\r\n '4xl': '2.25rem',\r\n '5xl': '3rem',\r\n },\r\n fontWeight: {\r\n light: '300',\r\n normal: '400',\r\n medium: '500',\r\n semibold: '600',\r\n bold: '700',\r\n },\r\n lineHeight: {\r\n tight: '1.25',\r\n normal: '1.5',\r\n relaxed: '1.75',\r\n },\r\n },\r\n transitions: {\r\n fast: 'all 0.1s ease',\r\n normal: 'all 0.2s ease',\r\n slow: 'all 0.3s ease',\r\n bounce: 'all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55)',\r\n },\r\n zIndex: {\r\n dropdown: 1000,\r\n modal: 1050,\r\n tooltip: 1100,\r\n overlay: 1200,\r\n },\r\n};\r\n\r\n// Light theme\r\nexport const lightTheme: Theme = {\r\n name: 'light',\r\n mode: 'light',\r\n colors: lightColors,\r\n ...baseTheme,\r\n};\r\n\r\n// Dark theme\r\nexport const darkTheme: Theme = {\r\n name: 'dark',\r\n mode: 'dark',\r\n colors: darkColors,\r\n ...baseTheme,\r\n};\r\n\r\n// Default theme (light)\r\nexport const defaultTheme = lightTheme;\r\n\r\n// Theme presets\r\nexport const themes = {\r\n light: lightTheme,\r\n dark: darkTheme,\r\n};\r\n\r\n// Default themes for the provider\r\nexport const defaultThemes = {\r\n default: lightTheme,\r\n light: lightTheme,\r\n dark: darkTheme,\r\n};\r\n\r\n// Helper function to merge themes\r\nexport function mergeTheme(baseTheme: Theme, customTheme: Partial<Theme>): Theme {\r\n return {\r\n ...baseTheme,\r\n ...customTheme,\r\n colors: {\r\n ...baseTheme.colors,\r\n ...customTheme.colors,\r\n },\r\n spacing: {\r\n ...baseTheme.spacing,\r\n ...customTheme.spacing,\r\n },\r\n radius: {\r\n ...baseTheme.radius,\r\n ...customTheme.radius,\r\n },\r\n typography: {\r\n ...baseTheme.typography,\r\n ...customTheme.typography,\r\n fontFamily: {\r\n ...baseTheme.typography.fontFamily,\r\n ...customTheme.typography?.fontFamily,\r\n },\r\n fontSize: {\r\n ...baseTheme.typography.fontSize,\r\n ...customTheme.typography?.fontSize,\r\n },\r\n fontWeight: {\r\n ...baseTheme.typography.fontWeight,\r\n ...customTheme.typography?.fontWeight,\r\n },\r\n lineHeight: {\r\n ...baseTheme.typography.lineHeight,\r\n ...customTheme.typography?.lineHeight,\r\n },\r\n },\r\n transitions: {\r\n ...baseTheme.transitions,\r\n ...customTheme.transitions,\r\n },\r\n zIndex: {\r\n ...baseTheme.zIndex,\r\n ...customTheme.zIndex,\r\n },\r\n };\r\n}\r\n","import * as React from 'react';\r\nimport { createContext, useContext, useEffect, useState, ReactNode } from 'react';\r\nimport { Theme, ThemeConfig, ThemeMode } from '../types';\r\nimport { defaultThemes } from '../themes';\r\nimport { applyTheme } from '../utils/applyTheme';\r\n\r\nexport interface ThemeContextType {\r\n currentTheme: Theme;\r\n mode: ThemeMode;\r\n setMode: (mode: ThemeMode) => void;\r\n setTheme: (theme: Theme) => void;\r\n themes: Record<string, Theme>;\r\n toggleMode: () => void;\r\n}\r\n\r\nconst ThemeContext = createContext<ThemeContextType | undefined>(undefined);\r\n\r\nexport interface ThemeProviderProps {\r\n children: ReactNode;\r\n config?: ThemeConfig;\r\n defaultMode?: ThemeMode;\r\n defaultTheme?: string;\r\n persistMode?: boolean;\r\n storageKey?: string;\r\n customThemes?: Record<string, Theme>;\r\n}\r\n\r\nexport const ThemeProvider: React.FC<ThemeProviderProps> = ({\r\n children,\r\n defaultMode = 'auto',\r\n defaultTheme = 'default',\r\n persistMode = true,\r\n storageKey = 'asafarim-theme-mode',\r\n customThemes = {},\r\n}) => {\r\n const allThemes = { ...defaultThemes, ...customThemes };\r\n \r\n // Get initial mode from localStorage or use default\r\n const getInitialMode = (): ThemeMode => {\r\n if (!persistMode || typeof window === 'undefined') return defaultMode;\r\n \r\n try {\r\n const stored = localStorage.getItem(storageKey);\r\n if (stored && ['light', 'dark', 'auto'].includes(stored)) {\r\n return stored as ThemeMode;\r\n }\r\n } catch (error) {\r\n console.warn('Failed to read theme mode from localStorage:', error);\r\n }\r\n \r\n return defaultMode;\r\n };\r\n const [mode, setModeState] = useState<ThemeMode>(getInitialMode);\r\n const [currentThemeName, setCurrentThemeName] = useState<string>(defaultTheme);\r\n\r\n // Get the effective mode (resolving 'auto' to actual light/dark)\r\n const getEffectiveMode = (): 'light' | 'dark' => {\r\n if (mode === 'auto') {\r\n if (typeof window !== 'undefined') {\r\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\r\n }\r\n return 'light'; // fallback for SSR\r\n }\r\n return mode;\r\n };\r\n // Get the current theme based on mode and theme name\r\n const getCurrentTheme = (): Theme => {\r\n const effectiveMode = getEffectiveMode();\r\n \r\n // If user selected a specific theme, use it\r\n if (currentThemeName !== 'default' && currentThemeName in allThemes) {\r\n return allThemes[currentThemeName as keyof typeof allThemes];\r\n }\r\n \r\n // Otherwise use the theme that matches the effective mode\r\n return effectiveMode === 'dark' ? allThemes.dark : allThemes.light;\r\n };\r\n\r\n const currentTheme = getCurrentTheme();\r\n\r\n // Update mode and persist if enabled\r\n const setMode = (newMode: ThemeMode) => {\r\n setModeState(newMode);\r\n \r\n if (persistMode && typeof window !== 'undefined') {\r\n try {\r\n localStorage.setItem(storageKey, newMode);\r\n } catch (error) {\r\n console.warn('Failed to save theme mode to localStorage:', error);\r\n }\r\n }\r\n };\r\n\r\n // Toggle between light and dark modes\r\n const toggleMode = () => {\r\n if (mode === 'auto') {\r\n // If auto, switch to opposite of system preference\r\n const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;\r\n setMode(systemDark ? 'light' : 'dark');\r\n } else {\r\n setMode(mode === 'light' ? 'dark' : 'light');\r\n }\r\n };\r\n // Set theme by name\r\n const setTheme = (theme: Theme) => {\r\n setCurrentThemeName(theme.name);\r\n };\r\n // Apply theme to document\r\n useEffect(() => {\r\n applyTheme(currentTheme, mode);\r\n }, [currentTheme, mode, currentThemeName]); // Add currentThemeName as dependency\r\n\r\n // Listen for system theme changes when in auto mode\r\n useEffect(() => {\r\n if (mode !== 'auto') return;\r\n\r\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n const handleChange = () => {\r\n // Force re-render when system preference changes\r\n applyTheme(getCurrentTheme(), mode);\r\n };\r\n\r\n mediaQuery.addEventListener('change', handleChange);\r\n return () => mediaQuery.removeEventListener('change', handleChange);\r\n }, [mode]);\r\n\r\n const contextValue: ThemeContextType = {\r\n currentTheme,\r\n mode,\r\n setMode,\r\n setTheme,\r\n themes: allThemes,\r\n toggleMode,\r\n };\r\n\r\n return (\r\n <ThemeContext.Provider value={contextValue}>\r\n {children}\r\n </ThemeContext.Provider>\r\n );\r\n};\r\n\r\nexport const useThemeContext = () => {\r\n const context = useContext(ThemeContext);\r\n if (context === undefined) {\r\n throw new Error('useThemeContext must be used within a ThemeProvider');\r\n }\r\n return context;\r\n};\r\n","import { Theme, ThemeMode } from '../types';\r\n\r\n/**\r\n * Applies theme CSS variables to the document root\r\n */\r\nexport function applyTheme(theme: Theme, mode: ThemeMode): void {\r\n if (typeof document === 'undefined') return;\r\n\r\n const root = document.documentElement;\r\n \r\n // Determine the effective mode\r\n let effectiveMode = mode;\r\n if (mode === 'auto') {\r\n effectiveMode = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\r\n }\r\n\r\n // Set data attributes for CSS targeting\r\n root.setAttribute('data-theme', theme.name);\r\n root.setAttribute('data-theme-mode', effectiveMode);\r\n\r\n // Apply color variables\r\n Object.entries(theme.colors).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-color-${kebabCase(key)}`, value);\r\n });\r\n\r\n // Apply spacing variables\r\n Object.entries(theme.spacing).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-spacing-${key}`, value);\r\n });\r\n\r\n // Apply radius variables\r\n Object.entries(theme.radius).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-radius-${key}`, value);\r\n });\r\n\r\n // Apply typography variables\r\n Object.entries(theme.typography.fontFamily).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-font-family-${key}`, value);\r\n });\r\n\r\n Object.entries(theme.typography.fontSize).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-font-size-${key}`, value);\r\n });\r\n\r\n Object.entries(theme.typography.fontWeight).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-font-weight-${key}`, value);\r\n });\r\n\r\n Object.entries(theme.typography.lineHeight).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-line-height-${key}`, value);\r\n });\r\n\r\n // Apply transition variables\r\n Object.entries(theme.transitions).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-transition-${key}`, value);\r\n });\r\n\r\n // Apply z-index variables\r\n Object.entries(theme.zIndex).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-z-index-${kebabCase(key)}`, value.toString());\r\n });\r\n\r\n // Add theme class to body for additional styling\r\n document.body.className = document.body.className.replace(/theme-\\w+/g, '');\r\n document.body.classList.add(`theme-${theme.name}`, `theme-${effectiveMode}`);\r\n}\r\n\r\n/**\r\n * Removes all theme-related CSS variables and classes\r\n */\r\nexport function removeTheme(): void {\r\n if (typeof document === 'undefined') return;\r\n\r\n const root = document.documentElement;\r\n \r\n // Remove data attributes\r\n root.removeAttribute('data-theme');\r\n root.removeAttribute('data-theme-mode');\r\n\r\n // Remove CSS variables (this is a simplified approach - in production you might want to track which variables were set)\r\n const styles = root.style;\r\n for (let i = styles.length - 1; i >= 0; i--) {\r\n const property = styles[i];\r\n if (property.startsWith('--theme-')) {\r\n root.style.removeProperty(property);\r\n }\r\n }\r\n\r\n // Remove theme classes from body\r\n document.body.className = document.body.className.replace(/theme-\\w+/g, '');\r\n}\r\n\r\n/**\r\n * Converts camelCase to kebab-case\r\n */\r\nfunction kebabCase(str: string): string {\r\n return str.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);\r\n}\r\n","import { useThemeContext, ThemeContextType } from '../components/ThemeProvider';\r\n\r\n/**\r\n * Hook to access theme context\r\n */\r\nexport function useTheme(): ThemeContextType {\r\n return useThemeContext();\r\n}\r\n","import { useTheme } from './useTheme';\r\n\r\n/**\r\n * Hook that provides theme toggle functionality\r\n */\r\nexport function useThemeToggle() {\r\n const { mode, setMode, toggleMode } = useTheme();\r\n \r\n // Get effective mode (resolving 'auto' to actual light/dark)\r\n const getEffectiveMode = (): 'light' | 'dark' => {\r\n if (mode === 'auto') {\r\n if (typeof window !== 'undefined') {\r\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\r\n }\r\n return 'light'; // fallback for SSR\r\n }\r\n return mode;\r\n };\r\n\r\n const effectiveMode = getEffectiveMode();\r\n \r\n return {\r\n mode,\r\n setMode,\r\n toggleMode,\r\n isDark: effectiveMode === 'dark',\r\n isLight: effectiveMode === 'light',\r\n isAuto: mode === 'auto',\r\n effectiveMode, // Expose the resolved mode\r\n };\r\n}\r\n","import * as React from 'react';\r\nimport { useTheme } from '../hooks/useTheme';\r\n\r\nexport interface ThemeToggleProps {\r\n className?: string;\r\n style?: React.CSSProperties;\r\n showLabels?: boolean;\r\n size?: 'sm' | 'md' | 'lg';\r\n}\r\n\r\nexport const ThemeToggle: React.FC<ThemeToggleProps> = ({\r\n className = '',\r\n style = {},\r\n showLabels = false,\r\n size = 'md',\r\n}) => {\r\n const { mode, toggleMode } = useTheme();\r\n\r\n const sizeClasses = {\r\n sm: 'w-8 h-8 text-sm',\r\n md: 'w-10 h-10 text-base',\r\n lg: 'w-12 h-12 text-lg',\r\n };\r\n\r\n const buttonClass = `\r\n ${sizeClasses[size]}\r\n inline-flex items-center justify-center\r\n rounded-md border border-gray-300\r\n bg-white hover:bg-gray-50\r\n dark:bg-gray-800 dark:border-gray-600 dark:hover:bg-gray-700\r\n focus:outline-none focus:ring-2 focus:ring-blue-500\r\n transition-all duration-200\r\n ${className}\r\n `.trim();\r\n\r\n const getIcon = () => {\r\n switch (mode) {\r\n case 'light':\r\n return '☀️';\r\n case 'dark':\r\n return '🌙';\r\n case 'auto':\r\n default:\r\n return '🌓';\r\n }\r\n };\r\n\r\n const getLabel = () => {\r\n switch (mode) {\r\n case 'light':\r\n return 'Light';\r\n case 'dark':\r\n return 'Dark';\r\n case 'auto':\r\n default:\r\n return 'Auto';\r\n }\r\n };\r\n\r\n return (\r\n <button\r\n onClick={toggleMode}\r\n className={buttonClass}\r\n style={style}\r\n title={`Current theme: ${getLabel()}. Click to toggle.`}\r\n aria-label={`Switch theme. Current: ${getLabel()}`}\r\n >\r\n <span role=\"img\" aria-hidden=\"true\">\r\n {getIcon()}\r\n </span>\r\n {showLabels && (\r\n <span className=\"ml-2 text-sm font-medium\">\r\n {getLabel()}\r\n </span>\r\n )}\r\n </button>\r\n );\r\n};\r\n","import * as React from \"react\";\r\nimport { useTheme } from \"../hooks/useTheme\";\r\nimport { ThemeMode } from \"../types\";\r\n\r\nexport interface ThemeSelectorProps {\r\n className?: string;\r\n style?: React.CSSProperties;\r\n showLabels?: boolean;\r\n options?: Array<{\r\n mode: ThemeMode;\r\n label: string;\r\n icon?: string;\r\n }>;\r\n}\r\n\r\nexport const ThemeSelector: React.FC<ThemeSelectorProps> = ({\r\n className = \"\",\r\n style = {},\r\n showLabels = true,\r\n options = [\r\n { mode: \"light\", label: \"Light\", icon: \"☀️\" },\r\n { mode: \"dark\", label: \"Dark\", icon: \"🌙\" },\r\n { mode: \"auto\", label: \"Auto\", icon: \"🌓\" },\r\n ],\r\n}) => {\r\n const { mode, setMode } = useTheme();\r\n\r\n const selectClass = `\r\n px-3 py-2 border border-gray-300 rounded-md\r\n bg-white dark:bg-gray-800 dark:border-gray-600\r\n text-gray-900 dark:text-gray-100\r\n focus:outline-none focus:ring-2 focus:ring-blue-500\r\n transition-all duration-200\r\n ${className}\r\n `.trim();\r\n\r\n return (\r\n <select\r\n value={mode}\r\n onChange={(e) => setMode(e.target.value as ThemeMode)}\r\n className={selectClass}\r\n style={style}\r\n aria-label=\"Select theme mode\"\r\n >\r\n {options.map((option) => (\r\n <option key={option.mode} value={option.mode}>\r\n {showLabels\r\n ? `${option.icon ? option.icon + \" \" : \"\"}${option.label}`\r\n : option.icon || option.label}\r\n </option>\r\n ))}\r\n </select>\r\n );\r\n};\r\n","import { Theme } from '../types';\r\n\r\n/**\r\n * Creates a new theme by merging a base theme with custom properties\r\n */\r\nexport function createTheme(\r\n baseTheme: Theme,\r\n customTheme: Partial<Theme>\r\n): Theme {\r\n return {\r\n ...baseTheme,\r\n ...customTheme,\r\n name: customTheme.name || `${baseTheme.name}-custom`,\r\n colors: {\r\n ...baseTheme.colors,\r\n ...customTheme.colors,\r\n },\r\n spacing: {\r\n ...baseTheme.spacing,\r\n ...customTheme.spacing,\r\n },\r\n radius: {\r\n ...baseTheme.radius,\r\n ...customTheme.radius,\r\n },\r\n typography: {\r\n ...baseTheme.typography,\r\n ...customTheme.typography,\r\n fontFamily: {\r\n ...baseTheme.typography.fontFamily,\r\n ...customTheme.typography?.fontFamily,\r\n },\r\n fontSize: {\r\n ...baseTheme.typography.fontSize,\r\n ...customTheme.typography?.fontSize,\r\n },\r\n fontWeight: {\r\n ...baseTheme.typography.fontWeight,\r\n ...customTheme.typography?.fontWeight,\r\n },\r\n lineHeight: {\r\n ...baseTheme.typography.lineHeight,\r\n ...customTheme.typography?.lineHeight,\r\n },\r\n },\r\n transitions: {\r\n ...baseTheme.transitions,\r\n ...customTheme.transitions,\r\n },\r\n zIndex: {\r\n ...baseTheme.zIndex,\r\n ...customTheme.zIndex,\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Creates a theme variant with modified colors\r\n */\r\nexport function createThemeVariant(\r\n baseTheme: Theme,\r\n colorOverrides: Partial<Theme['colors']>,\r\n name?: string\r\n): Theme {\r\n return createTheme(baseTheme, {\r\n name: name || `${baseTheme.name}-variant`,\r\n colors: {\r\n ...baseTheme.colors,\r\n ...colorOverrides,\r\n },\r\n });\r\n}\r\n","import { Theme } from '../types';\r\n\r\n/**\r\n * Merges multiple themes into a single theme\r\n * Later themes in the array take precedence over earlier ones\r\n */\r\nexport function mergeThemes(...themes: Array<Theme | Partial<Theme>>): Theme {\r\n if (themes.length === 0) {\r\n throw new Error('At least one theme must be provided to mergeThemes');\r\n }\r\n\r\n const [baseTheme, ...additionalThemes] = themes;\r\n \r\n if (!isFullTheme(baseTheme)) {\r\n throw new Error('First theme must be a complete theme object');\r\n }\r\n return additionalThemes.reduce((merged: Theme, theme): Theme => {\r\n return {\r\n ...merged,\r\n ...theme,\r\n name: theme.name || merged.name,\r\n mode: theme.mode || merged.mode,\r\n colors: {\r\n ...merged.colors,\r\n ...theme.colors,\r\n },\r\n spacing: {\r\n ...merged.spacing,\r\n ...theme.spacing,\r\n },\r\n radius: {\r\n ...merged.radius,\r\n ...theme.radius,\r\n },\r\n typography: {\r\n ...merged.typography,\r\n ...theme.typography,\r\n fontFamily: {\r\n ...merged.typography.fontFamily,\r\n ...theme.typography?.fontFamily,\r\n },\r\n fontSize: {\r\n ...merged.typography.fontSize,\r\n ...theme.typography?.fontSize,\r\n },\r\n fontWeight: {\r\n ...merged.typography.fontWeight,\r\n ...theme.typography?.fontWeight,\r\n },\r\n lineHeight: {\r\n ...merged.typography.lineHeight,\r\n ...theme.typography?.lineHeight,\r\n },\r\n },\r\n transitions: {\r\n ...merged.transitions,\r\n ...theme.transitions,\r\n },\r\n zIndex: {\r\n ...merged.zIndex,\r\n ...theme.zIndex,\r\n },\r\n };\r\n }, baseTheme);\r\n}\r\n\r\n/**\r\n * Type guard to check if an object is a complete theme\r\n */\r\nfunction isFullTheme(theme: Theme | Partial<Theme>): theme is Theme {\r\n return !!(\r\n theme &&\r\n typeof theme === 'object' &&\r\n 'name' in theme &&\r\n 'mode' in theme &&\r\n 'colors' in theme &&\r\n 'spacing' in theme &&\r\n 'radius' in theme &&\r\n 'typography' in theme &&\r\n 'transitions' in theme &&\r\n 'zIndex' in theme\r\n );\r\n}\r\n\r\n/**\r\n * Merges theme colors only\r\n */\r\nexport function mergeThemeColors(\r\n baseColors: Theme['colors'],\r\n ...colorSets: Array<Partial<Theme['colors']>>\r\n): Theme['colors'] {\r\n return colorSets.reduce((merged: Theme['colors'], colors): Theme['colors'] => ({\r\n ...merged,\r\n ...colors,\r\n }), baseColors);\r\n}\r\n\r\n/**\r\n * Deep merge utility for complex theme objects\r\n */\r\nexport function deepMergeThemes(target: Theme, ...sources: Array<Partial<Theme>>): Theme {\r\n return sources.reduce((merged: Theme, source): Theme => {\r\n const result = { ...merged };\r\n \r\n for (const key in source) {\r\n const sourceValue = source[key as keyof Theme];\r\n const targetValue = merged[key as keyof Theme];\r\n \r\n if (sourceValue && typeof sourceValue === 'object' && !Array.isArray(sourceValue) && targetValue && typeof targetValue === 'object') {\r\n result[key as keyof Theme] = {\r\n ...targetValue,\r\n ...sourceValue,\r\n } as any;\r\n } else if (sourceValue !== undefined) {\r\n result[key as keyof Theme] = sourceValue as any;\r\n }\r\n }\r\n \r\n return result;\r\n }, target);\r\n}\r\n"],"mappings":"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","names":["index_exports","__export","ThemeProvider","ThemeSelector","ThemeToggle","applyTheme","createTheme","darkTheme","deepMergeThemes","defaultTheme","defaultThemes","lightTheme","mergeTheme","mergeThemeColors","mergeThemes","themes","useTheme","useThemeToggle","__toCommonJS","lightColors","darkColors","baseTheme","lightTheme","darkTheme","defaultTheme","themes","defaultThemes","mergeTheme","customTheme","import_react","applyTheme","theme","mode","root","effectiveMode","key","value","kebabCase","kebabCase","str","match","import_jsx_runtime","ThemeContext","ThemeProvider","children","defaultMode","defaultTheme","persistMode","storageKey","customThemes","allThemes","defaultThemes","getInitialMode","stored","error","mode","setModeState","currentThemeName","setCurrentThemeName","getEffectiveMode","getCurrentTheme","effectiveMode","currentTheme","setMode","newMode","toggleMode","systemDark","setTheme","theme","applyTheme","mediaQuery","handleChange","contextValue","useThemeContext","context","useTheme","useThemeContext","useThemeToggle","mode","setMode","toggleMode","useTheme","effectiveMode","import_jsx_runtime","ThemeToggle","className","style","showLabels","size","mode","toggleMode","useTheme","buttonClass","getIcon","getLabel","import_jsx_runtime","ThemeSelector","className","style","showLabels","options","mode","setMode","useTheme","selectClass","e","option","createTheme","baseTheme","customTheme","mergeThemes","themes","baseTheme","additionalThemes","isFullTheme","merged","theme","mergeThemeColors","baseColors","colorSets","colors","deepMergeThemes","target","sources","source","result","key","sourceValue","targetValue"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
var N={background:"#ffffff",backgroundSecondary:"#f8fafc",backgroundTertiary:"#f1f5f9",text:"#0f172a",textSecondary:"#475569",textMuted:"#64748b",border:"#e2e8f0",borderLight:"#f1f5f9",borderHover:"#cbd5e1",primary:"#3b82f6",primaryHover:"#2563eb",primaryActive:"#1d4ed8",success:"#10b981",warning:"#f59e0b",error:"#ef4444",info:"#06b6d4",hover:"#f8fafc",active:"#f1f5f9",focus:"rgba(59, 130, 246, 0.1)",shadow:"0 1px 2px 0 rgba(0, 0, 0, 0.05)",shadowMd:"0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",shadowLg:"0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)"},L={background:"#0f172a",backgroundSecondary:"#1e293b",backgroundTertiary:"#334155",text:"#f8fafc",textSecondary:"#cbd5e1",textMuted:"#94a3b8",border:"#334155",borderLight:"#475569",borderHover:"#64748b",primary:"#60a5fa",primaryHover:"#3b82f6",primaryActive:"#2563eb",success:"#34d399",warning:"#fbbf24",error:"#f87171",info:"#22d3ee",hover:"#1e293b",active:"#334155",focus:"rgba(96, 165, 250, 0.1)",shadow:"0 1px 2px 0 rgba(0, 0, 0, 0.3)",shadowMd:"0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.3)",shadowLg:"0 10px 15px -3px rgba(0, 0, 0, 0.4), 0 4px 6px -2px rgba(0, 0, 0, 0.3)"},T={spacing:{xs:"0.25rem",sm:"0.5rem",md:"0.75rem",lg:"1rem",xl:"1.25rem","2xl":"1.5rem","3xl":"2rem","4xl":"3rem"},radius:{none:"0",sm:"0.25rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem",full:"9999px"},typography:{fontFamily:{sans:'ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif',serif:'ui-serif, Georgia, Cambria, "Times New Roman", Times, serif',mono:'ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo, monospace'},fontSize:{xs:"0.75rem",sm:"0.875rem",base:"1rem",lg:"1.125rem",xl:"1.25rem","2xl":"1.5rem","3xl":"1.875rem","4xl":"2.25rem","5xl":"3rem"},fontWeight:{light:"300",normal:"400",medium:"500",semibold:"600",bold:"700"},lineHeight:{tight:"1.25",normal:"1.5",relaxed:"1.75"}},transitions:{fast:"all 0.1s ease",normal:"all 0.2s ease",slow:"all 0.3s ease",bounce:"all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55)"},zIndex:{dropdown:1e3,modal:1050,tooltip:1100,overlay:1200}},f={name:"light",mode:"light",colors:N,...T},b={name:"dark",mode:"dark",colors:L,...T},J=f,K={light:f,dark:b},k={default:f,light:f,dark:b};function X(e,o){return{...e,...o,colors:{...e.colors,...o.colors},spacing:{...e.spacing,...o.spacing},radius:{...e.radius,...o.radius},typography:{...e.typography,...o.typography,fontFamily:{...e.typography.fontFamily,...o.typography?.fontFamily},fontSize:{...e.typography.fontSize,...o.typography?.fontSize},fontWeight:{...e.typography.fontWeight,...o.typography?.fontWeight},lineHeight:{...e.typography.lineHeight,...o.typography?.lineHeight}},transitions:{...e.transitions,...o.transitions},zIndex:{...e.zIndex,...o.zIndex}}}import{createContext as R,useContext as W,useEffect as v,useState as M}from"react";function g(e,o){if(typeof document>"u")return;let n=document.documentElement,r=o;o==="auto"&&(r=window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"),n.setAttribute("data-theme",e.name),n.setAttribute("data-theme-mode",r),Object.entries(e.colors).forEach(([t,a])=>{n.style.setProperty(`--theme-color-${w(t)}`,a)}),Object.entries(e.spacing).forEach(([t,a])=>{n.style.setProperty(`--theme-spacing-${t}`,a)}),Object.entries(e.radius).forEach(([t,a])=>{n.style.setProperty(`--theme-radius-${t}`,a)}),Object.entries(e.typography.fontFamily).forEach(([t,a])=>{n.style.setProperty(`--theme-font-family-${t}`,a)}),Object.entries(e.typography.fontSize).forEach(([t,a])=>{n.style.setProperty(`--theme-font-size-${t}`,a)}),Object.entries(e.typography.fontWeight).forEach(([t,a])=>{n.style.setProperty(`--theme-font-weight-${t}`,a)}),Object.entries(e.typography.lineHeight).forEach(([t,a])=>{n.style.setProperty(`--theme-line-height-${t}`,a)}),Object.entries(e.transitions).forEach(([t,a])=>{n.style.setProperty(`--theme-transition-${t}`,a)}),Object.entries(e.zIndex).forEach(([t,a])=>{n.style.setProperty(`--theme-z-index-${w(t)}`,a.toString())}),document.body.className=document.body.className.replace(/theme-\w+/g,""),document.body.classList.add(`theme-${e.name}`,`theme-${r}`)}function w(e){return e.replace(/[A-Z]/g,o=>`-${o.toLowerCase()}`)}import{jsx as j}from"react/jsx-runtime";var C=R(void 0),S=({children:e,defaultMode:o="auto",defaultTheme:n="default",persistMode:r=!0,storageKey:t="asafarim-theme-mode",customThemes:a={}})=>{let l={...k,...a},i=()=>{if(!r||typeof window>"u")return o;try{let s=localStorage.getItem(t);if(s&&["light","dark","auto"].includes(s))return s}catch(s){console.warn("Failed to read theme mode from localStorage:",s)}return o},[m,c]=M(i),[p,$]=M(n),E=()=>m==="auto"?typeof window<"u"&&window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":m,x=()=>{let s=E();return p!=="default"&&p in l?l[p]:s==="dark"?l.dark:l.light},y=x(),u=s=>{if(c(s),r&&typeof window<"u")try{localStorage.setItem(t,s)}catch(h){console.warn("Failed to save theme mode to localStorage:",h)}},A=()=>{if(m==="auto"){let s=window.matchMedia("(prefers-color-scheme: dark)").matches;u(s?"light":"dark")}else u(m==="light"?"dark":"light")},I=s=>{$(s.name)};v(()=>{g(y,m)},[y,m,p]),v(()=>{if(m!=="auto")return;let s=window.matchMedia("(prefers-color-scheme: dark)"),h=()=>{g(x(),m)};return s.addEventListener("change",h),()=>s.removeEventListener("change",h)},[m]);let H={currentTheme:y,mode:m,setMode:u,setTheme:I,themes:l,toggleMode:A};return j(C.Provider,{value:H,children:e})},P=()=>{let e=W(C);if(e===void 0)throw new Error("useThemeContext must be used within a ThemeProvider");return e};function d(){return P()}function O(){let{mode:e,setMode:o,toggleMode:n}=d(),t=e==="auto"?typeof window<"u"&&window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":e;return{mode:e,setMode:o,toggleMode:n,isDark:t==="dark",isLight:t==="light",isAuto:e==="auto",effectiveMode:t}}import{jsx as z,jsxs as V}from"react/jsx-runtime";var D=({className:e="",style:o={},showLabels:n=!1,size:r="md"})=>{let{mode:t,toggleMode:a}=d(),i=`
|
|
2
|
+
${{sm:"w-8 h-8 text-sm",md:"w-10 h-10 text-base",lg:"w-12 h-12 text-lg"}[r]}
|
|
3
|
+
inline-flex items-center justify-center
|
|
4
|
+
rounded-md border border-gray-300
|
|
5
|
+
bg-white hover:bg-gray-50
|
|
6
|
+
dark:bg-gray-800 dark:border-gray-600 dark:hover:bg-gray-700
|
|
7
|
+
focus:outline-none focus:ring-2 focus:ring-blue-500
|
|
8
|
+
transition-all duration-200
|
|
9
|
+
${e}
|
|
10
|
+
`.trim(),m=()=>{switch(t){case"light":return"\u2600\uFE0F";case"dark":return"\u{1F319}";case"auto":default:return"\u{1F313}"}},c=()=>{switch(t){case"light":return"Light";case"dark":return"Dark";case"auto":default:return"Auto"}};return V("button",{onClick:a,className:i,style:o,title:`Current theme: ${c()}. Click to toggle.`,"aria-label":`Switch theme. Current: ${c()}`,children:[z("span",{role:"img","aria-hidden":"true",children:m()}),n&&z("span",{className:"ml-2 text-sm font-medium",children:c()})]})};import{jsx as F}from"react/jsx-runtime";var B=({className:e="",style:o={},showLabels:n=!0,options:r=[{mode:"light",label:"Light",icon:"\u2600\uFE0F"},{mode:"dark",label:"Dark",icon:"\u{1F319}"},{mode:"auto",label:"Auto",icon:"\u{1F313}"}]})=>{let{mode:t,setMode:a}=d(),l=`
|
|
11
|
+
px-3 py-2 border border-gray-300 rounded-md
|
|
12
|
+
bg-white dark:bg-gray-800 dark:border-gray-600
|
|
13
|
+
text-gray-900 dark:text-gray-100
|
|
14
|
+
focus:outline-none focus:ring-2 focus:ring-blue-500
|
|
15
|
+
transition-all duration-200
|
|
16
|
+
${e}
|
|
17
|
+
`.trim();return F("select",{value:t,onChange:i=>a(i.target.value),className:l,style:o,"aria-label":"Select theme mode",children:r.map(i=>F("option",{value:i.mode,children:n?`${i.icon?i.icon+" ":""}${i.label}`:i.icon||i.label},i.mode))})};function G(e,o){return{...e,...o,name:o.name||`${e.name}-custom`,colors:{...e.colors,...o.colors},spacing:{...e.spacing,...o.spacing},radius:{...e.radius,...o.radius},typography:{...e.typography,...o.typography,fontFamily:{...e.typography.fontFamily,...o.typography?.fontFamily},fontSize:{...e.typography.fontSize,...o.typography?.fontSize},fontWeight:{...e.typography.fontWeight,...o.typography?.fontWeight},lineHeight:{...e.typography.lineHeight,...o.typography?.lineHeight}},transitions:{...e.transitions,...o.transitions},zIndex:{...e.zIndex,...o.zIndex}}}function Q(...e){if(e.length===0)throw new Error("At least one theme must be provided to mergeThemes");let[o,...n]=e;if(!U(o))throw new Error("First theme must be a complete theme object");return n.reduce((r,t)=>({...r,...t,name:t.name||r.name,mode:t.mode||r.mode,colors:{...r.colors,...t.colors},spacing:{...r.spacing,...t.spacing},radius:{...r.radius,...t.radius},typography:{...r.typography,...t.typography,fontFamily:{...r.typography.fontFamily,...t.typography?.fontFamily},fontSize:{...r.typography.fontSize,...t.typography?.fontSize},fontWeight:{...r.typography.fontWeight,...t.typography?.fontWeight},lineHeight:{...r.typography.lineHeight,...t.typography?.lineHeight}},transitions:{...r.transitions,...t.transitions},zIndex:{...r.zIndex,...t.zIndex}}),o)}function U(e){return!!(e&&typeof e=="object"&&"name"in e&&"mode"in e&&"colors"in e&&"spacing"in e&&"radius"in e&&"typography"in e&&"transitions"in e&&"zIndex"in e)}function Z(e,...o){return o.reduce((n,r)=>({...n,...r}),e)}function q(e,...o){return o.reduce((n,r)=>{let t={...n};for(let a in r){let l=r[a],i=n[a];l&&typeof l=="object"&&!Array.isArray(l)&&i&&typeof i=="object"?t[a]={...i,...l}:l!==void 0&&(t[a]=l)}return t},e)}export{S as ThemeProvider,B as ThemeSelector,D as ThemeToggle,g as applyTheme,G as createTheme,b as darkTheme,q as deepMergeThemes,S as default,J as defaultTheme,k as defaultThemes,f as lightTheme,X as mergeTheme,Z as mergeThemeColors,Q as mergeThemes,K as themes,d as useTheme,O as useThemeToggle};
|
|
18
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/themes.ts","../src/components/ThemeProvider.tsx","../src/utils/applyTheme.ts","../src/hooks/useTheme.ts","../src/hooks/useThemeToggle.ts","../src/components/ThemeToggle.tsx","../src/components/ThemeSelector.tsx","../src/utils/createTheme.ts","../src/utils/mergeThemes.ts"],"sourcesContent":["import type { Theme, ThemeColors } from './types';\r\n\r\n// Light theme colors\r\nconst lightColors: ThemeColors = {\r\n // Background colors\r\n background: '#ffffff',\r\n backgroundSecondary: '#f8fafc',\r\n backgroundTertiary: '#f1f5f9',\r\n \r\n // Text colors\r\n text: '#0f172a',\r\n textSecondary: '#475569',\r\n textMuted: '#64748b',\r\n \r\n // Border colors\r\n border: '#e2e8f0',\r\n borderLight: '#f1f5f9',\r\n borderHover: '#cbd5e1',\r\n \r\n // Accent colors\r\n primary: '#3b82f6',\r\n primaryHover: '#2563eb',\r\n primaryActive: '#1d4ed8',\r\n \r\n // Status colors\r\n success: '#10b981',\r\n warning: '#f59e0b',\r\n error: '#ef4444',\r\n info: '#06b6d4',\r\n \r\n // Interactive states\r\n hover: '#f8fafc',\r\n active: '#f1f5f9',\r\n focus: 'rgba(59, 130, 246, 0.1)',\r\n \r\n // Shadows\r\n shadow: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',\r\n shadowMd: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',\r\n shadowLg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',\r\n};\r\n\r\n// Dark theme colors\r\nconst darkColors: ThemeColors = {\r\n // Background colors\r\n background: '#0f172a',\r\n backgroundSecondary: '#1e293b',\r\n backgroundTertiary: '#334155',\r\n \r\n // Text colors\r\n text: '#f8fafc',\r\n textSecondary: '#cbd5e1',\r\n textMuted: '#94a3b8',\r\n \r\n // Border colors\r\n border: '#334155',\r\n borderLight: '#475569',\r\n borderHover: '#64748b',\r\n \r\n // Accent colors\r\n primary: '#60a5fa',\r\n primaryHover: '#3b82f6',\r\n primaryActive: '#2563eb',\r\n \r\n // Status colors\r\n success: '#34d399',\r\n warning: '#fbbf24',\r\n error: '#f87171',\r\n info: '#22d3ee',\r\n \r\n // Interactive states\r\n hover: '#1e293b',\r\n active: '#334155',\r\n focus: 'rgba(96, 165, 250, 0.1)',\r\n \r\n // Shadows\r\n shadow: '0 1px 2px 0 rgba(0, 0, 0, 0.3)',\r\n shadowMd: '0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.3)',\r\n shadowLg: '0 10px 15px -3px rgba(0, 0, 0, 0.4), 0 4px 6px -2px rgba(0, 0, 0, 0.3)',\r\n};\r\n\r\n// Base theme structure\r\nconst baseTheme = {\r\n spacing: {\r\n xs: '0.25rem',\r\n sm: '0.5rem',\r\n md: '0.75rem',\r\n lg: '1rem',\r\n xl: '1.25rem',\r\n '2xl': '1.5rem',\r\n '3xl': '2rem',\r\n '4xl': '3rem',\r\n },\r\n radius: {\r\n none: '0',\r\n sm: '0.25rem',\r\n md: '0.375rem',\r\n lg: '0.5rem',\r\n xl: '0.75rem',\r\n '2xl': '1rem',\r\n full: '9999px',\r\n },\r\n typography: {\r\n fontFamily: {\r\n sans: 'ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif',\r\n serif: 'ui-serif, Georgia, Cambria, \"Times New Roman\", Times, serif',\r\n mono: 'ui-monospace, SFMono-Regular, \"SF Mono\", Consolas, \"Liberation Mono\", Menlo, monospace',\r\n },\r\n fontSize: {\r\n xs: '0.75rem',\r\n sm: '0.875rem',\r\n base: '1rem',\r\n lg: '1.125rem',\r\n xl: '1.25rem',\r\n '2xl': '1.5rem',\r\n '3xl': '1.875rem',\r\n '4xl': '2.25rem',\r\n '5xl': '3rem',\r\n },\r\n fontWeight: {\r\n light: '300',\r\n normal: '400',\r\n medium: '500',\r\n semibold: '600',\r\n bold: '700',\r\n },\r\n lineHeight: {\r\n tight: '1.25',\r\n normal: '1.5',\r\n relaxed: '1.75',\r\n },\r\n },\r\n transitions: {\r\n fast: 'all 0.1s ease',\r\n normal: 'all 0.2s ease',\r\n slow: 'all 0.3s ease',\r\n bounce: 'all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55)',\r\n },\r\n zIndex: {\r\n dropdown: 1000,\r\n modal: 1050,\r\n tooltip: 1100,\r\n overlay: 1200,\r\n },\r\n};\r\n\r\n// Light theme\r\nexport const lightTheme: Theme = {\r\n name: 'light',\r\n mode: 'light',\r\n colors: lightColors,\r\n ...baseTheme,\r\n};\r\n\r\n// Dark theme\r\nexport const darkTheme: Theme = {\r\n name: 'dark',\r\n mode: 'dark',\r\n colors: darkColors,\r\n ...baseTheme,\r\n};\r\n\r\n// Default theme (light)\r\nexport const defaultTheme = lightTheme;\r\n\r\n// Theme presets\r\nexport const themes = {\r\n light: lightTheme,\r\n dark: darkTheme,\r\n};\r\n\r\n// Default themes for the provider\r\nexport const defaultThemes = {\r\n default: lightTheme,\r\n light: lightTheme,\r\n dark: darkTheme,\r\n};\r\n\r\n// Helper function to merge themes\r\nexport function mergeTheme(baseTheme: Theme, customTheme: Partial<Theme>): Theme {\r\n return {\r\n ...baseTheme,\r\n ...customTheme,\r\n colors: {\r\n ...baseTheme.colors,\r\n ...customTheme.colors,\r\n },\r\n spacing: {\r\n ...baseTheme.spacing,\r\n ...customTheme.spacing,\r\n },\r\n radius: {\r\n ...baseTheme.radius,\r\n ...customTheme.radius,\r\n },\r\n typography: {\r\n ...baseTheme.typography,\r\n ...customTheme.typography,\r\n fontFamily: {\r\n ...baseTheme.typography.fontFamily,\r\n ...customTheme.typography?.fontFamily,\r\n },\r\n fontSize: {\r\n ...baseTheme.typography.fontSize,\r\n ...customTheme.typography?.fontSize,\r\n },\r\n fontWeight: {\r\n ...baseTheme.typography.fontWeight,\r\n ...customTheme.typography?.fontWeight,\r\n },\r\n lineHeight: {\r\n ...baseTheme.typography.lineHeight,\r\n ...customTheme.typography?.lineHeight,\r\n },\r\n },\r\n transitions: {\r\n ...baseTheme.transitions,\r\n ...customTheme.transitions,\r\n },\r\n zIndex: {\r\n ...baseTheme.zIndex,\r\n ...customTheme.zIndex,\r\n },\r\n };\r\n}\r\n","import * as React from 'react';\r\nimport { createContext, useContext, useEffect, useState, ReactNode } from 'react';\r\nimport { Theme, ThemeConfig, ThemeMode } from '../types';\r\nimport { defaultThemes } from '../themes';\r\nimport { applyTheme } from '../utils/applyTheme';\r\n\r\nexport interface ThemeContextType {\r\n currentTheme: Theme;\r\n mode: ThemeMode;\r\n setMode: (mode: ThemeMode) => void;\r\n setTheme: (theme: Theme) => void;\r\n themes: Record<string, Theme>;\r\n toggleMode: () => void;\r\n}\r\n\r\nconst ThemeContext = createContext<ThemeContextType | undefined>(undefined);\r\n\r\nexport interface ThemeProviderProps {\r\n children: ReactNode;\r\n config?: ThemeConfig;\r\n defaultMode?: ThemeMode;\r\n defaultTheme?: string;\r\n persistMode?: boolean;\r\n storageKey?: string;\r\n customThemes?: Record<string, Theme>;\r\n}\r\n\r\nexport const ThemeProvider: React.FC<ThemeProviderProps> = ({\r\n children,\r\n defaultMode = 'auto',\r\n defaultTheme = 'default',\r\n persistMode = true,\r\n storageKey = 'asafarim-theme-mode',\r\n customThemes = {},\r\n}) => {\r\n const allThemes = { ...defaultThemes, ...customThemes };\r\n \r\n // Get initial mode from localStorage or use default\r\n const getInitialMode = (): ThemeMode => {\r\n if (!persistMode || typeof window === 'undefined') return defaultMode;\r\n \r\n try {\r\n const stored = localStorage.getItem(storageKey);\r\n if (stored && ['light', 'dark', 'auto'].includes(stored)) {\r\n return stored as ThemeMode;\r\n }\r\n } catch (error) {\r\n console.warn('Failed to read theme mode from localStorage:', error);\r\n }\r\n \r\n return defaultMode;\r\n };\r\n const [mode, setModeState] = useState<ThemeMode>(getInitialMode);\r\n const [currentThemeName, setCurrentThemeName] = useState<string>(defaultTheme);\r\n\r\n // Get the effective mode (resolving 'auto' to actual light/dark)\r\n const getEffectiveMode = (): 'light' | 'dark' => {\r\n if (mode === 'auto') {\r\n if (typeof window !== 'undefined') {\r\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\r\n }\r\n return 'light'; // fallback for SSR\r\n }\r\n return mode;\r\n };\r\n // Get the current theme based on mode and theme name\r\n const getCurrentTheme = (): Theme => {\r\n const effectiveMode = getEffectiveMode();\r\n \r\n // If user selected a specific theme, use it\r\n if (currentThemeName !== 'default' && currentThemeName in allThemes) {\r\n return allThemes[currentThemeName as keyof typeof allThemes];\r\n }\r\n \r\n // Otherwise use the theme that matches the effective mode\r\n return effectiveMode === 'dark' ? allThemes.dark : allThemes.light;\r\n };\r\n\r\n const currentTheme = getCurrentTheme();\r\n\r\n // Update mode and persist if enabled\r\n const setMode = (newMode: ThemeMode) => {\r\n setModeState(newMode);\r\n \r\n if (persistMode && typeof window !== 'undefined') {\r\n try {\r\n localStorage.setItem(storageKey, newMode);\r\n } catch (error) {\r\n console.warn('Failed to save theme mode to localStorage:', error);\r\n }\r\n }\r\n };\r\n\r\n // Toggle between light and dark modes\r\n const toggleMode = () => {\r\n if (mode === 'auto') {\r\n // If auto, switch to opposite of system preference\r\n const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;\r\n setMode(systemDark ? 'light' : 'dark');\r\n } else {\r\n setMode(mode === 'light' ? 'dark' : 'light');\r\n }\r\n };\r\n // Set theme by name\r\n const setTheme = (theme: Theme) => {\r\n setCurrentThemeName(theme.name);\r\n };\r\n // Apply theme to document\r\n useEffect(() => {\r\n applyTheme(currentTheme, mode);\r\n }, [currentTheme, mode, currentThemeName]); // Add currentThemeName as dependency\r\n\r\n // Listen for system theme changes when in auto mode\r\n useEffect(() => {\r\n if (mode !== 'auto') return;\r\n\r\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n const handleChange = () => {\r\n // Force re-render when system preference changes\r\n applyTheme(getCurrentTheme(), mode);\r\n };\r\n\r\n mediaQuery.addEventListener('change', handleChange);\r\n return () => mediaQuery.removeEventListener('change', handleChange);\r\n }, [mode]);\r\n\r\n const contextValue: ThemeContextType = {\r\n currentTheme,\r\n mode,\r\n setMode,\r\n setTheme,\r\n themes: allThemes,\r\n toggleMode,\r\n };\r\n\r\n return (\r\n <ThemeContext.Provider value={contextValue}>\r\n {children}\r\n </ThemeContext.Provider>\r\n );\r\n};\r\n\r\nexport const useThemeContext = () => {\r\n const context = useContext(ThemeContext);\r\n if (context === undefined) {\r\n throw new Error('useThemeContext must be used within a ThemeProvider');\r\n }\r\n return context;\r\n};\r\n","import { Theme, ThemeMode } from '../types';\r\n\r\n/**\r\n * Applies theme CSS variables to the document root\r\n */\r\nexport function applyTheme(theme: Theme, mode: ThemeMode): void {\r\n if (typeof document === 'undefined') return;\r\n\r\n const root = document.documentElement;\r\n \r\n // Determine the effective mode\r\n let effectiveMode = mode;\r\n if (mode === 'auto') {\r\n effectiveMode = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\r\n }\r\n\r\n // Set data attributes for CSS targeting\r\n root.setAttribute('data-theme', theme.name);\r\n root.setAttribute('data-theme-mode', effectiveMode);\r\n\r\n // Apply color variables\r\n Object.entries(theme.colors).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-color-${kebabCase(key)}`, value);\r\n });\r\n\r\n // Apply spacing variables\r\n Object.entries(theme.spacing).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-spacing-${key}`, value);\r\n });\r\n\r\n // Apply radius variables\r\n Object.entries(theme.radius).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-radius-${key}`, value);\r\n });\r\n\r\n // Apply typography variables\r\n Object.entries(theme.typography.fontFamily).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-font-family-${key}`, value);\r\n });\r\n\r\n Object.entries(theme.typography.fontSize).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-font-size-${key}`, value);\r\n });\r\n\r\n Object.entries(theme.typography.fontWeight).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-font-weight-${key}`, value);\r\n });\r\n\r\n Object.entries(theme.typography.lineHeight).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-line-height-${key}`, value);\r\n });\r\n\r\n // Apply transition variables\r\n Object.entries(theme.transitions).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-transition-${key}`, value);\r\n });\r\n\r\n // Apply z-index variables\r\n Object.entries(theme.zIndex).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-z-index-${kebabCase(key)}`, value.toString());\r\n });\r\n\r\n // Add theme class to body for additional styling\r\n document.body.className = document.body.className.replace(/theme-\\w+/g, '');\r\n document.body.classList.add(`theme-${theme.name}`, `theme-${effectiveMode}`);\r\n}\r\n\r\n/**\r\n * Removes all theme-related CSS variables and classes\r\n */\r\nexport function removeTheme(): void {\r\n if (typeof document === 'undefined') return;\r\n\r\n const root = document.documentElement;\r\n \r\n // Remove data attributes\r\n root.removeAttribute('data-theme');\r\n root.removeAttribute('data-theme-mode');\r\n\r\n // Remove CSS variables (this is a simplified approach - in production you might want to track which variables were set)\r\n const styles = root.style;\r\n for (let i = styles.length - 1; i >= 0; i--) {\r\n const property = styles[i];\r\n if (property.startsWith('--theme-')) {\r\n root.style.removeProperty(property);\r\n }\r\n }\r\n\r\n // Remove theme classes from body\r\n document.body.className = document.body.className.replace(/theme-\\w+/g, '');\r\n}\r\n\r\n/**\r\n * Converts camelCase to kebab-case\r\n */\r\nfunction kebabCase(str: string): string {\r\n return str.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);\r\n}\r\n","import { useThemeContext, ThemeContextType } from '../components/ThemeProvider';\r\n\r\n/**\r\n * Hook to access theme context\r\n */\r\nexport function useTheme(): ThemeContextType {\r\n return useThemeContext();\r\n}\r\n","import { useTheme } from './useTheme';\r\n\r\n/**\r\n * Hook that provides theme toggle functionality\r\n */\r\nexport function useThemeToggle() {\r\n const { mode, setMode, toggleMode } = useTheme();\r\n \r\n // Get effective mode (resolving 'auto' to actual light/dark)\r\n const getEffectiveMode = (): 'light' | 'dark' => {\r\n if (mode === 'auto') {\r\n if (typeof window !== 'undefined') {\r\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\r\n }\r\n return 'light'; // fallback for SSR\r\n }\r\n return mode;\r\n };\r\n\r\n const effectiveMode = getEffectiveMode();\r\n \r\n return {\r\n mode,\r\n setMode,\r\n toggleMode,\r\n isDark: effectiveMode === 'dark',\r\n isLight: effectiveMode === 'light',\r\n isAuto: mode === 'auto',\r\n effectiveMode, // Expose the resolved mode\r\n };\r\n}\r\n","import * as React from 'react';\r\nimport { useTheme } from '../hooks/useTheme';\r\n\r\nexport interface ThemeToggleProps {\r\n className?: string;\r\n style?: React.CSSProperties;\r\n showLabels?: boolean;\r\n size?: 'sm' | 'md' | 'lg';\r\n}\r\n\r\nexport const ThemeToggle: React.FC<ThemeToggleProps> = ({\r\n className = '',\r\n style = {},\r\n showLabels = false,\r\n size = 'md',\r\n}) => {\r\n const { mode, toggleMode } = useTheme();\r\n\r\n const sizeClasses = {\r\n sm: 'w-8 h-8 text-sm',\r\n md: 'w-10 h-10 text-base',\r\n lg: 'w-12 h-12 text-lg',\r\n };\r\n\r\n const buttonClass = `\r\n ${sizeClasses[size]}\r\n inline-flex items-center justify-center\r\n rounded-md border border-gray-300\r\n bg-white hover:bg-gray-50\r\n dark:bg-gray-800 dark:border-gray-600 dark:hover:bg-gray-700\r\n focus:outline-none focus:ring-2 focus:ring-blue-500\r\n transition-all duration-200\r\n ${className}\r\n `.trim();\r\n\r\n const getIcon = () => {\r\n switch (mode) {\r\n case 'light':\r\n return '☀️';\r\n case 'dark':\r\n return '🌙';\r\n case 'auto':\r\n default:\r\n return '🌓';\r\n }\r\n };\r\n\r\n const getLabel = () => {\r\n switch (mode) {\r\n case 'light':\r\n return 'Light';\r\n case 'dark':\r\n return 'Dark';\r\n case 'auto':\r\n default:\r\n return 'Auto';\r\n }\r\n };\r\n\r\n return (\r\n <button\r\n onClick={toggleMode}\r\n className={buttonClass}\r\n style={style}\r\n title={`Current theme: ${getLabel()}. Click to toggle.`}\r\n aria-label={`Switch theme. Current: ${getLabel()}`}\r\n >\r\n <span role=\"img\" aria-hidden=\"true\">\r\n {getIcon()}\r\n </span>\r\n {showLabels && (\r\n <span className=\"ml-2 text-sm font-medium\">\r\n {getLabel()}\r\n </span>\r\n )}\r\n </button>\r\n );\r\n};\r\n","import * as React from \"react\";\r\nimport { useTheme } from \"../hooks/useTheme\";\r\nimport { ThemeMode } from \"../types\";\r\n\r\nexport interface ThemeSelectorProps {\r\n className?: string;\r\n style?: React.CSSProperties;\r\n showLabels?: boolean;\r\n options?: Array<{\r\n mode: ThemeMode;\r\n label: string;\r\n icon?: string;\r\n }>;\r\n}\r\n\r\nexport const ThemeSelector: React.FC<ThemeSelectorProps> = ({\r\n className = \"\",\r\n style = {},\r\n showLabels = true,\r\n options = [\r\n { mode: \"light\", label: \"Light\", icon: \"☀️\" },\r\n { mode: \"dark\", label: \"Dark\", icon: \"🌙\" },\r\n { mode: \"auto\", label: \"Auto\", icon: \"🌓\" },\r\n ],\r\n}) => {\r\n const { mode, setMode } = useTheme();\r\n\r\n const selectClass = `\r\n px-3 py-2 border border-gray-300 rounded-md\r\n bg-white dark:bg-gray-800 dark:border-gray-600\r\n text-gray-900 dark:text-gray-100\r\n focus:outline-none focus:ring-2 focus:ring-blue-500\r\n transition-all duration-200\r\n ${className}\r\n `.trim();\r\n\r\n return (\r\n <select\r\n value={mode}\r\n onChange={(e) => setMode(e.target.value as ThemeMode)}\r\n className={selectClass}\r\n style={style}\r\n aria-label=\"Select theme mode\"\r\n >\r\n {options.map((option) => (\r\n <option key={option.mode} value={option.mode}>\r\n {showLabels\r\n ? `${option.icon ? option.icon + \" \" : \"\"}${option.label}`\r\n : option.icon || option.label}\r\n </option>\r\n ))}\r\n </select>\r\n );\r\n};\r\n","import { Theme } from '../types';\r\n\r\n/**\r\n * Creates a new theme by merging a base theme with custom properties\r\n */\r\nexport function createTheme(\r\n baseTheme: Theme,\r\n customTheme: Partial<Theme>\r\n): Theme {\r\n return {\r\n ...baseTheme,\r\n ...customTheme,\r\n name: customTheme.name || `${baseTheme.name}-custom`,\r\n colors: {\r\n ...baseTheme.colors,\r\n ...customTheme.colors,\r\n },\r\n spacing: {\r\n ...baseTheme.spacing,\r\n ...customTheme.spacing,\r\n },\r\n radius: {\r\n ...baseTheme.radius,\r\n ...customTheme.radius,\r\n },\r\n typography: {\r\n ...baseTheme.typography,\r\n ...customTheme.typography,\r\n fontFamily: {\r\n ...baseTheme.typography.fontFamily,\r\n ...customTheme.typography?.fontFamily,\r\n },\r\n fontSize: {\r\n ...baseTheme.typography.fontSize,\r\n ...customTheme.typography?.fontSize,\r\n },\r\n fontWeight: {\r\n ...baseTheme.typography.fontWeight,\r\n ...customTheme.typography?.fontWeight,\r\n },\r\n lineHeight: {\r\n ...baseTheme.typography.lineHeight,\r\n ...customTheme.typography?.lineHeight,\r\n },\r\n },\r\n transitions: {\r\n ...baseTheme.transitions,\r\n ...customTheme.transitions,\r\n },\r\n zIndex: {\r\n ...baseTheme.zIndex,\r\n ...customTheme.zIndex,\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Creates a theme variant with modified colors\r\n */\r\nexport function createThemeVariant(\r\n baseTheme: Theme,\r\n colorOverrides: Partial<Theme['colors']>,\r\n name?: string\r\n): Theme {\r\n return createTheme(baseTheme, {\r\n name: name || `${baseTheme.name}-variant`,\r\n colors: {\r\n ...baseTheme.colors,\r\n ...colorOverrides,\r\n },\r\n });\r\n}\r\n","import { Theme } from '../types';\r\n\r\n/**\r\n * Merges multiple themes into a single theme\r\n * Later themes in the array take precedence over earlier ones\r\n */\r\nexport function mergeThemes(...themes: Array<Theme | Partial<Theme>>): Theme {\r\n if (themes.length === 0) {\r\n throw new Error('At least one theme must be provided to mergeThemes');\r\n }\r\n\r\n const [baseTheme, ...additionalThemes] = themes;\r\n \r\n if (!isFullTheme(baseTheme)) {\r\n throw new Error('First theme must be a complete theme object');\r\n }\r\n return additionalThemes.reduce((merged: Theme, theme): Theme => {\r\n return {\r\n ...merged,\r\n ...theme,\r\n name: theme.name || merged.name,\r\n mode: theme.mode || merged.mode,\r\n colors: {\r\n ...merged.colors,\r\n ...theme.colors,\r\n },\r\n spacing: {\r\n ...merged.spacing,\r\n ...theme.spacing,\r\n },\r\n radius: {\r\n ...merged.radius,\r\n ...theme.radius,\r\n },\r\n typography: {\r\n ...merged.typography,\r\n ...theme.typography,\r\n fontFamily: {\r\n ...merged.typography.fontFamily,\r\n ...theme.typography?.fontFamily,\r\n },\r\n fontSize: {\r\n ...merged.typography.fontSize,\r\n ...theme.typography?.fontSize,\r\n },\r\n fontWeight: {\r\n ...merged.typography.fontWeight,\r\n ...theme.typography?.fontWeight,\r\n },\r\n lineHeight: {\r\n ...merged.typography.lineHeight,\r\n ...theme.typography?.lineHeight,\r\n },\r\n },\r\n transitions: {\r\n ...merged.transitions,\r\n ...theme.transitions,\r\n },\r\n zIndex: {\r\n ...merged.zIndex,\r\n ...theme.zIndex,\r\n },\r\n };\r\n }, baseTheme);\r\n}\r\n\r\n/**\r\n * Type guard to check if an object is a complete theme\r\n */\r\nfunction isFullTheme(theme: Theme | Partial<Theme>): theme is Theme {\r\n return !!(\r\n theme &&\r\n typeof theme === 'object' &&\r\n 'name' in theme &&\r\n 'mode' in theme &&\r\n 'colors' in theme &&\r\n 'spacing' in theme &&\r\n 'radius' in theme &&\r\n 'typography' in theme &&\r\n 'transitions' in theme &&\r\n 'zIndex' in theme\r\n );\r\n}\r\n\r\n/**\r\n * Merges theme colors only\r\n */\r\nexport function mergeThemeColors(\r\n baseColors: Theme['colors'],\r\n ...colorSets: Array<Partial<Theme['colors']>>\r\n): Theme['colors'] {\r\n return colorSets.reduce((merged: Theme['colors'], colors): Theme['colors'] => ({\r\n ...merged,\r\n ...colors,\r\n }), baseColors);\r\n}\r\n\r\n/**\r\n * Deep merge utility for complex theme objects\r\n */\r\nexport function deepMergeThemes(target: Theme, ...sources: Array<Partial<Theme>>): Theme {\r\n return sources.reduce((merged: Theme, source): Theme => {\r\n const result = { ...merged };\r\n \r\n for (const key in source) {\r\n const sourceValue = source[key as keyof Theme];\r\n const targetValue = merged[key as keyof Theme];\r\n \r\n if (sourceValue && typeof sourceValue === 'object' && !Array.isArray(sourceValue) && targetValue && typeof targetValue === 'object') {\r\n result[key as keyof Theme] = {\r\n ...targetValue,\r\n ...sourceValue,\r\n } as any;\r\n } else if (sourceValue !== undefined) {\r\n result[key as keyof Theme] = sourceValue as any;\r\n }\r\n }\r\n \r\n return result;\r\n }, target);\r\n}\r\n"],"mappings":"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","names":["lightColors","darkColors","baseTheme","lightTheme","darkTheme","defaultTheme","themes","defaultThemes","mergeTheme","customTheme","createContext","useContext","useEffect","useState","applyTheme","theme","mode","root","effectiveMode","key","value","kebabCase","kebabCase","str","match","jsx","ThemeContext","createContext","ThemeProvider","children","defaultMode","defaultTheme","persistMode","storageKey","customThemes","allThemes","defaultThemes","getInitialMode","stored","error","mode","setModeState","useState","currentThemeName","setCurrentThemeName","getEffectiveMode","getCurrentTheme","effectiveMode","currentTheme","setMode","newMode","toggleMode","systemDark","setTheme","theme","useEffect","applyTheme","mediaQuery","handleChange","contextValue","useThemeContext","context","useContext","useTheme","useThemeContext","useThemeToggle","mode","setMode","toggleMode","useTheme","effectiveMode","jsx","jsxs","ThemeToggle","className","style","showLabels","size","mode","toggleMode","useTheme","buttonClass","getIcon","getLabel","jsx","ThemeSelector","className","style","showLabels","options","mode","setMode","useTheme","selectClass","e","option","createTheme","baseTheme","customTheme","mergeThemes","themes","baseTheme","additionalThemes","isFullTheme","merged","theme","mergeThemeColors","baseColors","colorSets","colors","deepMergeThemes","target","sources","source","result","key","sourceValue","targetValue"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@asafarim/react-themes",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A comprehensive theme management system for React applications with automatic dark/light mode detection, custom theme creation, and smooth transitions.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.mjs",
|
|
15
|
+
"require": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./styles.css": "./src/styles.css"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"README.md",
|
|
22
|
+
"LICENSE"
|
|
23
|
+
],
|
|
24
|
+
"keywords": [
|
|
25
|
+
"react",
|
|
26
|
+
"themes",
|
|
27
|
+
"dark-mode",
|
|
28
|
+
"light-mode",
|
|
29
|
+
"css-variables",
|
|
30
|
+
"theme-management",
|
|
31
|
+
"typescript",
|
|
32
|
+
"ui",
|
|
33
|
+
"components"
|
|
34
|
+
],
|
|
35
|
+
"author": "Ali Safari <ali@asafarim.com>",
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"homepage": "https://github.com/AliSafari-IT/asafarim/tree/main/ASafariM.Clients/packages/react-themes#readme",
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "https://github.com/AliSafari-IT/asafarim.git",
|
|
41
|
+
"directory": "ASafariM.Clients/packages/react-themes"
|
|
42
|
+
},
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/AliSafari-IT/asafarim/issues"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"react": ">=16.8.0",
|
|
48
|
+
"react-dom": ">=16.8.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/react": "^18.2.66",
|
|
52
|
+
"@types/react-dom": "^18.2.22",
|
|
53
|
+
"@typescript-eslint/eslint-plugin": "^7.2.0",
|
|
54
|
+
"@typescript-eslint/parser": "^7.2.0",
|
|
55
|
+
"eslint": "^8.57.0",
|
|
56
|
+
"eslint-plugin-react": "^7.34.0",
|
|
57
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
58
|
+
"tsup": "^8.0.2",
|
|
59
|
+
"typescript": "^5.4.2"
|
|
60
|
+
},
|
|
61
|
+
"tsup": {
|
|
62
|
+
"entry": [
|
|
63
|
+
"src/index.ts"
|
|
64
|
+
],
|
|
65
|
+
"format": [
|
|
66
|
+
"cjs",
|
|
67
|
+
"esm"
|
|
68
|
+
],
|
|
69
|
+
"dts": true,
|
|
70
|
+
"splitting": false,
|
|
71
|
+
"sourcemap": true,
|
|
72
|
+
"clean": true,
|
|
73
|
+
"minify": true,
|
|
74
|
+
"external": [
|
|
75
|
+
"react",
|
|
76
|
+
"react-dom"
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
"scripts": {
|
|
80
|
+
"build": "tsup",
|
|
81
|
+
"dev": "tsup --watch",
|
|
82
|
+
"type-check": "tsc --noEmit",
|
|
83
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
84
|
+
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
85
|
+
"clean": "rm -rf dist"
|
|
86
|
+
}
|
|
87
|
+
}
|