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 CHANGED
@@ -1,25 +1,25 @@
1
1
  # Resonare [![Version](https://img.shields.io/npm/v/resonare.svg?labelColor=black&color=blue)](https://www.npmjs.com/package/resonare)
2
2
 
3
- A configuration-based theme store for building deeply personal user interface.
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, eg:
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
- - SSR-friendly
17
+ - Flexible client-side persistence options, defaulting to localStorage
18
+ - Support server-side persistence
19
19
 
20
20
  ## Demo
21
21
 
22
- - [Demo](https://resonare.universse.workers.dev)
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. If your project's bundler supports importing static asset as string, you can inline the minified version of Resonare to reduce the number of HTTP requests. Check out the demo for example of this pattern with Vite.
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, optionKey] of Object.entries(resolvedThemes)) {
64
- document.documentElement.dataset[theme] = optionKey
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
- If you are using TypeScript, add `node_modules/resonare/global.d.ts` to `include` in `tsconfig.json`.
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
- ```json
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 config = {
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 config>
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 SSR
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
- // Get an existing theme store by key
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
- // Get an existing theme store by key
195
- const themeStore = destroyThemeStore('resonare')
263
+ // destroy an existing theme store by key
264
+ destroyThemeStore('resonare')
196
265
  ```
197
266
 
198
- ### ThemeStore Methods
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 Integration
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(config).map(([theme, options]) => (
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
- ### Server-side persistence
318
+ ## Server-side Persistence
272
319
 
273
- If you are storing theme selection on the server, you can choose to use `memoryStorageAdapter` to avoid storing any data client-side. There's no need to initialize Resonare in a synchronous script. Ensure you pass the persisted theme selection when initializing Resonare as `initialState`.
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 config = {
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(config).map(([theme, options]) => (
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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"}
@@ -1 +1 @@
1
- export const resonareInlineScript = "/**\n* resonare v0.0.11\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})({});"
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":";;;;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,SAAA,EAA4B,GAA5BJ;AAA4BC,IAAA,KAAAD;AAAAC,IAAA,KAAAE;OAAAA,MAAAF,EAAA;CAA5B,MAAA,EAAAI,aAAAC,OAAAH;CAAE,MAAAE,cAAAC,OAAAF,SAAA,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"}
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"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * resonare v0.0.11
2
+ * resonare v0.0.13
3
3
  *
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
package/package.json CHANGED
@@ -1,9 +1,11 @@
1
1
  {
2
2
  "name": "resonare",
3
- "version": "0.0.11",
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
- "@size-limit/preset-small-lib": "12.0.0",
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": "5.1.4",
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": "28.1.0",
53
+ "jsdom": "29.0.1",
47
54
  "react": "19.2.4",
48
55
  "react-dom": "19.2.4",
49
- "size-limit": "12.0.0",
50
- "tsdown": "0.20.3",
56
+ "size-limit": "12.0.1",
57
+ "tsdown": "0.21.4",
51
58
  "typescript": "5.9.3",
52
- "vitest": "4.0.18"
59
+ "vite": "8.0.1",
60
+ "vitest": "4.1.0"
53
61
  },
54
62
  "peerDependencies": {
55
63
  "react": "^18.0.0 || ^19.0.0"