@ttoss/fsl-theme 1.1.11
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/LICENSE +21 -0
- package/README.md +390 -0
- package/dist/Types-6tR0_2Ss.d.ts +1452 -0
- package/dist/css.d.ts +164 -0
- package/dist/dataviz/index.d.ts +62 -0
- package/dist/dtcg.d.ts +49 -0
- package/dist/esm/chunk-4Q4P3JBB.js +185 -0
- package/dist/esm/chunk-5PWPAQMC.js +9 -0
- package/dist/esm/chunk-BXKVVQEP.js +29 -0
- package/dist/esm/chunk-DU4QDQUC.js +29 -0
- package/dist/esm/chunk-FBVUI2PK.js +147 -0
- package/dist/esm/chunk-HRNXVRS3.js +54 -0
- package/dist/esm/chunk-IJGA42O6.js +141 -0
- package/dist/esm/chunk-PQPQNZ73.js +262 -0
- package/dist/esm/chunk-SE5Z52RE.js +1898 -0
- package/dist/esm/chunk-TPMN75JM.js +29 -0
- package/dist/esm/chunk-UMRQ4OTX.js +11 -0
- package/dist/esm/chunk-VL6EGE6Z.js +222 -0
- package/dist/esm/chunk-WVQSTQD5.js +192 -0
- package/dist/esm/css.js +6 -0
- package/dist/esm/dataviz/index.js +19 -0
- package/dist/esm/dtcg.js +65 -0
- package/dist/esm/index.js +10 -0
- package/dist/esm/react.js +8 -0
- package/dist/esm/runtime-entry.js +4 -0
- package/dist/esm/themes/bruttal.js +6 -0
- package/dist/esm/themes/corporate.js +6 -0
- package/dist/esm/themes/oca.js +6 -0
- package/dist/esm/themes/ventures.js +6 -0
- package/dist/esm/vars.js +28 -0
- package/dist/index.d.ts +86 -0
- package/dist/react.d.ts +346 -0
- package/dist/runtime-entry.d.ts +95 -0
- package/dist/themes/bruttal.d.ts +5 -0
- package/dist/themes/corporate.d.ts +5 -0
- package/dist/themes/oca.d.ts +5 -0
- package/dist/themes/ventures.d.ts +5 -0
- package/dist/vars.d.ts +127 -0
- package/llms.txt +731 -0
- package/package.json +88 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { T as ThemeTokens, M as ModeOverride, a as ThemeBundle, D as DeepPartial } from './Types-6tR0_2Ss.js';
|
|
2
|
+
export { S as SemanticTokens } from './Types-6tR0_2Ss.js';
|
|
3
|
+
export { ThemeHeadProps, ThemeStylesProps } from './react.js';
|
|
4
|
+
export { ThemeMode } from './runtime-entry.js';
|
|
5
|
+
export { bruttal } from './themes/bruttal.js';
|
|
6
|
+
export { corporate } from './themes/corporate.js';
|
|
7
|
+
export { oca } from './themes/oca.js';
|
|
8
|
+
export { ventures } from './themes/ventures.js';
|
|
9
|
+
import 'react/jsx-runtime';
|
|
10
|
+
import 'react';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* **Foundation** — Neutral baseline theme.
|
|
14
|
+
*
|
|
15
|
+
* System fonts, gray palette, and balanced proportions. Serves as the
|
|
16
|
+
* canonical base that all other themes extend via `createTheme`.
|
|
17
|
+
*/
|
|
18
|
+
declare const baseTheme: ThemeTokens;
|
|
19
|
+
declare const darkAlternate: ModeOverride;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Creates a theme bundle with an optional alternate color mode.
|
|
23
|
+
*
|
|
24
|
+
* The `extends` param is the idiomatic way to build on a built-in theme:
|
|
25
|
+
* it inherits the base tokens **and** the dark-mode alternate automatically.
|
|
26
|
+
*
|
|
27
|
+
* @param params.extends - Parent bundle to inherit from. `base`, `baseMode`, and
|
|
28
|
+
* `alternate` default to the parent's values when this is provided.
|
|
29
|
+
* @param params.baseMode - Which mode the base represents. Defaults to `'light'`.
|
|
30
|
+
* @param params.base - Base theme to extend. Defaults to `extends.base` or `baseTheme`.
|
|
31
|
+
* @param params.overrides - Brand overrides applied to the base theme.
|
|
32
|
+
* @param params.alternate - Semantic remapping overrides for the opposite color mode.
|
|
33
|
+
* Defaults to `darkAlternate` (built-in dark mode) when neither `alternate` nor
|
|
34
|
+
* `extends` is provided. Inherits from `extends.alternate` when `extends` is given.
|
|
35
|
+
* Pass `null` to explicitly opt out of any alternate (single-mode theme).
|
|
36
|
+
* Core tokens are immutable — only semantic references change between modes.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* // Path A — default foundation (light base + dark alternate included)
|
|
41
|
+
* const myTheme = createTheme();
|
|
42
|
+
* <ThemeProvider theme={myTheme} />
|
|
43
|
+
*
|
|
44
|
+
* // Path B — custom brand overrides (dark mode still included)
|
|
45
|
+
* const myTheme = createTheme({
|
|
46
|
+
* overrides: { core: { colors: { brand: { 500: '#FF0000' } } } },
|
|
47
|
+
* });
|
|
48
|
+
*
|
|
49
|
+
* // Path C — custom semantic dark alternate
|
|
50
|
+
* const myTheme = createTheme({
|
|
51
|
+
* overrides: { core: { colors: { brand: { 500: '#FF0000' } } } },
|
|
52
|
+
* alternate: {
|
|
53
|
+
* semantic: {
|
|
54
|
+
* colors: { informational: { primary: { background: { default: '{core.colors.neutral.900}' } } } },
|
|
55
|
+
* },
|
|
56
|
+
* },
|
|
57
|
+
* });
|
|
58
|
+
*
|
|
59
|
+
* // Path D — single-mode theme (no dark alternate)
|
|
60
|
+
* const myTheme = createTheme({ alternate: null });
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
declare const createTheme: ({ extends: parentBundle, baseMode, base, overrides, alternate, }?: {
|
|
64
|
+
/**
|
|
65
|
+
* Parent bundle to inherit from. `base`, `baseMode`, and `alternate` all
|
|
66
|
+
* default to the parent's values — including dark-mode inheritance.
|
|
67
|
+
*
|
|
68
|
+
* `extends` is a reserved word in JS — destructured as `parentBundle`
|
|
69
|
+
* in the implementation.
|
|
70
|
+
*/
|
|
71
|
+
extends?: ThemeBundle;
|
|
72
|
+
/** Which mode the base represents. Defaults to `extends.baseMode` or `'light'`. */
|
|
73
|
+
baseMode?: "light" | "dark";
|
|
74
|
+
/** Base theme to extend. Defaults to `extends.base` or `baseTheme`. */
|
|
75
|
+
base?: ThemeTokens;
|
|
76
|
+
/** Brand overrides applied to the base theme. */
|
|
77
|
+
overrides?: DeepPartial<ThemeTokens>;
|
|
78
|
+
/**
|
|
79
|
+
* Semantic remapping overrides for the opposite mode.
|
|
80
|
+
* Defaults to `darkAlternate` when not provided (and no `extends`).
|
|
81
|
+
* Pass `null` to opt out of any alternate (single-mode theme).
|
|
82
|
+
*/
|
|
83
|
+
alternate?: ModeOverride | null;
|
|
84
|
+
}) => ThemeBundle;
|
|
85
|
+
|
|
86
|
+
export { DeepPartial, ModeOverride, ThemeBundle, ThemeTokens, baseTheme, createTheme, darkAlternate };
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { ThemeMode, ResolvedMode, ThemeScriptConfig } from './runtime-entry.js';
|
|
4
|
+
import { a as ThemeBundle, S as SemanticTokens } from './Types-6tR0_2Ss.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Props for the `ThemeProvider` component.
|
|
8
|
+
*/
|
|
9
|
+
interface ThemeProviderProps {
|
|
10
|
+
/** Mode to use when no persisted value is found. Only read on initial mount. @default 'system' */
|
|
11
|
+
defaultMode?: ThemeMode;
|
|
12
|
+
/** localStorage key for persistence. Only read on initial mount. @default 'tt-theme' */
|
|
13
|
+
storageKey?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Theme identifier written to `data-tt-theme`. Reactive — changing this
|
|
16
|
+
* prop recreates the runtime and rewrites the attribute so the browser
|
|
17
|
+
* matches the scoped CSS (e.g. `[data-tt-theme="<id>"]`). Provide only
|
|
18
|
+
* for MFE / multi-theme CSS scoping (Storybook toolbar, runtime theme swap).
|
|
19
|
+
*/
|
|
20
|
+
themeId?: string;
|
|
21
|
+
/**
|
|
22
|
+
* The theme bundle for the app — the canonical 1-theme / 2-mode model.
|
|
23
|
+
*
|
|
24
|
+
* Passing `theme` enables `useTokens()` and `useResolvedTokens()` for all
|
|
25
|
+
* descendants, and automatically injects the CSS Custom Properties `<style>`
|
|
26
|
+
* tag into the document head (React 19 hoisting).
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```tsx
|
|
30
|
+
* import { createTheme } from '@ttoss/fsl-theme';
|
|
31
|
+
* import { ThemeProvider } from '@ttoss/fsl-theme/react';
|
|
32
|
+
*
|
|
33
|
+
* const myTheme = createTheme();
|
|
34
|
+
*
|
|
35
|
+
* <ThemeProvider theme={myTheme}>
|
|
36
|
+
* <App />
|
|
37
|
+
* </ThemeProvider>
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
theme?: ThemeBundle;
|
|
41
|
+
/**
|
|
42
|
+
* Called after each mode transition. Does **not** fire on initial mount —
|
|
43
|
+
* only on subsequent user-triggered or system-triggered mode changes.
|
|
44
|
+
*
|
|
45
|
+
* Receives both `mode` (user intent: `'light' | 'dark' | 'system'`) and
|
|
46
|
+
* `resolvedMode` (actual: `'light' | 'dark'`), covering all integration
|
|
47
|
+
* needs in one callback.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```tsx
|
|
51
|
+
* <ThemeProvider
|
|
52
|
+
* theme={myTheme}
|
|
53
|
+
* onModeChange={(mode, resolvedMode) => {
|
|
54
|
+
* analytics.track('modeChanged', { mode, resolvedMode });
|
|
55
|
+
* }}
|
|
56
|
+
* >
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
onModeChange?: (mode: ThemeMode, resolvedMode: ResolvedMode) => void;
|
|
60
|
+
/**
|
|
61
|
+
* Root element to anchor `data-tt-theme` / `data-tt-mode` attributes.
|
|
62
|
+
* Defaults to `document.documentElement`. Pass a container element for
|
|
63
|
+
* Storybook isolation or micro-frontend use cases.
|
|
64
|
+
*
|
|
65
|
+
* Because the element is often `null` on the first render when passed via
|
|
66
|
+
* `ref.current`, `root` is reactive: the runtime is recreated once when
|
|
67
|
+
* it transitions from `undefined` to the actual element.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```tsx
|
|
71
|
+
* // Storybook decorator — isolates each story from <html>
|
|
72
|
+
* const rootRef = React.useRef<HTMLDivElement>(null);
|
|
73
|
+
* <div ref={rootRef}>
|
|
74
|
+
* <ThemeProvider theme={myTheme} root={rootRef.current ?? undefined}>
|
|
75
|
+
* <Story />
|
|
76
|
+
* </ThemeProvider>
|
|
77
|
+
* </div>
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
root?: HTMLElement;
|
|
81
|
+
children: React.ReactNode;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* React provider that manages theme switching via `createThemeRuntime`.
|
|
85
|
+
*
|
|
86
|
+
* Applies `data-tt-theme` and `data-tt-mode` on `<html>` (or `root`),
|
|
87
|
+
* persists to localStorage, and listens to system color scheme changes.
|
|
88
|
+
* When `theme` is provided, automatically injects CSS Custom Properties into
|
|
89
|
+
* the document `<head>` via React 19 style hoisting.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```tsx
|
|
93
|
+
* import { ThemeProvider } from '@ttoss/fsl-theme/react';
|
|
94
|
+
* import { createTheme } from '@ttoss/fsl-theme';
|
|
95
|
+
*
|
|
96
|
+
* const myTheme = createTheme();
|
|
97
|
+
*
|
|
98
|
+
* export const App = () => (
|
|
99
|
+
* <ThemeProvider theme={myTheme}>
|
|
100
|
+
* <YourApp />
|
|
101
|
+
* </ThemeProvider>
|
|
102
|
+
* );
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
declare const ThemeProvider: ({ defaultMode, storageKey, theme, themeId, onModeChange, root, children, }: ThemeProviderProps) => react_jsx_runtime.JSX.Element;
|
|
106
|
+
/**
|
|
107
|
+
* Access mode state and the mode setter — without subscribing to theme changes.
|
|
108
|
+
*
|
|
109
|
+
* Consumers of `useColorMode()` only re-render on mode transitions, never on
|
|
110
|
+
* `themeId` changes. Use this for components that only need dark/light toggling
|
|
111
|
+
* (e.g. a sun/moon icon button) to avoid unnecessary re-renders.
|
|
112
|
+
*
|
|
113
|
+
* Must be used within a `<ThemeProvider>`.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```tsx
|
|
117
|
+
* import { useColorMode } from '@ttoss/fsl-theme/react';
|
|
118
|
+
*
|
|
119
|
+
* const DarkModeToggle = () => {
|
|
120
|
+
* const { resolvedMode, setMode } = useColorMode();
|
|
121
|
+
* return (
|
|
122
|
+
* <button onClick={() => setMode(resolvedMode === 'dark' ? 'light' : 'dark')}>
|
|
123
|
+
* {resolvedMode === 'dark' ? '☀️' : '🌙'}
|
|
124
|
+
* </button>
|
|
125
|
+
* );
|
|
126
|
+
* };
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
interface UseColorModeResult {
|
|
130
|
+
mode: ThemeMode;
|
|
131
|
+
resolvedMode: ResolvedMode;
|
|
132
|
+
setMode: (mode: ThemeMode) => void;
|
|
133
|
+
}
|
|
134
|
+
declare const useColorMode: () => UseColorModeResult;
|
|
135
|
+
/**
|
|
136
|
+
* Access the current theme's **semantic tokens only** — the structural tree
|
|
137
|
+
* with **unresolved** `TokenRef` values (e.g. `'{core.colors.brand.500}'`).
|
|
138
|
+
*
|
|
139
|
+
* ### Primary use cases
|
|
140
|
+
* - Introspection and devtools
|
|
141
|
+
* - Token path comparison (e.g. checking which tokens differ between themes)
|
|
142
|
+
* - Passing to `createTheme` calls
|
|
143
|
+
*
|
|
144
|
+
* ### ✗ Do not use for styling
|
|
145
|
+
* `TokenRef` values are reference strings, not CSS values. Using them in
|
|
146
|
+
* inline styles produces silently broken rendering:
|
|
147
|
+
*
|
|
148
|
+
* ```tsx
|
|
149
|
+
* // ✗ WRONG — tokens.colors.brand.main is '{core.colors.brand.main}', not '#FF0000'
|
|
150
|
+
* <div style={{ color: tokens.colors.brand.main }} />
|
|
151
|
+
*
|
|
152
|
+
* // ✓ CSS consumers — use vars:
|
|
153
|
+
* <div style={{ color: 'var(--tt-color-brand-main)' }} />
|
|
154
|
+
*
|
|
155
|
+
* // ✓ Non-CSS consumers (React Native, canvas) — use useResolvedTokens():
|
|
156
|
+
* const resolved = useResolvedTokens();
|
|
157
|
+
* <View style={{ backgroundColor: resolved['semantic.colors.action.primary.background.default'] }} />
|
|
158
|
+
* ```
|
|
159
|
+
*
|
|
160
|
+
* Requires `<ThemeProvider theme={...}>`.
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```tsx
|
|
164
|
+
* import { useTokens } from '@ttoss/fsl-theme/react';
|
|
165
|
+
*
|
|
166
|
+
* const Button = () => {
|
|
167
|
+
* const tokens = useTokens(); // introspection only
|
|
168
|
+
* // tokens.colors.action.primary.background.default → '{core.colors.brand.500}'
|
|
169
|
+
* return <button style={{ background: 'var(--tt-action-primary-background-default)' }} />;
|
|
170
|
+
* };
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
declare const useTokens: () => SemanticTokens;
|
|
174
|
+
/**
|
|
175
|
+
* Access fully resolved token values as a flat `Record<string, string | number>`.
|
|
176
|
+
*
|
|
177
|
+
* All `{ref}` indirections are resolved to their final raw values — hex colors,
|
|
178
|
+
* px sizes, unitless numbers, etc. Keys use `semantic.*` dot-path notation.
|
|
179
|
+
*
|
|
180
|
+
* ### When to use
|
|
181
|
+
* Use in non-CSS environments where CSS custom properties (`var()`) are not
|
|
182
|
+
* available: React Native, canvas renderers, PDF generation, test assertions.
|
|
183
|
+
*
|
|
184
|
+
* ### ✗ Do not use for CSS rendering
|
|
185
|
+
* CSS consumers should use `vars.*` instead for zero-JS rendering:
|
|
186
|
+
*
|
|
187
|
+
* ```tsx
|
|
188
|
+
* // ✓ CSS (browser)
|
|
189
|
+
* <div style={{ color: 'var(--tt-color-informational-primary-default)' }} />
|
|
190
|
+
*
|
|
191
|
+
* // ✓ Non-CSS (React Native, canvas)
|
|
192
|
+
* const resolved = useResolvedTokens();
|
|
193
|
+
* <View style={{ backgroundColor: resolved['semantic.colors.action.primary.background.default'] }} />
|
|
194
|
+
* ```
|
|
195
|
+
*
|
|
196
|
+
* Requires `<ThemeProvider theme={...}>`.
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* ```tsx
|
|
200
|
+
* import { useResolvedTokens } from '@ttoss/fsl-theme/react';
|
|
201
|
+
*
|
|
202
|
+
* const ReactNativeButton = () => {
|
|
203
|
+
* const resolved = useResolvedTokens();
|
|
204
|
+
* return (
|
|
205
|
+
* <View style={{ backgroundColor: resolved['semantic.colors.action.primary.background.default'] }}>
|
|
206
|
+
* <Text>Click</Text>
|
|
207
|
+
* </View>
|
|
208
|
+
* );
|
|
209
|
+
* };
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
declare const useResolvedTokens: () => Record<string, string | number>;
|
|
213
|
+
/**
|
|
214
|
+
* Props for the `ThemeScript` component.
|
|
215
|
+
*/
|
|
216
|
+
interface ThemeScriptProps extends ThemeScriptConfig {
|
|
217
|
+
/** CSP nonce for the inline script. */
|
|
218
|
+
nonce?: string;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Renders an inline `<script>` that prevents theme flash on SSR/SSG.
|
|
222
|
+
*
|
|
223
|
+
* Place in the `<head>` before stylesheets.
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* ```tsx
|
|
227
|
+
* // Next.js app/layout.tsx
|
|
228
|
+
* import { ThemeScript } from '@ttoss/fsl-theme/react';
|
|
229
|
+
*
|
|
230
|
+
* export default function RootLayout({ children }) {
|
|
231
|
+
* return (
|
|
232
|
+
* <html lang="en">
|
|
233
|
+
* <head>
|
|
234
|
+
* <ThemeScript defaultTheme="bruttal" />
|
|
235
|
+
* </head>
|
|
236
|
+
* <body>{children}</body>
|
|
237
|
+
* </html>
|
|
238
|
+
* );
|
|
239
|
+
* }
|
|
240
|
+
* ```
|
|
241
|
+
*/
|
|
242
|
+
declare const ThemeScript: ({ defaultTheme, defaultMode, storageKey, nonce, }?: ThemeScriptProps) => react_jsx_runtime.JSX.Element;
|
|
243
|
+
/**
|
|
244
|
+
* Props for the `ThemeStyles` component.
|
|
245
|
+
*/
|
|
246
|
+
interface ThemeStylesProps {
|
|
247
|
+
/** The theme bundle to generate CSS for. */
|
|
248
|
+
theme: ThemeBundle;
|
|
249
|
+
/**
|
|
250
|
+
* Theme identifier for CSS scoping (`[data-tt-theme="<themeId>"]`).
|
|
251
|
+
*
|
|
252
|
+
* **Omit in the canonical 1-theme model** — CSS targets `:root` and the
|
|
253
|
+
* alternate mode selector becomes `:root[data-tt-mode="dark"]`. No theme
|
|
254
|
+
* name repetition required.
|
|
255
|
+
*
|
|
256
|
+
* Pass `themeId` only for multi-theme scenarios (Storybook, micro-frontends,
|
|
257
|
+
* apps with visual theme switching).
|
|
258
|
+
*/
|
|
259
|
+
themeId?: string;
|
|
260
|
+
/** CSP nonce for the inline style tag. */
|
|
261
|
+
nonce?: string;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Renders an inline `<style>` tag with all CSS Custom Properties for a theme
|
|
265
|
+
* bundle — including coarse-pointer, reduced-motion, and container query
|
|
266
|
+
* progressive enhancement blocks.
|
|
267
|
+
*
|
|
268
|
+
* Use as an escape hatch for SSR frameworks that need explicit `<head>` style
|
|
269
|
+
* injection. In most React apps, `<ThemeProvider theme={...}>` already injects
|
|
270
|
+
* styles automatically via React 19 style hoisting — no `<ThemeStyles>` needed.
|
|
271
|
+
*
|
|
272
|
+
* `dangerouslySetInnerHTML` is safe: content comes exclusively from
|
|
273
|
+
* `toCssVars()` (a pure internal function) — no user input is interpolated.
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* ```tsx
|
|
277
|
+
* // SSR escape hatch — no themeId needed for canonical 1-theme model
|
|
278
|
+
* import { ThemeScript, ThemeStyles } from '@ttoss/fsl-theme/react';
|
|
279
|
+
* import { createTheme } from '@ttoss/fsl-theme';
|
|
280
|
+
*
|
|
281
|
+
* const myTheme = createTheme();
|
|
282
|
+
*
|
|
283
|
+
* export default function RootLayout({ children }) {
|
|
284
|
+
* return (
|
|
285
|
+
* <html lang="en">
|
|
286
|
+
* <head>
|
|
287
|
+
* <ThemeScript />
|
|
288
|
+
* <ThemeStyles theme={myTheme} />
|
|
289
|
+
* </head>
|
|
290
|
+
* <body>
|
|
291
|
+
* <ThemeProvider theme={myTheme}>{children}</ThemeProvider>
|
|
292
|
+
* </body>
|
|
293
|
+
* </html>
|
|
294
|
+
* );
|
|
295
|
+
* }
|
|
296
|
+
* ```
|
|
297
|
+
*
|
|
298
|
+
* @example
|
|
299
|
+
* ```tsx
|
|
300
|
+
* // Multi-theme: explicit themeId for CSS scoping
|
|
301
|
+
* <ThemeStyles theme={brandA} themeId="brand-a" />
|
|
302
|
+
* <ThemeStyles theme={brandB} themeId="brand-b" />
|
|
303
|
+
* ```
|
|
304
|
+
*/
|
|
305
|
+
declare const ThemeStyles: ({ theme, themeId, nonce }: ThemeStylesProps) => react_jsx_runtime.JSX.Element;
|
|
306
|
+
/**
|
|
307
|
+
* Props for the `ThemeHead` component.
|
|
308
|
+
*/
|
|
309
|
+
interface ThemeHeadProps extends ThemeStylesProps {
|
|
310
|
+
/** Mode to use when no persisted value is found. @default 'system' */
|
|
311
|
+
defaultMode?: ThemeMode;
|
|
312
|
+
/** localStorage key for persistence. Must match `ThemeProvider`'s `storageKey`. @default 'tt-theme' */
|
|
313
|
+
storageKey?: string;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Convenience component that renders both `<ThemeScript>` and `<ThemeStyles>`
|
|
317
|
+
* in a single line — the complete SSR `<head>` setup for flash-free theming.
|
|
318
|
+
*
|
|
319
|
+
* Use in SSR frameworks (Next.js, Remix) where you need explicit `<head>`
|
|
320
|
+
* injection. In CSR apps, `<ThemeProvider theme={...}>` handles everything.
|
|
321
|
+
*
|
|
322
|
+
* @example
|
|
323
|
+
* ```tsx
|
|
324
|
+
* // Next.js app/layout.tsx
|
|
325
|
+
* import { ThemeHead, ThemeProvider } from '@ttoss/fsl-theme/react';
|
|
326
|
+
* import { createTheme } from '@ttoss/fsl-theme';
|
|
327
|
+
*
|
|
328
|
+
* const myTheme = createTheme();
|
|
329
|
+
*
|
|
330
|
+
* export default function RootLayout({ children }) {
|
|
331
|
+
* return (
|
|
332
|
+
* <html lang="en">
|
|
333
|
+
* <head>
|
|
334
|
+
* <ThemeHead theme={myTheme} />
|
|
335
|
+
* </head>
|
|
336
|
+
* <body>
|
|
337
|
+
* <ThemeProvider theme={myTheme}>{children}</ThemeProvider>
|
|
338
|
+
* </body>
|
|
339
|
+
* </html>
|
|
340
|
+
* );
|
|
341
|
+
* }
|
|
342
|
+
* ```
|
|
343
|
+
*/
|
|
344
|
+
declare const ThemeHead: ({ theme, themeId, nonce, defaultMode, storageKey, }: ThemeHeadProps) => react_jsx_runtime.JSX.Element;
|
|
345
|
+
|
|
346
|
+
export { ResolvedMode, ThemeHead, type ThemeHeadProps, ThemeMode, ThemeProvider, type ThemeProviderProps, ThemeScript, type ThemeScriptProps, ThemeStyles, type ThemeStylesProps, type UseColorModeResult, useColorMode, useResolvedTokens, useTokens };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
declare const DATA_THEME_ATTR = "data-tt-theme";
|
|
2
|
+
declare const DATA_MODE_ATTR = "data-tt-mode";
|
|
3
|
+
/**
|
|
4
|
+
* Theme mode. `'system'` delegates to the OS `prefers-color-scheme` preference.
|
|
5
|
+
*/
|
|
6
|
+
type ThemeMode = 'light' | 'dark' | 'system';
|
|
7
|
+
/**
|
|
8
|
+
* Resolved mode — always `'light'` or `'dark'` (never `'system'`).
|
|
9
|
+
*/
|
|
10
|
+
type ResolvedMode = 'light' | 'dark';
|
|
11
|
+
/**
|
|
12
|
+
* Snapshot of the current theme state.
|
|
13
|
+
*/
|
|
14
|
+
interface ThemeState {
|
|
15
|
+
mode: ThemeMode;
|
|
16
|
+
resolvedMode: ResolvedMode;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Configuration for `createThemeRuntime()`.
|
|
20
|
+
*/
|
|
21
|
+
interface ThemeRuntimeConfig {
|
|
22
|
+
/** Theme identifier written to `data-tt-theme`. Provide only for MFE / multi-theme CSS scoping. When omitted, `data-tt-theme` is not written to the DOM. */
|
|
23
|
+
defaultTheme?: string;
|
|
24
|
+
/** Mode to use when no persisted value is found. @default 'system' */
|
|
25
|
+
defaultMode?: ThemeMode;
|
|
26
|
+
/** localStorage key for persistence. @default 'tt-theme' */
|
|
27
|
+
storageKey?: string;
|
|
28
|
+
/** Root element to apply data attributes to. @default document.documentElement */
|
|
29
|
+
root?: HTMLElement;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Public API returned by `createThemeRuntime()`.
|
|
33
|
+
*/
|
|
34
|
+
interface ThemeRuntime {
|
|
35
|
+
getState: () => ThemeState;
|
|
36
|
+
setMode: (mode: ThemeMode) => void;
|
|
37
|
+
subscribe: (listener: (state: ThemeState) => void) => () => void;
|
|
38
|
+
destroy: () => void;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Creates a framework-agnostic runtime that manages theme switching.
|
|
42
|
+
*
|
|
43
|
+
* - Sets `data-tt-mode` (and `data-tt-theme` when `defaultTheme` is provided) attributes on the root element.
|
|
44
|
+
* - Updates `style.colorScheme` for native dark/light UI.
|
|
45
|
+
* - Persists `{ mode }` to localStorage.
|
|
46
|
+
* - Listens to `prefers-color-scheme` media query when mode is `'system'`.
|
|
47
|
+
* - Pub/sub pattern for state changes.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* const runtime = createThemeRuntime({ defaultMode: 'dark' });
|
|
52
|
+
* runtime.setMode('system');
|
|
53
|
+
* const unsub = runtime.subscribe(console.log);
|
|
54
|
+
* runtime.destroy();
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
declare const createThemeRuntime: (config?: ThemeRuntimeConfig) => ThemeRuntime;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Configuration for the SSR bootstrap script.
|
|
61
|
+
*/
|
|
62
|
+
interface ThemeScriptConfig {
|
|
63
|
+
/** Theme identifier written to `data-tt-theme`. When omitted, `data-tt-theme` is not written. */
|
|
64
|
+
defaultTheme?: string;
|
|
65
|
+
/** Mode to use when no persisted value is found. @default 'system' */
|
|
66
|
+
defaultMode?: ThemeMode;
|
|
67
|
+
/** localStorage key. Must match the runtime's `storageKey`. @default 'tt-theme' */
|
|
68
|
+
storageKey?: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Returns self-contained JavaScript code that prevents theme flash on SSR/SSG.
|
|
72
|
+
*
|
|
73
|
+
* Insert the returned string into an inline `<script>` tag in the `<head>`,
|
|
74
|
+
* before any stylesheets or the app bundle.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```tsx
|
|
78
|
+
* // Next.js app/layout.tsx
|
|
79
|
+
* import { getThemeScriptContent } from '@ttoss/fsl-theme/runtime';
|
|
80
|
+
*
|
|
81
|
+
* export default function RootLayout({ children }) {
|
|
82
|
+
* return (
|
|
83
|
+
* <html lang="en">
|
|
84
|
+
* <head>
|
|
85
|
+
* <script dangerouslySetInnerHTML={{ __html: getThemeScriptContent() }} />
|
|
86
|
+
* </head>
|
|
87
|
+
* <body>{children}</body>
|
|
88
|
+
* </html>
|
|
89
|
+
* );
|
|
90
|
+
* }
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
declare const getThemeScriptContent: (config?: ThemeScriptConfig) => string;
|
|
94
|
+
|
|
95
|
+
export { DATA_MODE_ATTR, DATA_THEME_ATTR, type ResolvedMode, type ThemeMode, type ThemeRuntime, type ThemeRuntimeConfig, type ThemeScriptConfig, type ThemeState, createThemeRuntime, getThemeScriptContent };
|
package/dist/vars.d.ts
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { T as ThemeTokens, S as SemanticTokens } from './Types-6tR0_2Ss.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Transforms a token-tree type into an identical structure where every leaf
|
|
5
|
+
* value becomes `string` (a CSS `var(--tt-*)` reference).
|
|
6
|
+
*
|
|
7
|
+
* Keys starting with `$` (e.g. `$deprecated`) are excluded — they are
|
|
8
|
+
* metadata, not consumable tokens.
|
|
9
|
+
*
|
|
10
|
+
* Optional keys in the source type remain optional in the mapped type, so
|
|
11
|
+
* theme extensions such as `dataviz?` are typed as `CssVarsMap<...> | undefined`
|
|
12
|
+
* and TypeScript will require callers to guard against `undefined` before
|
|
13
|
+
* accessing their members.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* type Colors = { action: { primary: { background: { default: TokenRef } } } };
|
|
18
|
+
* type ColorVars = CssVarsMap<Colors>;
|
|
19
|
+
* // → { action: { primary: { background: { default: string } } } }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
type CssVarsMap<T> = {
|
|
23
|
+
[K in keyof T as K extends `$${string}` ? never : K]: NonNullable<T[K]> extends string | number ? string : undefined extends T[K] ? CssVarsMap<NonNullable<T[K]>> | undefined : CssVarsMap<NonNullable<T[K]>>;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Build a deeply-nested CSS var-reference map from a theme's semantic layer.
|
|
27
|
+
*
|
|
28
|
+
* Walks `theme.semantic` recursively and replaces every leaf value with the
|
|
29
|
+
* corresponding `var(--tt-*)` CSS custom property reference. The resulting
|
|
30
|
+
* object has the exact same shape as `theme.semantic` but with `string` leaves.
|
|
31
|
+
*
|
|
32
|
+
* Keys starting with `$` are skipped (deprecation metadata).
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* import { buildVarsMap } from './roots/toVars';
|
|
37
|
+
* import { baseTheme } from './baseTheme';
|
|
38
|
+
*
|
|
39
|
+
* const vars = buildVarsMap(baseTheme);
|
|
40
|
+
* vars.colors.action.primary.background.default
|
|
41
|
+
* // → 'var(--tt-action-primary-background-default)'
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
declare const buildVarsMap: (theme: ThemeTokens) => CssVarsMap<ThemeTokens["semantic"]>;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Static map of all semantic tokens as typed CSS `var(--tt-*)` references.
|
|
48
|
+
*
|
|
49
|
+
* Every leaf value is a CSS Custom Property reference string — zero runtime
|
|
50
|
+
* overhead, full autocomplete, structural parity with `SemanticTokens`.
|
|
51
|
+
*
|
|
52
|
+
* The var names are stable across themes and modes: only the values behind
|
|
53
|
+
* the CSS vars change when the theme or mode switches. Components reference
|
|
54
|
+
* the vars; CSS (generated by `toCssVars`) carries the values.
|
|
55
|
+
*
|
|
56
|
+
* ## Usage with Ark UI / CSS-in-JS
|
|
57
|
+
*
|
|
58
|
+
* ```tsx
|
|
59
|
+
* import { vars } from '@ttoss/fsl-theme/vars';
|
|
60
|
+
*
|
|
61
|
+
* <Button style={{ background: vars.colors.action.primary.background.default }} />
|
|
62
|
+
* // → background: 'var(--tt-action-primary-background-default)'
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* ## Usage in CSS / CSS Modules
|
|
66
|
+
*
|
|
67
|
+
* ```css
|
|
68
|
+
* .button {
|
|
69
|
+
* background: var(--tt-action-primary-background-default);
|
|
70
|
+
* color: var(--tt-action-primary-text-default);
|
|
71
|
+
* }
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* (For plain CSS you can use the var names directly — `vars` is most valuable
|
|
75
|
+
* when you need TypeScript autocomplete in inline styles or CSS-in-JS.)
|
|
76
|
+
*
|
|
77
|
+
* ## Usage in Tailwind plugins / PostCSS
|
|
78
|
+
*
|
|
79
|
+
* ```ts
|
|
80
|
+
* import { toCssVarName } from '@ttoss/fsl-theme/css';
|
|
81
|
+
* // toCssVarName gives you the raw CSS property name without `var()`.
|
|
82
|
+
* ```
|
|
83
|
+
*
|
|
84
|
+
* ## Limitations
|
|
85
|
+
*
|
|
86
|
+
* `vars` reflects the semantic token shape of the **default theme**. If your
|
|
87
|
+
* project extends `SemanticTokens` with custom token families (e.g. a
|
|
88
|
+
* `dataviz` palette, project-specific component tokens), those extra leaves
|
|
89
|
+
* won't appear on this export.
|
|
90
|
+
*
|
|
91
|
+
* ### Typed extension recipe
|
|
92
|
+
*
|
|
93
|
+
* Build your own typed vars object using the public `buildVarsMap` helper
|
|
94
|
+
* together with `CssVarsMap`:
|
|
95
|
+
*
|
|
96
|
+
* ```ts
|
|
97
|
+
* // my-theme.ts
|
|
98
|
+
* import { createTheme, type SemanticTokens } from '@ttoss/fsl-theme';
|
|
99
|
+
* import { buildVarsMap, type CssVarsMap } from '@ttoss/fsl-theme/vars';
|
|
100
|
+
*
|
|
101
|
+
* // 1. Extend the semantic shape structurally.
|
|
102
|
+
* type MySemanticTokens = SemanticTokens & {
|
|
103
|
+
* colors: SemanticTokens['colors'] & {
|
|
104
|
+
* brandX: { primary: { default: string } };
|
|
105
|
+
* };
|
|
106
|
+
* };
|
|
107
|
+
*
|
|
108
|
+
* const myTheme = createTheme({ ... });
|
|
109
|
+
*
|
|
110
|
+
* // 2. Build a typed mirror of the extended shape.
|
|
111
|
+
* export const myVars: CssVarsMap<MySemanticTokens> =
|
|
112
|
+
* buildVarsMap(myTheme.base) as CssVarsMap<MySemanticTokens>;
|
|
113
|
+
*
|
|
114
|
+
* myVars.colors.brandX.primary.default;
|
|
115
|
+
* // → 'var(--tt-colors-brandx-primary-default)'
|
|
116
|
+
* ```
|
|
117
|
+
*
|
|
118
|
+
* For one-off custom keys where the extra structure is trivial, use
|
|
119
|
+
* `toCssVarName` from `'@ttoss/fsl-theme/css'` to construct individual var
|
|
120
|
+
* references without declaring a full extended type.
|
|
121
|
+
*
|
|
122
|
+
* @see {@link toCssVarName} — for raw CSS property names (without `var()`)
|
|
123
|
+
* @see {@link useResolvedTokens} — for resolved raw values in non-CSS environments (React Native, canvas, PDF)
|
|
124
|
+
*/
|
|
125
|
+
declare const vars: CssVarsMap<SemanticTokens>;
|
|
126
|
+
|
|
127
|
+
export { type CssVarsMap, buildVarsMap, vars };
|