@atomazing-org/design-system 2.0.2 → 3.7.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 CHANGED
@@ -1,19 +1,74 @@
1
1
  # @atomazing-org/design-system
2
2
 
3
- Modern MUI v7 + Emotion design system with strongly differentiated visual presets,
4
- scheme-based light and dark tokens, SSR-safe theming, and persistence.
3
+ Modern MUI v7 + Emotion design system built around visual presets, explicit
4
+ light and dark schemes, SSR-safe theming, and persisted runtime settings.
5
+
6
+ ## Preview
7
+
8
+ ![Design system preview](./preview.gif)
9
+
10
+ ## At A Glance
11
+
12
+ - React 18 and 19 support
13
+ - MUI 7 + Emotion 11
14
+ - Preset-first theming via `ThemePreset`
15
+ - Runtime theme and dark-mode switching
16
+ - SSR-safe provider flow
17
+ - Curated root API plus `/presets` entrypoint
18
+
19
+ ## Contents
20
+
21
+ - [Why This Library](#why-this-library)
22
+ - [Installation](#installation)
23
+ - [Package Format](#package-format)
24
+ - [Quick Start](#quick-start)
25
+ - [Built-In Presets](#built-in-presets)
26
+ - [Dark Mode](#dark-mode)
27
+ - [Custom Presets](#custom-presets)
28
+ - [Persistence](#persistence)
29
+ - [SSR Notes](#ssr-notes)
30
+ - [API Reference](#api-reference)
31
+ - [Migration Docs](#migration-docs)
32
+ - [Examples](#examples)
33
+ - [Troubleshooting](#troubleshooting)
34
+ - [Contributing](#contributing)
35
+ - [Releases](#releases)
36
+ - [License](#license)
37
+
38
+ ## Why This Library
39
+
40
+ - Preset-first theming built on `ThemePreset`, not ad hoc per-app theme files
41
+ - True light and dark schemes via `colorSchemes`, not only `palette.mode`
42
+ - Strong visual differentiation between presets instead of subtle palette swaps
43
+ - Runtime theme selection and dark-mode switching with persisted settings
44
+ - SSR-safe provider flow with no browser APIs touched at module scope
45
+ - Curated public API for app integrations and consumer documentation
46
+ - Test coverage for contrast, baseline preset shape, and SSR behavior
5
47
 
6
48
  ## Installation
7
49
 
50
+ ### npm
51
+
8
52
  ```bash
9
- npm install @atomazing-org/design-system
10
- npm install react react-dom @mui/material @emotion/react @emotion/styled
53
+ npm install @atomazing-org/design-system react react-dom @mui/material @emotion/react @emotion/styled
11
54
  ```
12
55
 
13
- Optional peers:
56
+ ### pnpm
57
+
58
+ ```bash
59
+ pnpm add @atomazing-org/design-system react react-dom @mui/material @emotion/react @emotion/styled
60
+ ```
61
+
62
+ Optional peer:
14
63
 
15
64
  - `@mui/icons-material`
16
- - `@emotion/css`
65
+
66
+ Expected ecosystem:
67
+
68
+ - React `^18 || ^19`
69
+ - React DOM `^18 || ^19`
70
+ - MUI `^7`
71
+ - Emotion `^11`
17
72
 
18
73
  ## Package Format
19
74
 
@@ -22,49 +77,176 @@ Optional peers:
22
77
  - `@atomazing-org/design-system`
23
78
  - `@atomazing-org/design-system/presets`
24
79
 
80
+ The root entrypoint is intentionally curated. Preset registries and individual
81
+ presets live under the `/presets` subpath.
82
+
25
83
  ## Quick Start
26
84
 
27
85
  ```tsx
86
+ import ReactDOM from "react-dom/client";
28
87
  import { ThemeProviderWrapper } from "@atomazing-org/design-system";
29
88
  import { defaultThemes } from "@atomazing-org/design-system/presets";
30
89
 
31
- export function App() {
90
+ import App from "./App";
91
+
92
+ ReactDOM.createRoot(document.getElementById("root")!).render(
93
+ <ThemeProviderWrapper themes={defaultThemes}>
94
+ <App />
95
+ </ThemeProviderWrapper>,
96
+ );
97
+ ```
98
+
99
+ Use `useThemeSettings()` when you need runtime access to:
100
+
101
+ - the selected preset id
102
+ - the current dark-mode setting
103
+ - setters for both
104
+
105
+ Example:
106
+
107
+ ```tsx
108
+ import { useThemeSettings } from "@atomazing-org/design-system";
109
+
110
+ export function ThemeDebug() {
111
+ const { theme, darkMode, setTheme, setDarkMode } = useThemeSettings();
112
+
32
113
  return (
33
- <ThemeProviderWrapper themes={defaultThemes}>
34
- {/* your app */}
35
- </ThemeProviderWrapper>
114
+ <>
115
+ <button onClick={() => setTheme("modern-minimal")}>Modern Minimal</button>
116
+ <button onClick={() => setDarkMode("dark")}>Dark</button>
117
+ <pre>{JSON.stringify({ theme, darkMode }, null, 2)}</pre>
118
+ </>
36
119
  );
37
120
  }
38
121
  ```
39
122
 
40
- Use `useThemeSettings()` for runtime preset and dark-mode controls.
123
+ ## Built-In Presets
124
+
125
+ Ship-ready preset packs live under `@atomazing-org/design-system/presets`.
126
+
127
+ ```ts
128
+ import {
129
+ allBuiltInThemes,
130
+ defaultThemes,
131
+ landingPageThemes,
132
+ modernMinimal,
133
+ } from "@atomazing-org/design-system/presets";
134
+ ```
135
+
136
+ ### `defaultThemes`
137
+
138
+ Baseline application presets:
139
+
140
+ - `Editorial Classic`
141
+ - `Airport Ops`
142
+ - `Modern Minimal`
143
+ - `Neo Glass`
144
+ - `Retro Terminal`
145
+ - `Warm Earth`
146
+
147
+ ### `landingPageThemes`
148
+
149
+ Extended pack for landing pages, brand-heavy surfaces, and more expressive
150
+ visual directions. Representative families include:
151
+
152
+ - `Flow Editorial`
153
+ - `Acid Editorial`
154
+ - `Bauhaus Ops`
155
+ - `Neon Bauhaus Grid`
156
+ - `Neon Bauhaus Ops`
157
+ - `Brutalist Sprint`
158
+ - `Brand Neon Motion`
159
+ - `Glass Reactor`
160
+ - `Holographic Ledger`
161
+ - `Kintsugi Protocol`
162
+ - `Solarpunk Enterprise`
41
163
 
42
- ## Built-In Preset Packs
164
+ ### `allBuiltInThemes`
43
165
 
44
- - `defaultThemes`: baseline application presets
45
- - `landingPageThemes`: extended landing and marketing presets
46
- - `allBuiltInThemes`: combined pack
166
+ Combined pack of `defaultThemes` and `landingPageThemes`.
167
+
168
+ ## Dark Mode
169
+
170
+ Supported dark-mode values:
171
+
172
+ - `light`
173
+ - `dark`
174
+ - `system`
175
+
176
+ `ThemeProviderWrapper` resolves the effective scheme from the selected dark-mode
177
+ value and the current system preference. The root export `darkModeOptions` is
178
+ available for building dark-mode UI controls.
179
+
180
+ ```tsx
181
+ import { darkModeOptions, useThemeSettings } from "@atomazing-org/design-system";
182
+ import { FormControlLabel, Radio, RadioGroup } from "@mui/material";
183
+
184
+ export function DarkModeSelector() {
185
+ const { darkMode, setDarkMode } = useThemeSettings();
186
+
187
+ return (
188
+ <RadioGroup
189
+ row
190
+ value={darkMode}
191
+ onChange={(event) => setDarkMode(event.target.value as typeof darkMode)}
192
+ >
193
+ {darkModeOptions.map((option) => (
194
+ <FormControlLabel
195
+ key={option.value}
196
+ control={<Radio />}
197
+ label={option.label}
198
+ value={option.value}
199
+ />
200
+ ))}
201
+ </RadioGroup>
202
+ );
203
+ }
204
+ ```
47
205
 
48
206
  ## Custom Presets
49
207
 
50
- Custom presets must follow the `ThemePreset` contract:
208
+ Custom presets should follow the `ThemePreset` contract.
209
+
210
+ ```ts
211
+ import type { ThemePreset } from "@atomazing-org/design-system/presets";
212
+
213
+ export const myPreset: ThemePreset = {
214
+ id: "my-brand",
215
+ label: "My Brand",
216
+ colorSchemes: {
217
+ light: {
218
+ palette: {
219
+ background: { default: "#ffffff", paper: "#ffffff" },
220
+ text: { primary: "#111111", secondary: "#444444" },
221
+ divider: "rgba(0, 0, 0, 0.12)",
222
+ },
223
+ },
224
+ dark: {
225
+ palette: {
226
+ background: { default: "#0f1115", paper: "#151922" },
227
+ text: { primary: "#f1f3f5", secondary: "#c6cbd1" },
228
+ divider: "rgba(241, 243, 245, 0.16)",
229
+ },
230
+ },
231
+ },
232
+ };
233
+ ```
234
+
235
+ Merge custom presets with the built-ins:
51
236
 
52
- - stable `id`
53
- - human-readable `label`
54
- - `colorSchemes.light`
55
- - `colorSchemes.dark`
237
+ ```ts
238
+ const themes = [...defaultThemes, myPreset];
239
+ ```
56
240
 
57
- Each scheme should define:
241
+ Rules worth keeping in mind:
58
242
 
59
- - `palette.background.default`
60
- - `palette.background.paper`
61
- - `palette.text.primary`
62
- - `palette.text.secondary`
63
- - `palette.divider`
243
+ - preset ids must be unique and non-empty
244
+ - duplicate ids are deduped by id with last-wins token resolution
245
+ - first occurrence order is preserved for the visible preset list
64
246
 
65
247
  ## Persistence
66
248
 
67
- Theme settings are stored in `localStorage` under `appSettings`.
249
+ Theme settings are stored in `localStorage` under `appSettings` by default.
68
250
 
69
251
  Current JSON shape:
70
252
 
@@ -72,15 +254,81 @@ Current JSON shape:
72
254
  { "themeId": "editorial-classic", "darkMode": "system" }
73
255
  ```
74
256
 
257
+ If multiple applications share the same origin, override the storage key with
258
+ `settingsStorageKey` on `ThemeProviderWrapper`.
259
+
260
+ ```tsx
261
+ <ThemeProviderWrapper
262
+ themes={defaultThemes}
263
+ settingsStorageKey="pampaLegacyThemeSettings"
264
+ >
265
+ <App />
266
+ </ThemeProviderWrapper>
267
+ ```
268
+
75
269
  ## SSR Notes
76
270
 
77
- - Keep `ThemeProviderWrapper` inside a client boundary for Next.js and other SSR apps.
271
+ - Keep `ThemeProviderWrapper` inside a client boundary for Next.js and other SSR
272
+ apps.
78
273
  - Do not access `window`, `document`, or `localStorage` at module scope.
79
- - When dark mode uses `system`, the effective mode resolves on the client after hydration.
274
+ - When dark mode uses `system`, the effective mode resolves on the client after
275
+ hydration.
276
+
277
+ ## API Reference
278
+
279
+ ### `ThemeProviderWrapper`
280
+
281
+ | Prop | Type | Default | Description |
282
+ | --- | --- | --- | --- |
283
+ | `themes` | `ThemePreset[]` | `defaultThemes` | Preset list used by the provider. |
284
+ | `fontFamily` | `string` | `undefined` | Optional global font stack applied by `GlobalStyles`. |
285
+ | `darkMode` | `"light" \| "dark" \| "system"` | `undefined` | Optional hard override for dark mode. |
286
+ | `initialThemeId` | `string` | `undefined` | Fallback theme id when persisted settings are absent. |
287
+ | `initialDarkMode` | `"light" \| "dark" \| "system"` | `undefined` | Fallback dark mode when persisted settings are absent. |
288
+ | `settingsStorageKey` | `string` | `"appSettings"` | Optional localStorage key override. |
289
+ | `children` | `ReactNode` | required | Application content. |
290
+
291
+ If `darkMode` is passed as a prop, `setDarkMode()` becomes a no-op because the
292
+ provider is operating in controlled override mode.
293
+
294
+ ### `useThemeSettings()`
295
+
296
+ Returns:
297
+
298
+ - `theme`
299
+ - `setTheme(themeId)`
300
+ - `darkMode`
301
+ - `setDarkMode(mode)`
302
+ - `themes`
303
+ - `selectedTheme`
304
+ - `defaultThemeName`
305
+
306
+ ### Root Exports
307
+
308
+ The curated root entrypoint exports:
309
+
310
+ - `ThemeProviderWrapper`
311
+ - `useThemeSettings`
312
+ - `mergeThemes`
313
+ - `normalizeThemes`
314
+ - `resolveDefaultThemeName`
315
+ - `resolveThemeById`
316
+ - `GlobalStyles`
317
+ - `buildMuiTheme`
318
+ - `resolveEffectiveMode`
319
+ - `selectThemeOptions`
320
+ - `validateSchemeTokens`
321
+ - `darkModeOptions`
322
+ - `useSystemTheme`
323
+ - `readAppSettings`
324
+ - `writeAppSettings`
325
+
326
+ Preset registries and individual presets live under
327
+ `@atomazing-org/design-system/presets`.
80
328
 
81
329
  ## Migration Docs
82
330
 
83
- If you are migrating an app to this package, start with:
331
+ If you are migrating an existing app to this package, start with:
84
332
 
85
333
  - `migrations/README.UPDATE.md`
86
334
  - `migrations/docs/migrations/design-system/README.md`
@@ -90,8 +338,68 @@ If you are migrating an app to this package, start with:
90
338
 
91
339
  ## Examples
92
340
 
93
- - `examples/react-app`: canonical Vite smoke consumer for local package validation
94
- - `examples/next-app-router`: canonical Next.js App Router starter reference
341
+ Run examples from the repository root after `pnpm install`.
342
+
343
+ ### React App Smoke Consumer
344
+
345
+ Fastest local validation path for presets and runtime theme switching:
346
+
347
+ ```bash
348
+ pnpm --dir examples/react-app dev
349
+ ```
350
+
351
+ ### Next.js App Router Reference
352
+
353
+ Starter reference for SSR-safe integration:
354
+
355
+ ```bash
356
+ pnpm --dir examples/next-app-router dev
357
+ ```
358
+
359
+ ## Troubleshooting
360
+
361
+ - Dark mode does not visibly change the app:
362
+ Ensure both `colorSchemes.light` and `colorSchemes.dark` define
363
+ `palette.background.default`, `palette.background.paper`, and readable text
364
+ colors.
365
+ - Preset switching appears stuck:
366
+ Check for duplicate or empty preset ids and clear the relevant
367
+ `localStorage` key if invalid persisted state exists.
368
+ - One app keeps overwriting another app's theme:
369
+ Use a custom `settingsStorageKey` instead of the shared default key.
370
+ - SSR build or hydration warnings appear:
371
+ Make sure the provider is mounted in a client boundary and that no browser API
372
+ access happens at module scope.
373
+
374
+ ## Contributing
375
+
376
+ ```bash
377
+ pnpm lint
378
+ pnpm test
379
+ pnpm build
380
+ pnpm run smoke:esm
381
+ pnpm run smoke:react-app
382
+ pnpm run smoke:next
383
+ pnpm run check:migration-readiness
384
+ ```
385
+
386
+ ## Releases
387
+
388
+ This repo uses Changesets for package versioning and release automation.
389
+
390
+ Intended flow:
391
+
392
+ - run `pnpm changeset`
393
+ - merge changes into `master`
394
+ - GitHub Actions opens or updates a release PR
395
+ - merge the release PR to publish to npm
396
+
397
+ See:
398
+
399
+ - `RELEASING.md` for the release checklist and example changeset
400
+ - `RELEASE-STATUS.md` if automation is temporarily blocked by GitHub
401
+ organization permissions
402
+
403
+ ## License
95
404
 
96
- For starter-specific rules, runbooks, and customization guidance, use the local docs
97
- pack under `examples/next-app-router/`.
405
+ MIT
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { FC, PropsWithChildren } from 'react';
2
- import { T as ThemeContextProps, a as ThemePreset, N as NamedThemeOptions, D as DarkModeOptions, b as ThemeModeBackground, c as NormalizedPreset, O as OptionItem, A as AppSettings } from './typography-B-BeIk0v.js';
3
- export { C as CustomTypographyVariants, f as DarkModeSetting, d as ThemeId, e as ThemeScheme } from './typography-B-BeIk0v.js';
4
- import { Theme, Components, TypographyVariantsOptions } from '@mui/material';
2
+ import { T as ThemeContextProps, a as ThemePreset, N as NamedThemeOptions, D as DarkModeOptions, b as ThemeModeBackground, c as NormalizedPreset, O as OptionItem, A as AppSettings } from './themePresets-CwgG5XEL.js';
3
+ export { f as DarkModeSetting, d as ThemeId, e as ThemeScheme } from './themePresets-CwgG5XEL.js';
4
+ import { Theme } from '@mui/material';
5
5
  import { ThemeOptions, PaletteMode, Theme as Theme$1 } from '@mui/material/styles';
6
6
 
7
7
  /**
@@ -47,6 +47,11 @@ type ThemeProviderWrapperProps = PropsWithChildren<{
47
47
  * Initial dark mode used as fallback when persisted settings are not available.
48
48
  */
49
49
  initialDarkMode?: DarkModeOptions;
50
+ /**
51
+ * Optional localStorage key override used for persisted theme settings.
52
+ * Defaults to the shared `appSettings` key when not provided.
53
+ */
54
+ settingsStorageKey?: string;
50
55
  }>;
51
56
  declare const ThemeProviderWrapper: FC<ThemeProviderWrapperProps>;
52
57
 
@@ -89,15 +94,6 @@ interface SurfaceTokens {
89
94
  declare const getSurfaceTokens: (theme: ThemeWithPalette) => SurfaceTokens;
90
95
  declare const alphaText: (theme: ThemeWithPalette, opacity: number) => string;
91
96
 
92
- /**
93
- * Mapping of custom typography variants to corresponding HTML elements.
94
- */
95
- declare const muiTypography: Components<Theme>["MuiTypography"];
96
- /**
97
- * Custom typography variant definitions with adjusted display sizes.
98
- */
99
- declare const typographyVariants: TypographyVariantsOptions;
100
-
101
97
  declare const validateSchemeTokens: (options: ThemeOptions) => string[];
102
98
 
103
99
  /**
@@ -187,8 +183,8 @@ interface StoredAppSettings {
187
183
  themeId: string;
188
184
  darkMode: DarkModeOptions;
189
185
  }
190
- declare const readAppSettings: () => StoredAppSettings | null;
191
- declare const writeAppSettings: (settings: StoredAppSettings) => void;
186
+ declare const readAppSettings: (storageKey?: string) => StoredAppSettings | null;
187
+ declare const writeAppSettings: (settings: StoredAppSettings, storageKey?: string) => void;
192
188
 
193
189
  /**
194
190
  * Determines whether dark mode should be enabled based on user settings and system conditions.
@@ -199,4 +195,4 @@ declare const writeAppSettings: (settings: StoredAppSettings) => void;
199
195
  */
200
196
  declare const isDarkMode: (darkMode: AppSettings["darkMode"], systemTheme: SystemTheme) => boolean;
201
197
 
202
- export { AppSettings, DarkModeOptions, GlobalStyles, NamedThemeOptions, NormalizedPreset, OptionItem, type StoredAppSettings, type SurfaceTokens, type SystemTheme, ThemeContextProps, ThemeModeBackground, ThemePreset, ThemeProviderWrapper, type ThemesInput, alphaText, buildMuiTheme, canUseDom, commonComponentProps, darkModeOptions, fadeIn, fadeInLeft, getSurfaceTokens, isDarkMode, mergeThemes, muiTypography, normalizeThemes, progressPulse, pulseAnimation, readAppSettings, resolveDefaultThemeName, resolveEffectiveMode, resolveThemeById, scale, selectThemeOptions, slideIn, slideInBottom, typographyVariants, useSystemTheme, useThemeSettings, validateSchemeTokens, writeAppSettings };
198
+ export { AppSettings, DarkModeOptions, GlobalStyles, NamedThemeOptions, NormalizedPreset, OptionItem, type StoredAppSettings, type SurfaceTokens, type SystemTheme, ThemeContextProps, ThemeModeBackground, ThemePreset, ThemeProviderWrapper, type ThemesInput, alphaText, buildMuiTheme, canUseDom, commonComponentProps, darkModeOptions, fadeIn, fadeInLeft, getSurfaceTokens, isDarkMode, mergeThemes, normalizeThemes, progressPulse, pulseAnimation, readAppSettings, resolveDefaultThemeName, resolveEffectiveMode, resolveThemeById, scale, selectThemeOptions, slideIn, slideInBottom, useSystemTheme, useThemeSettings, validateSchemeTokens, writeAppSettings };