@dheme/react 2.0.0 → 2.1.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/README.md +61 -62
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -71,36 +71,38 @@ The main provider. Manages theme state, API calls, caching, and CSS variable app
|
|
|
71
71
|
|
|
72
72
|
```tsx
|
|
73
73
|
<DhemeProvider
|
|
74
|
-
apiKey="dheme_abc12345_..."
|
|
75
|
-
theme="#3b82f6"
|
|
76
|
-
themeParams={{
|
|
74
|
+
apiKey="dheme_abc12345_..." // Required — your Dheme API key
|
|
75
|
+
theme="#3b82f6" // Primary color (auto-generates on mount)
|
|
76
|
+
themeParams={{
|
|
77
|
+
// Optional generation params
|
|
77
78
|
radius: 0.75,
|
|
78
79
|
saturationAdjust: 10,
|
|
79
80
|
secondaryColor: '#10b981',
|
|
81
|
+
borderIsColored: false,
|
|
80
82
|
}}
|
|
81
|
-
defaultMode="light"
|
|
82
|
-
persist={true}
|
|
83
|
-
autoApply={true}
|
|
84
|
-
onThemeChange={(theme) => {}}
|
|
85
|
-
onModeChange={(mode) => {}}
|
|
86
|
-
onError={(error) => {}}
|
|
83
|
+
defaultMode="light" // 'light' | 'dark' (default: 'light')
|
|
84
|
+
persist={true} // Cache in localStorage (default: true)
|
|
85
|
+
autoApply={true} // Apply CSS vars automatically (default: true)
|
|
86
|
+
onThemeChange={(theme) => {}} // Callback when theme changes
|
|
87
|
+
onModeChange={(mode) => {}} // Callback when mode changes
|
|
88
|
+
onError={(error) => {}} // Callback on error
|
|
87
89
|
>
|
|
88
90
|
<App />
|
|
89
91
|
</DhemeProvider>
|
|
90
92
|
```
|
|
91
93
|
|
|
92
|
-
| Prop | Type | Default | Description
|
|
93
|
-
| --------------- | ---------------------------------------- | --------- |
|
|
94
|
-
| `apiKey` | `string` | - | **Required.** Your Dheme API key.
|
|
94
|
+
| Prop | Type | Default | Description |
|
|
95
|
+
| --------------- | ---------------------------------------- | --------- | ------------------------------------------- |
|
|
96
|
+
| `apiKey` | `string` | - | **Required.** Your Dheme API key. |
|
|
95
97
|
| `theme` | `string` | - | Primary HEX color. Auto-generates on mount. |
|
|
96
|
-
| `themeParams` | `Omit<GenerateThemeRequest, 'theme'>` | - | Additional generation parameters.
|
|
97
|
-
| `defaultMode` | `'light' \| 'dark'` | `'light'` | Initial color mode.
|
|
98
|
-
| `baseUrl` | `string` | - | Override API base URL.
|
|
99
|
-
| `persist` | `boolean` | `true` | Cache theme in localStorage.
|
|
100
|
-
| `autoApply` | `boolean` | `true` | Apply CSS variables to `:root`.
|
|
101
|
-
| `onThemeChange` | `(theme: GenerateThemeResponse) => void` | - | Called when theme data changes.
|
|
102
|
-
| `onModeChange` | `(mode: ThemeMode) => void` | - | Called when mode changes.
|
|
103
|
-
| `onError` | `(error: Error) => void` | - | Called on API errors.
|
|
98
|
+
| `themeParams` | `Omit<GenerateThemeRequest, 'theme'>` | - | Additional generation parameters. |
|
|
99
|
+
| `defaultMode` | `'light' \| 'dark'` | `'light'` | Initial color mode. |
|
|
100
|
+
| `baseUrl` | `string` | - | Override API base URL. |
|
|
101
|
+
| `persist` | `boolean` | `true` | Cache theme in localStorage. |
|
|
102
|
+
| `autoApply` | `boolean` | `true` | Apply CSS variables to `:root`. |
|
|
103
|
+
| `onThemeChange` | `(theme: GenerateThemeResponse) => void` | - | Called when theme data changes. |
|
|
104
|
+
| `onModeChange` | `(mode: ThemeMode) => void` | - | Called when mode changes. |
|
|
105
|
+
| `onError` | `(error: Error) => void` | - | Called on API errors. |
|
|
104
106
|
|
|
105
107
|
### `<DhemeScript>`
|
|
106
108
|
|
|
@@ -108,17 +110,17 @@ Blocking script that prevents FOUC by applying cached theme CSS variables before
|
|
|
108
110
|
|
|
109
111
|
```tsx
|
|
110
112
|
<DhemeScript
|
|
111
|
-
defaultMode="light"
|
|
112
|
-
nonce="abc123"
|
|
113
|
+
defaultMode="light" // Fallback mode (default: 'light')
|
|
114
|
+
nonce="abc123" // CSP nonce (optional)
|
|
113
115
|
/>
|
|
114
116
|
```
|
|
115
117
|
|
|
116
118
|
Place it **before** `<DhemeProvider>` in your component tree, as high as possible.
|
|
117
119
|
|
|
118
|
-
| Prop | Type
|
|
119
|
-
| ------------- |
|
|
120
|
-
| `defaultMode` | `'light' \| 'dark'`
|
|
121
|
-
| `nonce` | `string`
|
|
120
|
+
| Prop | Type | Default | Description |
|
|
121
|
+
| ------------- | ------------------- | --------- | ------------------------- |
|
|
122
|
+
| `defaultMode` | `'light' \| 'dark'` | `'light'` | Fallback if no cache. |
|
|
123
|
+
| `nonce` | `string` | - | CSP nonce for the script. |
|
|
122
124
|
|
|
123
125
|
## Hooks
|
|
124
126
|
|
|
@@ -134,17 +136,15 @@ function MyComponent() {
|
|
|
134
136
|
|
|
135
137
|
if (!isReady) return <Skeleton />;
|
|
136
138
|
|
|
137
|
-
return
|
|
138
|
-
<p>Primary: {theme.colors[mode].primary.h}°</p>
|
|
139
|
-
);
|
|
139
|
+
return <p>Primary: {theme.colors[mode].primary.h}°</p>;
|
|
140
140
|
}
|
|
141
141
|
```
|
|
142
142
|
|
|
143
|
-
| Return | Type
|
|
144
|
-
| --------- |
|
|
145
|
-
| `theme` | `GenerateThemeResponse \| null` | The full theme data.
|
|
146
|
-
| `mode` | `'light' \| 'dark'`
|
|
147
|
-
| `isReady` | `boolean`
|
|
143
|
+
| Return | Type | Description |
|
|
144
|
+
| --------- | ------------------------------- | ---------------------------- |
|
|
145
|
+
| `theme` | `GenerateThemeResponse \| null` | The full theme data. |
|
|
146
|
+
| `mode` | `'light' \| 'dark'` | Current color mode. |
|
|
147
|
+
| `isReady` | `boolean` | `true` once theme is loaded. |
|
|
148
148
|
|
|
149
149
|
### `useThemeActions()`
|
|
150
150
|
|
|
@@ -157,24 +157,21 @@ function ThemeToggle() {
|
|
|
157
157
|
const { setMode, isLoading } = useThemeActions();
|
|
158
158
|
|
|
159
159
|
return (
|
|
160
|
-
<button
|
|
161
|
-
disabled={isLoading}
|
|
162
|
-
onClick={() => setMode(mode === 'light' ? 'dark' : 'light')}
|
|
163
|
-
>
|
|
160
|
+
<button disabled={isLoading} onClick={() => setMode(mode === 'light' ? 'dark' : 'light')}>
|
|
164
161
|
Toggle
|
|
165
162
|
</button>
|
|
166
163
|
);
|
|
167
164
|
}
|
|
168
165
|
```
|
|
169
166
|
|
|
170
|
-
| Return | Type
|
|
171
|
-
| --------------- |
|
|
172
|
-
| `generateTheme` | `(params: GenerateThemeRequest) => Promise<void>` | Generate a new theme.
|
|
173
|
-
| `setMode` | `(mode: ThemeMode) => void`
|
|
174
|
-
| `clearTheme` | `() => void`
|
|
175
|
-
| `isLoading` | `boolean`
|
|
176
|
-
| `error` | `Error \| null`
|
|
177
|
-
| `client` | `DhemeClient`
|
|
167
|
+
| Return | Type | Description |
|
|
168
|
+
| --------------- | ------------------------------------------------- | ------------------------ |
|
|
169
|
+
| `generateTheme` | `(params: GenerateThemeRequest) => Promise<void>` | Generate a new theme. |
|
|
170
|
+
| `setMode` | `(mode: ThemeMode) => void` | Switch light/dark mode. |
|
|
171
|
+
| `clearTheme` | `() => void` | Clear theme and cache. |
|
|
172
|
+
| `isLoading` | `boolean` | `true` during API call. |
|
|
173
|
+
| `error` | `Error \| null` | Last error, if any. |
|
|
174
|
+
| `client` | `DhemeClient` | Raw SDK client instance. |
|
|
178
175
|
|
|
179
176
|
### `useGenerateTheme()`
|
|
180
177
|
|
|
@@ -187,10 +184,7 @@ function ColorPicker() {
|
|
|
187
184
|
const { generateTheme, isGenerating, error } = useGenerateTheme();
|
|
188
185
|
|
|
189
186
|
return (
|
|
190
|
-
<button
|
|
191
|
-
disabled={isGenerating}
|
|
192
|
-
onClick={() => generateTheme({ theme: '#ef4444' })}
|
|
193
|
-
>
|
|
187
|
+
<button disabled={isGenerating} onClick={() => generateTheme({ theme: '#ef4444' })}>
|
|
194
188
|
{isGenerating ? 'Generating...' : 'Apply Red'}
|
|
195
189
|
</button>
|
|
196
190
|
);
|
|
@@ -220,10 +214,10 @@ function UsageInfo() {
|
|
|
220
214
|
|
|
221
215
|
The provider uses **two separate React contexts** to minimize re-renders:
|
|
222
216
|
|
|
223
|
-
| Context | Contains
|
|
224
|
-
| --------------------- |
|
|
225
|
-
| `ThemeDataContext`
|
|
226
|
-
| `ThemeActionsContext`
|
|
217
|
+
| Context | Contains | Changes when |
|
|
218
|
+
| --------------------- | ------------------------------------------------ | -------------------------- |
|
|
219
|
+
| `ThemeDataContext` | `theme`, `mode`, `isReady` | Theme data or mode changes |
|
|
220
|
+
| `ThemeActionsContext` | `generateTheme`, `setMode`, `isLoading`, `error` | Actions are triggered |
|
|
227
221
|
|
|
228
222
|
Components using `useTheme()` (data) **do not re-render** when `isLoading` changes.
|
|
229
223
|
Components using `useThemeActions()` (actions) **do not re-render** when theme data changes.
|
|
@@ -238,11 +232,12 @@ Themes are cached in `localStorage` with deterministic keys based on input param
|
|
|
238
232
|
same input params → same cache key → same theme
|
|
239
233
|
```
|
|
240
234
|
|
|
241
|
-
The cache key is derived from: `theme`, `secondaryColor`, `radius`, `saturationAdjust`, `lightnessAdjust`, `contrastAdjust`, `cardIsColored`, `backgroundIsColored`.
|
|
235
|
+
The cache key is derived from: `theme`, `secondaryColor`, `radius`, `saturationAdjust`, `lightnessAdjust`, `contrastAdjust`, `cardIsColored`, `backgroundIsColored`, `borderIsColored`.
|
|
242
236
|
|
|
243
237
|
### Stale-while-revalidate
|
|
244
238
|
|
|
245
239
|
On cached visits, the provider:
|
|
240
|
+
|
|
246
241
|
1. Serves the cached theme **immediately** (zero latency)
|
|
247
242
|
2. Fires a background API request to check for updates
|
|
248
243
|
3. Only updates the UI if the response differs from the cache
|
|
@@ -335,7 +330,7 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
|
335
330
|
>
|
|
336
331
|
<App />
|
|
337
332
|
</DhemeProvider>
|
|
338
|
-
</React.StrictMode
|
|
333
|
+
</React.StrictMode>
|
|
339
334
|
);
|
|
340
335
|
```
|
|
341
336
|
|
|
@@ -351,7 +346,11 @@ export default function App() {
|
|
|
351
346
|
|
|
352
347
|
return (
|
|
353
348
|
<div>
|
|
354
|
-
<h1
|
|
349
|
+
<h1
|
|
350
|
+
style={{
|
|
351
|
+
color: `hsl(${theme.colors[mode].primary.h} ${theme.colors[mode].primary.s}% ${theme.colors[mode].primary.l}%)`,
|
|
352
|
+
}}
|
|
353
|
+
>
|
|
355
354
|
Dheme Theme
|
|
356
355
|
</h1>
|
|
357
356
|
<button onClick={() => setMode(mode === 'light' ? 'dark' : 'light')}>
|
|
@@ -382,11 +381,11 @@ import type {
|
|
|
382
381
|
|
|
383
382
|
## Related Packages
|
|
384
383
|
|
|
385
|
-
| Package | Description
|
|
386
|
-
| -------------- |
|
|
387
|
-
| `@dheme/sdk` | Core TypeScript SDK
|
|
388
|
-
| `@dheme/react` | React bindings (this package)
|
|
389
|
-
| `@dheme/next` | Next.js App Router bindings
|
|
384
|
+
| Package | Description | When to use |
|
|
385
|
+
| -------------- | ----------------------------- | -------------------------- |
|
|
386
|
+
| `@dheme/sdk` | Core TypeScript SDK | Direct API access, Node.js |
|
|
387
|
+
| `@dheme/react` | React bindings (this package) | Vite, CRA, React SPAs |
|
|
388
|
+
| `@dheme/next` | Next.js App Router bindings | Next.js 14+ with SSR |
|
|
390
389
|
|
|
391
390
|
## License
|
|
392
391
|
|
package/dist/index.d.mts
CHANGED
|
@@ -18,7 +18,8 @@ interface ThemeActionsState {
|
|
|
18
18
|
client: DhemeClient;
|
|
19
19
|
}
|
|
20
20
|
interface DhemeProviderProps {
|
|
21
|
-
|
|
21
|
+
/** API key (obrigatório para uso externo; omitir para rotas internas sem autenticação) */
|
|
22
|
+
apiKey?: string;
|
|
22
23
|
theme?: string;
|
|
23
24
|
themeParams?: Omit<GenerateThemeRequest, 'theme'>;
|
|
24
25
|
defaultMode?: ThemeMode;
|
package/dist/index.d.ts
CHANGED
|
@@ -18,7 +18,8 @@ interface ThemeActionsState {
|
|
|
18
18
|
client: DhemeClient;
|
|
19
19
|
}
|
|
20
20
|
interface DhemeProviderProps {
|
|
21
|
-
|
|
21
|
+
/** API key (obrigatório para uso externo; omitir para rotas internas sem autenticação) */
|
|
22
|
+
apiKey?: string;
|
|
22
23
|
theme?: string;
|
|
23
24
|
themeParams?: Omit<GenerateThemeRequest, 'theme'>;
|
|
24
25
|
defaultMode?: ThemeMode;
|