@atomazing-org/design-system 2.0.2 → 3.7.3

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,177 @@ 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
+ - `Brand Neon Admin`
144
+ - `Neo Glass`
145
+ - `Retro Terminal`
146
+ - `Warm Earth`
147
+
148
+ ### `landingPageThemes`
149
+
150
+ Extended pack for landing pages, brand-heavy surfaces, and more expressive
151
+ visual directions. Representative families include:
152
+
153
+ - `Flow Editorial`
154
+ - `Acid Editorial`
155
+ - `Bauhaus Ops`
156
+ - `Neon Bauhaus Grid`
157
+ - `Neon Bauhaus Ops`
158
+ - `Brutalist Sprint`
159
+ - `Brand Neon Motion`
160
+ - `Glass Reactor`
161
+ - `Holographic Ledger`
162
+ - `Kintsugi Protocol`
163
+ - `Solarpunk Enterprise`
41
164
 
42
- ## Built-In Preset Packs
165
+ ### `allBuiltInThemes`
43
166
 
44
- - `defaultThemes`: baseline application presets
45
- - `landingPageThemes`: extended landing and marketing presets
46
- - `allBuiltInThemes`: combined pack
167
+ Combined pack of `defaultThemes` and `landingPageThemes`.
168
+
169
+ ## Dark Mode
170
+
171
+ Supported dark-mode values:
172
+
173
+ - `light`
174
+ - `dark`
175
+ - `system`
176
+
177
+ `ThemeProviderWrapper` resolves the effective scheme from the selected dark-mode
178
+ value and the current system preference. The root export `darkModeOptions` is
179
+ available for building dark-mode UI controls.
180
+
181
+ ```tsx
182
+ import { darkModeOptions, useThemeSettings } from "@atomazing-org/design-system";
183
+ import { FormControlLabel, Radio, RadioGroup } from "@mui/material";
184
+
185
+ export function DarkModeSelector() {
186
+ const { darkMode, setDarkMode } = useThemeSettings();
187
+
188
+ return (
189
+ <RadioGroup
190
+ row
191
+ value={darkMode}
192
+ onChange={(event) => setDarkMode(event.target.value as typeof darkMode)}
193
+ >
194
+ {darkModeOptions.map((option) => (
195
+ <FormControlLabel
196
+ key={option.value}
197
+ control={<Radio />}
198
+ label={option.label}
199
+ value={option.value}
200
+ />
201
+ ))}
202
+ </RadioGroup>
203
+ );
204
+ }
205
+ ```
47
206
 
48
207
  ## Custom Presets
49
208
 
50
- Custom presets must follow the `ThemePreset` contract:
209
+ Custom presets should follow the `ThemePreset` contract.
210
+
211
+ ```ts
212
+ import type { ThemePreset } from "@atomazing-org/design-system/presets";
213
+
214
+ export const myPreset: ThemePreset = {
215
+ id: "my-brand",
216
+ label: "My Brand",
217
+ colorSchemes: {
218
+ light: {
219
+ palette: {
220
+ background: { default: "#ffffff", paper: "#ffffff" },
221
+ text: { primary: "#111111", secondary: "#444444" },
222
+ divider: "rgba(0, 0, 0, 0.12)",
223
+ },
224
+ },
225
+ dark: {
226
+ palette: {
227
+ background: { default: "#0f1115", paper: "#151922" },
228
+ text: { primary: "#f1f3f5", secondary: "#c6cbd1" },
229
+ divider: "rgba(241, 243, 245, 0.16)",
230
+ },
231
+ },
232
+ },
233
+ };
234
+ ```
235
+
236
+ Merge custom presets with the built-ins:
51
237
 
52
- - stable `id`
53
- - human-readable `label`
54
- - `colorSchemes.light`
55
- - `colorSchemes.dark`
238
+ ```ts
239
+ const themes = [...defaultThemes, myPreset];
240
+ ```
56
241
 
57
- Each scheme should define:
242
+ Rules worth keeping in mind:
58
243
 
59
- - `palette.background.default`
60
- - `palette.background.paper`
61
- - `palette.text.primary`
62
- - `palette.text.secondary`
63
- - `palette.divider`
244
+ - preset ids must be unique and non-empty
245
+ - duplicate ids are deduped by id with last-wins token resolution
246
+ - first occurrence order is preserved for the visible preset list
64
247
 
65
248
  ## Persistence
66
249
 
67
- Theme settings are stored in `localStorage` under `appSettings`.
250
+ Theme settings are stored in `localStorage` under `appSettings` by default.
68
251
 
69
252
  Current JSON shape:
70
253
 
@@ -72,15 +255,81 @@ Current JSON shape:
72
255
  { "themeId": "editorial-classic", "darkMode": "system" }
73
256
  ```
74
257
 
258
+ If multiple applications share the same origin, override the storage key with
259
+ `settingsStorageKey` on `ThemeProviderWrapper`.
260
+
261
+ ```tsx
262
+ <ThemeProviderWrapper
263
+ themes={defaultThemes}
264
+ settingsStorageKey="pampaLegacyThemeSettings"
265
+ >
266
+ <App />
267
+ </ThemeProviderWrapper>
268
+ ```
269
+
75
270
  ## SSR Notes
76
271
 
77
- - Keep `ThemeProviderWrapper` inside a client boundary for Next.js and other SSR apps.
272
+ - Keep `ThemeProviderWrapper` inside a client boundary for Next.js and other SSR
273
+ apps.
78
274
  - 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.
275
+ - When dark mode uses `system`, the effective mode resolves on the client after
276
+ hydration.
277
+
278
+ ## API Reference
279
+
280
+ ### `ThemeProviderWrapper`
281
+
282
+ | Prop | Type | Default | Description |
283
+ | --- | --- | --- | --- |
284
+ | `themes` | `ThemePreset[]` | `defaultThemes` | Preset list used by the provider. |
285
+ | `fontFamily` | `string` | `undefined` | Optional global font stack applied by `GlobalStyles`. |
286
+ | `darkMode` | `"light" \| "dark" \| "system"` | `undefined` | Optional hard override for dark mode. |
287
+ | `initialThemeId` | `string` | `undefined` | Fallback theme id when persisted settings are absent. |
288
+ | `initialDarkMode` | `"light" \| "dark" \| "system"` | `undefined` | Fallback dark mode when persisted settings are absent. |
289
+ | `settingsStorageKey` | `string` | `"appSettings"` | Optional localStorage key override. |
290
+ | `children` | `ReactNode` | required | Application content. |
291
+
292
+ If `darkMode` is passed as a prop, `setDarkMode()` becomes a no-op because the
293
+ provider is operating in controlled override mode.
294
+
295
+ ### `useThemeSettings()`
296
+
297
+ Returns:
298
+
299
+ - `theme`
300
+ - `setTheme(themeId)`
301
+ - `darkMode`
302
+ - `setDarkMode(mode)`
303
+ - `themes`
304
+ - `selectedTheme`
305
+ - `defaultThemeName`
306
+
307
+ ### Root Exports
308
+
309
+ The curated root entrypoint exports:
310
+
311
+ - `ThemeProviderWrapper`
312
+ - `useThemeSettings`
313
+ - `mergeThemes`
314
+ - `normalizeThemes`
315
+ - `resolveDefaultThemeName`
316
+ - `resolveThemeById`
317
+ - `GlobalStyles`
318
+ - `buildMuiTheme`
319
+ - `resolveEffectiveMode`
320
+ - `selectThemeOptions`
321
+ - `validateSchemeTokens`
322
+ - `darkModeOptions`
323
+ - `useSystemTheme`
324
+ - `readAppSettings`
325
+ - `writeAppSettings`
326
+
327
+ Preset registries and individual presets live under
328
+ `@atomazing-org/design-system/presets`.
80
329
 
81
330
  ## Migration Docs
82
331
 
83
- If you are migrating an app to this package, start with:
332
+ If you are migrating an existing app to this package, start with:
84
333
 
85
334
  - `migrations/README.UPDATE.md`
86
335
  - `migrations/docs/migrations/design-system/README.md`
@@ -90,8 +339,68 @@ If you are migrating an app to this package, start with:
90
339
 
91
340
  ## Examples
92
341
 
93
- - `examples/react-app`: canonical Vite smoke consumer for local package validation
94
- - `examples/next-app-router`: canonical Next.js App Router starter reference
342
+ Run examples from the repository root after `pnpm install`.
343
+
344
+ ### React App Smoke Consumer
345
+
346
+ Fastest local validation path for presets and runtime theme switching:
347
+
348
+ ```bash
349
+ pnpm --dir examples/react-app dev
350
+ ```
351
+
352
+ ### Next.js App Router Reference
353
+
354
+ Starter reference for SSR-safe integration:
355
+
356
+ ```bash
357
+ pnpm --dir examples/next-app-router dev
358
+ ```
359
+
360
+ ## Troubleshooting
361
+
362
+ - Dark mode does not visibly change the app:
363
+ Ensure both `colorSchemes.light` and `colorSchemes.dark` define
364
+ `palette.background.default`, `palette.background.paper`, and readable text
365
+ colors.
366
+ - Preset switching appears stuck:
367
+ Check for duplicate or empty preset ids and clear the relevant
368
+ `localStorage` key if invalid persisted state exists.
369
+ - One app keeps overwriting another app's theme:
370
+ Use a custom `settingsStorageKey` instead of the shared default key.
371
+ - SSR build or hydration warnings appear:
372
+ Make sure the provider is mounted in a client boundary and that no browser API
373
+ access happens at module scope.
374
+
375
+ ## Contributing
376
+
377
+ ```bash
378
+ pnpm lint
379
+ pnpm test
380
+ pnpm build
381
+ pnpm run smoke:esm
382
+ pnpm run smoke:react-app
383
+ pnpm run smoke:next
384
+ pnpm run check:migration-readiness
385
+ ```
386
+
387
+ ## Releases
388
+
389
+ This repo uses Changesets for package versioning and release automation.
390
+
391
+ Intended flow:
392
+
393
+ - run `pnpm changeset`
394
+ - merge changes into `master`
395
+ - GitHub Actions opens or updates a release PR
396
+ - merge the release PR to publish to npm
397
+
398
+ See:
399
+
400
+ - `RELEASING.md` for the release checklist and example changeset
401
+ - `RELEASE-STATUS.md` if automation is temporarily blocked by GitHub
402
+ organization permissions
403
+
404
+ ## License
95
405
 
96
- For starter-specific rules, runbooks, and customization guidance, use the local docs
97
- pack under `examples/next-app-router/`.
406
+ 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 };