@nationaldesignstudio/react 0.6.0 → 0.7.0
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/dist/accordion/index.d.ts +95 -0
- package/dist/accordion/index.js +143 -0
- package/dist/accordion/index.js.map +1 -0
- package/dist/background/index.d.ts +149 -0
- package/dist/background/index.js +200 -0
- package/dist/background/index.js.map +1 -0
- package/dist/banner/index.d.ts +101 -0
- package/dist/banner/index.js +81 -0
- package/dist/banner/index.js.map +1 -0
- package/dist/blurred-video-backdrop/index.d.ts +233 -0
- package/dist/blurred-video-backdrop/index.js +266 -0
- package/dist/blurred-video-backdrop/index.js.map +1 -0
- package/dist/button/index.d.ts +180 -0
- package/dist/button/index.js +169 -0
- package/dist/button/index.js.map +1 -0
- package/dist/button-B2g5fH9b.d.ts +152 -0
- package/dist/card/index.d.ts +406 -0
- package/dist/card/index.js +219 -0
- package/dist/card/index.js.map +1 -0
- package/dist/card-grid/index.d.ts +90 -0
- package/dist/card-grid/index.js +74 -0
- package/dist/card-grid/index.js.map +1 -0
- package/dist/component-registry.md +136 -2
- package/dist/dev-toolbar/index.d.ts +8 -0
- package/dist/dev-toolbar/index.js +206 -0
- package/dist/dev-toolbar/index.js.map +1 -0
- package/dist/dialog/index.d.ts +268 -0
- package/dist/dialog/index.js +288 -0
- package/dist/dialog/index.js.map +1 -0
- package/dist/faq-section/index.d.ts +47 -0
- package/dist/faq-section/index.js +152 -0
- package/dist/faq-section/index.js.map +1 -0
- package/dist/grid-overlay/index.d.ts +10 -0
- package/dist/grid-overlay/index.js +38 -0
- package/dist/grid-overlay/index.js.map +1 -0
- package/dist/hero/index.d.ts +462 -0
- package/dist/hero/index.js +494 -0
- package/dist/hero/index.js.map +1 -0
- package/dist/hooks/index.d.ts +150 -0
- package/dist/hooks/index.js +339 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/index.d.ts +46 -5339
- package/dist/index.js +157 -4080
- package/dist/index.js.map +1 -1
- package/dist/input/index.d.ts +404 -0
- package/dist/input/index.js +393 -0
- package/dist/input/index.js.map +1 -0
- package/dist/navbar/index.d.ts +68 -0
- package/dist/navbar/index.js +227 -0
- package/dist/navbar/index.js.map +1 -0
- package/dist/ndstudio-footer/index.d.ts +32 -0
- package/dist/ndstudio-footer/index.js +35 -0
- package/dist/ndstudio-footer/index.js.map +1 -0
- package/dist/pager-control/index.d.ts +173 -0
- package/dist/pager-control/index.js +267 -0
- package/dist/pager-control/index.js.map +1 -0
- package/dist/popover/index.d.ts +200 -0
- package/dist/popover/index.js +290 -0
- package/dist/popover/index.js.map +1 -0
- package/dist/prose/index.d.ts +39 -0
- package/dist/prose/index.js +56 -0
- package/dist/prose/index.js.map +1 -0
- package/dist/quote-block/index.d.ts +156 -0
- package/dist/quote-block/index.js +321 -0
- package/dist/quote-block/index.js.map +1 -0
- package/dist/river/index.d.ts +100 -0
- package/dist/river/index.js +107 -0
- package/dist/river/index.js.map +1 -0
- package/dist/select/index.d.ts +188 -0
- package/dist/select/index.js +295 -0
- package/dist/select/index.js.map +1 -0
- package/dist/theme/index.d.ts +149 -0
- package/dist/theme/index.js +211 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme-CzBPUlh_.d.ts +332 -0
- package/dist/tooltip/index.d.ts +166 -0
- package/dist/tooltip/index.js +200 -0
- package/dist/tooltip/index.js.map +1 -0
- package/dist/tout/index.d.ts +157 -0
- package/dist/tout/index.js +315 -0
- package/dist/tout/index.js.map +1 -0
- package/dist/two-column-section/index.d.ts +122 -0
- package/dist/two-column-section/index.js +121 -0
- package/dist/two-column-section/index.js.map +1 -0
- package/dist/us-gov-banner/index.d.ts +141 -0
- package/dist/us-gov-banner/index.js +74 -0
- package/dist/us-gov-banner/index.js.map +1 -0
- package/dist/use-captions-AkKlJhov.d.ts +71 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.js +12 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/video-dialog/index.d.ts +106 -0
- package/dist/video-dialog/index.js +1305 -0
- package/dist/video-dialog/index.js.map +1 -0
- package/dist/video-player/index.d.ts +115 -0
- package/dist/video-player/index.js +879 -0
- package/dist/video-player/index.js.map +1 -0
- package/dist/video-player-qxf-BURH.d.ts +236 -0
- package/dist/video-with-backdrop/index.d.ts +267 -0
- package/dist/video-with-backdrop/index.js +1284 -0
- package/dist/video-with-backdrop/index.js.map +1 -0
- package/package.json +13 -2
- package/src/components/organisms/us-gov-banner/us-gov-banner.tsx +5 -27
- package/src/theme/hooks.ts +2 -0
- package/src/theme/index.ts +2 -0
- package/src/theme/theme-provider.tsx +2 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { CSSVariableMap, NestedStringRecord, ColorThemeName, SurfaceThemeName, ResolvedProjectTheme } from '@nds-design-system/tokens';
|
|
2
|
+
export { APICollection, CSSVariableMap, CollectionDefinition, ColorThemeName, NestedStringRecord, ResolvedProjectTheme, SurfaceThemeName, ThemeComposition, colorThemeNames, colorThemes, defineTheme, generateThemeCSS, srgb, surfaceThemeNames, surfaceThemes } from '@nds-design-system/tokens';
|
|
3
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
+
import * as React$1 from 'react';
|
|
5
|
+
import { ReactNode } from 'react';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Theme context value
|
|
9
|
+
*/
|
|
10
|
+
interface ThemeContextValue {
|
|
11
|
+
/** CSS variables map for inline styles */
|
|
12
|
+
cssVars: CSSVariableMap;
|
|
13
|
+
/** Resolved nested tokens */
|
|
14
|
+
tokens: NestedStringRecord;
|
|
15
|
+
/** Current color theme name */
|
|
16
|
+
colorTheme: ColorThemeName;
|
|
17
|
+
/** Current surface theme name */
|
|
18
|
+
surfaceTheme: SurfaceThemeName;
|
|
19
|
+
}
|
|
20
|
+
declare const ThemeContext: React$1.Context<ThemeContextValue | null>;
|
|
21
|
+
/**
|
|
22
|
+
* Props for ThemeProvider
|
|
23
|
+
*/
|
|
24
|
+
interface ThemeProviderProps {
|
|
25
|
+
/** Color theme name (defaults to "base") */
|
|
26
|
+
color?: ColorThemeName;
|
|
27
|
+
/** Surface theme name (defaults to "base") */
|
|
28
|
+
surface?: SurfaceThemeName;
|
|
29
|
+
/**
|
|
30
|
+
* Custom project theme created with defineTheme()
|
|
31
|
+
* When provided, overrides color/surface props with custom theme tokens
|
|
32
|
+
*/
|
|
33
|
+
customTheme?: ResolvedProjectTheme;
|
|
34
|
+
/** Children to render */
|
|
35
|
+
children: ReactNode;
|
|
36
|
+
/** Optional className for the wrapper div */
|
|
37
|
+
className?: string;
|
|
38
|
+
/** Whether to render a wrapper div with CSS variables applied (defaults to true) */
|
|
39
|
+
applyStyles?: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* ThemeProvider component
|
|
43
|
+
*
|
|
44
|
+
* Applies theme tokens as CSS variables using type-safe theme names.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```tsx
|
|
48
|
+
* // Use default base themes
|
|
49
|
+
* <ThemeProvider>
|
|
50
|
+
* <App />
|
|
51
|
+
* </ThemeProvider>
|
|
52
|
+
*
|
|
53
|
+
* // Use specific themes by name
|
|
54
|
+
* <ThemeProvider color="civic" surface="sharp">
|
|
55
|
+
* <App />
|
|
56
|
+
* </ThemeProvider>
|
|
57
|
+
*
|
|
58
|
+
* // Use a custom project theme
|
|
59
|
+
* import { defineTheme, srgb } from "@nds-design-system/tokens";
|
|
60
|
+
*
|
|
61
|
+
* const myTheme = defineTheme({
|
|
62
|
+
* name: "my-project",
|
|
63
|
+
* extends: "base",
|
|
64
|
+
* tokens: {
|
|
65
|
+
* semantic: {
|
|
66
|
+
* color: {
|
|
67
|
+
* bg: { page: srgb("#FEFDF9") },
|
|
68
|
+
* accent: { brand: srgb("#A68B5E") },
|
|
69
|
+
* },
|
|
70
|
+
* },
|
|
71
|
+
* },
|
|
72
|
+
* });
|
|
73
|
+
*
|
|
74
|
+
* <ThemeProvider customTheme={myTheme}>
|
|
75
|
+
* <App />
|
|
76
|
+
* </ThemeProvider>
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
declare function ThemeProvider({ color, surface, customTheme, children, className, applyStyles, }: ThemeProviderProps): react_jsx_runtime.JSX.Element;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Theme Hooks
|
|
83
|
+
*
|
|
84
|
+
* React hooks for accessing theme context.
|
|
85
|
+
*/
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Hook to access the theme context
|
|
89
|
+
* @throws Error if used outside of ThemeProvider
|
|
90
|
+
*/
|
|
91
|
+
declare function useTheme(): ThemeContextValue;
|
|
92
|
+
/**
|
|
93
|
+
* Hook to get just the nested tokens
|
|
94
|
+
*/
|
|
95
|
+
declare function useThemeTokens(): NestedStringRecord;
|
|
96
|
+
/**
|
|
97
|
+
* Hook to get CSS variables for inline styles
|
|
98
|
+
*/
|
|
99
|
+
declare function useCSSVars(): CSSVariableMap;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Theme Utilities
|
|
103
|
+
*
|
|
104
|
+
* Helper functions for working with theme tokens and CSS variables.
|
|
105
|
+
*/
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Convert nested token object to CSS variable map
|
|
109
|
+
* @example
|
|
110
|
+
* toCSSVars({ color: { bg: { page: '#fff' } } })
|
|
111
|
+
* // Returns: { '--color-bg-page': '#fff' }
|
|
112
|
+
*/
|
|
113
|
+
declare function toCSSVars(tokens: NestedStringRecord): CSSVariableMap;
|
|
114
|
+
/**
|
|
115
|
+
* Apply CSS variables to an element
|
|
116
|
+
* @example
|
|
117
|
+
* applyTheme(document.body, { '--color-bg-page': '#fff' })
|
|
118
|
+
*/
|
|
119
|
+
declare function applyTheme(element: HTMLElement, cssVars: CSSVariableMap): void;
|
|
120
|
+
/**
|
|
121
|
+
* Remove CSS variables from an element
|
|
122
|
+
*/
|
|
123
|
+
declare function removeTheme(element: HTMLElement, cssVars: CSSVariableMap): void;
|
|
124
|
+
/**
|
|
125
|
+
* Get a specific token value from nested tokens using dot notation
|
|
126
|
+
* @example
|
|
127
|
+
* getToken({ color: { bg: { page: '#fff' } } }, 'color.bg.page')
|
|
128
|
+
* // Returns: '#fff'
|
|
129
|
+
*/
|
|
130
|
+
declare function getToken(tokens: NestedStringRecord, path: string): string | undefined;
|
|
131
|
+
/**
|
|
132
|
+
* Create a style object with CSS variables for React inline styles
|
|
133
|
+
* @example
|
|
134
|
+
* <div style={createThemeStyle(cssVars)}>...</div>
|
|
135
|
+
*/
|
|
136
|
+
declare function createThemeStyle(cssVars: CSSVariableMap): React.CSSProperties;
|
|
137
|
+
/**
|
|
138
|
+
* Merge multiple CSS variable maps
|
|
139
|
+
*/
|
|
140
|
+
declare function mergeCSSVars(...maps: CSSVariableMap[]): CSSVariableMap;
|
|
141
|
+
/**
|
|
142
|
+
* Filter CSS variables by prefix
|
|
143
|
+
* @example
|
|
144
|
+
* filterCSSVars(cssVars, '--color-')
|
|
145
|
+
* // Returns only variables starting with --color-
|
|
146
|
+
*/
|
|
147
|
+
declare function filterCSSVars(cssVars: CSSVariableMap, prefix: string): CSSVariableMap;
|
|
148
|
+
|
|
149
|
+
export { ThemeContext, type ThemeContextValue, ThemeProvider, type ThemeProviderProps, applyTheme, createThemeStyle, filterCSSVars, getToken, mergeCSSVars, removeTheme, toCSSVars, useCSSVars, useTheme, useThemeTokens };
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { colorThemes, surfaceThemes, flatToNested, flatToCSSVars, nestedToCSSVars, isColorValue, isDimensionValue } from '@nds-design-system/tokens';
|
|
3
|
+
export { colorThemeNames, colorThemes, defineTheme, generateThemeCSS, srgb, surfaceThemeNames, surfaceThemes } from '@nds-design-system/tokens';
|
|
4
|
+
import { createContext, useMemo, useContext } from 'react';
|
|
5
|
+
import { jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
// src/theme/index.ts
|
|
8
|
+
var ThemeContext = createContext(null);
|
|
9
|
+
function colorToCSS(color) {
|
|
10
|
+
const [r, g, b] = color.components;
|
|
11
|
+
if (color.alpha < 1) {
|
|
12
|
+
return `color(srgb ${r} ${g} ${b} / ${color.alpha})`;
|
|
13
|
+
}
|
|
14
|
+
return `color(srgb ${r} ${g} ${b})`;
|
|
15
|
+
}
|
|
16
|
+
function tokenValueToCSS(value) {
|
|
17
|
+
if (isColorValue(value)) {
|
|
18
|
+
return colorToCSS(value);
|
|
19
|
+
}
|
|
20
|
+
if (isDimensionValue(value)) {
|
|
21
|
+
return `${value.value}${value.unit}`;
|
|
22
|
+
}
|
|
23
|
+
if (typeof value === "string") {
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
if (typeof value === "number") {
|
|
27
|
+
return String(value);
|
|
28
|
+
}
|
|
29
|
+
return String(value);
|
|
30
|
+
}
|
|
31
|
+
function processColorTokens(colorObj, path = []) {
|
|
32
|
+
const result = {};
|
|
33
|
+
for (const [key, value] of Object.entries(colorObj)) {
|
|
34
|
+
if (key.startsWith("$")) continue;
|
|
35
|
+
const currentPath = [...path, key];
|
|
36
|
+
if (typeof value === "object" && value !== null) {
|
|
37
|
+
const record = value;
|
|
38
|
+
if ("$value" in record) {
|
|
39
|
+
const varName = `color-${currentPath.join("-")}`;
|
|
40
|
+
const tokenValue = record.$value;
|
|
41
|
+
if (typeof tokenValue === "string" && tokenValue.startsWith("{")) {
|
|
42
|
+
let refPath = tokenValue.slice(1, -1).replace(/\./g, "-");
|
|
43
|
+
refPath = refPath.replace(/^primitive-/, "");
|
|
44
|
+
refPath = refPath.replace(/^semantic-color-/, "color-");
|
|
45
|
+
result[varName] = `var(--${refPath})`;
|
|
46
|
+
} else {
|
|
47
|
+
result[varName] = tokenValueToCSS(tokenValue);
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
Object.assign(result, processColorTokens(record, currentPath));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
function processSurfaceTokens(surfaceObj, path = []) {
|
|
57
|
+
const result = {};
|
|
58
|
+
for (const [key, value] of Object.entries(surfaceObj)) {
|
|
59
|
+
if (key.startsWith("$")) continue;
|
|
60
|
+
const currentPath = [...path, key];
|
|
61
|
+
if (typeof value === "object" && value !== null) {
|
|
62
|
+
const record = value;
|
|
63
|
+
if ("$value" in record) {
|
|
64
|
+
const tokenValue = record.$value;
|
|
65
|
+
let varName;
|
|
66
|
+
let cssValue;
|
|
67
|
+
if (currentPath[currentPath.length - 1] === "radius") {
|
|
68
|
+
const componentName = currentPath[0];
|
|
69
|
+
varName = `radius-surface-${componentName}`;
|
|
70
|
+
} else if (currentPath[currentPath.length - 1] === "stroke") {
|
|
71
|
+
const componentName = currentPath[0];
|
|
72
|
+
varName = `surface-${componentName}-stroke`;
|
|
73
|
+
} else {
|
|
74
|
+
varName = `surface-${currentPath.join("-")}`;
|
|
75
|
+
}
|
|
76
|
+
if (typeof tokenValue === "string" && tokenValue.startsWith("{")) {
|
|
77
|
+
let refPath = tokenValue.slice(1, -1).replace(/\./g, "-");
|
|
78
|
+
refPath = refPath.replace(/^primitive-/, "");
|
|
79
|
+
refPath = refPath.replace(/^radii-/, "radius-");
|
|
80
|
+
cssValue = `var(--${refPath})`;
|
|
81
|
+
} else {
|
|
82
|
+
cssValue = tokenValueToCSS(tokenValue);
|
|
83
|
+
}
|
|
84
|
+
result[varName] = cssValue;
|
|
85
|
+
} else {
|
|
86
|
+
Object.assign(result, processSurfaceTokens(record, currentPath));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
function mergeTokenModules(base, override) {
|
|
93
|
+
const result = JSON.parse(JSON.stringify(base));
|
|
94
|
+
deepMerge(result, override);
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
function deepMerge(target, source) {
|
|
98
|
+
for (const [key, value] of Object.entries(source)) {
|
|
99
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value) && typeof target[key] === "object" && target[key] !== null) {
|
|
100
|
+
deepMerge(
|
|
101
|
+
target[key],
|
|
102
|
+
value
|
|
103
|
+
);
|
|
104
|
+
} else {
|
|
105
|
+
target[key] = value;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function ThemeProvider({
|
|
110
|
+
color = "base",
|
|
111
|
+
surface = "base",
|
|
112
|
+
customTheme,
|
|
113
|
+
children,
|
|
114
|
+
className,
|
|
115
|
+
applyStyles = true
|
|
116
|
+
}) {
|
|
117
|
+
const { tokens, cssVars } = useMemo(() => {
|
|
118
|
+
const flatTokens = {};
|
|
119
|
+
const baseColorModule = colorThemes.base;
|
|
120
|
+
const effectiveColor = customTheme ? customTheme.extends : color;
|
|
121
|
+
const colorModule = colorThemes[effectiveColor] ?? colorThemes.base;
|
|
122
|
+
const mergedColor = effectiveColor === "base" ? baseColorModule : mergeTokenModules(baseColorModule, colorModule);
|
|
123
|
+
const colorTokens = mergedColor?.semantic?.color ?? mergedColor;
|
|
124
|
+
Object.assign(flatTokens, processColorTokens(colorTokens));
|
|
125
|
+
const baseSurfaceModule = surfaceThemes.base;
|
|
126
|
+
const surfaceModule = surfaceThemes[surface];
|
|
127
|
+
const mergedSurface = surface === "base" ? baseSurfaceModule : mergeTokenModules(baseSurfaceModule, surfaceModule);
|
|
128
|
+
const surfaceTokens = mergedSurface?.semantic?.surface ?? mergedSurface;
|
|
129
|
+
Object.assign(flatTokens, processSurfaceTokens(surfaceTokens));
|
|
130
|
+
const nestedTokens = flatToNested(flatTokens);
|
|
131
|
+
let cssVariables = flatToCSSVars(flatTokens);
|
|
132
|
+
if (customTheme) {
|
|
133
|
+
cssVariables = {
|
|
134
|
+
...cssVariables,
|
|
135
|
+
...Object.fromEntries(
|
|
136
|
+
Object.entries(customTheme.cssVars).map(([key, value]) => [
|
|
137
|
+
key.startsWith("--") ? key : `--${key}`,
|
|
138
|
+
value
|
|
139
|
+
])
|
|
140
|
+
)
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
return { tokens: nestedTokens, cssVars: cssVariables };
|
|
144
|
+
}, [color, surface, customTheme]);
|
|
145
|
+
const contextValue = {
|
|
146
|
+
cssVars,
|
|
147
|
+
tokens,
|
|
148
|
+
colorTheme: customTheme ? customTheme.extends : color,
|
|
149
|
+
surfaceTheme: surface
|
|
150
|
+
};
|
|
151
|
+
return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: contextValue, children: applyStyles ? /* @__PURE__ */ jsx("div", { style: cssVars, className, children }) : children });
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// src/theme/hooks.ts
|
|
155
|
+
function useTheme() {
|
|
156
|
+
const context = useContext(ThemeContext);
|
|
157
|
+
if (!context) {
|
|
158
|
+
throw new Error("useTheme must be used within a ThemeProvider");
|
|
159
|
+
}
|
|
160
|
+
return context;
|
|
161
|
+
}
|
|
162
|
+
function useThemeTokens() {
|
|
163
|
+
const { tokens } = useTheme();
|
|
164
|
+
return tokens;
|
|
165
|
+
}
|
|
166
|
+
function useCSSVars() {
|
|
167
|
+
const { cssVars } = useTheme();
|
|
168
|
+
return cssVars;
|
|
169
|
+
}
|
|
170
|
+
function toCSSVars(tokens) {
|
|
171
|
+
return nestedToCSSVars(tokens);
|
|
172
|
+
}
|
|
173
|
+
function applyTheme(element, cssVars) {
|
|
174
|
+
for (const [name, value] of Object.entries(cssVars)) {
|
|
175
|
+
element.style.setProperty(name, value);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function removeTheme(element, cssVars) {
|
|
179
|
+
for (const name of Object.keys(cssVars)) {
|
|
180
|
+
element.style.removeProperty(name);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function getToken(tokens, path) {
|
|
184
|
+
const parts = path.split(".");
|
|
185
|
+
let current = tokens;
|
|
186
|
+
for (const part of parts) {
|
|
187
|
+
if (typeof current === "string") return void 0;
|
|
188
|
+
current = current[part];
|
|
189
|
+
if (current === void 0) return void 0;
|
|
190
|
+
}
|
|
191
|
+
return typeof current === "string" ? current : void 0;
|
|
192
|
+
}
|
|
193
|
+
function createThemeStyle(cssVars) {
|
|
194
|
+
return cssVars;
|
|
195
|
+
}
|
|
196
|
+
function mergeCSSVars(...maps) {
|
|
197
|
+
return Object.assign({}, ...maps);
|
|
198
|
+
}
|
|
199
|
+
function filterCSSVars(cssVars, prefix) {
|
|
200
|
+
const result = {};
|
|
201
|
+
for (const [name, value] of Object.entries(cssVars)) {
|
|
202
|
+
if (name.startsWith(prefix)) {
|
|
203
|
+
result[name] = value;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return result;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export { ThemeContext, ThemeProvider, applyTheme, createThemeStyle, filterCSSVars, getToken, mergeCSSVars, removeTheme, toCSSVars, useCSSVars, useTheme, useThemeTokens };
|
|
210
|
+
//# sourceMappingURL=index.js.map
|
|
211
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/theme/theme-provider.tsx","../../src/theme/hooks.ts","../../src/theme/utils.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["\"use client\";\n\n/**\n * ThemeProvider\n *\n * React context provider for applying theme tokens as CSS variables.\n * Use string theme names for type-safe selection, with \"base\" as default.\n */\n\nimport type {\n\tColorThemeName,\n\tCSSVariableMap,\n\tNestedStringRecord,\n\tResolvedProjectTheme,\n\tSurfaceThemeName,\n\tTokenModule,\n} from \"@nds-design-system/tokens\";\nimport {\n\tcolorThemes,\n\tflatToCSSVars,\n\tflatToNested,\n\tisColorValue,\n\tisDimensionValue,\n\tsurfaceThemes,\n} from \"@nds-design-system/tokens\";\nimport { createContext, type ReactNode, useMemo } from \"react\";\n\n/**\n * Theme context value\n */\nexport interface ThemeContextValue {\n\t/** CSS variables map for inline styles */\n\tcssVars: CSSVariableMap;\n\t/** Resolved nested tokens */\n\ttokens: NestedStringRecord;\n\t/** Current color theme name */\n\tcolorTheme: ColorThemeName;\n\t/** Current surface theme name */\n\tsurfaceTheme: SurfaceThemeName;\n}\n\nexport const ThemeContext = createContext<ThemeContextValue | null>(null);\n\n/**\n * Props for ThemeProvider\n */\nexport interface ThemeProviderProps {\n\t/** Color theme name (defaults to \"base\") */\n\tcolor?: ColorThemeName;\n\t/** Surface theme name (defaults to \"base\") */\n\tsurface?: SurfaceThemeName;\n\t/**\n\t * Custom project theme created with defineTheme()\n\t * When provided, overrides color/surface props with custom theme tokens\n\t */\n\tcustomTheme?: ResolvedProjectTheme;\n\t/** Children to render */\n\tchildren: ReactNode;\n\t/** Optional className for the wrapper div */\n\tclassName?: string;\n\t/** Whether to render a wrapper div with CSS variables applied (defaults to true) */\n\tapplyStyles?: boolean;\n}\n\n/**\n * Convert a color value to CSS string\n */\nfunction colorToCSS(color: { components: number[]; alpha: number }): string {\n\tconst [r, g, b] = color.components;\n\tif (color.alpha < 1) {\n\t\treturn `color(srgb ${r} ${g} ${b} / ${color.alpha})`;\n\t}\n\treturn `color(srgb ${r} ${g} ${b})`;\n}\n\n/**\n * Convert a token value to CSS string\n */\nfunction tokenValueToCSS(value: unknown): string {\n\tif (isColorValue(value)) {\n\t\treturn colorToCSS(value);\n\t}\n\tif (isDimensionValue(value)) {\n\t\treturn `${value.value}${value.unit}`;\n\t}\n\tif (typeof value === \"string\") {\n\t\treturn value;\n\t}\n\tif (typeof value === \"number\") {\n\t\treturn String(value);\n\t}\n\treturn String(value);\n}\n\n/**\n * Process color tokens to flat key-value pairs (without -- prefix)\n */\nfunction processColorTokens(\n\tcolorObj: Record<string, unknown>,\n\tpath: string[] = [],\n): Record<string, string> {\n\tconst result: Record<string, string> = {};\n\n\tfor (const [key, value] of Object.entries(colorObj)) {\n\t\tif (key.startsWith(\"$\")) continue;\n\n\t\tconst currentPath = [...path, key];\n\n\t\tif (typeof value === \"object\" && value !== null) {\n\t\t\tconst record = value as Record<string, unknown>;\n\n\t\t\tif (\"$value\" in record) {\n\t\t\t\t// This is a token - key without -- prefix\n\t\t\t\tconst varName = `color-${currentPath.join(\"-\")}`;\n\t\t\t\tconst tokenValue = record.$value;\n\n\t\t\t\tif (typeof tokenValue === \"string\" && tokenValue.startsWith(\"{\")) {\n\t\t\t\t\t// Alias reference - resolve to CSS var\n\t\t\t\t\tlet refPath = tokenValue.slice(1, -1).replace(/\\./g, \"-\");\n\t\t\t\t\t// Strip prefixes that aren't used in CSS variable names\n\t\t\t\t\trefPath = refPath.replace(/^primitive-/, \"\");\n\t\t\t\t\trefPath = refPath.replace(/^semantic-color-/, \"color-\");\n\t\t\t\t\tresult[varName] = `var(--${refPath})`;\n\t\t\t\t} else {\n\t\t\t\t\tresult[varName] = tokenValueToCSS(tokenValue);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Nested object - recurse\n\t\t\t\tObject.assign(result, processColorTokens(record, currentPath));\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Process surface tokens to flat key-value pairs (without -- prefix)\n */\nfunction processSurfaceTokens(\n\tsurfaceObj: Record<string, unknown>,\n\tpath: string[] = [],\n): Record<string, string> {\n\tconst result: Record<string, string> = {};\n\n\tfor (const [key, value] of Object.entries(surfaceObj)) {\n\t\tif (key.startsWith(\"$\")) continue;\n\n\t\tconst currentPath = [...path, key];\n\n\t\tif (typeof value === \"object\" && value !== null) {\n\t\t\tconst record = value as Record<string, unknown>;\n\n\t\t\tif (\"$value\" in record) {\n\t\t\t\t// This is a token\n\t\t\t\tconst tokenValue = record.$value;\n\t\t\t\tlet varName: string;\n\t\t\t\tlet cssValue: string;\n\n\t\t\t\t// Determine variable name based on token type (without -- prefix)\n\t\t\t\tif (currentPath[currentPath.length - 1] === \"radius\") {\n\t\t\t\t\t// e.g., button.radius -> radius-surface-button\n\t\t\t\t\tconst componentName = currentPath[0];\n\t\t\t\t\tvarName = `radius-surface-${componentName}`;\n\t\t\t\t} else if (currentPath[currentPath.length - 1] === \"stroke\") {\n\t\t\t\t\t// e.g., button.stroke -> surface-button-stroke\n\t\t\t\t\tconst componentName = currentPath[0];\n\t\t\t\t\tvarName = `surface-${componentName}-stroke`;\n\t\t\t\t} else {\n\t\t\t\t\tvarName = `surface-${currentPath.join(\"-\")}`;\n\t\t\t\t}\n\n\t\t\t\t// Resolve value\n\t\t\t\tif (typeof tokenValue === \"string\" && tokenValue.startsWith(\"{\")) {\n\t\t\t\t\t// Alias reference\n\t\t\t\t\tlet refPath = tokenValue.slice(1, -1).replace(/\\./g, \"-\");\n\t\t\t\t\t// Strip prefixes that aren't used in CSS variable names\n\t\t\t\t\trefPath = refPath.replace(/^primitive-/, \"\");\n\t\t\t\t\trefPath = refPath.replace(/^radii-/, \"radius-\");\n\t\t\t\t\tcssValue = `var(--${refPath})`;\n\t\t\t\t} else {\n\t\t\t\t\tcssValue = tokenValueToCSS(tokenValue);\n\t\t\t\t}\n\n\t\t\t\tresult[varName] = cssValue;\n\t\t\t} else {\n\t\t\t\t// Nested object - recurse\n\t\t\t\tObject.assign(result, processSurfaceTokens(record, currentPath));\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Deep merge two token modules\n */\nfunction mergeTokenModules(\n\tbase: TokenModule,\n\toverride: TokenModule,\n): Record<string, unknown> {\n\tconst result: Record<string, unknown> = JSON.parse(JSON.stringify(base));\n\tdeepMerge(result, override as Record<string, unknown>);\n\treturn result;\n}\n\n/**\n * Deep merge objects\n */\nfunction deepMerge(\n\ttarget: Record<string, unknown>,\n\tsource: Record<string, unknown>,\n): void {\n\tfor (const [key, value] of Object.entries(source)) {\n\t\tif (\n\t\t\ttypeof value === \"object\" &&\n\t\t\tvalue !== null &&\n\t\t\t!Array.isArray(value) &&\n\t\t\ttypeof target[key] === \"object\" &&\n\t\t\ttarget[key] !== null\n\t\t) {\n\t\t\tdeepMerge(\n\t\t\t\ttarget[key] as Record<string, unknown>,\n\t\t\t\tvalue as Record<string, unknown>,\n\t\t\t);\n\t\t} else {\n\t\t\ttarget[key] = value;\n\t\t}\n\t}\n}\n\n/**\n * ThemeProvider component\n *\n * Applies theme tokens as CSS variables using type-safe theme names.\n *\n * @example\n * ```tsx\n * // Use default base themes\n * <ThemeProvider>\n * <App />\n * </ThemeProvider>\n *\n * // Use specific themes by name\n * <ThemeProvider color=\"civic\" surface=\"sharp\">\n * <App />\n * </ThemeProvider>\n *\n * // Use a custom project theme\n * import { defineTheme, srgb } from \"@nds-design-system/tokens\";\n *\n * const myTheme = defineTheme({\n * name: \"my-project\",\n * extends: \"base\",\n * tokens: {\n * semantic: {\n * color: {\n * bg: { page: srgb(\"#FEFDF9\") },\n * accent: { brand: srgb(\"#A68B5E\") },\n * },\n * },\n * },\n * });\n *\n * <ThemeProvider customTheme={myTheme}>\n * <App />\n * </ThemeProvider>\n * ```\n */\nexport function ThemeProvider({\n\tcolor = \"base\",\n\tsurface = \"base\",\n\tcustomTheme,\n\tchildren,\n\tclassName,\n\tapplyStyles = true,\n}: ThemeProviderProps) {\n\tconst { tokens, cssVars } = useMemo(() => {\n\t\tconst flatTokens: Record<string, string> = {};\n\n\t\t// Get base color theme\n\t\tconst baseColorModule = colorThemes.base;\n\n\t\t// If customTheme is provided, use its base theme; otherwise use the color prop\n\t\tconst effectiveColor = customTheme ? customTheme.extends : color;\n\t\tconst colorModule =\n\t\t\tcolorThemes[effectiveColor as keyof typeof colorThemes] ??\n\t\t\tcolorThemes.base;\n\n\t\tconst mergedColor =\n\t\t\teffectiveColor === \"base\"\n\t\t\t\t? (baseColorModule as Record<string, unknown>)\n\t\t\t\t: mergeTokenModules(baseColorModule, colorModule);\n\n\t\t// Navigate to semantic.color\n\t\tconst colorTokens =\n\t\t\t(mergedColor as { semantic?: { color?: Record<string, unknown> } })\n\t\t\t\t?.semantic?.color ?? mergedColor;\n\t\tObject.assign(flatTokens, processColorTokens(colorTokens));\n\n\t\t// Get surface theme (merge with base if not base)\n\t\tconst baseSurfaceModule = surfaceThemes.base;\n\t\tconst surfaceModule = surfaceThemes[surface];\n\n\t\tconst mergedSurface =\n\t\t\tsurface === \"base\"\n\t\t\t\t? (baseSurfaceModule as Record<string, unknown>)\n\t\t\t\t: mergeTokenModules(baseSurfaceModule, surfaceModule);\n\n\t\t// Navigate to semantic.surface\n\t\tconst surfaceTokens =\n\t\t\t(mergedSurface as { semantic?: { surface?: Record<string, unknown> } })\n\t\t\t\t?.semantic?.surface ?? mergedSurface;\n\t\tObject.assign(flatTokens, processSurfaceTokens(surfaceTokens));\n\n\t\t// Use shared utilities from tokens package\n\t\tconst nestedTokens = flatToNested(flatTokens);\n\t\tlet cssVariables = flatToCSSVars(flatTokens);\n\n\t\t// If customTheme provided, merge its CSS variables (overriding base values)\n\t\tif (customTheme) {\n\t\t\tcssVariables = {\n\t\t\t\t...cssVariables,\n\t\t\t\t...Object.fromEntries(\n\t\t\t\t\tObject.entries(customTheme.cssVars).map(([key, value]) => [\n\t\t\t\t\t\tkey.startsWith(\"--\") ? key : `--${key}`,\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t]),\n\t\t\t\t),\n\t\t\t};\n\t\t}\n\n\t\treturn { tokens: nestedTokens, cssVars: cssVariables };\n\t}, [color, surface, customTheme]);\n\n\tconst contextValue: ThemeContextValue = {\n\t\tcssVars,\n\t\ttokens,\n\t\tcolorTheme: customTheme ? (customTheme.extends as ColorThemeName) : color,\n\t\tsurfaceTheme: surface,\n\t};\n\n\treturn (\n\t\t<ThemeContext.Provider value={contextValue}>\n\t\t\t{applyStyles ? (\n\t\t\t\t<div style={cssVars} className={className}>\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\tchildren\n\t\t\t)}\n\t\t</ThemeContext.Provider>\n\t);\n}\n","\"use client\";\n\n/**\n * Theme Hooks\n *\n * React hooks for accessing theme context.\n */\n\nimport type {\n\tCSSVariableMap,\n\tNestedStringRecord,\n} from \"@nds-design-system/tokens\";\nimport { useContext } from \"react\";\nimport { ThemeContext, type ThemeContextValue } from \"./theme-provider\";\n\n/**\n * Hook to access the theme context\n * @throws Error if used outside of ThemeProvider\n */\nexport function useTheme(): ThemeContextValue {\n\tconst context = useContext(ThemeContext);\n\tif (!context) {\n\t\tthrow new Error(\"useTheme must be used within a ThemeProvider\");\n\t}\n\treturn context;\n}\n\n/**\n * Hook to get just the nested tokens\n */\nexport function useThemeTokens(): NestedStringRecord {\n\tconst { tokens } = useTheme();\n\treturn tokens;\n}\n\n/**\n * Hook to get CSS variables for inline styles\n */\nexport function useCSSVars(): CSSVariableMap {\n\tconst { cssVars } = useTheme();\n\treturn cssVars;\n}\n","/**\n * Theme Utilities\n *\n * Helper functions for working with theme tokens and CSS variables.\n */\n\nimport type {\n\tCSSVariableMap,\n\tNestedStringRecord,\n} from \"@nds-design-system/tokens\";\nimport { nestedToCSSVars } from \"@nds-design-system/tokens\";\n\n/**\n * Convert nested token object to CSS variable map\n * @example\n * toCSSVars({ color: { bg: { page: '#fff' } } })\n * // Returns: { '--color-bg-page': '#fff' }\n */\nexport function toCSSVars(tokens: NestedStringRecord): CSSVariableMap {\n\treturn nestedToCSSVars(tokens);\n}\n\n/**\n * Apply CSS variables to an element\n * @example\n * applyTheme(document.body, { '--color-bg-page': '#fff' })\n */\nexport function applyTheme(\n\telement: HTMLElement,\n\tcssVars: CSSVariableMap,\n): void {\n\tfor (const [name, value] of Object.entries(cssVars)) {\n\t\telement.style.setProperty(name, value);\n\t}\n}\n\n/**\n * Remove CSS variables from an element\n */\nexport function removeTheme(\n\telement: HTMLElement,\n\tcssVars: CSSVariableMap,\n): void {\n\tfor (const name of Object.keys(cssVars)) {\n\t\telement.style.removeProperty(name);\n\t}\n}\n\n/**\n * Get a specific token value from nested tokens using dot notation\n * @example\n * getToken({ color: { bg: { page: '#fff' } } }, 'color.bg.page')\n * // Returns: '#fff'\n */\nexport function getToken(\n\ttokens: NestedStringRecord,\n\tpath: string,\n): string | undefined {\n\tconst parts = path.split(\".\");\n\tlet current: NestedStringRecord | string = tokens;\n\n\tfor (const part of parts) {\n\t\tif (typeof current === \"string\") return undefined;\n\t\tcurrent = current[part];\n\t\tif (current === undefined) return undefined;\n\t}\n\n\treturn typeof current === \"string\" ? current : undefined;\n}\n\n/**\n * Create a style object with CSS variables for React inline styles\n * @example\n * <div style={createThemeStyle(cssVars)}>...</div>\n */\nexport function createThemeStyle(cssVars: CSSVariableMap): React.CSSProperties {\n\treturn cssVars as React.CSSProperties;\n}\n\n/**\n * Merge multiple CSS variable maps\n */\nexport function mergeCSSVars(...maps: CSSVariableMap[]): CSSVariableMap {\n\treturn Object.assign({}, ...maps);\n}\n\n/**\n * Filter CSS variables by prefix\n * @example\n * filterCSSVars(cssVars, '--color-')\n * // Returns only variables starting with --color-\n */\nexport function filterCSSVars(\n\tcssVars: CSSVariableMap,\n\tprefix: string,\n): CSSVariableMap {\n\tconst result: CSSVariableMap = {};\n\tfor (const [name, value] of Object.entries(cssVars)) {\n\t\tif (name.startsWith(prefix)) {\n\t\t\tresult[name] = value;\n\t\t}\n\t}\n\treturn result;\n}\n"]}
|