@qodin-co/sol 0.1.3 → 0.1.4
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 +450 -469
- package/dist/devtools/index.js +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/{solar-theme-provider-WbsezzLH.js → solar-theme-provider-DSYQUslj.js} +9 -4
- package/dist/solar-theme-provider-DSYQUslj.js.map +1 -0
- package/package.json +1 -1
- package/dist/solar-theme-provider-WbsezzLH.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,470 +1,451 @@
|
|
|
1
|
-
<div align="center">
|
|
2
|
-
|
|
3
|
-
<img src=".github/banner.png" alt="@qodin-co/sol — solar-aware React widgets" width="100%" />
|
|
4
|
-
|
|
5
|
-
<br />
|
|
6
|
-
<br />
|
|
7
|
-
|
|
8
|
-
<a href="https://www.npmjs.com/package/@qodin-co/sol">
|
|
9
|
-
<img src="https://img.shields.io/npm/v/@qodin-co/sol?style=flat-square&color=111&labelColor=111&logo=npm" alt="npm version" />
|
|
10
|
-
</a>
|
|
11
|
-
<a href="https://www.npmjs.com/package/@qodin-co/sol">
|
|
12
|
-
<img src="https://img.shields.io/npm/dm/@qodin-co/sol?style=flat-square&color=111&labelColor=111" alt="npm downloads" />
|
|
13
|
-
</a>
|
|
14
|
-
<a href="https://github.com/qodin-co/sol/blob/main/LICENSE">
|
|
15
|
-
<img src="https://img.shields.io/npm/l/@qodin-co/sol?style=flat-square&color=111&labelColor=111" alt="license" />
|
|
16
|
-
</a>
|
|
17
|
-
<a href="https://github.com/qodin-co/sol/actions/workflows/validate.yml">
|
|
18
|
-
<img src="https://img.shields.io/github/actions/workflow/status/qodin-co/sol/validate.yml?style=flat-square&color=111&labelColor=111&label=ci" alt="CI" />
|
|
19
|
-
</a>
|
|
20
|
-
|
|
21
|
-
<br />
|
|
22
|
-
<br />
|
|
23
|
-
|
|
24
|
-
**Solar-aware React widgets that follow the real position of the sun.**
|
|
25
|
-
|
|
26
|
-
[npm](https://www.npmjs.com/package/@qodin-co/sol) · [GitHub](https://github.com/qodin-co/sol) · withsol.app — launching soon
|
|
27
|
-
|
|
28
|
-
</div>
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
bun add @qodin-co/sol
|
|
34
|
-
# or
|
|
35
|
-
npm install @qodin-co/sol
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
`@qodin-co/sol` gives you a full `SolarWidget`, a `CompactWidget`, 10 skins, 9 solar phases, optional live weather, optional flag display, and a dev-only timeline scrubber via `SolarDevTools`. No solar API required — solar position is computed locally from latitude, longitude, timezone, and current time.
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
## Features
|
|
43
|
-
|
|
44
|
-
- **2 widget variants** — `SolarWidget` (full card) and `CompactWidget` (slim pill/bar)
|
|
45
|
-
- **10 skins** — `foundry`, `paper`, `signal`, `meridian`, `mineral`, `aurora`, `tide`, `void`, `sundial`, `parchment`
|
|
46
|
-
- **9 solar phases** — `midnight`, `night`, `dawn`, `sunrise`, `morning`, `solar-noon`, `afternoon`, `sunset`, `dusk`
|
|
47
|
-
- **Built-in fallback strategy** — geolocation → browser timezone → timezone centroid
|
|
48
|
-
- **Optional live weather** — powered by Open-Meteo (no API key required)
|
|
49
|
-
- **Dev preview tooling** — `SolarDevTools` lets you scrub through the day and preview phase colors
|
|
50
|
-
|
|
51
|
-
---
|
|
52
|
-
|
|
53
|
-
## Installation
|
|
54
|
-
|
|
55
|
-
Import the package styles once at your app root — no Tailwind setup required:
|
|
56
|
-
|
|
57
|
-
```ts
|
|
58
|
-
import '@qodin-co/sol/styles.css';
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
---
|
|
62
|
-
|
|
63
|
-
## Quick Start
|
|
64
|
-
|
|
65
|
-
### 1. Wrap your app
|
|
66
|
-
|
|
67
|
-
```tsx
|
|
68
|
-
import '@qodin-co/sol/styles.css';
|
|
69
|
-
import { SolarThemeProvider } from '@qodin-co/sol';
|
|
70
|
-
|
|
71
|
-
export function AppProviders({ children }: { children: React.ReactNode }) {
|
|
72
|
-
return (
|
|
73
|
-
<SolarThemeProvider
|
|
74
|
-
{children}
|
|
75
|
-
</SolarThemeProvider>
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### 2. Render a widget
|
|
81
|
-
|
|
82
|
-
```tsx
|
|
83
|
-
import { SolarWidget } from '@qodin-co/sol';
|
|
84
|
-
|
|
85
|
-
export default function Page() {
|
|
86
|
-
return (
|
|
87
|
-
<SolarWidget
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
<
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
|
230
|
-
|
|
|
231
|
-
|
|
|
232
|
-
|
|
|
233
|
-
|
|
|
234
|
-
|
|
|
235
|
-
|
|
|
236
|
-
|
|
|
237
|
-
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
<
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
###
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
---
|
|
406
|
-
|
|
407
|
-
##
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
---
|
|
431
|
-
|
|
432
|
-
##
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
## Coming Soon
|
|
452
|
-
|
|
453
|
-
**SOL** website is launching soon — a dedicated site for Sol with full documentation, live skin previews, and a playground to explore every phase and skin combination.
|
|
454
|
-
|
|
455
|
-
Sol is actively being developed. Things in progress:
|
|
456
|
-
|
|
457
|
-
- **Seasonal theme system** — 4 seasons (Summer, Autumn, Winter, Spring) that blend automatically with the existing 9-phase system, computed from date and location with no configuration required
|
|
458
|
-
- More skins
|
|
459
|
-
- Vue and Svelte adapters
|
|
460
|
-
- Deep token override system
|
|
461
|
-
|
|
462
|
-
Follow the repo or watch releases to stay updated.
|
|
463
|
-
|
|
464
|
-
---
|
|
465
|
-
|
|
466
|
-
<div align="center">
|
|
467
|
-
|
|
468
|
-
MIT © [qodin](https://github.com/qodin-co)
|
|
469
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src=".github/banner.png" alt="@qodin-co/sol — solar-aware React widgets" width="100%" />
|
|
4
|
+
|
|
5
|
+
<br />
|
|
6
|
+
<br />
|
|
7
|
+
|
|
8
|
+
<a href="https://www.npmjs.com/package/@qodin-co/sol">
|
|
9
|
+
<img src="https://img.shields.io/npm/v/@qodin-co/sol?style=flat-square&color=111&labelColor=111&logo=npm" alt="npm version" />
|
|
10
|
+
</a>
|
|
11
|
+
<a href="https://www.npmjs.com/package/@qodin-co/sol">
|
|
12
|
+
<img src="https://img.shields.io/npm/dm/@qodin-co/sol?style=flat-square&color=111&labelColor=111" alt="npm downloads" />
|
|
13
|
+
</a>
|
|
14
|
+
<a href="https://github.com/qodin-co/sol/blob/main/LICENSE">
|
|
15
|
+
<img src="https://img.shields.io/npm/l/@qodin-co/sol?style=flat-square&color=111&labelColor=111" alt="license" />
|
|
16
|
+
</a>
|
|
17
|
+
<a href="https://github.com/qodin-co/sol/actions/workflows/validate.yml">
|
|
18
|
+
<img src="https://img.shields.io/github/actions/workflow/status/qodin-co/sol/validate.yml?style=flat-square&color=111&labelColor=111&label=ci" alt="CI" />
|
|
19
|
+
</a>
|
|
20
|
+
|
|
21
|
+
<br />
|
|
22
|
+
<br />
|
|
23
|
+
|
|
24
|
+
**Solar-aware React widgets that follow the real position of the sun.**
|
|
25
|
+
|
|
26
|
+
[npm](https://www.npmjs.com/package/@qodin-co/sol) · [GitHub](https://github.com/qodin-co/sol) · withsol.app — launching soon
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
bun add @qodin-co/sol
|
|
34
|
+
# or
|
|
35
|
+
npm install @qodin-co/sol
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`@qodin-co/sol` gives you a full `SolarWidget`, a `CompactWidget`, 10 skins, 9 solar phases, optional live weather, optional flag display, and a dev-only timeline scrubber via `SolarDevTools`. No solar API required — solar position is computed locally from latitude, longitude, timezone, and current time.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Features
|
|
43
|
+
|
|
44
|
+
- **2 widget variants** — `SolarWidget` (full card) and `CompactWidget` (slim pill/bar)
|
|
45
|
+
- **10 skins** — `foundry`, `paper`, `signal`, `meridian`, `mineral`, `aurora`, `tide`, `void`, `sundial`, `parchment`
|
|
46
|
+
- **9 solar phases** — `midnight`, `night`, `dawn`, `sunrise`, `morning`, `solar-noon`, `afternoon`, `sunset`, `dusk`
|
|
47
|
+
- **Built-in fallback strategy** — geolocation → browser timezone → timezone centroid
|
|
48
|
+
- **Optional live weather** — powered by Open-Meteo (no API key required)
|
|
49
|
+
- **Dev preview tooling** — `SolarDevTools` lets you scrub through the day and preview phase colors
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Installation
|
|
54
|
+
|
|
55
|
+
Import the package styles once at your app root — no Tailwind setup required:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import '@qodin-co/sol/styles.css';
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Quick Start
|
|
64
|
+
|
|
65
|
+
### 1. Wrap your app
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import '@qodin-co/sol/styles.css';
|
|
69
|
+
import { SolarThemeProvider } from '@qodin-co/sol';
|
|
70
|
+
|
|
71
|
+
export function AppProviders({ children }: { children: React.ReactNode }) {
|
|
72
|
+
return (
|
|
73
|
+
<SolarThemeProvider initialDesign="foundry">
|
|
74
|
+
{children}
|
|
75
|
+
</SolarThemeProvider>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 2. Render a widget
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
import { SolarWidget } from '@qodin-co/sol';
|
|
84
|
+
|
|
85
|
+
export default function Page() {
|
|
86
|
+
return (
|
|
87
|
+
<SolarWidget
|
|
88
|
+
showWeather
|
|
89
|
+
showFlag
|
|
90
|
+
hoverEffect
|
|
91
|
+
/>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 3. Or use the compact variant
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
import { CompactWidget } from '@qodin-co/sol';
|
|
100
|
+
|
|
101
|
+
export default function HeaderStatus() {
|
|
102
|
+
return (
|
|
103
|
+
<CompactWidget
|
|
104
|
+
design="signal"
|
|
105
|
+
showWeather
|
|
106
|
+
showFlag
|
|
107
|
+
size="md"
|
|
108
|
+
/>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Provider Setup
|
|
116
|
+
|
|
117
|
+
`SolarThemeProvider` is the shared runtime for solar phase computation, timezone, coordinates, skin selection, and live/manual overrides.
|
|
118
|
+
|
|
119
|
+
### Basic
|
|
120
|
+
|
|
121
|
+
```tsx
|
|
122
|
+
<SolarThemeProvider initialDesign="paper">
|
|
123
|
+
<App />
|
|
124
|
+
</SolarThemeProvider>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Location is automatic
|
|
128
|
+
|
|
129
|
+
`SolarThemeProvider` resolves the user's location automatically using a 3-step fallback:
|
|
130
|
+
|
|
131
|
+
1. **Browser Geolocation API** — most accurate (requires user permission)
|
|
132
|
+
2. **Browser timezone** (`Intl.DateTimeFormat`) — instant, no permission needed
|
|
133
|
+
3. **Timezone centroid lookup** — maps the IANA timezone to approximate city coordinates
|
|
134
|
+
|
|
135
|
+
Solar phases are accurate to ~15–30 minutes from timezone alone, and refine to exact values when geolocation is granted.
|
|
136
|
+
|
|
137
|
+
### Override location (optional)
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
<SolarThemeProvider
|
|
141
|
+
initialDesign="meridian"
|
|
142
|
+
>
|
|
143
|
+
<App />
|
|
144
|
+
</SolarThemeProvider>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
> These props override automatic resolution. Omit them to let Sol detect location automatically.
|
|
148
|
+
|
|
149
|
+
### With global CSS variables
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
<SolarThemeProvider initialDesign="aurora">
|
|
153
|
+
<App />
|
|
154
|
+
</SolarThemeProvider>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Provider Props
|
|
158
|
+
|
|
159
|
+
| Prop | Type | Default | Description |
|
|
160
|
+
|---|---|---|---|
|
|
161
|
+
| `children` | `ReactNode` | — | Required |
|
|
162
|
+
| `initialDesign` | `DesignMode` | `'foundry'` | Default design/skin |
|
|
163
|
+
| `isolated` | `boolean` | `false` | Scope CSS vars to wrapper instead of `:root` |
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## SolarWidget
|
|
168
|
+
|
|
169
|
+
```tsx
|
|
170
|
+
<SolarWidget
|
|
171
|
+
expandDirection="top-left"
|
|
172
|
+
size="lg"
|
|
173
|
+
showWeather
|
|
174
|
+
showFlag
|
|
175
|
+
hoverEffect
|
|
176
|
+
/>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Props
|
|
180
|
+
|
|
181
|
+
| Prop | Type | Default | Description |
|
|
182
|
+
|---|---|---|---|
|
|
183
|
+
| `expandDirection` | `ExpandDirection` | `'bottom-right'` | Direction the card opens |
|
|
184
|
+
| `size` | `WidgetSize` | `'lg'` | Widget size |
|
|
185
|
+
| `showWeather` | `boolean` | `false` | Enable live weather display |
|
|
186
|
+
| `showFlag` | `boolean` | `false` | Show country flag |
|
|
187
|
+
| `hoverEffect` | `boolean` | `false` | Enable hover animation |
|
|
188
|
+
| `phaseOverride` | `SolarPhase` | — | Force a discrete phase |
|
|
189
|
+
| `simulatedDate` | `Date` | — | Simulate a specific time |
|
|
190
|
+
| `weatherCategoryOverride` | `WeatherCategory \| null` | — | Force weather condition |
|
|
191
|
+
| `customPalettes` | `CustomPalettes` | — | Override phase colors |
|
|
192
|
+
| `forceExpanded` | `boolean` | — | Lock expanded/collapsed state |
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## CompactWidget
|
|
197
|
+
|
|
198
|
+
```tsx
|
|
199
|
+
<CompactWidget
|
|
200
|
+
design="signal"
|
|
201
|
+
size="md"
|
|
202
|
+
showWeather
|
|
203
|
+
showFlag
|
|
204
|
+
showTemperature
|
|
205
|
+
/>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Props
|
|
209
|
+
|
|
210
|
+
| Prop | Type | Default | Description |
|
|
211
|
+
|---|---|---|---|
|
|
212
|
+
| `design` | `DesignMode` | provider design | Design/skin override |
|
|
213
|
+
| `size` | `CompactSize` | `'md'` | Compact size |
|
|
214
|
+
| `showWeather` | `boolean` | `false` | Show weather icon |
|
|
215
|
+
| `showFlag` | `boolean` | `false` | Show country flag |
|
|
216
|
+
| `showTemperature` | `boolean` | `true` | Show live temperature |
|
|
217
|
+
| `overridePhase` | `SolarPhase \| null` | — | Force a discrete phase |
|
|
218
|
+
| `simulatedDate` | `Date` | — | Simulate a time |
|
|
219
|
+
| `className` | `string` | — | Wrapper CSS class |
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Skins
|
|
224
|
+
|
|
225
|
+
10 designs, each with a full widget and compact variant. If `design` is omitted on a widget, it uses the provider's active design.
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
type DesignMode =
|
|
229
|
+
| 'aurora' // luminous ethereal
|
|
230
|
+
| 'foundry' // warm volumetric industrial
|
|
231
|
+
| 'tide' // fluid organic wave
|
|
232
|
+
| 'void' // minimal negative space
|
|
233
|
+
| 'mineral' // faceted crystal gem
|
|
234
|
+
| 'meridian' // hairline geometric
|
|
235
|
+
| 'signal' // pixel/blocky lo-fi
|
|
236
|
+
| 'paper' // flat ink editorial
|
|
237
|
+
| 'sundial' // roman/classical carved
|
|
238
|
+
| 'parchment'; // document strokes
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Positioning
|
|
244
|
+
|
|
245
|
+
```tsx
|
|
246
|
+
<SolarWidget /> // inline (default)
|
|
247
|
+
<SolarWidget position="bottom-right" /> // fixed to viewport
|
|
248
|
+
<SolarWidget position="bottom-right" expandDirection="top-left" /> // with expand direction
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Supported positions: `top-left` `top-center` `top-right` `center-left` `center` `center-right` `bottom-left` `bottom-center` `bottom-right` `inline`
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Weather
|
|
256
|
+
|
|
257
|
+
```tsx
|
|
258
|
+
<SolarWidget showWeather />
|
|
259
|
+
|
|
260
|
+
// Force a category for preview
|
|
261
|
+
<SolarWidget showWeather weatherCategoryOverride="thunder" />
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Powered by [Open-Meteo](https://open-meteo.com/) — free, no API key. Available categories: `clear` `partly-cloudy` `overcast` `fog` `drizzle` `rain` `heavy-rain` `snow` `heavy-snow` `thunder`
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Phase & Time Overrides
|
|
269
|
+
|
|
270
|
+
```tsx
|
|
271
|
+
// Force a discrete phase
|
|
272
|
+
<SolarWidget phaseOverride="sunset" />
|
|
273
|
+
|
|
274
|
+
// Simulate a specific time (with blend)
|
|
275
|
+
const preview = new Date();
|
|
276
|
+
preview.setHours(6, 45, 0, 0);
|
|
277
|
+
<SolarWidget simulatedDate={preview} />
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Use `simulatedDate` for realistic continuous previews. Use `phaseOverride` for simple hard overrides.
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## Custom Palettes
|
|
285
|
+
|
|
286
|
+
```tsx
|
|
287
|
+
<SolarWidget
|
|
288
|
+
customPalettes={{
|
|
289
|
+
dawn: { bg: ['#20122a', '#7f3b5d', '#f5a66e'] },
|
|
290
|
+
sunset: { bg: ['#2e0f18', '#b84a3d', '#ffbe7a'] },
|
|
291
|
+
}}
|
|
292
|
+
/>
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## SolarDevTools
|
|
298
|
+
|
|
299
|
+
A dev-only bottom-fixed pill for scrubbing through the day. Imported from a dedicated subpath — never included in production bundles unless explicitly imported.
|
|
300
|
+
|
|
301
|
+
```tsx
|
|
302
|
+
import { SolarDevTools } from '@qodin-co/sol/devtools';
|
|
303
|
+
|
|
304
|
+
// Vite
|
|
305
|
+
{import.meta.env.DEV && <SolarDevTools />}
|
|
306
|
+
|
|
307
|
+
// Next.js
|
|
308
|
+
{process.env.NODE_ENV === 'development' && <SolarDevTools />}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Full example
|
|
312
|
+
|
|
313
|
+
```tsx
|
|
314
|
+
import '@qodin-co/sol/styles.css';
|
|
315
|
+
import { SolarThemeProvider, SolarWidget } from '@qodin-co/sol';
|
|
316
|
+
import { SolarDevTools } from '@qodin-co/sol/devtools';
|
|
317
|
+
|
|
318
|
+
export default function Demo() {
|
|
319
|
+
return (
|
|
320
|
+
<SolarThemeProvider initialDesign="foundry">
|
|
321
|
+
<SolarWidget showWeather showFlag />
|
|
322
|
+
{process.env.NODE_ENV === 'development' && (
|
|
323
|
+
<SolarDevTools position="bottom-center" />
|
|
324
|
+
)}
|
|
325
|
+
</SolarThemeProvider>
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Props
|
|
331
|
+
|
|
332
|
+
| Prop | Type | Default | Description |
|
|
333
|
+
|---|---|---|---|
|
|
334
|
+
| `defaultOpen` | `boolean` | `false` | Start expanded |
|
|
335
|
+
| `position` | `'bottom-left' \| 'bottom-center' \| 'bottom-right'` | `'bottom-center'` | Pill position |
|
|
336
|
+
| `enabled` | `boolean` | `true` | Programmatic enable/disable |
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
## useSolarTheme
|
|
341
|
+
|
|
342
|
+
```tsx
|
|
343
|
+
import { useSolarTheme } from '@qodin-co/sol';
|
|
344
|
+
|
|
345
|
+
function DebugPanel() {
|
|
346
|
+
const { phase, timezone, latitude, longitude, design } = useSolarTheme();
|
|
347
|
+
return (
|
|
348
|
+
<pre>{JSON.stringify({ phase, timezone, latitude, longitude, design }, null, 2)}</pre>
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Return shape
|
|
354
|
+
|
|
355
|
+
| Property | Type | Description |
|
|
356
|
+
|---|---|---|
|
|
357
|
+
| `phase` | `SolarPhase` | Current active phase |
|
|
358
|
+
| `blend` | `SolarBlend` | Phase blend state (phase, nextPhase, t) |
|
|
359
|
+
| `isDaytime` | `boolean` | Whether the sun is above the horizon |
|
|
360
|
+
| `brightness` | `number` | 0–1 brightness value |
|
|
361
|
+
| `mode` | `'light' \| 'dim' \| 'dark'` | Current light mode |
|
|
362
|
+
| `accentColor` | `string` | Active accent hex |
|
|
363
|
+
| `timezone` | `string \| null` | Resolved timezone |
|
|
364
|
+
| `latitude` | `number \| null` | Resolved latitude |
|
|
365
|
+
| `longitude` | `number \| null` | Resolved longitude |
|
|
366
|
+
| `coordsReady` | `boolean` | Whether coordinates have resolved |
|
|
367
|
+
| `design` | `DesignMode` | Active skin name |
|
|
368
|
+
| `activeSkin` | `SkinDefinition` | Full skin definition object |
|
|
369
|
+
| `setOverridePhase` | `(phase \| null) => void` | Set/clear phase override |
|
|
370
|
+
| `setDesign` | `(skin: DesignMode) => void` | Change active skin |
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Multiple Widgets
|
|
375
|
+
|
|
376
|
+
```tsx
|
|
377
|
+
<SolarThemeProvider initialDesign="foundry">
|
|
378
|
+
<SolarWidget showWeather />
|
|
379
|
+
<CompactWidget design="signal" />
|
|
380
|
+
<SolarWidget />
|
|
381
|
+
</SolarThemeProvider>
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
Each widget can have its own design. The provider manages shared solar state.
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## TypeScript
|
|
389
|
+
|
|
390
|
+
```ts
|
|
391
|
+
import type {
|
|
392
|
+
DesignMode,
|
|
393
|
+
SolarPhase,
|
|
394
|
+
SolarBlend,
|
|
395
|
+
WeatherCategory,
|
|
396
|
+
ExpandDirection,
|
|
397
|
+
WidgetSize,
|
|
398
|
+
CompactSize,
|
|
399
|
+
SkinDefinition,
|
|
400
|
+
WidgetPalette,
|
|
401
|
+
SolarTheme,
|
|
402
|
+
} from '@qodin-co/sol';
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
## SSR / Hydration Notes
|
|
408
|
+
|
|
409
|
+
Sol is client-aware and uses browser APIs for geolocation, timezone, and storage. The provider falls back safely when coordinates are not yet resolved. Use the `ClientOnly` wrapper if you encounter hydration mismatches in SSR frameworks.
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
## What's Included
|
|
414
|
+
|
|
415
|
+
| | |
|
|
416
|
+
|---|---|
|
|
417
|
+
| ✅ | Full widget + compact widget |
|
|
418
|
+
| ✅ | 10 skins with full + compact variants |
|
|
419
|
+
| ✅ | Solar math (NOAA equations, no external API) |
|
|
420
|
+
| ✅ | Timezone fallback logic |
|
|
421
|
+
| ✅ | Optional live weather (Open-Meteo) |
|
|
422
|
+
| ✅ | Skin-aware country flags |
|
|
423
|
+
| ✅ | Dev timeline scrubber |
|
|
424
|
+
| ✅ | Compiled CSS (no Tailwind required) |
|
|
425
|
+
| ❌ | No solar API key needed |
|
|
426
|
+
| ❌ | No weather API key needed |
|
|
427
|
+
| ❌ | No Tailwind in your app |
|
|
428
|
+
| ❌ | No geolocation permission required |
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
## Coming Soon
|
|
433
|
+
|
|
434
|
+
**SOL** website is launching soon — a dedicated site for Sol with full documentation, live skin previews, and a playground to explore every phase and skin combination.
|
|
435
|
+
|
|
436
|
+
Sol is actively being developed. Things in progress:
|
|
437
|
+
|
|
438
|
+
- **Seasonal theme system** — 4 seasons (Summer, Autumn, Winter, Spring) that blend automatically with the existing 9-phase system, computed from date and location with no configuration required
|
|
439
|
+
- More skins
|
|
440
|
+
- Vue and Svelte adapters
|
|
441
|
+
- Deep token override system
|
|
442
|
+
|
|
443
|
+
Follow the repo or watch releases to stay updated.
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
<div align="center">
|
|
448
|
+
|
|
449
|
+
MIT © [qodin](https://github.com/qodin-co)
|
|
450
|
+
|
|
470
451
|
</div>
|