resonare 0.0.11 → 0.0.13
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 +132 -87
- package/dist/index.js +1 -3
- package/dist/index.js.map +1 -1
- package/dist/inline-script.ts +1 -1
- package/dist/react.js +1 -2
- package/dist/react.js.map +1 -1
- package/dist/resonare.iife.min.js +1 -1
- package/package.json +16 -8
package/README.md
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
# Resonare [](https://www.npmjs.com/package/resonare)
|
|
2
2
|
|
|
3
|
-
A configuration-based
|
|
3
|
+
A configuration-based store for managing themes and user preferences.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- Define and manage multi-dimensional themes,
|
|
7
|
+
- Define and manage multi-dimensional themes, e.g.:
|
|
8
8
|
- Color scheme: system, light, dark
|
|
9
9
|
- Contrast preference: standard, high
|
|
10
10
|
- Spacing: compact, comfortable, spacious
|
|
11
|
-
- etc
|
|
11
|
+
- etc.
|
|
12
12
|
- Framework-agnostic
|
|
13
13
|
- Prevent theme flicker on page load
|
|
14
14
|
- Honor system preferences
|
|
15
15
|
- Create sections with independent theming
|
|
16
16
|
- Sync theme selection across tabs and windows
|
|
17
|
-
- Flexible persistence options, defaulting to localStorage
|
|
18
|
-
-
|
|
17
|
+
- Flexible client-side persistence options, defaulting to localStorage
|
|
18
|
+
- Support server-side persistence
|
|
19
19
|
|
|
20
20
|
## Demo
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
[Check it out](https://resonare.universse.workers.dev).
|
|
23
23
|
|
|
24
24
|
## Installation
|
|
25
25
|
|
|
@@ -35,7 +35,9 @@ pnpm add resonare
|
|
|
35
35
|
|
|
36
36
|
## Basic Usage
|
|
37
37
|
|
|
38
|
-
It's recommended to initialize Resonare in a synchronous script to avoid theme flicker on page load.
|
|
38
|
+
It's recommended to initialize Resonare in a synchronous script to avoid theme flicker on page load.
|
|
39
|
+
|
|
40
|
+
Load via CDN:
|
|
39
41
|
|
|
40
42
|
```html
|
|
41
43
|
<script src="https://unpkg.com/resonare"></script>
|
|
@@ -54,32 +56,70 @@ It's recommended to initialize Resonare in a synchronous script to avoid theme f
|
|
|
54
56
|
},
|
|
55
57
|
'light',
|
|
56
58
|
'dark',
|
|
57
|
-
]
|
|
59
|
+
],
|
|
58
60
|
},
|
|
59
61
|
},
|
|
60
62
|
})
|
|
61
63
|
|
|
62
64
|
themeStore.subscribe(({ resolvedThemes }) => {
|
|
63
|
-
for (const [theme,
|
|
64
|
-
document.documentElement.dataset[theme] =
|
|
65
|
+
for (const [theme, option] of Object.entries(resolvedThemes)) {
|
|
66
|
+
document.documentElement.dataset[theme] = option
|
|
65
67
|
}
|
|
66
68
|
})
|
|
67
69
|
|
|
68
70
|
themeStore.restore()
|
|
71
|
+
|
|
69
72
|
themeStore.sync()
|
|
70
73
|
})()
|
|
71
74
|
</script>
|
|
72
75
|
```
|
|
73
76
|
|
|
74
|
-
|
|
77
|
+
Alternatively, inline the stringified version to reduce the number of HTTP requests:
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import { type ThemeConfig, type ThemeStore } from 'resonare'
|
|
81
|
+
import { resonareInlineScript } from 'resonare/inline-script'
|
|
82
|
+
|
|
83
|
+
const themeConfig = {
|
|
84
|
+
colorScheme: {
|
|
85
|
+
options: [
|
|
86
|
+
{
|
|
87
|
+
value: 'system',
|
|
88
|
+
media: ['(prefers-color-scheme: dark)', 'dark', 'light'],
|
|
89
|
+
},
|
|
90
|
+
'light',
|
|
91
|
+
'dark',
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
} as const satisfies ThemeConfig
|
|
95
|
+
|
|
96
|
+
declare module 'resonare' {
|
|
97
|
+
interface ThemeStoreRegistry {
|
|
98
|
+
resonare: ThemeStore<typeof themeConfig>
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function initTheme({ config }: { config: ThemeConfig }) {
|
|
103
|
+
const themeStore = window.resonare.createThemeStore({ config })
|
|
104
|
+
|
|
105
|
+
themeStore.subscribe(({ resolvedThemes }) => {
|
|
106
|
+
Object.entries(resolvedThemes).forEach(([theme, option]) => {
|
|
107
|
+
document.documentElement.dataset[theme] = option
|
|
108
|
+
})
|
|
109
|
+
})
|
|
75
110
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
"include": [
|
|
79
|
-
"node_modules/resonare/global.d.ts",
|
|
80
|
-
// ...
|
|
81
|
-
]
|
|
111
|
+
themeStore.restore()
|
|
112
|
+
themeStore.sync()
|
|
82
113
|
}
|
|
114
|
+
|
|
115
|
+
export const themeScript = `${resonareInlineScript};
|
|
116
|
+
(${initTheme.toString()})(${JSON.stringify({ config: themeConfig })})`
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Add a triple-slash directive to any `.d.ts` file in your project (e.g. `env.d.ts`):
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
/// <reference types="resonare/global" />
|
|
83
123
|
```
|
|
84
124
|
|
|
85
125
|
## API
|
|
@@ -89,7 +129,7 @@ If you are using TypeScript, add `node_modules/resonare/global.d.ts` to `include
|
|
|
89
129
|
```ts
|
|
90
130
|
import { createThemeStore, type ThemeConfig, type ThemeStore } from 'resonare'
|
|
91
131
|
|
|
92
|
-
const
|
|
132
|
+
const themeConfig = {
|
|
93
133
|
colorScheme: {
|
|
94
134
|
options: [
|
|
95
135
|
{
|
|
@@ -98,7 +138,7 @@ const config = {
|
|
|
98
138
|
},
|
|
99
139
|
'light',
|
|
100
140
|
'dark',
|
|
101
|
-
]
|
|
141
|
+
],
|
|
102
142
|
},
|
|
103
143
|
contrast: {
|
|
104
144
|
options: [
|
|
@@ -114,31 +154,28 @@ const config = {
|
|
|
114
154
|
'high',
|
|
115
155
|
],
|
|
116
156
|
initialValue: 'standard',
|
|
117
|
-
}
|
|
157
|
+
},
|
|
158
|
+
sidebarWidth: {
|
|
159
|
+
initialValue: 240,
|
|
160
|
+
},
|
|
118
161
|
} as const satisfies ThemeConfig
|
|
119
162
|
|
|
120
163
|
declare module 'resonare' {
|
|
121
164
|
interface ThemeStoreRegistry {
|
|
122
|
-
resonare: ThemeStore<typeof
|
|
165
|
+
resonare: ThemeStore<typeof themeConfig>
|
|
123
166
|
}
|
|
124
167
|
}
|
|
125
168
|
|
|
126
|
-
|
|
127
169
|
const themeStore = createThemeStore({
|
|
128
170
|
// optional, default 'resonare'
|
|
129
171
|
// should be unique, also used as client storage key
|
|
130
172
|
key: 'resonare',
|
|
131
173
|
|
|
132
174
|
// required, specify theme and options
|
|
133
|
-
config,
|
|
175
|
+
config: themeConfig,
|
|
134
176
|
|
|
135
|
-
// optional, useful for
|
|
136
|
-
initialState:
|
|
137
|
-
themes: {
|
|
138
|
-
colorScheme: 'dark',
|
|
139
|
-
contrast: 'high',
|
|
140
|
-
},
|
|
141
|
-
},
|
|
177
|
+
// optional, useful for server-side persistence
|
|
178
|
+
initialState: persistedStateFromDb, // persisted state returned by themeStore.toPersist()
|
|
142
179
|
|
|
143
180
|
// optional, specify your own client storage
|
|
144
181
|
// localStorage is used by default
|
|
@@ -157,7 +194,7 @@ const themeStore = createThemeStore({
|
|
|
157
194
|
window.addEventListener(
|
|
158
195
|
'storage',
|
|
159
196
|
(e) => {
|
|
160
|
-
if (e.storageArea !== localStorage) return
|
|
197
|
+
if (e.storageArea !== window.localStorage) return
|
|
161
198
|
|
|
162
199
|
cb(e.key, JSON.parse(e.newValue!))
|
|
163
200
|
},
|
|
@@ -175,6 +212,38 @@ const themeStore = createThemeStore({
|
|
|
175
212
|
},
|
|
176
213
|
})
|
|
177
214
|
})
|
|
215
|
+
|
|
216
|
+
// get current theme selection
|
|
217
|
+
// e.g.: { colorScheme: 'system', contrast: 'standard', sidebarWidth: 240 }
|
|
218
|
+
themeStore.getThemes()
|
|
219
|
+
|
|
220
|
+
// get resolved theme selection (after media queries)
|
|
221
|
+
// e.g.: { colorScheme: 'dark', contrast: 'standard', sidebarWidth: 240 }
|
|
222
|
+
themeStore.getResolvedThemes()
|
|
223
|
+
|
|
224
|
+
// update theme
|
|
225
|
+
themeStore.setThemes({ colorScheme: 'light', sidebarWidth: 280 })
|
|
226
|
+
|
|
227
|
+
// get state to persist, useful for server-side persistence
|
|
228
|
+
// to restore, pass the returned object to createThemeStore's initialState
|
|
229
|
+
themeStore.toPersist()
|
|
230
|
+
|
|
231
|
+
// restore persisted state from client-side storage
|
|
232
|
+
themeStore.restore()
|
|
233
|
+
|
|
234
|
+
// sync theme selection across tabs/windows if supported by the storage adapter
|
|
235
|
+
themeStore.sync()
|
|
236
|
+
|
|
237
|
+
// subscribe to theme changes
|
|
238
|
+
themeStore.subscribe(({ themes, resolvedThemes }) => {
|
|
239
|
+
for (const [key, value] of Object.entries(resolvedThemes)) {
|
|
240
|
+
if (key === 'sidebarWidth') {
|
|
241
|
+
document.documentElement.style.setProperty('--sidebar-width', `${value}px`)
|
|
242
|
+
} else {
|
|
243
|
+
document.documentElement.dataset[key] = value
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
})
|
|
178
247
|
```
|
|
179
248
|
|
|
180
249
|
### `getThemeStore`
|
|
@@ -182,8 +251,8 @@ const themeStore = createThemeStore({
|
|
|
182
251
|
```ts
|
|
183
252
|
import { getThemeStore } from 'resonare'
|
|
184
253
|
|
|
185
|
-
//
|
|
186
|
-
const themeStore = getThemeStore('resonare')
|
|
254
|
+
// get an existing theme store by key
|
|
255
|
+
const themeStore = getThemeStore('resonare')
|
|
187
256
|
```
|
|
188
257
|
|
|
189
258
|
### `destroyThemeStore`
|
|
@@ -191,62 +260,40 @@ const themeStore = getThemeStore('resonare')
|
|
|
191
260
|
```ts
|
|
192
261
|
import { destroyThemeStore } from 'resonare'
|
|
193
262
|
|
|
194
|
-
//
|
|
195
|
-
|
|
263
|
+
// destroy an existing theme store by key
|
|
264
|
+
destroyThemeStore('resonare')
|
|
196
265
|
```
|
|
197
266
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
```ts
|
|
201
|
-
interface ThemeStore<T> {
|
|
202
|
-
// get current theme selection
|
|
203
|
-
getThemes(): Record<string, string>
|
|
204
|
-
|
|
205
|
-
// get resolved theme selection (after media queries)
|
|
206
|
-
getResolvedThemes(): Record<string, string>
|
|
207
|
-
|
|
208
|
-
// update theme
|
|
209
|
-
setThemes(themes: Partial<Record<string, string>>): Promise<void>
|
|
210
|
-
|
|
211
|
-
// get state to persist, useful for server-side persistence
|
|
212
|
-
// to restore, pass the returned object to initialState
|
|
213
|
-
toPersist(): object
|
|
214
|
-
|
|
215
|
-
// restore persisted theme selection from client storage
|
|
216
|
-
restore(): Promise<void>
|
|
217
|
-
|
|
218
|
-
// sync theme selection across tabs/windows
|
|
219
|
-
sync(): () => void
|
|
220
|
-
|
|
221
|
-
// subscribe to theme changes
|
|
222
|
-
subscribe(
|
|
223
|
-
callback: ({
|
|
224
|
-
themes,
|
|
225
|
-
resolvedThemes,
|
|
226
|
-
}: {
|
|
227
|
-
themes: Record<string, string>
|
|
228
|
-
resolvedThemes: Record<string, string>
|
|
229
|
-
}) => void,
|
|
230
|
-
options?: { immediate?: boolean }
|
|
231
|
-
): () => void
|
|
232
|
-
}
|
|
233
|
-
```
|
|
267
|
+
## Framework Integrations
|
|
234
268
|
|
|
235
|
-
### React
|
|
269
|
+
### React
|
|
236
270
|
|
|
237
271
|
Ensure that you have initialized Resonare as per instructions under [Basic Usage](#basic-usage).
|
|
238
272
|
|
|
239
273
|
```tsx
|
|
240
274
|
import * as React from 'react'
|
|
241
|
-
import { getThemesAndOptions } from 'resonare'
|
|
275
|
+
import { getThemesAndOptions, type ThemeConfig } from 'resonare'
|
|
242
276
|
import { useResonare } from 'resonare/react'
|
|
243
277
|
|
|
278
|
+
const themeConfig = {
|
|
279
|
+
colorScheme: {
|
|
280
|
+
options: [
|
|
281
|
+
{
|
|
282
|
+
value: 'system',
|
|
283
|
+
media: ['(prefers-color-scheme: dark)', 'dark', 'light'],
|
|
284
|
+
},
|
|
285
|
+
'light',
|
|
286
|
+
'dark',
|
|
287
|
+
],
|
|
288
|
+
},
|
|
289
|
+
} as const satisfies ThemeConfig
|
|
290
|
+
|
|
244
291
|
function ThemeSelect() {
|
|
245
292
|
const { themes, setThemes } = useResonare(() =>
|
|
246
293
|
window.resonare.getThemeStore(),
|
|
247
294
|
)
|
|
248
295
|
|
|
249
|
-
return getThemesAndOptions(
|
|
296
|
+
return getThemesAndOptions(themeConfig).map(([theme, options]) => (
|
|
250
297
|
<div key={theme}>
|
|
251
298
|
<label htmlFor={theme}>{theme}</label>
|
|
252
299
|
<select
|
|
@@ -268,9 +315,9 @@ function ThemeSelect() {
|
|
|
268
315
|
}
|
|
269
316
|
```
|
|
270
317
|
|
|
271
|
-
|
|
318
|
+
## Server-side Persistence
|
|
272
319
|
|
|
273
|
-
|
|
320
|
+
Use `memoryStorageAdapter` to avoid storing any data client-side. The synchronous script is not required.
|
|
274
321
|
|
|
275
322
|
```tsx
|
|
276
323
|
import {
|
|
@@ -278,12 +325,11 @@ import {
|
|
|
278
325
|
getThemesAndOptions,
|
|
279
326
|
memoryStorageAdapter,
|
|
280
327
|
type ThemeConfig,
|
|
281
|
-
type Themes,
|
|
282
328
|
} from 'resonare'
|
|
283
329
|
import { useResonare } from 'resonare/react'
|
|
284
330
|
import * as React from 'react'
|
|
285
331
|
|
|
286
|
-
const
|
|
332
|
+
const themeConfig = {
|
|
287
333
|
colorScheme: {
|
|
288
334
|
options: ['light', 'dark'],
|
|
289
335
|
},
|
|
@@ -292,15 +338,11 @@ const config = {
|
|
|
292
338
|
},
|
|
293
339
|
} as const satisfies ThemeConfig
|
|
294
340
|
|
|
295
|
-
export function ThemeSelect({
|
|
296
|
-
persistedServerThemes,
|
|
297
|
-
}: { persistedServerThemes: Themes<typeof config> }) {
|
|
341
|
+
export function ThemeSelect({ persistedStateFromDb }) {
|
|
298
342
|
const [themeStore] = React.useState(() =>
|
|
299
343
|
createThemeStore({
|
|
300
|
-
config,
|
|
301
|
-
initialState:
|
|
302
|
-
themes: persistedServerThemes,
|
|
303
|
-
},
|
|
344
|
+
config: themeConfig,
|
|
345
|
+
initialState: persistedStateFromDb,
|
|
304
346
|
storage: memoryStorageAdapter(),
|
|
305
347
|
}),
|
|
306
348
|
)
|
|
@@ -309,14 +351,17 @@ export function ThemeSelect({
|
|
|
309
351
|
initOnMount: true,
|
|
310
352
|
})
|
|
311
353
|
|
|
312
|
-
return getThemesAndOptions(
|
|
354
|
+
return getThemesAndOptions(themeConfig).map(([theme, options]) => (
|
|
313
355
|
<div key={theme}>
|
|
314
356
|
<label htmlFor={theme}>{theme}</label>
|
|
315
357
|
<select
|
|
316
358
|
id={theme}
|
|
317
359
|
name={theme}
|
|
318
|
-
onChange={(e) => {
|
|
360
|
+
onChange={async (e) => {
|
|
319
361
|
setThemes({ [theme]: e.target.value })
|
|
362
|
+
|
|
363
|
+
// save to server-side storage
|
|
364
|
+
await saveToDb(themeStore.toPersist())
|
|
320
365
|
}}
|
|
321
366
|
value={themes[theme]}
|
|
322
367
|
>
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
//#region package.json
|
|
2
2
|
var name = "resonare";
|
|
3
|
-
|
|
4
3
|
//#endregion
|
|
5
4
|
//#region src/storage.ts
|
|
6
5
|
const localStorageAdapter = ({ type = "localStorage" } = {}) => {
|
|
@@ -54,7 +53,6 @@ const memoryStorageAdapter = () => {
|
|
|
54
53
|
};
|
|
55
54
|
};
|
|
56
55
|
};
|
|
57
|
-
|
|
58
56
|
//#endregion
|
|
59
57
|
//#region src/index.ts
|
|
60
58
|
function getThemesAndOptions(config) {
|
|
@@ -236,7 +234,7 @@ const registry = new Registry();
|
|
|
236
234
|
const createThemeStore = registry.create;
|
|
237
235
|
const getThemeStore = registry.get;
|
|
238
236
|
const destroyThemeStore = registry.destroy;
|
|
239
|
-
|
|
240
237
|
//#endregion
|
|
241
238
|
export { ThemeStore, createThemeStore, destroyThemeStore, getDefaultThemes, getThemeStore, getThemesAndOptions, localStorageAdapter, memoryStorageAdapter };
|
|
239
|
+
|
|
242
240
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["name","PACKAGE_NAME","type","StorageAdapter","get","key","set","value","broadcast","watch","cb","StorageAdapterCreate","abortController","AbortController","StorageAdapterCreator","options","Options","localStorageAdapter","JSON","parse","window","getItem","setItem","stringify","controller","addEventListener","e","storageArea","newValue","signal","AbortSignal","any","abort","memoryStorageAdapter","storage","Map","channel","BroadcastChannel","postMessage","data","name","PACKAGE_NAME","type","localStorageAdapter","StorageAdapter","StorageAdapterCreate","ThemeOptionValue","ThemeOption","value","T","media","ThemeOptions","options","ReadonlyArray","initialValue","ThemeConfig","Record","KeyedThemeConfig","Themes","K","U","Listener","themes","resolvedThemes","ThemeKeysWithSystemOption","NonSystemOptionValues","SystemOptions","PersistedState","version","Partial","systemOptions","ThemeStoreOptions","key","config","initialState","storage","ThemeAndOptions","Array","getThemesAndOptions","Object","entries","map","themeKey","themeOptions","option","getDefaultThemes","fromEntries","defaultValue","ThemeStore","defaultThemes","currentThemes","listeners","Set","mediaQueryCache","MediaQueryList","abortController","AbortController","constructor","keyedConfig","forEach","hasOwn","String","getThemes","getResolvedThemes","resolveThemes","setThemes","updatedThemes","setThemesAndNotify","stateToPersist","toPersist","set","broadcast","updateSystemOption","ifMatch","ifNotMatch","restore","persistedState","get","subscribe","callback","immediate","add","delete","sync","watch","___destroy","clear","abort","#setThemesAndNotify","notify","#resolveThemes","optionKey","resolveThemeOption","#resolveThemeOption","IIFE","window","document","createElement","console","warn","mediaQuery","mediaQueryList","matchMedia","addEventListener","signal","matches","#notify","listener","Registry","registry","Map","create","storeKey","themeStore","ThemeStoreRegistry","has","Error","destroy","createThemeStore","getThemeStore","destroyThemeStore"],"sources":["../package.json","../src/storage.ts","../src/index.ts"],"sourcesContent":["","import { name as PACKAGE_NAME } from '../package.json' with { type: 'json' }\n\nexport type StorageAdapter = {\n\tget: (key: string) => object | null\n\tset: (key: string, value: object) => void\n\t// del: (key: string) => void\n\tbroadcast?: (key: string, value: object) => void\n\twatch?: (cb: (key: string | null, value: object) => void) => () => void\n}\n\nexport type StorageAdapterCreate = ({\n\tabortController,\n}: {\n\tabortController: AbortController\n}) => StorageAdapter\n\nexport type StorageAdapterCreator<Options> = (\n\toptions?: Options,\n) => StorageAdapterCreate\n\nexport const localStorageAdapter: StorageAdapterCreator<{\n\ttype?: 'localStorage' | 'sessionStorage'\n}> = ({ type = 'localStorage' } = {}) => {\n\treturn ({ abortController }) => {\n\t\treturn {\n\t\t\tget: (key: string) => {\n\t\t\t\treturn JSON.parse(window[type].getItem(key) || 'null')\n\t\t\t},\n\n\t\t\tset: (key: string, value: object) => {\n\t\t\t\twindow[type].setItem(key, JSON.stringify(value))\n\t\t\t},\n\n\t\t\t// del: (key: string) => {\n\t\t\t// \twindow[type].removeItem(key)\n\t\t\t// },\n\n\t\t\twatch: (cb) => {\n\t\t\t\tconst controller = new AbortController()\n\n\t\t\t\twindow.addEventListener(\n\t\t\t\t\t'storage',\n\t\t\t\t\t(e) => {\n\t\t\t\t\t\tif (e.storageArea !== window[type]) return\n\n\t\t\t\t\t\tcb(e.key, JSON.parse(e.newValue!))\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tsignal: AbortSignal.any([\n\t\t\t\t\t\t\tabortController.signal,\n\t\t\t\t\t\t\tcontroller.signal,\n\t\t\t\t\t\t]),\n\t\t\t\t\t},\n\t\t\t\t)\n\n\t\t\t\treturn () => {\n\t\t\t\t\tcontroller.abort()\n\t\t\t\t}\n\t\t\t},\n\t\t}\n\t}\n}\n\nexport const memoryStorageAdapter: StorageAdapterCreator<never> = () => {\n\treturn ({ abortController }) => {\n\t\tconst storage = new Map<string, object>()\n\t\tconst channel = new BroadcastChannel(PACKAGE_NAME)\n\n\t\treturn {\n\t\t\tget: (key: string) => {\n\t\t\t\treturn storage.get(key) || null\n\t\t\t},\n\n\t\t\tset: (key: string, value: object) => {\n\t\t\t\tstorage.set(key, value)\n\t\t\t},\n\n\t\t\t// del: (key: string) => {\n\t\t\t// \tstorage.delete(key)\n\t\t\t// },\n\n\t\t\tbroadcast: (key: string, value: object) => {\n\t\t\t\tchannel.postMessage({ key, value })\n\t\t\t},\n\n\t\t\twatch: (cb) => {\n\t\t\t\tconst controller = new AbortController()\n\n\t\t\t\tchannel.addEventListener(\n\t\t\t\t\t'message',\n\t\t\t\t\t(e) => {\n\t\t\t\t\t\tcb(e.data.key, e.data.value)\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tsignal: AbortSignal.any([\n\t\t\t\t\t\t\tabortController.signal,\n\t\t\t\t\t\t\tcontroller.signal,\n\t\t\t\t\t\t]),\n\t\t\t\t\t},\n\t\t\t\t)\n\n\t\t\t\treturn () => {\n\t\t\t\t\tcontroller.abort()\n\t\t\t\t}\n\t\t\t},\n\t\t}\n\t}\n}\n","import { name as PACKAGE_NAME } from '../package.json' with { type: 'json' }\nimport {\n\tlocalStorageAdapter,\n\ttype StorageAdapter,\n\ttype StorageAdapterCreate,\n} from './storage'\n\ntype ThemeOptionValue = string | number | boolean\n\ntype ThemeOption<T extends ThemeOptionValue = string> = {\n\tvalue: T\n\tmedia?: [string, T, T]\n}\n\ntype ThemeOptions<T extends ThemeOptionValue = string> =\n\t| {\n\t\t\toptions: [\n\t\t\t\tT | ThemeOption<T>,\n\t\t\t\tT | ThemeOption<T>,\n\t\t\t\t...ReadonlyArray<T | ThemeOption<T>>,\n\t\t\t]\n\t\t\tinitialValue?: T\n\t }\n\t| {\n\t\t\tinitialValue: T\n\t }\n\nexport type ThemeConfig = Record<\n\tstring,\n\tThemeOptions<string> | ThemeOptions<number> | ThemeOptions<boolean>\n>\n\n// { [themeKey]: { [optionKey]: ThemeOption } }\ntype KeyedThemeConfig<T extends ThemeConfig> = {\n\t[K in keyof T]: Record<string, ThemeOption>\n}\n\nexport type Themes<T extends ThemeConfig> = {\n\t[K in keyof T]: T[K] extends { options: ReadonlyArray<infer U> }\n\t\t? U extends ThemeOption\n\t\t\t? U['value']\n\t\t\t: U\n\t\t: T[K] extends { initialValue: infer U }\n\t\t\t? U extends string\n\t\t\t\t? string\n\t\t\t\t: U extends number\n\t\t\t\t\t? number\n\t\t\t\t\t: boolean\n\t\t\t: never\n}\n\ntype Listener<T extends ThemeConfig> = (value: {\n\tthemes: Themes<T>\n\tresolvedThemes: Themes<T>\n}) => void\n\ntype ThemeKeysWithSystemOption<T extends ThemeConfig> = {\n\t[K in keyof T]: T[K] extends { options: ReadonlyArray<infer U> }\n\t\t? U extends { media: ReadonlyArray<unknown> }\n\t\t\t? K\n\t\t\t: never\n\t\t: never\n}[keyof T]\n\ntype NonSystemOptionValues<\n\tT extends ThemeConfig,\n\tK extends keyof T,\n> = T[K] extends { options: ReadonlyArray<infer U> }\n\t? U extends ThemeOptionValue\n\t\t? U\n\t\t: U extends ThemeOption\n\t\t\t? U extends { media: [string, string, string] }\n\t\t\t\t? never\n\t\t\t\t: U['value']\n\t\t\t: never\n\t: never\n\ntype SystemOptions<T extends ThemeConfig> = {\n\t[K in ThemeKeysWithSystemOption<T>]?: [\n\t\tNonSystemOptionValues<T, K>,\n\t\tNonSystemOptionValues<T, K>,\n\t]\n}\n\ntype PersistedState<T extends ThemeConfig> = {\n\tversion: 1\n\tthemes: Partial<Themes<T>>\n\tsystemOptions: SystemOptions<T>\n}\n\nexport type ThemeStoreOptions<T extends ThemeConfig> = {\n\tkey?: string\n\tconfig: T\n\tinitialState?: Partial<PersistedState<T>>\n\tstorage?: StorageAdapterCreate | null\n}\n\nexport type ThemeAndOptions<T extends ThemeConfig> = Array<\n\t{\n\t\t[K in keyof T]: [\n\t\t\tK,\n\t\t\tArray<\n\t\t\t\tT[K] extends { options: ReadonlyArray<infer U> }\n\t\t\t\t\t? U extends ThemeOption\n\t\t\t\t\t\t? U['value']\n\t\t\t\t\t\t: U\n\t\t\t\t\t: never\n\t\t\t>,\n\t\t]\n\t}[keyof T]\n>\n\nexport function getThemesAndOptions<T extends ThemeConfig>(config: T) {\n\treturn Object.entries(config).map(([themeKey, themeOptions]) => {\n\t\treturn [\n\t\t\tthemeKey,\n\t\t\t'options' in themeOptions\n\t\t\t\t? themeOptions.options.map((option) =>\n\t\t\t\t\t\ttypeof option === 'string' ? option : option.value,\n\t\t\t\t\t)\n\t\t\t\t: [],\n\t\t]\n\t}) as ThemeAndOptions<T>\n}\n\nexport function getDefaultThemes<T extends ThemeConfig>(config: T) {\n\treturn Object.fromEntries(\n\t\tObject.entries(config).map(([themeKey, themeOptions]) => {\n\t\t\tconst defaultValue =\n\t\t\t\tthemeOptions.initialValue ??\n\t\t\t\tthemeOptions.options[0].value ??\n\t\t\t\tthemeOptions.options[0]\n\n\t\t\treturn [themeKey, defaultValue]\n\t\t}),\n\t) as Themes<T>\n}\n\nexport class ThemeStore<T extends ThemeConfig> {\n\t#defaultThemes: Themes<T>\n\t#currentThemes: Themes<T>\n\n\t#options: {\n\t\tkey: string\n\t\tconfig: KeyedThemeConfig<T>\n\t}\n\n\t#systemOptions: SystemOptions<T>\n\n\t#storage: StorageAdapter | null\n\n\t#listeners: Set<Listener<T>> = new Set<Listener<T>>()\n\n\t#mediaQueryCache: Record<string, MediaQueryList>\n\n\t#abortController = new AbortController()\n\n\tconstructor({\n\t\tkey = PACKAGE_NAME,\n\t\tconfig,\n\t\tinitialState = {},\n\t\tstorage = localStorageAdapter(),\n\t}: ThemeStoreOptions<T>) {\n\t\tconst keyedConfig: Record<string, Record<string, ThemeOption<any>>> = {}\n\t\tconst systemOptions: Record<string, [ThemeOptionValue, ThemeOptionValue]> =\n\t\t\t{\n\t\t\t\t...initialState.systemOptions,\n\t\t\t}\n\n\t\tObject.entries(config).forEach(([themeKey, themeOptions]) => {\n\t\t\tkeyedConfig[themeKey] = {}\n\n\t\t\tif ('options' in themeOptions) {\n\t\t\t\tthemeOptions.options.forEach((option) => {\n\t\t\t\t\tif (typeof option === 'object') {\n\t\t\t\t\t\tif (option.media && !Object.hasOwn(systemOptions, themeKey)) {\n\t\t\t\t\t\t\tsystemOptions[themeKey] = [option.media[1], option.media[2]]\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tkeyedConfig[themeKey]![String(option.value)] = option\n\t\t\t\t\t} else {\n\t\t\t\t\t\tkeyedConfig[themeKey]![String(option)] = { value: option }\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\n\t\tthis.#options = {\n\t\t\tkey,\n\t\t\tconfig: keyedConfig as KeyedThemeConfig<T>,\n\t\t}\n\n\t\tthis.#systemOptions = systemOptions as SystemOptions<T>\n\n\t\tthis.#defaultThemes = getDefaultThemes(config)\n\n\t\tthis.#currentThemes = { ...this.#defaultThemes, ...initialState.themes }\n\n\t\tthis.#storage =\n\t\t\tstorage?.({\n\t\t\t\tabortController: this.#abortController,\n\t\t\t}) ?? null\n\n\t\tthis.#mediaQueryCache = {}\n\t}\n\n\tgetThemes = (): Themes<T> => {\n\t\treturn this.#currentThemes\n\t}\n\n\tgetResolvedThemes = (): Themes<T> => {\n\t\treturn this.#resolveThemes()\n\t}\n\n\tsetThemes = (\n\t\tthemes:\n\t\t\t| Partial<Themes<T>>\n\t\t\t| ((currentThemes: Themes<T>) => Partial<Themes<T>>),\n\t): void => {\n\t\tconst updatedThemes =\n\t\t\ttypeof themes === 'function' ? themes(this.#currentThemes) : themes\n\n\t\tthis.#setThemesAndNotify({ ...this.#currentThemes, ...updatedThemes })\n\n\t\tconst stateToPersist = this.toPersist()\n\n\t\tif (this.#storage) {\n\t\t\tthis.#storage.set(this.#options.key, stateToPersist)\n\t\t\tthis.#storage.broadcast?.(this.#options.key, stateToPersist)\n\t\t}\n\t}\n\n\tupdateSystemOption = <K extends ThemeKeysWithSystemOption<T>>(\n\t\tthemeKey: K,\n\t\t[ifMatch, ifNotMatch]: [\n\t\t\tNonSystemOptionValues<T, K>,\n\t\t\tNonSystemOptionValues<T, K>,\n\t\t],\n\t) => {\n\t\tthis.#systemOptions[themeKey] = [ifMatch, ifNotMatch]\n\n\t\tthis.setThemes({ ...this.#currentThemes })\n\t}\n\n\ttoPersist = (): PersistedState<T> => {\n\t\treturn {\n\t\t\tversion: 1,\n\t\t\tthemes: this.#currentThemes,\n\t\t\tsystemOptions: this.#systemOptions,\n\t\t}\n\t}\n\n\trestore = (): void => {\n\t\tlet persistedState = this.#storage?.get(this.#options.key)\n\n\t\tif (!persistedState) {\n\t\t\tthis.#setThemesAndNotify({ ...this.#defaultThemes })\n\t\t\treturn\n\t\t}\n\n\t\t// for backward compatibility\n\t\tif (!Object.hasOwn(persistedState, 'version')) {\n\t\t\tpersistedState = {\n\t\t\t\tversion: 1,\n\t\t\t\tthemes: persistedState,\n\t\t\t\tsystemOptions: this.#systemOptions,\n\t\t\t}\n\t\t}\n\n\t\tthis.#systemOptions = {\n\t\t\t...this.#systemOptions,\n\t\t\t...persistedState.systemOptions,\n\t\t}\n\n\t\tthis.#setThemesAndNotify({\n\t\t\t...this.#defaultThemes,\n\t\t\t...persistedState.themes,\n\t\t})\n\t}\n\n\tsubscribe = (\n\t\tcallback: Listener<T>,\n\t\t{ immediate = false }: { immediate?: boolean } = {},\n\t): (() => void) => {\n\t\tif (immediate) {\n\t\t\tcallback({\n\t\t\t\tthemes: this.#currentThemes,\n\t\t\t\tresolvedThemes: this.#resolveThemes(),\n\t\t\t})\n\t\t}\n\n\t\tthis.#listeners.add(callback)\n\n\t\treturn () => {\n\t\t\tthis.#listeners.delete(callback)\n\t\t}\n\t}\n\n\tsync = (): (() => void) | undefined => {\n\t\tif (!this.#storage?.watch) {\n\t\t\t// if (this.#storage) {\n\t\t\t// \tconsole.warn(\n\t\t\t// \t\t`[${PACKAGE_NAME}] No watch method was provided for storage.`,\n\t\t\t// \t)\n\t\t\t// } else {\n\t\t\t// \tconsole.warn(`[${PACKAGE_NAME}] No storage was provided.`)\n\t\t\t// }\n\n\t\t\treturn\n\t\t}\n\n\t\treturn this.#storage.watch((key, persistedState) => {\n\t\t\tif (key !== this.#options.key) return\n\n\t\t\tthis.#systemOptions = (persistedState as PersistedState<T>).systemOptions\n\n\t\t\tthis.#setThemesAndNotify((persistedState as PersistedState<T>).themes)\n\t\t})\n\t}\n\n\t___destroy = (): void => {\n\t\tthis.#listeners.clear()\n\t\tthis.#abortController.abort()\n\t}\n\n\t#setThemesAndNotify = (themes: Themes<T>): void => {\n\t\tthis.#currentThemes = themes\n\t\tthis.#notify()\n\t}\n\n\t#resolveThemes = (): Themes<T> => {\n\t\treturn Object.fromEntries(\n\t\t\tObject.entries(this.#currentThemes).map(([themeKey, optionKey]) => {\n\t\t\t\tconst option = this.#options.config[themeKey]?.[optionKey]\n\n\t\t\t\treturn [\n\t\t\t\t\tthemeKey,\n\t\t\t\t\toption ? this.#resolveThemeOption({ themeKey, option }) : optionKey,\n\t\t\t\t]\n\t\t\t}),\n\t\t) as Themes<T>\n\t}\n\n\t#resolveThemeOption = ({\n\t\tthemeKey,\n\t\toption,\n\t}: {\n\t\tthemeKey: string\n\t\toption: ThemeOption\n\t}): string => {\n\t\tif (!option.media) return option.value\n\n\t\tif (!IIFE) {\n\t\t\tif (\n\t\t\t\t!(\n\t\t\t\t\ttypeof window !== 'undefined' &&\n\t\t\t\t\ttypeof window.document !== 'undefined' &&\n\t\t\t\t\ttypeof window.document.createElement !== 'undefined'\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`[${PACKAGE_NAME}] Option with key \"media\" cannot be resolved in server environment.`,\n\t\t\t\t)\n\n\t\t\t\treturn option.value\n\t\t\t}\n\t\t}\n\n\t\tconst [mediaQuery] = option.media\n\n\t\tif (!this.#mediaQueryCache[mediaQuery]) {\n\t\t\tconst mediaQueryList = window.matchMedia(mediaQuery)\n\n\t\t\tthis.#mediaQueryCache[mediaQuery] = mediaQueryList\n\n\t\t\tmediaQueryList.addEventListener(\n\t\t\t\t'change',\n\t\t\t\t() => {\n\t\t\t\t\tif (this.#currentThemes[themeKey] === option.value) {\n\t\t\t\t\t\tthis.#setThemesAndNotify({ ...this.#currentThemes })\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{ signal: this.#abortController.signal },\n\t\t\t)\n\t\t}\n\n\t\tconst [ifMatch, ifNotMatch] = this.#systemOptions[themeKey]!\n\n\t\treturn this.#mediaQueryCache[mediaQuery].matches ? ifMatch : ifNotMatch\n\t}\n\n\t#notify = (): void => {\n\t\tfor (const listener of this.#listeners) {\n\t\t\tlistener({\n\t\t\t\tthemes: this.#currentThemes,\n\t\t\t\tresolvedThemes: this.#resolveThemes(),\n\t\t\t})\n\t\t}\n\t}\n}\n\nclass Registry {\n\t#registry = new Map<string, ThemeStore<ThemeConfig>>()\n\n\tcreate = <T extends ThemeConfig>(\n\t\toptions: ThemeStoreOptions<T>,\n\t): ThemeStore<T> => {\n\t\tconst storeKey = options.key || PACKAGE_NAME\n\n\t\tlet themeStore = this.#registry.get(storeKey) as ThemeStore<T>\n\n\t\tif (!themeStore) {\n\t\t\tthemeStore = new ThemeStore<T>(options)\n\t\t\tthis.#registry.set(storeKey, themeStore as ThemeStore<ThemeConfig>)\n\t\t}\n\n\t\treturn themeStore\n\t}\n\n\tget = <T extends keyof ThemeStoreRegistry>(key?: T) => {\n\t\tconst storeKey = key || PACKAGE_NAME\n\n\t\tif (!this.#registry.has(storeKey)) {\n\t\t\tif (IIFE) {\n\t\t\t\tthrow new Error(`Theme store '${storeKey}' not found.`)\n\t\t\t}\n\t\t\tthrow new Error(\n\t\t\t\t`[${PACKAGE_NAME}] Theme store with key '${storeKey}' could not be found. Please run \\`createThemeStore\\` with key '${storeKey}' first.`,\n\t\t\t)\n\t\t}\n\n\t\treturn this.#registry.get(storeKey)! as ThemeStoreRegistry[T]\n\t}\n\n\tdestroy = <T extends keyof ThemeStoreRegistry>(key?: T) => {\n\t\tconst storeKey = key || PACKAGE_NAME\n\n\t\tif (!this.#registry.has(storeKey)) return\n\n\t\tthis.#registry.get(storeKey)!.___destroy()\n\t\tthis.#registry.delete(storeKey)\n\t}\n}\n\nconst registry = new Registry()\n\nexport const createThemeStore = registry.create\nexport const getThemeStore = registry.get\nexport const destroyThemeStore = registry.destroy\n\nexport * from './storage'\n\nexport interface ThemeStoreRegistry {}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["name","PACKAGE_NAME","type","StorageAdapter","get","key","set","value","broadcast","watch","cb","StorageAdapterCreate","abortController","AbortController","StorageAdapterCreator","options","Options","localStorageAdapter","JSON","parse","window","getItem","setItem","stringify","controller","addEventListener","e","storageArea","newValue","signal","AbortSignal","any","abort","memoryStorageAdapter","storage","Map","channel","BroadcastChannel","postMessage","data","name","PACKAGE_NAME","type","localStorageAdapter","StorageAdapter","StorageAdapterCreate","ThemeOptionValue","ThemeOption","value","T","media","ThemeOptions","options","ReadonlyArray","initialValue","ThemeConfig","Record","KeyedThemeConfig","Themes","K","U","Listener","themes","resolvedThemes","ThemeKeysWithSystemOption","NonSystemOptionValues","SystemOptions","PersistedState","version","Partial","systemOptions","ThemeStoreOptions","key","config","initialState","storage","ThemeAndOptions","Array","getThemesAndOptions","Object","entries","map","themeKey","themeOptions","option","getDefaultThemes","fromEntries","defaultValue","ThemeStore","defaultThemes","currentThemes","listeners","Set","mediaQueryCache","MediaQueryList","abortController","AbortController","constructor","keyedConfig","forEach","hasOwn","String","getThemes","getResolvedThemes","resolveThemes","setThemes","updatedThemes","setThemesAndNotify","stateToPersist","toPersist","set","broadcast","updateSystemOption","ifMatch","ifNotMatch","restore","persistedState","get","subscribe","callback","immediate","add","delete","sync","watch","___destroy","clear","abort","#setThemesAndNotify","notify","#resolveThemes","optionKey","resolveThemeOption","#resolveThemeOption","IIFE","window","document","createElement","console","warn","mediaQuery","mediaQueryList","matchMedia","addEventListener","signal","matches","#notify","listener","Registry","registry","Map","create","storeKey","themeStore","ThemeStoreRegistry","has","Error","destroy","createThemeStore","getThemeStore","destroyThemeStore"],"sources":["../package.json","../src/storage.ts","../src/index.ts"],"sourcesContent":["","import { name as PACKAGE_NAME } from '../package.json' with { type: 'json' }\n\nexport type StorageAdapter = {\n\tget: (key: string) => object | null\n\tset: (key: string, value: object) => void\n\t// del: (key: string) => void\n\tbroadcast?: (key: string, value: object) => void\n\twatch?: (cb: (key: string | null, value: object) => void) => () => void\n}\n\nexport type StorageAdapterCreate = ({\n\tabortController,\n}: {\n\tabortController: AbortController\n}) => StorageAdapter\n\nexport type StorageAdapterCreator<Options> = (\n\toptions?: Options,\n) => StorageAdapterCreate\n\nexport const localStorageAdapter: StorageAdapterCreator<{\n\ttype?: 'localStorage' | 'sessionStorage'\n}> = ({ type = 'localStorage' } = {}) => {\n\treturn ({ abortController }) => {\n\t\treturn {\n\t\t\tget: (key: string) => {\n\t\t\t\treturn JSON.parse(window[type].getItem(key) || 'null')\n\t\t\t},\n\n\t\t\tset: (key: string, value: object) => {\n\t\t\t\twindow[type].setItem(key, JSON.stringify(value))\n\t\t\t},\n\n\t\t\t// del: (key: string) => {\n\t\t\t// \twindow[type].removeItem(key)\n\t\t\t// },\n\n\t\t\twatch: (cb) => {\n\t\t\t\tconst controller = new AbortController()\n\n\t\t\t\twindow.addEventListener(\n\t\t\t\t\t'storage',\n\t\t\t\t\t(e) => {\n\t\t\t\t\t\tif (e.storageArea !== window[type]) return\n\n\t\t\t\t\t\tcb(e.key, JSON.parse(e.newValue!))\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tsignal: AbortSignal.any([\n\t\t\t\t\t\t\tabortController.signal,\n\t\t\t\t\t\t\tcontroller.signal,\n\t\t\t\t\t\t]),\n\t\t\t\t\t},\n\t\t\t\t)\n\n\t\t\t\treturn () => {\n\t\t\t\t\tcontroller.abort()\n\t\t\t\t}\n\t\t\t},\n\t\t}\n\t}\n}\n\nexport const memoryStorageAdapter: StorageAdapterCreator<never> = () => {\n\treturn ({ abortController }) => {\n\t\tconst storage = new Map<string, object>()\n\t\tconst channel = new BroadcastChannel(PACKAGE_NAME)\n\n\t\treturn {\n\t\t\tget: (key: string) => {\n\t\t\t\treturn storage.get(key) || null\n\t\t\t},\n\n\t\t\tset: (key: string, value: object) => {\n\t\t\t\tstorage.set(key, value)\n\t\t\t},\n\n\t\t\t// del: (key: string) => {\n\t\t\t// \tstorage.delete(key)\n\t\t\t// },\n\n\t\t\tbroadcast: (key: string, value: object) => {\n\t\t\t\tchannel.postMessage({ key, value })\n\t\t\t},\n\n\t\t\twatch: (cb) => {\n\t\t\t\tconst controller = new AbortController()\n\n\t\t\t\tchannel.addEventListener(\n\t\t\t\t\t'message',\n\t\t\t\t\t(e) => {\n\t\t\t\t\t\tcb(e.data.key, e.data.value)\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tsignal: AbortSignal.any([\n\t\t\t\t\t\t\tabortController.signal,\n\t\t\t\t\t\t\tcontroller.signal,\n\t\t\t\t\t\t]),\n\t\t\t\t\t},\n\t\t\t\t)\n\n\t\t\t\treturn () => {\n\t\t\t\t\tcontroller.abort()\n\t\t\t\t}\n\t\t\t},\n\t\t}\n\t}\n}\n","import { name as PACKAGE_NAME } from '../package.json' with { type: 'json' }\nimport {\n\tlocalStorageAdapter,\n\ttype StorageAdapter,\n\ttype StorageAdapterCreate,\n} from './storage'\n\ntype ThemeOptionValue = string | number | boolean\n\ntype ThemeOption<T extends ThemeOptionValue = string> = {\n\tvalue: T\n\tmedia?: [string, T, T]\n}\n\ntype ThemeOptions<T extends ThemeOptionValue = string> =\n\t| {\n\t\t\toptions: [\n\t\t\t\tT | ThemeOption<T>,\n\t\t\t\tT | ThemeOption<T>,\n\t\t\t\t...ReadonlyArray<T | ThemeOption<T>>,\n\t\t\t]\n\t\t\tinitialValue?: T\n\t }\n\t| {\n\t\t\tinitialValue: T\n\t }\n\nexport type ThemeConfig = Record<\n\tstring,\n\tThemeOptions<string> | ThemeOptions<number> | ThemeOptions<boolean>\n>\n\n// { [themeKey]: { [optionKey]: ThemeOption } }\ntype KeyedThemeConfig<T extends ThemeConfig> = {\n\t[K in keyof T]: Record<string, ThemeOption>\n}\n\nexport type Themes<T extends ThemeConfig> = {\n\t[K in keyof T]: T[K] extends { options: ReadonlyArray<infer U> }\n\t\t? U extends ThemeOption\n\t\t\t? U['value']\n\t\t\t: U\n\t\t: T[K] extends { initialValue: infer U }\n\t\t\t? U extends string\n\t\t\t\t? string\n\t\t\t\t: U extends number\n\t\t\t\t\t? number\n\t\t\t\t\t: boolean\n\t\t\t: never\n}\n\ntype Listener<T extends ThemeConfig> = (value: {\n\tthemes: Themes<T>\n\tresolvedThemes: Themes<T>\n}) => void\n\ntype ThemeKeysWithSystemOption<T extends ThemeConfig> = {\n\t[K in keyof T]: T[K] extends { options: ReadonlyArray<infer U> }\n\t\t? U extends { media: ReadonlyArray<unknown> }\n\t\t\t? K\n\t\t\t: never\n\t\t: never\n}[keyof T]\n\ntype NonSystemOptionValues<\n\tT extends ThemeConfig,\n\tK extends keyof T,\n> = T[K] extends { options: ReadonlyArray<infer U> }\n\t? U extends ThemeOptionValue\n\t\t? U\n\t\t: U extends ThemeOption\n\t\t\t? U extends { media: [string, string, string] }\n\t\t\t\t? never\n\t\t\t\t: U['value']\n\t\t\t: never\n\t: never\n\ntype SystemOptions<T extends ThemeConfig> = {\n\t[K in ThemeKeysWithSystemOption<T>]?: [\n\t\tNonSystemOptionValues<T, K>,\n\t\tNonSystemOptionValues<T, K>,\n\t]\n}\n\ntype PersistedState<T extends ThemeConfig> = {\n\tversion: 1\n\tthemes: Partial<Themes<T>>\n\tsystemOptions: SystemOptions<T>\n}\n\nexport type ThemeStoreOptions<T extends ThemeConfig> = {\n\tkey?: string\n\tconfig: T\n\tinitialState?: Partial<PersistedState<T>>\n\tstorage?: StorageAdapterCreate | null\n}\n\nexport type ThemeAndOptions<T extends ThemeConfig> = Array<\n\t{\n\t\t[K in keyof T]: [\n\t\t\tK,\n\t\t\tArray<\n\t\t\t\tT[K] extends { options: ReadonlyArray<infer U> }\n\t\t\t\t\t? U extends ThemeOption\n\t\t\t\t\t\t? U['value']\n\t\t\t\t\t\t: U\n\t\t\t\t\t: never\n\t\t\t>,\n\t\t]\n\t}[keyof T]\n>\n\nexport function getThemesAndOptions<T extends ThemeConfig>(config: T) {\n\treturn Object.entries(config).map(([themeKey, themeOptions]) => {\n\t\treturn [\n\t\t\tthemeKey,\n\t\t\t'options' in themeOptions\n\t\t\t\t? themeOptions.options.map((option) =>\n\t\t\t\t\t\ttypeof option === 'string' ? option : option.value,\n\t\t\t\t\t)\n\t\t\t\t: [],\n\t\t]\n\t}) as ThemeAndOptions<T>\n}\n\nexport function getDefaultThemes<T extends ThemeConfig>(config: T) {\n\treturn Object.fromEntries(\n\t\tObject.entries(config).map(([themeKey, themeOptions]) => {\n\t\t\tconst defaultValue =\n\t\t\t\tthemeOptions.initialValue ??\n\t\t\t\tthemeOptions.options[0].value ??\n\t\t\t\tthemeOptions.options[0]\n\n\t\t\treturn [themeKey, defaultValue]\n\t\t}),\n\t) as Themes<T>\n}\n\nexport class ThemeStore<T extends ThemeConfig> {\n\t#defaultThemes: Themes<T>\n\t#currentThemes: Themes<T>\n\n\t#options: {\n\t\tkey: string\n\t\tconfig: KeyedThemeConfig<T>\n\t}\n\n\t#systemOptions: SystemOptions<T>\n\n\t#storage: StorageAdapter | null\n\n\t#listeners: Set<Listener<T>> = new Set<Listener<T>>()\n\n\t#mediaQueryCache: Record<string, MediaQueryList>\n\n\t#abortController = new AbortController()\n\n\tconstructor({\n\t\tkey = PACKAGE_NAME,\n\t\tconfig,\n\t\tinitialState = {},\n\t\tstorage = localStorageAdapter(),\n\t}: ThemeStoreOptions<T>) {\n\t\tconst keyedConfig: Record<string, Record<string, ThemeOption<any>>> = {}\n\t\tconst systemOptions: Record<string, [ThemeOptionValue, ThemeOptionValue]> =\n\t\t\t{\n\t\t\t\t...initialState.systemOptions,\n\t\t\t}\n\n\t\tObject.entries(config).forEach(([themeKey, themeOptions]) => {\n\t\t\tkeyedConfig[themeKey] = {}\n\n\t\t\tif ('options' in themeOptions) {\n\t\t\t\tthemeOptions.options.forEach((option) => {\n\t\t\t\t\tif (typeof option === 'object') {\n\t\t\t\t\t\tif (option.media && !Object.hasOwn(systemOptions, themeKey)) {\n\t\t\t\t\t\t\tsystemOptions[themeKey] = [option.media[1], option.media[2]]\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tkeyedConfig[themeKey]![String(option.value)] = option\n\t\t\t\t\t} else {\n\t\t\t\t\t\tkeyedConfig[themeKey]![String(option)] = { value: option }\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\n\t\tthis.#options = {\n\t\t\tkey,\n\t\t\tconfig: keyedConfig as KeyedThemeConfig<T>,\n\t\t}\n\n\t\tthis.#systemOptions = systemOptions as SystemOptions<T>\n\n\t\tthis.#defaultThemes = getDefaultThemes(config)\n\n\t\tthis.#currentThemes = { ...this.#defaultThemes, ...initialState.themes }\n\n\t\tthis.#storage =\n\t\t\tstorage?.({\n\t\t\t\tabortController: this.#abortController,\n\t\t\t}) ?? null\n\n\t\tthis.#mediaQueryCache = {}\n\t}\n\n\tgetThemes = (): Themes<T> => {\n\t\treturn this.#currentThemes\n\t}\n\n\tgetResolvedThemes = (): Themes<T> => {\n\t\treturn this.#resolveThemes()\n\t}\n\n\tsetThemes = (\n\t\tthemes:\n\t\t\t| Partial<Themes<T>>\n\t\t\t| ((currentThemes: Themes<T>) => Partial<Themes<T>>),\n\t): void => {\n\t\tconst updatedThemes =\n\t\t\ttypeof themes === 'function' ? themes(this.#currentThemes) : themes\n\n\t\tthis.#setThemesAndNotify({ ...this.#currentThemes, ...updatedThemes })\n\n\t\tconst stateToPersist = this.toPersist()\n\n\t\tif (this.#storage) {\n\t\t\tthis.#storage.set(this.#options.key, stateToPersist)\n\t\t\tthis.#storage.broadcast?.(this.#options.key, stateToPersist)\n\t\t}\n\t}\n\n\tupdateSystemOption = <K extends ThemeKeysWithSystemOption<T>>(\n\t\tthemeKey: K,\n\t\t[ifMatch, ifNotMatch]: [\n\t\t\tNonSystemOptionValues<T, K>,\n\t\t\tNonSystemOptionValues<T, K>,\n\t\t],\n\t) => {\n\t\tthis.#systemOptions[themeKey] = [ifMatch, ifNotMatch]\n\n\t\tthis.setThemes({ ...this.#currentThemes })\n\t}\n\n\ttoPersist = (): PersistedState<T> => {\n\t\treturn {\n\t\t\tversion: 1,\n\t\t\tthemes: this.#currentThemes,\n\t\t\tsystemOptions: this.#systemOptions,\n\t\t}\n\t}\n\n\trestore = (): void => {\n\t\tlet persistedState = this.#storage?.get(this.#options.key)\n\n\t\tif (!persistedState) {\n\t\t\tthis.#setThemesAndNotify({ ...this.#defaultThemes })\n\t\t\treturn\n\t\t}\n\n\t\t// for backward compatibility\n\t\tif (!Object.hasOwn(persistedState, 'version')) {\n\t\t\tpersistedState = {\n\t\t\t\tversion: 1,\n\t\t\t\tthemes: persistedState,\n\t\t\t\tsystemOptions: this.#systemOptions,\n\t\t\t}\n\t\t}\n\n\t\tthis.#systemOptions = {\n\t\t\t...this.#systemOptions,\n\t\t\t...persistedState.systemOptions,\n\t\t}\n\n\t\tthis.#setThemesAndNotify({\n\t\t\t...this.#defaultThemes,\n\t\t\t...persistedState.themes,\n\t\t})\n\t}\n\n\tsubscribe = (\n\t\tcallback: Listener<T>,\n\t\t{ immediate = false }: { immediate?: boolean } = {},\n\t): (() => void) => {\n\t\tif (immediate) {\n\t\t\tcallback({\n\t\t\t\tthemes: this.#currentThemes,\n\t\t\t\tresolvedThemes: this.#resolveThemes(),\n\t\t\t})\n\t\t}\n\n\t\tthis.#listeners.add(callback)\n\n\t\treturn () => {\n\t\t\tthis.#listeners.delete(callback)\n\t\t}\n\t}\n\n\tsync = (): (() => void) | undefined => {\n\t\tif (!this.#storage?.watch) {\n\t\t\t// if (this.#storage) {\n\t\t\t// \tconsole.warn(\n\t\t\t// \t\t`[${PACKAGE_NAME}] No watch method was provided for storage.`,\n\t\t\t// \t)\n\t\t\t// } else {\n\t\t\t// \tconsole.warn(`[${PACKAGE_NAME}] No storage was provided.`)\n\t\t\t// }\n\n\t\t\treturn\n\t\t}\n\n\t\treturn this.#storage.watch((key, persistedState) => {\n\t\t\tif (key !== this.#options.key) return\n\n\t\t\tthis.#systemOptions = (persistedState as PersistedState<T>).systemOptions\n\n\t\t\tthis.#setThemesAndNotify((persistedState as PersistedState<T>).themes)\n\t\t})\n\t}\n\n\t___destroy = (): void => {\n\t\tthis.#listeners.clear()\n\t\tthis.#abortController.abort()\n\t}\n\n\t#setThemesAndNotify = (themes: Themes<T>): void => {\n\t\tthis.#currentThemes = themes\n\t\tthis.#notify()\n\t}\n\n\t#resolveThemes = (): Themes<T> => {\n\t\treturn Object.fromEntries(\n\t\t\tObject.entries(this.#currentThemes).map(([themeKey, optionKey]) => {\n\t\t\t\tconst option = this.#options.config[themeKey]?.[optionKey]\n\n\t\t\t\treturn [\n\t\t\t\t\tthemeKey,\n\t\t\t\t\toption ? this.#resolveThemeOption({ themeKey, option }) : optionKey,\n\t\t\t\t]\n\t\t\t}),\n\t\t) as Themes<T>\n\t}\n\n\t#resolveThemeOption = ({\n\t\tthemeKey,\n\t\toption,\n\t}: {\n\t\tthemeKey: string\n\t\toption: ThemeOption\n\t}): string => {\n\t\tif (!option.media) return option.value\n\n\t\tif (!IIFE) {\n\t\t\tif (\n\t\t\t\t!(\n\t\t\t\t\ttypeof window !== 'undefined' &&\n\t\t\t\t\ttypeof window.document !== 'undefined' &&\n\t\t\t\t\ttypeof window.document.createElement !== 'undefined'\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`[${PACKAGE_NAME}] Option with key \"media\" cannot be resolved in server environment.`,\n\t\t\t\t)\n\n\t\t\t\treturn option.value\n\t\t\t}\n\t\t}\n\n\t\tconst [mediaQuery] = option.media\n\n\t\tif (!this.#mediaQueryCache[mediaQuery]) {\n\t\t\tconst mediaQueryList = window.matchMedia(mediaQuery)\n\n\t\t\tthis.#mediaQueryCache[mediaQuery] = mediaQueryList\n\n\t\t\tmediaQueryList.addEventListener(\n\t\t\t\t'change',\n\t\t\t\t() => {\n\t\t\t\t\tif (this.#currentThemes[themeKey] === option.value) {\n\t\t\t\t\t\tthis.#setThemesAndNotify({ ...this.#currentThemes })\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{ signal: this.#abortController.signal },\n\t\t\t)\n\t\t}\n\n\t\tconst [ifMatch, ifNotMatch] = this.#systemOptions[themeKey]!\n\n\t\treturn this.#mediaQueryCache[mediaQuery].matches ? ifMatch : ifNotMatch\n\t}\n\n\t#notify = (): void => {\n\t\tfor (const listener of this.#listeners) {\n\t\t\tlistener({\n\t\t\t\tthemes: this.#currentThemes,\n\t\t\t\tresolvedThemes: this.#resolveThemes(),\n\t\t\t})\n\t\t}\n\t}\n}\n\nclass Registry {\n\t#registry = new Map<string, ThemeStore<ThemeConfig>>()\n\n\tcreate = <T extends ThemeConfig>(\n\t\toptions: ThemeStoreOptions<T>,\n\t): ThemeStore<T> => {\n\t\tconst storeKey = options.key || PACKAGE_NAME\n\n\t\tlet themeStore = this.#registry.get(storeKey) as ThemeStore<T>\n\n\t\tif (!themeStore) {\n\t\t\tthemeStore = new ThemeStore<T>(options)\n\t\t\tthis.#registry.set(storeKey, themeStore as ThemeStore<ThemeConfig>)\n\t\t}\n\n\t\treturn themeStore\n\t}\n\n\tget = <T extends keyof ThemeStoreRegistry>(key?: T) => {\n\t\tconst storeKey = key || PACKAGE_NAME\n\n\t\tif (!this.#registry.has(storeKey)) {\n\t\t\tif (IIFE) {\n\t\t\t\tthrow new Error(`Theme store '${storeKey}' not found.`)\n\t\t\t}\n\t\t\tthrow new Error(\n\t\t\t\t`[${PACKAGE_NAME}] Theme store with key '${storeKey}' could not be found. Please run \\`createThemeStore\\` with key '${storeKey}' first.`,\n\t\t\t)\n\t\t}\n\n\t\treturn this.#registry.get(storeKey)! as ThemeStoreRegistry[T]\n\t}\n\n\tdestroy = <T extends keyof ThemeStoreRegistry>(key?: T) => {\n\t\tconst storeKey = key || PACKAGE_NAME\n\n\t\tif (!this.#registry.has(storeKey)) return\n\n\t\tthis.#registry.get(storeKey)!.___destroy()\n\t\tthis.#registry.delete(storeKey)\n\t}\n}\n\nconst registry = new Registry()\n\nexport const createThemeStore = registry.create\nexport const getThemeStore = registry.get\nexport const destroyThemeStore = registry.destroy\n\nexport * from './storage'\n\nexport interface ThemeStoreRegistry {}\n"],"mappings":"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"}
|
package/dist/inline-script.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const resonareInlineScript = "/**\n* resonare v0.0.
|
|
1
|
+
export const resonareInlineScript = "/**\n* resonare v0.0.13\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/\nvar resonare=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=`resonare`;let n=({type:e=`localStorage`}={})=>({abortController:t})=>({get:t=>JSON.parse(window[e].getItem(t)||`null`),set:(t,n)=>{window[e].setItem(t,JSON.stringify(n))},watch:n=>{let r=new AbortController;return window.addEventListener(`storage`,t=>{t.storageArea===window[e]&&n(t.key,JSON.parse(t.newValue))},{signal:AbortSignal.any([t.signal,r.signal])}),()=>{r.abort()}}});function r(e){return Object.fromEntries(Object.entries(e).map(([e,t])=>[e,t.initialValue??t.options[0].value??t.options[0]]))}var i=class{#e;#t;#n;#r;#i;#a=new Set;#o;#s=new AbortController;constructor({key:e=t,config:i,initialState:a={},storage:o=n()}){let s={},c={...a.systemOptions};Object.entries(i).forEach(([e,t])=>{s[e]={},`options`in t&&t.options.forEach(t=>{typeof t==`object`?(t.media&&!Object.hasOwn(c,e)&&(c[e]=[t.media[1],t.media[2]]),s[e][String(t.value)]=t):s[e][String(t)]={value:t}})}),this.#n={key:e,config:s},this.#r=c,this.#e=r(i),this.#t={...this.#e,...a.themes},this.#i=o?.({abortController:this.#s})??null,this.#o={}}getThemes=()=>this.#t;getResolvedThemes=()=>this.#l();setThemes=e=>{let t=typeof e==`function`?e(this.#t):e;this.#c({...this.#t,...t});let n=this.toPersist();this.#i&&(this.#i.set(this.#n.key,n),this.#i.broadcast?.(this.#n.key,n))};updateSystemOption=(e,[t,n])=>{this.#r[e]=[t,n],this.setThemes({...this.#t})};toPersist=()=>({version:1,themes:this.#t,systemOptions:this.#r});restore=()=>{let e=this.#i?.get(this.#n.key);if(!e){this.#c({...this.#e});return}Object.hasOwn(e,`version`)||(e={version:1,themes:e,systemOptions:this.#r}),this.#r={...this.#r,...e.systemOptions},this.#c({...this.#e,...e.themes})};subscribe=(e,{immediate:t=!1}={})=>(t&&e({themes:this.#t,resolvedThemes:this.#l()}),this.#a.add(e),()=>{this.#a.delete(e)});sync=()=>{if(this.#i?.watch)return this.#i.watch((e,t)=>{e===this.#n.key&&(this.#r=t.systemOptions,this.#c(t.themes))})};___destroy=()=>{this.#a.clear(),this.#s.abort()};#c=e=>{this.#t=e,this.#d()};#l=()=>Object.fromEntries(Object.entries(this.#t).map(([e,t])=>{let n=this.#n.config[e]?.[t];return[e,n?this.#u({themeKey:e,option:n}):t]}));#u=({themeKey:e,option:t})=>{if(!t.media)return t.value;let[n]=t.media;if(!this.#o[n]){let r=window.matchMedia(n);this.#o[n]=r,r.addEventListener(`change`,()=>{this.#t[e]===t.value&&this.#c({...this.#t})},{signal:this.#s.signal})}let[r,i]=this.#r[e];return this.#o[n].matches?r:i};#d=()=>{for(let e of this.#a)e({themes:this.#t,resolvedThemes:this.#l()})}};let a=new class{#e=new Map;create=e=>{let n=e.key||t,r=this.#e.get(n);return r||(r=new i(e),this.#e.set(n,r)),r};get=e=>{let n=e||t;if(!this.#e.has(n))throw Error(`Theme store '${n}' not found.`);return this.#e.get(n)};destroy=e=>{let n=e||t;this.#e.has(n)&&(this.#e.get(n).___destroy(),this.#e.delete(n))}},o=a.create,s=a.get,c=a.destroy;return e.createThemeStore=o,e.destroyThemeStore=c,e.getThemeStore=s,e})({});"
|
package/dist/react.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { c } from "react-compiler-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
|
-
|
|
4
3
|
//#region src/react.ts
|
|
5
4
|
function noop() {}
|
|
6
5
|
const emptyObject = {};
|
|
@@ -66,7 +65,7 @@ function useResonare(getStore, t0) {
|
|
|
66
65
|
} else t6 = $[12];
|
|
67
66
|
return t6;
|
|
68
67
|
}
|
|
69
|
-
|
|
70
68
|
//#endregion
|
|
71
69
|
export { useResonare };
|
|
70
|
+
|
|
72
71
|
//# sourceMappingURL=react.js.map
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","names":["React","ThemeConfig","ThemeStore","noop","emptyObject","emptyStore","getThemes","getResolvedThemes","setThemes","updateSystemOption","toPersist","restore","sync","subscribe","useResonare","getStore","t0","$","_c","t1","undefined","initOnMount","t2","isMounted","setIsMounted","useState","t3","t4","Symbol","for","useEffect","T","themes","useSyncExternalStore","t5","t6","resolvedThemes"],"sources":["../src/react.ts"],"sourcesContent":["import * as React from 'react'\nimport type { ThemeConfig, ThemeStore } from '.'\n\nfunction noop() {}\nconst emptyObject = {}\n\nconst emptyStore = {\n\tgetThemes: () => emptyObject,\n\tgetResolvedThemes: () => emptyObject,\n\tsetThemes: noop,\n\tupdateSystemOption: noop,\n\ttoPersist: noop,\n\trestore: noop,\n\tsync: noop,\n\t// clear: noop,\n\tsubscribe: () => noop,\n}\n\nexport function useResonare<T extends ThemeConfig>(\n\tgetStore: () => ThemeStore<T>,\n\t{ initOnMount = false } = {},\n) {\n\tconst [isMounted, setIsMounted] = React.useState(initOnMount)\n\n\tReact.useEffect(() => {\n\t\tsetIsMounted(true)\n\t}, [])\n\n\tconst {\n\t\tgetThemes,\n\t\tgetResolvedThemes,\n\t\tsetThemes,\n\t\tupdateSystemOption,\n\t\ttoPersist,\n\t\trestore,\n\t\tsync,\n\t\t// clear,\n\t\tsubscribe,\n\t} = isMounted ? getStore() : (emptyStore as unknown as ThemeStore<T>)\n\n\tconst themes = React.useSyncExternalStore(subscribe, getThemes, getThemes)\n\n\treturn {\n\t\tthemes,\n\t\tresolvedThemes: getResolvedThemes(),\n\t\tsetThemes,\n\t\tupdateSystemOption,\n\t\ttoPersist,\n\t\trestore,\n\t\tsync,\n\t\t// clear,\n\t\tsubscribe,\n\t}\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"react.js","names":["React","ThemeConfig","ThemeStore","noop","emptyObject","emptyStore","getThemes","getResolvedThemes","setThemes","updateSystemOption","toPersist","restore","sync","subscribe","useResonare","getStore","t0","$","_c","t1","undefined","initOnMount","t2","isMounted","setIsMounted","useState","t3","t4","Symbol","for","useEffect","T","themes","useSyncExternalStore","t5","t6","resolvedThemes"],"sources":["../src/react.ts"],"sourcesContent":["import * as React from 'react'\nimport type { ThemeConfig, ThemeStore } from '.'\n\nfunction noop() {}\nconst emptyObject = {}\n\nconst emptyStore = {\n\tgetThemes: () => emptyObject,\n\tgetResolvedThemes: () => emptyObject,\n\tsetThemes: noop,\n\tupdateSystemOption: noop,\n\ttoPersist: noop,\n\trestore: noop,\n\tsync: noop,\n\t// clear: noop,\n\tsubscribe: () => noop,\n}\n\nexport function useResonare<T extends ThemeConfig>(\n\tgetStore: () => ThemeStore<T>,\n\t{ initOnMount = false } = {},\n) {\n\tconst [isMounted, setIsMounted] = React.useState(initOnMount)\n\n\tReact.useEffect(() => {\n\t\tsetIsMounted(true)\n\t}, [])\n\n\tconst {\n\t\tgetThemes,\n\t\tgetResolvedThemes,\n\t\tsetThemes,\n\t\tupdateSystemOption,\n\t\ttoPersist,\n\t\trestore,\n\t\tsync,\n\t\t// clear,\n\t\tsubscribe,\n\t} = isMounted ? getStore() : (emptyStore as unknown as ThemeStore<T>)\n\n\tconst themes = React.useSyncExternalStore(subscribe, getThemes, getThemes)\n\n\treturn {\n\t\tthemes,\n\t\tresolvedThemes: getResolvedThemes(),\n\t\tsetThemes,\n\t\tupdateSystemOption,\n\t\ttoPersist,\n\t\trestore,\n\t\tsync,\n\t\t// clear,\n\t\tsubscribe,\n\t}\n}\n"],"mappings":";;;AAGA,SAASG,OAAO;AAChB,MAAMC,cAAc,EAAE;AAEtB,MAAMC,aAAa;CAClBC,iBAAiBF;CACjBG,yBAAyBH;CACzBI,WAAWL;CACXM,oBAAoBN;CACpBO,WAAWP;CACXQ,SAASR;CACTS,MAAMT;CAENU,iBAAiBV;CACjB;AAED,SAAOW,YAAAC,UAAAC,IAAA;CAAA,MAAAC,IAAAC,EAAA,GAAA;CAAA,IAAAC;AAAA,KAAAF,EAAA,OAAAD,IAAA;AAENG,OAAAH,OAAAI,KAAAA,IAAA,EAA4B,GAA5BJ;AAA4BC,IAAA,KAAAD;AAAAC,IAAA,KAAAE;OAAAA,MAAAF,EAAA;CAA5B,MAAA,EAAAI,aAAAC,OAAAH;CAAE,MAAAE,cAAAC,OAAAF,KAAAA,IAAA,QAAAE;CAEF,MAAA,CAAAC,WAAAC,gBAAkCxB,MAAKyB,SAAUJ,YAAY;CAAA,IAAAK;CAAA,IAAAC;AAAA,KAAAV,EAAA,OAAAW,OAAAC,IAAA,4BAAA,EAAA;AAE7CH,aAAA;AACfF,gBAAa,KAAK;;AAChBG,OAAA,EAAE;AAAAV,IAAA,KAAAS;AAAAT,IAAA,KAAAU;QAAA;AAAAD,OAAAT,EAAA;AAAAU,OAAAV,EAAA;;AAFLjB,OAAK8B,UAAWJ,IAEbC,GAAG;CAEN,MAAA,EAAArB,WAAAC,mBAAAC,WAAAC,oBAAAC,WAAAC,SAAAC,MAAAC,cAUIU,YAAYR,UAAqD,GAAvCV;CAE9B,MAAA2B,SAAehC,MAAKiC,qBAAsBpB,WAAWP,WAAWA,UAAU;CAIzD,MAAA4B,KAAA3B,mBAAmB;CAAA,IAAA4B;AAAA,KAAAlB,EAAA,OAAAN,WAAAM,EAAA,OAAAT,aAAAS,EAAA,OAAAJ,aAAAI,EAAA,OAAAL,QAAAK,EAAA,OAAAiB,MAAAjB,EAAA,OAAAe,UAAAf,EAAA,QAAAP,aAAAO,EAAA,QAAAR,oBAAA;AAF7B0B,OAAA;GAAAH;GAAAI,gBAEUF;GAAmB1B;GAAAC;GAAAC;GAAAC;GAAAC;GAAAC;GAQnC;AAAAI,IAAA,KAAAN;AAAAM,IAAA,KAAAT;AAAAS,IAAA,KAAAJ;AAAAI,IAAA,KAAAL;AAAAK,IAAA,KAAAiB;AAAAjB,IAAA,KAAAe;AAAAf,IAAA,MAAAP;AAAAO,IAAA,MAAAR;AAAAQ,IAAA,MAAAkB;OAAAA,MAAAlB,EAAA;AAAA,QAVMkB"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "resonare",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"description": "Resonare",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"theming"
|
|
6
|
+
"theming",
|
|
7
|
+
"dark mode",
|
|
8
|
+
"user preferences"
|
|
7
9
|
],
|
|
8
10
|
"repository": {
|
|
9
11
|
"type": "git",
|
|
@@ -19,6 +21,9 @@
|
|
|
19
21
|
"types": "./dist/index.d.ts",
|
|
20
22
|
"import": "./dist/index.js"
|
|
21
23
|
},
|
|
24
|
+
"./global": {
|
|
25
|
+
"types": "./global.d.ts"
|
|
26
|
+
},
|
|
22
27
|
"./inline-script": {
|
|
23
28
|
"import": "./dist/inline-script.ts"
|
|
24
29
|
},
|
|
@@ -38,18 +43,21 @@
|
|
|
38
43
|
"react-compiler-runtime": "1.0.0"
|
|
39
44
|
},
|
|
40
45
|
"devDependencies": {
|
|
41
|
-
"@
|
|
46
|
+
"@rolldown/plugin-babel": "0.2.2",
|
|
47
|
+
"@size-limit/preset-small-lib": "12.0.1",
|
|
48
|
+
"@types/node": "25.5.0",
|
|
42
49
|
"@types/react": "19.2.14",
|
|
43
|
-
"@vitejs/plugin-react": "
|
|
50
|
+
"@vitejs/plugin-react": "6.0.1",
|
|
44
51
|
"babel-plugin-react-compiler": "1.0.0",
|
|
45
52
|
"cross-env": "10.1.0",
|
|
46
|
-
"jsdom": "
|
|
53
|
+
"jsdom": "29.0.1",
|
|
47
54
|
"react": "19.2.4",
|
|
48
55
|
"react-dom": "19.2.4",
|
|
49
|
-
"size-limit": "12.0.
|
|
50
|
-
"tsdown": "0.
|
|
56
|
+
"size-limit": "12.0.1",
|
|
57
|
+
"tsdown": "0.21.4",
|
|
51
58
|
"typescript": "5.9.3",
|
|
52
|
-
"
|
|
59
|
+
"vite": "8.0.1",
|
|
60
|
+
"vitest": "4.1.0"
|
|
53
61
|
},
|
|
54
62
|
"peerDependencies": {
|
|
55
63
|
"react": "^18.0.0 || ^19.0.0"
|