@molecule/app-theme 1.0.0 → 1.0.2

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 ADDED
@@ -0,0 +1,474 @@
1
+ <!--
2
+ AUTO-GENERATED — DO NOT EDIT THIS FILE.
3
+ Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
4
+ Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
5
+ To change this document, edit the module-level JSDoc in src/index.ts.
6
+ Generated: 2026-09-13T23:39:57.945Z
7
+ -->
8
+
9
+ # @molecule/app-theme
10
+
11
+ > **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
12
+ > It is written to be read by coding agents as much as by people, and is generated from this
13
+ > package's source — edit `src/index.ts` JSDoc, not this file.
14
+
15
+ Theme interface and utilities for molecule.dev.
16
+
17
+ Framework-agnostic theme contract — a {@link Theme} (colors, spacing,
18
+ typography, radii, shadows, z-index) plus a {@link ThemeProvider} bond for
19
+ reading/switching themes, dark/light toggling, and change subscriptions.
20
+ Bond a provider (e.g. `@molecule/app-theme-css-variables`, which applies the
21
+ palette as CSS variables) at startup; {@link lightTheme}/{@link darkTheme}
22
+ are the base defaults.
23
+
24
+ ## Quick Start
25
+
26
+ ```typescript
27
+ import { getProvider } from '@molecule/app-theme'
28
+
29
+ const theme = getProvider() // null until a bond is wired at startup
30
+ theme?.toggleMode() // light <-> dark
31
+ const unsubscribe = theme?.subscribe((t) => applyBranding(t))
32
+ ```
33
+
34
+ ## Type
35
+
36
+ `core`
37
+
38
+ ## Installation
39
+
40
+ ```bash
41
+ npm install @molecule/app-theme @molecule/app-bond
42
+ ```
43
+
44
+ ## API
45
+
46
+ ### Interfaces
47
+
48
+ #### `Theme`
49
+
50
+ Complete theme definition.
51
+
52
+ ```typescript
53
+ interface Theme {
54
+ name: string
55
+ mode: 'light' | 'dark'
56
+ colors: ThemeColors
57
+ breakpoints: ThemeBreakpoints
58
+ spacing: ThemeSpacing
59
+ typography: ThemeTypography
60
+ borderRadius: ThemeBorderRadius
61
+ shadows: ThemeShadows
62
+ transitions: ThemeTransitions
63
+ zIndex: ThemeZIndex
64
+ }
65
+ ```
66
+
67
+ #### `ThemeBorderRadius`
68
+
69
+ Border radius scale.
70
+
71
+ ```typescript
72
+ interface ThemeBorderRadius {
73
+ none: string
74
+ sm: string
75
+ md: string
76
+ lg: string
77
+ xl: string
78
+ full: string
79
+ }
80
+ ```
81
+
82
+ #### `ThemeBreakpoints`
83
+
84
+ Responsive viewport breakpoints from mobileS (320px) to desktop (2560px).
85
+
86
+ ```typescript
87
+ interface ThemeBreakpoints {
88
+ mobileS: string // 320px
89
+ mobileM: string // 375px
90
+ mobileL: string // 425px
91
+ tablet: string // 768px
92
+ laptop: string // 1024px
93
+ laptopL: string // 1440px
94
+ desktop: string // 2560px
95
+ }
96
+ ```
97
+
98
+ #### `ThemeColors`
99
+
100
+ Color palette definition.
101
+
102
+ ```typescript
103
+ interface ThemeColors {
104
+ // Base colors
105
+ background: string
106
+ backgroundSecondary: string
107
+ backgroundTertiary: string
108
+ surface: string
109
+ surfaceSecondary: string
110
+ inputBackground: string
111
+
112
+ // Text colors
113
+ text: string
114
+ textSecondary: string
115
+ textTertiary: string
116
+ textInverse: string
117
+
118
+ // Brand colors
119
+ primary: string
120
+ primaryLight: string
121
+ primaryDark: string
122
+ secondary: string
123
+ secondaryLight: string
124
+ secondaryDark: string
125
+
126
+ // Semantic colors
127
+ success: string
128
+ successLight: string
129
+ warning: string
130
+ warningLight: string
131
+ error: string
132
+ errorLight: string
133
+ info: string
134
+ infoLight: string
135
+
136
+ // Border colors
137
+ border: string
138
+ borderSecondary: string
139
+ borderFocus: string
140
+
141
+ // Other
142
+ overlay: string
143
+ shadow: string
144
+ }
145
+ ```
146
+
147
+ #### `ThemeProvider`
148
+
149
+ Manages theme state including the active theme, mode toggling,
150
+ and change subscriptions.
151
+
152
+ ```typescript
153
+ interface ThemeProvider {
154
+ /**
155
+ * Returns the currently active theme.
156
+ */
157
+ getTheme(): Theme
158
+
159
+ /**
160
+ * Sets the active theme by reference or by name.
161
+ *
162
+ * @param theme - A `Theme` object or a theme name string to activate.
163
+ */
164
+ setTheme(theme: Theme | string): void
165
+
166
+ /**
167
+ * Toggles between light and dark mode for the active theme.
168
+ */
169
+ toggleMode(): void
170
+
171
+ /**
172
+ * Subscribes to theme changes. The callback fires whenever
173
+ * `setTheme()` or `toggleMode()` is called.
174
+ *
175
+ * @param callback - Invoked with the new theme after each change.
176
+ * @returns An unsubscribe function.
177
+ */
178
+ subscribe(callback: (theme: Theme) => void): () => void
179
+
180
+ /**
181
+ * Returns all registered themes. Optional — not all providers
182
+ * support multiple themes.
183
+ */
184
+ getThemes?(): Theme[]
185
+
186
+ /**
187
+ * Returns the theme a render WITHOUT a browser produces — a server or
188
+ * build-time render, which has no storage and no `prefers-color-scheme`
189
+ * to read. A hydrating client renders this theme first, so its markup
190
+ * matches what the server sent, and switches to `getTheme()` right
191
+ * after. Optional — a provider whose theme cannot differ between the two
192
+ * need not implement it.
193
+ */
194
+ getServerTheme?(): Theme
195
+ }
196
+ ```
197
+
198
+ #### `ThemeShadows`
199
+
200
+ Box-shadow scale from none to xl for elevation levels.
201
+
202
+ ```typescript
203
+ interface ThemeShadows {
204
+ none: string
205
+ sm: string
206
+ md: string
207
+ lg: string
208
+ xl: string
209
+ }
210
+ ```
211
+
212
+ #### `ThemeSpacing`
213
+
214
+ Theme spacing scale mapping size tokens (xs–3xl) to CSS values (e.g. '4px', '16px').
215
+
216
+ ```typescript
217
+ interface ThemeSpacing {
218
+ xs: string // 4px
219
+ sm: string // 8px
220
+ md: string // 16px
221
+ lg: string // 24px
222
+ xl: string // 32px
223
+ xxl: string // 48px
224
+ xxxl: string // 64px
225
+ }
226
+ ```
227
+
228
+ #### `ThemeTransitions`
229
+
230
+ CSS transition duration presets (fast, normal, slow).
231
+
232
+ ```typescript
233
+ interface ThemeTransitions {
234
+ fast: string
235
+ normal: string
236
+ slow: string
237
+ }
238
+ ```
239
+
240
+ #### `ThemeTypography`
241
+
242
+ Typography scale (font families, sizes, weights, and line heights).
243
+
244
+ ```typescript
245
+ interface ThemeTypography {
246
+ fontFamily: {
247
+ sans: string
248
+ serif: string
249
+ mono: string
250
+ }
251
+ fontSize: {
252
+ xs: string // 12px
253
+ sm: string // 14px
254
+ base: string // 16px
255
+ lg: string // 18px
256
+ xl: string // 20px
257
+ '2xl': string // 24px
258
+ '3xl': string // 30px
259
+ '4xl': string // 36px
260
+ '5xl': string // 48px
261
+ }
262
+ fontWeight: {
263
+ light: number
264
+ normal: number
265
+ medium: number
266
+ semibold: number
267
+ bold: number
268
+ }
269
+ lineHeight: {
270
+ tight: number
271
+ normal: number
272
+ relaxed: number
273
+ }
274
+ }
275
+ ```
276
+
277
+ #### `ThemeZIndex`
278
+
279
+ Theme z-index scale for layering UI elements (dropdowns, modals, toasts, etc.).
280
+
281
+ ```typescript
282
+ interface ThemeZIndex {
283
+ hide: number
284
+ base: number
285
+ dropdown: number
286
+ sticky: number
287
+ fixed: number
288
+ modal: number
289
+ popover: number
290
+ tooltip: number
291
+ toast: number
292
+ }
293
+ ```
294
+
295
+ ### Functions
296
+
297
+ #### `createDarkTheme(overrides)`
298
+
299
+ Creates a dark theme by merging default dark-mode tokens with
300
+ optional overrides for colors, spacing, typography, etc.
301
+
302
+ ```typescript
303
+ function createDarkTheme(overrides?: Partial<Theme>): Theme
304
+ ```
305
+
306
+ - `overrides` — Partial theme tokens to merge over the defaults.
307
+
308
+ **Returns:** A complete `Theme` object with `mode: 'dark'`.
309
+
310
+ #### `createLightTheme(overrides)`
311
+
312
+ Creates a light theme by merging default light-mode tokens with
313
+ optional overrides for colors, spacing, typography, etc.
314
+
315
+ ```typescript
316
+ function createLightTheme(overrides?: Partial<Theme>): Theme
317
+ ```
318
+
319
+ - `overrides` — Partial theme tokens to merge over the defaults.
320
+
321
+ **Returns:** A complete `Theme` object with `mode: 'light'`.
322
+
323
+ #### `getProvider()`
324
+
325
+ Retrieves the bonded theme provider, or `null` if none is configured.
326
+
327
+ ```typescript
328
+ function getProvider(): ThemeProvider | null
329
+ ```
330
+
331
+ **Returns:** The bonded theme provider, or `null`.
332
+
333
+ #### `hasProvider()`
334
+
335
+ Checks whether a theme provider is currently bonded.
336
+
337
+ ```typescript
338
+ function hasProvider(): boolean
339
+ ```
340
+
341
+ **Returns:** `true` if a theme provider is bonded.
342
+
343
+ #### `setProvider(provider)`
344
+
345
+ Registers a theme provider as the active singleton.
346
+
347
+ ```typescript
348
+ function setProvider(provider: ThemeProvider): void
349
+ ```
350
+
351
+ - `provider` — The theme provider implementation to bond.
352
+
353
+ ### Constants
354
+
355
+ #### `darkColors`
356
+
357
+ Default dark theme colors.
358
+
359
+ ```typescript
360
+ const darkColors: ThemeColors
361
+ ```
362
+
363
+ #### `darkTheme`
364
+
365
+ Default dark theme.
366
+
367
+ ```typescript
368
+ const darkTheme: Theme
369
+ ```
370
+
371
+ #### `defaultBorderRadius`
372
+
373
+ Default border radius.
374
+
375
+ ```typescript
376
+ const defaultBorderRadius: ThemeBorderRadius
377
+ ```
378
+
379
+ #### `defaultBreakpoints`
380
+
381
+ Default responsive breakpoints (320px mobileS → 2560px desktop).
382
+
383
+ ```typescript
384
+ const defaultBreakpoints: ThemeBreakpoints
385
+ ```
386
+
387
+ #### `defaultShadows`
388
+
389
+ Default box-shadow scale (none → xl, rgba-based).
390
+
391
+ ```typescript
392
+ const defaultShadows: ThemeShadows
393
+ ```
394
+
395
+ #### `defaultSpacing`
396
+
397
+ Default spacing scale (4px xs → 64px xxxl).
398
+
399
+ ```typescript
400
+ const defaultSpacing: ThemeSpacing
401
+ ```
402
+
403
+ #### `defaultTransitions`
404
+
405
+ Default CSS transition durations (150ms fast, 250ms normal, 350ms slow).
406
+
407
+ ```typescript
408
+ const defaultTransitions: ThemeTransitions
409
+ ```
410
+
411
+ #### `defaultTypography`
412
+
413
+ Default typography scale (system font stacks, rem-based sizes, weight/line-height presets).
414
+
415
+ ```typescript
416
+ const defaultTypography: ThemeTypography
417
+ ```
418
+
419
+ #### `defaultZIndex`
420
+
421
+ Default z-index scale.
422
+
423
+ ```typescript
424
+ const defaultZIndex: ThemeZIndex
425
+ ```
426
+
427
+ #### `lightColors`
428
+
429
+ Default light theme colors.
430
+
431
+ ```typescript
432
+ const lightColors: ThemeColors
433
+ ```
434
+
435
+ #### `lightTheme`
436
+
437
+ Default light theme.
438
+
439
+ ```typescript
440
+ const lightTheme: Theme
441
+ ```
442
+
443
+ ## Available Providers
444
+
445
+ | Provider | Package |
446
+ | ------------- | ------------------------------------------------ |
447
+ | CSS Variables | `@molecule/app-theme-css-variables` |
448
+ | Liquid Glass | `@molecule/app-theme-css-variables-liquid-glass` |
449
+
450
+ ## Injection Notes
451
+
452
+ ### Requirements
453
+
454
+ Peer dependencies:
455
+
456
+ - `@molecule/app-bond` ^1.0.1
457
+
458
+ ### Runtime Dependencies
459
+
460
+ - `@molecule/app-bond`
461
+
462
+ - **Recoloring: find the REAL source of truth first.** Apps scaffolded from a
463
+ template ship a per-app stylesheet (e.g. `app/src/theme.css`) that
464
+ hardcodes the `--color-*` variables and loads AFTER the bond — its values
465
+ win, and editing this package's `Theme` objects (or the bond's palette) has
466
+ NO visible effect there. Precedence: per-app theme stylesheet > theme
467
+ bond > base defaults. Recolor by editing whichever file actually defines
468
+ the variables; the bond's `Theme` palette applies only when no per-app
469
+ stylesheet defines colors.
470
+ - Read theme values through the provider or the CSS variables it emits —
471
+ never hardcode hex values in components; surfaces and status colors come
472
+ from the theme so light AND dark both work.
473
+ - {@link getProvider} returns `null` when nothing is bonded — theme switching
474
+ is optional; guard rather than throw.
@@ -41,6 +41,15 @@ export interface ThemeProvider {
41
41
  * support multiple themes.
42
42
  */
43
43
  getThemes?(): Theme[];
44
+ /**
45
+ * Returns the theme a render WITHOUT a browser produces — a server or
46
+ * build-time render, which has no storage and no `prefers-color-scheme`
47
+ * to read. A hydrating client renders this theme first, so its markup
48
+ * matches what the server sent, and switches to `getTheme()` right
49
+ * after. Optional — a provider whose theme cannot differ between the two
50
+ * need not implement it.
51
+ */
52
+ getServerTheme?(): Theme;
44
53
  }
45
54
  /**
46
55
  * Registers a theme provider as the active singleton.
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAEvC;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,QAAQ,IAAI,KAAK,CAAA;IAEjB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAAA;IAErC;;OAEG;IACH,UAAU,IAAI,IAAI,CAAA;IAElB;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,MAAM,IAAI,CAAA;IAEvD;;;OAGG;IACH,SAAS,CAAC,IAAI,KAAK,EAAE,CAAA;CACtB;AAID;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,UAAU,aAAa,KAAG,IAErD,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,WAAW,QAAO,aAAa,GAAG,IAAiD,CAAA;AAEhG;;;;GAIG;AACH,eAAO,MAAM,WAAW,QAAO,OAA8B,CAAA"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAEvC;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,QAAQ,IAAI,KAAK,CAAA;IAEjB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAAA;IAErC;;OAEG;IACH,UAAU,IAAI,IAAI,CAAA;IAElB;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,MAAM,IAAI,CAAA;IAEvD;;;OAGG;IACH,SAAS,CAAC,IAAI,KAAK,EAAE,CAAA;IAErB;;;;;;;OAOG;IACH,cAAc,CAAC,IAAI,KAAK,CAAA;CACzB;AAID;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,UAAU,aAAa,KAAG,IAErD,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,WAAW,QAAO,aAAa,GAAG,IAAiD,CAAA;AAEhG;;;;GAIG;AACH,eAAO,MAAM,WAAW,QAAO,OAA8B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AA0CnE,MAAM,SAAS,GAAG,OAAO,CAAA;AAEzB;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAuB,EAAQ,EAAE;IAC3D,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;AAC3B,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,GAAyB,EAAE,CAAC,OAAO,CAAgB,SAAS,CAAC,IAAI,IAAI,CAAA;AAEhG;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,GAAY,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA"}
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAoDnE,MAAM,SAAS,GAAG,OAAO,CAAA;AAEzB;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAuB,EAAQ,EAAE;IAC3D,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;AAC3B,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,GAAyB,EAAE,CAAC,OAAO,CAAgB,SAAS,CAAC,IAAI,IAAI,CAAA;AAEhG;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,GAAY,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@molecule/app-theme",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Theme interface and utilities for molecule.dev",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -17,7 +17,8 @@
17
17
  }
18
18
  },
19
19
  "files": [
20
- "dist"
20
+ "dist",
21
+ "README.md"
21
22
  ],
22
23
  "keywords": [
23
24
  "molecule",
@@ -27,13 +28,13 @@
27
28
  ],
28
29
  "license": "Apache-2.0",
29
30
  "peerDependencies": {
30
- "@molecule/app-bond": "^1.0.0"
31
+ "@molecule/app-bond": "^1.0.1"
31
32
  },
32
33
  "devDependencies": {
33
- "@molecule/app-bond": "1.0.0",
34
+ "@molecule/app-bond": "1.0.1",
34
35
  "@types/node": "26.1.2",
35
36
  "typescript": "6.0.3",
36
- "vitest": "4.1.10"
37
+ "vitest": "4.1.11"
37
38
  },
38
39
  "repository": {
39
40
  "type": "git",