@memberjunction/react-runtime 5.51.0 → 6.1.0-edge.1
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/.turbo/turbo-build.log +26 -18
- package/CHANGELOG.md +54 -0
- package/LICENSE +7 -0
- package/dist/324.runtime.umd.js +23 -32
- package/dist/{490.runtime.umd.js → 456.runtime.umd.js} +40 -40
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/runtime.umd.js +9276 -4844
- package/dist/utilities/component-styles.d.ts +2 -1
- package/dist/utilities/component-styles.d.ts.map +1 -1
- package/dist/utilities/component-styles.js +79 -0
- package/dist/utilities/component-styles.js.map +1 -1
- package/package.json +17 -17
- package/src/__tests__/component-styles.test.ts +252 -0
- package/src/index.ts +2 -1
- package/src/utilities/component-styles.ts +130 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { ComponentStyles } from '@memberjunction/interactive-component-types';
|
|
1
|
+
import { ComponentStyles, StyleOverrides } from '@memberjunction/interactive-component-types';
|
|
2
2
|
export declare function SetupStyles(): ComponentStyles;
|
|
3
3
|
export declare const createDefaultComponentStyles: typeof SetupStyles;
|
|
4
4
|
export declare function BuildStylesFromTheme(root?: Element): ComponentStyles;
|
|
5
|
+
export declare function ApplyStyleOverrides<T extends Partial<ComponentStyles>>(base: T, overrides?: StyleOverrides): T;
|
|
5
6
|
//# sourceMappingURL=component-styles.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component-styles.d.ts","sourceRoot":"","sources":["../../src/utilities/component-styles.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;
|
|
1
|
+
{"version":3,"file":"component-styles.d.ts","sourceRoot":"","sources":["../../src/utilities/component-styles.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,6CAA6C,CAAC;AAO9F,wBAAgB,WAAW,IAAI,eAAe,CAyI7C;AAGD,eAAO,MAAM,4BAA4B,oBAAc,CAAC;AAyExD,wBAAgB,oBAAoB,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,eAAe,CAoDpE;AA4CD,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,OAAO,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,EAAE,cAAc,GAAG,CAAC,CA0B9G"}
|
|
@@ -9,15 +9,24 @@ export function SetupStyles() {
|
|
|
9
9
|
secondaryHover: '#475569',
|
|
10
10
|
success: '#10B981',
|
|
11
11
|
successLight: '#D1FAE5',
|
|
12
|
+
successText: '#047857',
|
|
13
|
+
successBorder: '#b7eb8f',
|
|
12
14
|
warning: '#F59E0B',
|
|
13
15
|
warningLight: '#FEF3C7',
|
|
16
|
+
warningText: '#8c6c00',
|
|
17
|
+
warningBorder: '#ffe58f',
|
|
14
18
|
error: '#EF4444',
|
|
15
19
|
errorLight: '#FEE2E2',
|
|
20
|
+
errorText: '#B91C1C',
|
|
21
|
+
errorBorder: '#FECACA',
|
|
16
22
|
info: '#3B82F6',
|
|
17
23
|
infoLight: '#DBEAFE',
|
|
24
|
+
infoText: '#1D4ED8',
|
|
25
|
+
infoBorder: '#91d5ff',
|
|
18
26
|
background: '#FFFFFF',
|
|
19
27
|
surface: '#F8FAFC',
|
|
20
28
|
surfaceHover: '#F1F5F9',
|
|
29
|
+
overlay: 'rgba(0, 0, 0, 0.5)',
|
|
21
30
|
text: '#1E293B',
|
|
22
31
|
textSecondary: '#64748B',
|
|
23
32
|
textTertiary: '#94A3B8',
|
|
@@ -95,6 +104,14 @@ export function SetupStyles() {
|
|
|
95
104
|
'#2196F3', '#4CAF50', '#FF9800', '#E91E63', '#9C27B0',
|
|
96
105
|
'#00BCD4', '#F44336', '#8BC34A', '#FF5722', '#3F51B5',
|
|
97
106
|
],
|
|
107
|
+
sequentialScale: [
|
|
108
|
+
'#E3F2FD', '#BBDEFB', '#90CAF9', '#42A5F5', '#2196F3', '#1976D2', '#0D47A1',
|
|
109
|
+
],
|
|
110
|
+
divergingScale: {
|
|
111
|
+
low: '#F44336',
|
|
112
|
+
mid: '#EEEEEE',
|
|
113
|
+
high: '#4CAF50',
|
|
114
|
+
},
|
|
98
115
|
};
|
|
99
116
|
}
|
|
100
117
|
export const createDefaultComponentStyles = SetupStyles;
|
|
@@ -103,17 +120,28 @@ const THEME_COLOR_TOKEN_MAP = {
|
|
|
103
120
|
primaryHover: '--mj-brand-primary-hover',
|
|
104
121
|
primaryActive: '--mj-brand-primary-active',
|
|
105
122
|
primaryLight: '--mj-brand-primary-light',
|
|
123
|
+
secondary: '--mj-brand-secondary',
|
|
124
|
+
secondaryHover: '--mj-brand-secondary-hover',
|
|
106
125
|
success: '--mj-status-success',
|
|
107
126
|
successLight: '--mj-status-success-bg',
|
|
127
|
+
successText: '--mj-status-success-text',
|
|
128
|
+
successBorder: '--mj-status-success-border',
|
|
108
129
|
warning: '--mj-status-warning',
|
|
109
130
|
warningLight: '--mj-status-warning-bg',
|
|
131
|
+
warningText: '--mj-status-warning-text',
|
|
132
|
+
warningBorder: '--mj-status-warning-border',
|
|
110
133
|
error: '--mj-status-error',
|
|
111
134
|
errorLight: '--mj-status-error-bg',
|
|
135
|
+
errorText: '--mj-status-error-text',
|
|
136
|
+
errorBorder: '--mj-status-error-border',
|
|
112
137
|
info: '--mj-status-info',
|
|
113
138
|
infoLight: '--mj-status-info-bg',
|
|
139
|
+
infoText: '--mj-status-info-text',
|
|
140
|
+
infoBorder: '--mj-status-info-border',
|
|
114
141
|
background: '--mj-bg-page',
|
|
115
142
|
surface: '--mj-bg-surface',
|
|
116
143
|
surfaceHover: '--mj-bg-surface-hover',
|
|
144
|
+
overlay: '--mj-bg-overlay',
|
|
117
145
|
text: '--mj-text-primary',
|
|
118
146
|
textSecondary: '--mj-text-secondary',
|
|
119
147
|
textTertiary: '--mj-text-muted',
|
|
@@ -125,6 +153,7 @@ const THEME_COLOR_TOKEN_MAP = {
|
|
|
125
153
|
borderFocus: '--mj-border-focus',
|
|
126
154
|
};
|
|
127
155
|
const VIZ_TOKEN_COUNT = 10;
|
|
156
|
+
const VIZ_SEQ_TOKEN_COUNT = 7;
|
|
128
157
|
export function BuildStylesFromTheme(root) {
|
|
129
158
|
const base = SetupStyles();
|
|
130
159
|
const el = root ?? (typeof document !== 'undefined' ? document.documentElement : undefined);
|
|
@@ -149,6 +178,56 @@ export function BuildStylesFromTheme(root) {
|
|
|
149
178
|
if (palette.length > 0) {
|
|
150
179
|
base.chartPalette = palette;
|
|
151
180
|
}
|
|
181
|
+
const sequential = [];
|
|
182
|
+
for (let i = 1; i <= VIZ_SEQ_TOKEN_COUNT; i++) {
|
|
183
|
+
const value = read(`--mj-viz-seq-${i}`);
|
|
184
|
+
if (value) {
|
|
185
|
+
sequential.push(value);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (sequential.length > 1) {
|
|
189
|
+
base.sequentialScale = sequential;
|
|
190
|
+
}
|
|
191
|
+
const divLow = read('--mj-viz-div-low');
|
|
192
|
+
const divHigh = read('--mj-viz-div-high');
|
|
193
|
+
if (divLow && divHigh) {
|
|
194
|
+
const divMid = read('--mj-viz-div-mid');
|
|
195
|
+
base.divergingScale = divMid ? { low: divLow, mid: divMid, high: divHigh } : { low: divLow, high: divHigh };
|
|
196
|
+
}
|
|
152
197
|
return base;
|
|
153
198
|
}
|
|
199
|
+
const FONT_SCALE_FACTOR = { small: 0.875, large: 1.25 };
|
|
200
|
+
const MIN_FONT_SIZE_PX = 10;
|
|
201
|
+
function scaleFontSizes(fontSize, factor) {
|
|
202
|
+
const scaled = {};
|
|
203
|
+
for (const [key, value] of Object.entries(fontSize)) {
|
|
204
|
+
const px = typeof value === 'string' ? /^\s*(\d+(?:\.\d+)?)px\s*$/.exec(value) : null;
|
|
205
|
+
scaled[key] = px
|
|
206
|
+
? `${Math.max(MIN_FONT_SIZE_PX, Math.round(parseFloat(px[1]) * factor))}px`
|
|
207
|
+
: value;
|
|
208
|
+
}
|
|
209
|
+
return scaled;
|
|
210
|
+
}
|
|
211
|
+
export function ApplyStyleOverrides(base, overrides) {
|
|
212
|
+
if (!overrides) {
|
|
213
|
+
return base;
|
|
214
|
+
}
|
|
215
|
+
const hasChartPalette = Array.isArray(overrides.chartPalette) && overrides.chartPalette.length > 0;
|
|
216
|
+
const hasSequential = Array.isArray(overrides.sequentialScale) && overrides.sequentialScale.length > 1;
|
|
217
|
+
const hasDiverging = !!overrides.divergingScale?.low && !!overrides.divergingScale?.high;
|
|
218
|
+
const fontFactor = overrides.fontScale ? FONT_SCALE_FACTOR[overrides.fontScale] : undefined;
|
|
219
|
+
const hasFontScale = !!fontFactor && !!base.typography?.fontSize;
|
|
220
|
+
if (!hasChartPalette && !hasSequential && !hasDiverging && !hasFontScale) {
|
|
221
|
+
return base;
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
...base,
|
|
225
|
+
...(hasChartPalette ? { chartPalette: overrides.chartPalette } : {}),
|
|
226
|
+
...(hasSequential ? { sequentialScale: overrides.sequentialScale } : {}),
|
|
227
|
+
...(hasDiverging ? { divergingScale: overrides.divergingScale } : {}),
|
|
228
|
+
...(hasFontScale
|
|
229
|
+
? { typography: { ...base.typography, fontSize: scaleFontSizes(base.typography.fontSize, fontFactor) } }
|
|
230
|
+
: {}),
|
|
231
|
+
};
|
|
232
|
+
}
|
|
154
233
|
//# sourceMappingURL=component-styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component-styles.js","sourceRoot":"","sources":["../../src/utilities/component-styles.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Default component styles for React runtime\n * @module @memberjunction/react-runtime/utilities\n */\n\nimport { ComponentStyles } from '@memberjunction/interactive-component-types';\n\n/**\n * Creates the default component styles for Skip components\n * These provide a modern, contemporary look and feel\n * Copied from skip-chat implementation\n */\nexport function SetupStyles(): ComponentStyles {\n // Return modern, contemporary styles for generated components\n return {\n colors: {\n // Primary colors - modern purple/blue gradient feel\n primary: '#5B4FE9',\n primaryHover: '#4940D4',\n primaryActive: '#3E37B8',\n primaryLight: '#E8E6FF',\n\n // Secondary colors - sophisticated gray\n secondary: '#64748B',\n secondaryHover: '#475569',\n \n // Status colors\n success: '#10B981',\n successLight: '#D1FAE5',\n warning: '#F59E0B',\n warningLight: '#FEF3C7',\n error: '#EF4444',\n errorLight: '#FEE2E2',\n info: '#3B82F6',\n infoLight: '#DBEAFE',\n \n // Base colors\n background: '#FFFFFF',\n surface: '#F8FAFC',\n surfaceHover: '#F1F5F9',\n \n // Text colors with better contrast\n text: '#1E293B',\n textSecondary: '#64748B',\n textTertiary: '#94A3B8',\n textInverse: '#FFFFFF',\n\n // Link colors\n link: '#5B4FE9',\n linkHover: '#4940D4',\n\n // Border colors\n border: '#E2E8F0',\n borderLight: '#F1F5F9',\n borderFocus: '#5B4FE9',\n \n // Shadows (as color strings for easy use)\n shadow: 'rgba(0, 0, 0, 0.05)',\n shadowMedium: 'rgba(0, 0, 0, 0.1)',\n shadowLarge: 'rgba(0, 0, 0, 0.15)',\n },\n spacing: {\n xs: '4px',\n sm: '8px',\n md: '16px',\n lg: '24px',\n xl: '32px',\n xxl: '48px',\n xxxl: '64px',\n },\n typography: {\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Inter\", \"Segoe UI\", Roboto, sans-serif',\n fontSize: {\n xs: '11px',\n sm: '12px',\n md: '14px',\n lg: '16px',\n xl: '20px',\n xxl: '24px',\n xxxl: '32px',\n },\n fontWeight: {\n light: '300',\n regular: '400',\n medium: '500',\n semibold: '600',\n bold: '700',\n },\n lineHeight: {\n tight: '1.25',\n normal: '1.5',\n relaxed: '1.75',\n },\n },\n borders: {\n radius: {\n sm: '6px',\n md: '8px',\n lg: '12px',\n xl: '16px',\n full: '9999px',\n },\n width: {\n thin: '1px',\n medium: '2px',\n thick: '3px',\n },\n },\n shadows: {\n sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',\n md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',\n lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',\n xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',\n inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',\n },\n transitions: {\n fast: '150ms ease-in-out',\n normal: '250ms ease-in-out',\n slow: '350ms ease-in-out',\n },\n overflow: 'auto', // Default overflow style\n // Default categorical palette for multi-series charts. Overridden per-theme\n // from the host's `--mj-viz-*` tokens by BuildStylesFromTheme().\n chartPalette: [\n '#2196F3', '#4CAF50', '#FF9800', '#E91E63', '#9C27B0',\n '#00BCD4', '#F44336', '#8BC34A', '#FF5722', '#3F51B5',\n ],\n }\n}\n\n// Also export with the original name for backward compatibility\nexport const createDefaultComponentStyles = SetupStyles;\n\n/**\n * The `--mj-*` semantic token → `ComponentStyles` mapping used by the theme bridge.\n * Keys are ComponentStyles color paths; values are the CSS custom property to read.\n * Only theme-defining tokens with a clear semantic equivalent are mapped; every\n * other field keeps its `SetupStyles()` default.\n */\nconst THEME_COLOR_TOKEN_MAP: Record<string, string> = {\n // Brand / primary + interactive states\n primary: '--mj-brand-primary',\n primaryHover: '--mj-brand-primary-hover',\n primaryActive: '--mj-brand-primary-active',\n primaryLight: '--mj-brand-primary-light',\n // Status\n success: '--mj-status-success',\n successLight: '--mj-status-success-bg',\n warning: '--mj-status-warning',\n warningLight: '--mj-status-warning-bg',\n error: '--mj-status-error',\n errorLight: '--mj-status-error-bg',\n info: '--mj-status-info',\n infoLight: '--mj-status-info-bg',\n // Surfaces (MJ: page = tinted, surface = elevated/white in light mode)\n background: '--mj-bg-page',\n surface: '--mj-bg-surface',\n surfaceHover: '--mj-bg-surface-hover',\n // Text\n text: '--mj-text-primary',\n textSecondary: '--mj-text-secondary',\n textTertiary: '--mj-text-muted',\n textInverse: '--mj-text-inverse',\n // Links\n link: '--mj-text-link',\n linkHover: '--mj-text-link-hover',\n // Borders / focus\n border: '--mj-border-default',\n borderLight: '--mj-border-subtle',\n borderFocus: '--mj-border-focus',\n};\n\n/** Number of `--mj-viz-N` categorical tokens the bridge probes for `chartPalette`. */\nconst VIZ_TOKEN_COUNT = 10;\n\n/**\n * Reads the live MJ theme (`--mj-*` custom properties on the document root) and\n * layers it over `SetupStyles()`, producing a `ComponentStyles` that follows the\n * host's active theme — including dark mode and interactive-state (hover/active/\n * focus) families — instead of the frozen default palette. This is the Phase 1\n * theme bridge that gives generated components shell↔content cohesion.\n *\n * DOM-guarded: in non-DOM environments (Node test harness, SSR) there is no\n * computed theme to read, so it returns `SetupStyles()` unchanged. Any individual\n * token that is absent falls back to its `SetupStyles()` default, so a page\n * without MJ tokens loaded also degrades cleanly.\n *\n * @param root optional element to read tokens from (defaults to document root).\n */\nexport function BuildStylesFromTheme(root?: Element): ComponentStyles {\n const base = SetupStyles();\n\n const el = root ?? (typeof document !== 'undefined' ? document.documentElement : undefined);\n if (!el || typeof getComputedStyle === 'undefined') {\n return base;\n }\n\n const cs = getComputedStyle(el);\n const read = (token: string): string => cs.getPropertyValue(token).trim();\n\n for (const [path, token] of Object.entries(THEME_COLOR_TOKEN_MAP)) {\n const value = read(token);\n if (value) {\n base.colors[path] = value;\n }\n }\n\n const palette: string[] = [];\n for (let i = 1; i <= VIZ_TOKEN_COUNT; i++) {\n const value = read(`--mj-viz-${i}`);\n if (value) {\n palette.push(value);\n }\n }\n if (palette.length > 0) {\n base.chartPalette = palette;\n }\n\n return base;\n}"]}
|
|
1
|
+
{"version":3,"file":"component-styles.js","sourceRoot":"","sources":["../../src/utilities/component-styles.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Default component styles for React runtime\n * @module @memberjunction/react-runtime/utilities\n */\n\nimport { ComponentStyles, StyleOverrides } from '@memberjunction/interactive-component-types';\n\n/**\n * Creates the default component styles for Skip components\n * These provide a modern, contemporary look and feel\n * Copied from skip-chat implementation\n */\nexport function SetupStyles(): ComponentStyles {\n // Return modern, contemporary styles for generated components\n return {\n colors: {\n // Primary colors - modern purple/blue gradient feel\n primary: '#5B4FE9',\n primaryHover: '#4940D4',\n primaryActive: '#3E37B8',\n primaryLight: '#E8E6FF',\n\n // Secondary colors - sophisticated gray\n secondary: '#64748B',\n secondaryHover: '#475569',\n \n // Status colors\n success: '#10B981',\n successLight: '#D1FAE5',\n successText: '#047857',\n successBorder: '#b7eb8f',\n warning: '#F59E0B',\n warningLight: '#FEF3C7',\n warningText: '#8c6c00',\n warningBorder: '#ffe58f',\n error: '#EF4444',\n errorLight: '#FEE2E2',\n errorText: '#B91C1C',\n errorBorder: '#FECACA',\n info: '#3B82F6',\n infoLight: '#DBEAFE',\n infoText: '#1D4ED8',\n infoBorder: '#91d5ff',\n\n // Base colors\n background: '#FFFFFF',\n surface: '#F8FAFC',\n surfaceHover: '#F1F5F9',\n overlay: 'rgba(0, 0, 0, 0.5)', // Modal scrim\n \n // Text colors with better contrast\n text: '#1E293B',\n textSecondary: '#64748B',\n textTertiary: '#94A3B8',\n textInverse: '#FFFFFF',\n\n // Link colors\n link: '#5B4FE9',\n linkHover: '#4940D4',\n\n // Border colors\n border: '#E2E8F0',\n borderLight: '#F1F5F9',\n borderFocus: '#5B4FE9',\n \n // Shadows (as color strings for easy use)\n shadow: 'rgba(0, 0, 0, 0.05)',\n shadowMedium: 'rgba(0, 0, 0, 0.1)',\n shadowLarge: 'rgba(0, 0, 0, 0.15)',\n },\n spacing: {\n xs: '4px',\n sm: '8px',\n md: '16px',\n lg: '24px',\n xl: '32px',\n xxl: '48px',\n xxxl: '64px',\n },\n typography: {\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Inter\", \"Segoe UI\", Roboto, sans-serif',\n fontSize: {\n xs: '11px',\n sm: '12px',\n md: '14px',\n lg: '16px',\n xl: '20px',\n xxl: '24px',\n xxxl: '32px',\n },\n fontWeight: {\n light: '300',\n regular: '400',\n medium: '500',\n semibold: '600',\n bold: '700',\n },\n lineHeight: {\n tight: '1.25',\n normal: '1.5',\n relaxed: '1.75',\n },\n },\n borders: {\n radius: {\n sm: '6px',\n md: '8px',\n lg: '12px',\n xl: '16px',\n full: '9999px',\n },\n width: {\n thin: '1px',\n medium: '2px',\n thick: '3px',\n },\n },\n shadows: {\n sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',\n md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',\n lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',\n xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',\n inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',\n },\n transitions: {\n fast: '150ms ease-in-out',\n normal: '250ms ease-in-out',\n slow: '350ms ease-in-out',\n },\n overflow: 'auto', // Default overflow style\n // Default categorical palette for multi-series charts. Overridden per-theme\n // from the host's `--mj-viz-*` tokens by BuildStylesFromTheme().\n chartPalette: [\n '#2196F3', '#4CAF50', '#FF9800', '#E91E63', '#9C27B0',\n '#00BCD4', '#F44336', '#8BC34A', '#FF5722', '#3F51B5',\n ],\n // Default sequential (single-hue) intensity ramp, light-to-dark, for heatmaps\n // and density shading. Overridden per-theme from `--mj-viz-seq-*`.\n sequentialScale: [\n '#E3F2FD', '#BBDEFB', '#90CAF9', '#42A5F5', '#2196F3', '#1976D2', '#0D47A1',\n ],\n // Default diverging ramp for measures with a meaningful midpoint.\n // Overridden per-theme from `--mj-viz-div-*`.\n divergingScale: {\n low: '#F44336',\n mid: '#EEEEEE',\n high: '#4CAF50',\n },\n }\n}\n\n// Also export with the original name for backward compatibility\nexport const createDefaultComponentStyles = SetupStyles;\n\n/**\n * The `--mj-*` semantic token → `ComponentStyles` mapping used by the theme bridge.\n * Keys are ComponentStyles color paths; values are the CSS custom property to read.\n * Only theme-defining tokens with a clear semantic equivalent are mapped; every\n * other field keeps its `SetupStyles()` default.\n */\nconst THEME_COLOR_TOKEN_MAP: Record<string, string> = {\n // Brand / primary + interactive states\n primary: '--mj-brand-primary',\n primaryHover: '--mj-brand-primary-hover',\n primaryActive: '--mj-brand-primary-active',\n primaryLight: '--mj-brand-primary-light',\n // Secondary\n secondary: '--mj-brand-secondary',\n secondaryHover: '--mj-brand-secondary-hover',\n // Status\n success: '--mj-status-success',\n successLight: '--mj-status-success-bg',\n successText: '--mj-status-success-text',\n successBorder: '--mj-status-success-border',\n warning: '--mj-status-warning',\n warningLight: '--mj-status-warning-bg',\n warningText: '--mj-status-warning-text',\n warningBorder: '--mj-status-warning-border',\n error: '--mj-status-error',\n errorLight: '--mj-status-error-bg',\n errorText: '--mj-status-error-text',\n errorBorder: '--mj-status-error-border',\n info: '--mj-status-info',\n infoLight: '--mj-status-info-bg',\n infoText: '--mj-status-info-text',\n infoBorder: '--mj-status-info-border',\n // Surfaces (MJ: page = tinted, surface = elevated/white in light mode)\n background: '--mj-bg-page',\n surface: '--mj-bg-surface',\n surfaceHover: '--mj-bg-surface-hover',\n overlay: '--mj-bg-overlay',\n // Text\n text: '--mj-text-primary',\n textSecondary: '--mj-text-secondary',\n textTertiary: '--mj-text-muted',\n textInverse: '--mj-text-inverse',\n // Links\n link: '--mj-text-link',\n linkHover: '--mj-text-link-hover',\n // Borders / focus\n border: '--mj-border-default',\n borderLight: '--mj-border-subtle',\n borderFocus: '--mj-border-focus',\n};\n\n/** Number of `--mj-viz-N` categorical tokens the bridge probes for `chartPalette`. */\nconst VIZ_TOKEN_COUNT = 10;\n\n/** Number of `--mj-viz-seq-N` tokens the bridge probes for `sequentialScale`. */\nconst VIZ_SEQ_TOKEN_COUNT = 7;\n\n/**\n * Reads the live MJ theme (`--mj-*` custom properties on the document root) and\n * layers it over `SetupStyles()`, producing a `ComponentStyles` that follows the\n * host's active theme — including dark mode and interactive-state (hover/active/\n * focus) families — instead of the frozen default palette. This is the Phase 1\n * theme bridge that gives generated components shell↔content cohesion.\n *\n * DOM-guarded: in non-DOM environments (Node test harness, SSR) there is no\n * computed theme to read, so it returns `SetupStyles()` unchanged. Any individual\n * token that is absent falls back to its `SetupStyles()` default, so a page\n * without MJ tokens loaded also degrades cleanly.\n *\n * @param root optional element to read tokens from (defaults to document root).\n */\nexport function BuildStylesFromTheme(root?: Element): ComponentStyles {\n const base = SetupStyles();\n\n const el = root ?? (typeof document !== 'undefined' ? document.documentElement : undefined);\n if (!el || typeof getComputedStyle === 'undefined') {\n return base;\n }\n\n const cs = getComputedStyle(el);\n const read = (token: string): string => cs.getPropertyValue(token).trim();\n\n for (const [path, token] of Object.entries(THEME_COLOR_TOKEN_MAP)) {\n const value = read(token);\n if (value) {\n base.colors[path] = value;\n }\n }\n\n const palette: string[] = [];\n for (let i = 1; i <= VIZ_TOKEN_COUNT; i++) {\n const value = read(`--mj-viz-${i}`);\n if (value) {\n palette.push(value);\n }\n }\n if (palette.length > 0) {\n base.chartPalette = palette;\n }\n\n const sequential: string[] = [];\n for (let i = 1; i <= VIZ_SEQ_TOKEN_COUNT; i++) {\n const value = read(`--mj-viz-seq-${i}`);\n if (value) {\n sequential.push(value);\n }\n }\n // A ramp needs at least two stops to interpolate; a single resolved token is\n // treated as an incomplete theme and left on the default.\n if (sequential.length > 1) {\n base.sequentialScale = sequential;\n }\n\n // Endpoints are required for a diverging scale to mean anything; `mid` is\n // optional, so only the low/high pair gates the swap.\n const divLow = read('--mj-viz-div-low');\n const divHigh = read('--mj-viz-div-high');\n if (divLow && divHigh) {\n const divMid = read('--mj-viz-div-mid');\n base.divergingScale = divMid ? { low: divLow, mid: divMid, high: divHigh } : { low: divLow, high: divHigh };\n }\n\n return base;\n}\n\n/** Multipliers applied to the whole `fontSize` ladder per `StyleOverrides.fontScale`. */\nconst FONT_SCALE_FACTOR: Record<string, number> = { small: 0.875, large: 1.25 };\n\n/** Smallest px size the scale may produce, so `small` cannot render text illegible. */\nconst MIN_FONT_SIZE_PX = 10;\n\n/**\n * Rescales every px value in a `fontSize` token map, leaving anything not expressed\n * in whole px (rem, em, clamp(), a keyword) untouched rather than guessing at it.\n */\nfunction scaleFontSizes(fontSize: Record<string, string | undefined>, factor: number): Record<string, string | undefined> {\n const scaled: Record<string, string | undefined> = {};\n for (const [key, value] of Object.entries(fontSize)) {\n const px = typeof value === 'string' ? /^\\s*(\\d+(?:\\.\\d+)?)px\\s*$/.exec(value) : null;\n scaled[key] = px\n ? `${Math.max(MIN_FONT_SIZE_PX, Math.round(parseFloat(px[1]) * factor))}px`\n : value;\n }\n return scaled;\n}\n\n/**\n * Layers explicitly user-requested styling (`ComponentSpec.styleOverrides`) over\n * theme-resolved styles, producing the `styles` a component actually receives.\n *\n * This is what lets \"make the charts blue\" be honored without a color literal ever\n * entering generated code: the request is carried as spec data and resolved here,\n * above the org theme, so the component keeps reading `styles.chartPalette` and\n * friends. Of the color slots only visualization ones are merged — the override\n * contract deliberately has no background/text/border slots, since those cannot be\n * flipped for dark mode without derived per-mode variants.\n *\n * `fontScale` is the one non-color slot, and it rescales the `typography.fontSize`\n * ladder in place. Doing it here rather than in the generator is what makes a type\n * scale hold: every token moves at once, so text inside registry components and\n * third-party libraries scales along with the generated markup.\n *\n * Returns `base` unchanged when there are no overrides, and never mutates `base`.\n *\n * @param base theme-resolved styles (from `BuildStylesFromTheme()` or `SetupStyles()`)\n * @param overrides the spec's `styleOverrides`, if any\n */\nexport function ApplyStyleOverrides<T extends Partial<ComponentStyles>>(base: T, overrides?: StyleOverrides): T {\n if (!overrides) {\n return base;\n }\n\n const hasChartPalette = Array.isArray(overrides.chartPalette) && overrides.chartPalette.length > 0;\n // A ramp needs at least two stops to interpolate between.\n const hasSequential = Array.isArray(overrides.sequentialScale) && overrides.sequentialScale.length > 1;\n const hasDiverging = !!overrides.divergingScale?.low && !!overrides.divergingScale?.high;\n // 'normal' — and any unrecognized value — leaves the ladder alone.\n const fontFactor = overrides.fontScale ? FONT_SCALE_FACTOR[overrides.fontScale] : undefined;\n const hasFontScale = !!fontFactor && !!base.typography?.fontSize;\n\n if (!hasChartPalette && !hasSequential && !hasDiverging && !hasFontScale) {\n return base;\n }\n\n return {\n ...base,\n ...(hasChartPalette ? { chartPalette: overrides.chartPalette } : {}),\n ...(hasSequential ? { sequentialScale: overrides.sequentialScale } : {}),\n ...(hasDiverging ? { divergingScale: overrides.divergingScale } : {}),\n ...(hasFontScale\n ? { typography: { ...base.typography!, fontSize: scaleFontSizes(base.typography!.fontSize, fontFactor!) } }\n : {}),\n };\n}"]}
|
package/package.json
CHANGED
|
@@ -1,20 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/react-runtime",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.1.0-edge.1",
|
|
4
4
|
"description": "Platform-agnostic React component runtime for MemberJunction. Provides core compilation, registry, and execution capabilities for React components in any JavaScript environment.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
-
"scripts": {
|
|
9
|
-
"build": "npm run build:node && npm run build:umd",
|
|
10
|
-
"build:node": "tsc && tsc-alias -f",
|
|
11
|
-
"build:umd": "webpack --config webpack.umd.config.cjs",
|
|
12
|
-
"build:clean": "rimraf ./dist && npm run build",
|
|
13
|
-
"watch": "tsc -w",
|
|
14
|
-
"patchVersion": "npm version patch",
|
|
15
|
-
"test": "vitest run",
|
|
16
|
-
"test:watch": "vitest"
|
|
17
|
-
},
|
|
18
8
|
"keywords": [
|
|
19
9
|
"memberjunction",
|
|
20
10
|
"react",
|
|
@@ -29,11 +19,11 @@
|
|
|
29
19
|
},
|
|
30
20
|
"homepage": "https://github.com/MemberJunction/MJ#readme",
|
|
31
21
|
"dependencies": {
|
|
32
|
-
"@memberjunction/core": "
|
|
33
|
-
"@memberjunction/global": "
|
|
34
|
-
"@memberjunction/interactive-component-types": "
|
|
35
|
-
"@memberjunction/core-entities": "
|
|
36
|
-
"@memberjunction/graphql-dataprovider": "
|
|
22
|
+
"@memberjunction/core": "6.1.0-edge.1",
|
|
23
|
+
"@memberjunction/global": "6.1.0-edge.1",
|
|
24
|
+
"@memberjunction/interactive-component-types": "6.1.0-edge.1",
|
|
25
|
+
"@memberjunction/core-entities": "6.1.0-edge.1",
|
|
26
|
+
"@memberjunction/graphql-dataprovider": "6.1.0-edge.1",
|
|
37
27
|
"@babel/standalone": "^7.29.1",
|
|
38
28
|
"rxjs": "^7.8.2"
|
|
39
29
|
},
|
|
@@ -52,5 +42,15 @@
|
|
|
52
42
|
"repository": {
|
|
53
43
|
"type": "git",
|
|
54
44
|
"url": "https://github.com/MemberJunction/MJ"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "npm run build:node && npm run build:umd",
|
|
48
|
+
"build:node": "tsc && tsc-alias -f",
|
|
49
|
+
"build:umd": "webpack --config webpack.umd.config.cjs",
|
|
50
|
+
"build:clean": "rimraf ./dist && npm run build",
|
|
51
|
+
"watch": "tsc -w",
|
|
52
|
+
"patchVersion": "npm version patch",
|
|
53
|
+
"test": "vitest run",
|
|
54
|
+
"test:watch": "vitest"
|
|
55
55
|
}
|
|
56
|
-
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach } from 'vitest';
|
|
2
|
+
import { ComponentStyles, StyleOverrides } from '@memberjunction/interactive-component-types';
|
|
3
|
+
import { SetupStyles, BuildStylesFromTheme, ApplyStyleOverrides } from '../utilities/component-styles';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Installs a `getComputedStyle` stub resolving the given token map, so the theme
|
|
7
|
+
* bridge can be exercised in the node test environment (which has no DOM).
|
|
8
|
+
* Returns a throwaway element to pass as the bridge's `root`.
|
|
9
|
+
*/
|
|
10
|
+
function stubTheme(tokens: Record<string, string>): Element {
|
|
11
|
+
(globalThis as Record<string, unknown>).getComputedStyle = () => ({
|
|
12
|
+
getPropertyValue: (token: string) => tokens[token] ?? '',
|
|
13
|
+
});
|
|
14
|
+
return {} as Element;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
delete (globalThis as Record<string, unknown>).getComputedStyle;
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe('SetupStyles visualization defaults', () => {
|
|
22
|
+
it('ships a multi-stop sequential ramp', () => {
|
|
23
|
+
const scale = SetupStyles().sequentialScale;
|
|
24
|
+
expect(scale && scale.length).toBeGreaterThan(1);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('ships a diverging ramp with both endpoints', () => {
|
|
28
|
+
const diverging = SetupStyles().divergingScale;
|
|
29
|
+
expect(diverging?.low).toBeTruthy();
|
|
30
|
+
expect(diverging?.high).toBeTruthy();
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe('SetupStyles overlay and status defaults', () => {
|
|
35
|
+
it('ships an overlay scrim and status text/border colors', () => {
|
|
36
|
+
const colors = SetupStyles().colors;
|
|
37
|
+
expect(colors.overlay).toBeTruthy();
|
|
38
|
+
for (const key of [
|
|
39
|
+
'successText', 'successBorder',
|
|
40
|
+
'warningText', 'warningBorder',
|
|
41
|
+
'errorText', 'errorBorder',
|
|
42
|
+
'infoText', 'infoBorder',
|
|
43
|
+
]) {
|
|
44
|
+
expect(colors[key]).toBeTruthy();
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('BuildStylesFromTheme visualization ramps', () => {
|
|
50
|
+
it('populates both ramps from --mj-viz-seq-* / --mj-viz-div-* tokens', () => {
|
|
51
|
+
const root = stubTheme({
|
|
52
|
+
'--mj-viz-seq-1': '#eef', '--mj-viz-seq-2': '#99f', '--mj-viz-seq-3': '#22a',
|
|
53
|
+
'--mj-viz-div-low': '#c00', '--mj-viz-div-mid': '#eee', '--mj-viz-div-high': '#0c0',
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const styles = BuildStylesFromTheme(root);
|
|
57
|
+
|
|
58
|
+
expect(styles.sequentialScale).toEqual(['#eef', '#99f', '#22a']);
|
|
59
|
+
expect(styles.divergingScale).toEqual({ low: '#c00', mid: '#eee', high: '#0c0' });
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('omits mid when the theme does not define it', () => {
|
|
63
|
+
const root = stubTheme({ '--mj-viz-div-low': '#c00', '--mj-viz-div-high': '#0c0' });
|
|
64
|
+
|
|
65
|
+
expect(BuildStylesFromTheme(root).divergingScale).toEqual({ low: '#c00', high: '#0c0' });
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('keeps the default ramp when only one sequential stop resolves', () => {
|
|
69
|
+
// A single stop cannot be interpolated, so a partially-themed page should
|
|
70
|
+
// fall back rather than render a one-color "ramp".
|
|
71
|
+
const root = stubTheme({ '--mj-viz-seq-1': '#eef' });
|
|
72
|
+
|
|
73
|
+
expect(BuildStylesFromTheme(root).sequentialScale).toEqual(SetupStyles().sequentialScale);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('keeps the default diverging ramp when an endpoint is missing', () => {
|
|
77
|
+
const root = stubTheme({ '--mj-viz-div-low': '#c00' });
|
|
78
|
+
|
|
79
|
+
expect(BuildStylesFromTheme(root).divergingScale).toEqual(SetupStyles().divergingScale);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe('BuildStylesFromTheme overlay and status bridging', () => {
|
|
84
|
+
it('bridges the overlay scrim from --mj-bg-overlay', () => {
|
|
85
|
+
const root = stubTheme({ '--mj-bg-overlay': 'rgba(15, 23, 42, 0.5)' });
|
|
86
|
+
|
|
87
|
+
expect(BuildStylesFromTheme(root).colors.overlay).toBe('rgba(15, 23, 42, 0.5)');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('bridges status text and border tokens', () => {
|
|
91
|
+
const root = stubTheme({
|
|
92
|
+
'--mj-status-success-text': '#0a7d43',
|
|
93
|
+
'--mj-status-error-border': '#f5c2c0',
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const styles = BuildStylesFromTheme(root);
|
|
97
|
+
|
|
98
|
+
expect(styles.colors.successText).toBe('#0a7d43');
|
|
99
|
+
expect(styles.colors.errorBorder).toBe('#f5c2c0');
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('bridges the secondary palette from --mj-brand-secondary tokens', () => {
|
|
103
|
+
const root = stubTheme({
|
|
104
|
+
'--mj-brand-secondary': '#092340',
|
|
105
|
+
'--mj-brand-secondary-hover': '#004a71',
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const styles = BuildStylesFromTheme(root);
|
|
109
|
+
|
|
110
|
+
expect(styles.colors.secondary).toBe('#092340');
|
|
111
|
+
expect(styles.colors.secondaryHover).toBe('#004a71');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('keeps the defaults when the tokens are absent', () => {
|
|
115
|
+
const root = stubTheme({});
|
|
116
|
+
const styles = BuildStylesFromTheme(root);
|
|
117
|
+
const defaults = SetupStyles().colors;
|
|
118
|
+
|
|
119
|
+
expect(styles.colors.overlay).toBe(defaults.overlay);
|
|
120
|
+
expect(styles.colors.warningText).toBe(defaults.warningText);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe('ApplyStyleOverrides', () => {
|
|
125
|
+
const base = (): ComponentStyles => SetupStyles();
|
|
126
|
+
const userRequest = (partial: Partial<StyleOverrides>): StyleOverrides =>
|
|
127
|
+
({ ...partial, source: 'user-request' });
|
|
128
|
+
|
|
129
|
+
it('returns the base untouched when there are no overrides', () => {
|
|
130
|
+
const input = base();
|
|
131
|
+
expect(ApplyStyleOverrides(input, undefined)).toBe(input);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('returns the base untouched when no slot carries a usable value', () => {
|
|
135
|
+
const input = base();
|
|
136
|
+
expect(ApplyStyleOverrides(input, userRequest({ chartPalette: [] }))).toBe(input);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('replaces the chart palette with the requested colors', () => {
|
|
140
|
+
const styles = ApplyStyleOverrides(base(), userRequest({ chartPalette: ['#00f', '#fc0'] }));
|
|
141
|
+
expect(styles.chartPalette).toEqual(['#00f', '#fc0']);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('replaces the diverging ramp for a red-to-green request', () => {
|
|
145
|
+
const styles = ApplyStyleOverrides(base(), userRequest({ divergingScale: { low: '#f00', high: '#0f0' } }));
|
|
146
|
+
expect(styles.divergingScale).toEqual({ low: '#f00', high: '#0f0' });
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('ignores a diverging override missing an endpoint', () => {
|
|
150
|
+
const overrides = userRequest({ divergingScale: { low: '#f00', high: '' } });
|
|
151
|
+
expect(ApplyStyleOverrides(base(), overrides).divergingScale).toEqual(SetupStyles().divergingScale);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('ignores a single-stop sequential override', () => {
|
|
155
|
+
const styles = ApplyStyleOverrides(base(), userRequest({ sequentialScale: ['#00f'] }));
|
|
156
|
+
expect(styles.sequentialScale).toEqual(SetupStyles().sequentialScale);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('leaves non-visualization tokens alone', () => {
|
|
160
|
+
const input = base();
|
|
161
|
+
const styles = ApplyStyleOverrides(input, userRequest({ chartPalette: ['#00f'] }));
|
|
162
|
+
expect(styles.colors.primary).toBe(input.colors.primary);
|
|
163
|
+
expect(styles.typography.fontFamily).toBe(input.typography.fontFamily);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('does not mutate the base styles', () => {
|
|
167
|
+
const input = base();
|
|
168
|
+
const original = [...(input.chartPalette ?? [])];
|
|
169
|
+
ApplyStyleOverrides(input, userRequest({ chartPalette: ['#00f', '#fc0'] }));
|
|
170
|
+
expect(input.chartPalette).toEqual(original);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('applies overrides over theme-bridged styles, not just defaults', () => {
|
|
174
|
+
const root = stubTheme({ '--mj-viz-1': '#111', '--mj-viz-2': '#222' });
|
|
175
|
+
const themed = BuildStylesFromTheme(root);
|
|
176
|
+
|
|
177
|
+
const styles = ApplyStyleOverrides(themed, userRequest({ chartPalette: ['#00f'] }));
|
|
178
|
+
|
|
179
|
+
expect(styles.chartPalette).toEqual(['#00f']);
|
|
180
|
+
// The theme still supplies everything the user did not ask about.
|
|
181
|
+
expect(styles.colors.primary).toBe(themed.colors.primary);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
describe('ApplyStyleOverrides fontScale', () => {
|
|
186
|
+
const orgDefault = (partial: Partial<StyleOverrides>): StyleOverrides =>
|
|
187
|
+
({ ...partial, source: 'organization-default' });
|
|
188
|
+
|
|
189
|
+
it('scales every fontSize token up together for large', () => {
|
|
190
|
+
// The point of doing this here rather than in the generator: one factor, whole ladder.
|
|
191
|
+
const styles = ApplyStyleOverrides(SetupStyles(), orgDefault({ fontScale: 'large' }));
|
|
192
|
+
expect(styles.typography.fontSize).toEqual({
|
|
193
|
+
xs: '14px', sm: '15px', md: '18px', lg: '20px', xl: '25px', xxl: '30px', xxxl: '40px',
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('scales every fontSize token down together for small', () => {
|
|
198
|
+
const styles = ApplyStyleOverrides(SetupStyles(), orgDefault({ fontScale: 'small' }));
|
|
199
|
+
expect(styles.typography.fontSize).toEqual({
|
|
200
|
+
xs: '10px', sm: '11px', md: '12px', lg: '14px', xl: '18px', xxl: '21px', xxxl: '28px',
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('treats normal as no override at all', () => {
|
|
205
|
+
const input = SetupStyles();
|
|
206
|
+
expect(ApplyStyleOverrides(input, orgDefault({ fontScale: 'normal' }))).toBe(input);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('ignores an unrecognized scale rather than guessing a factor', () => {
|
|
210
|
+
const input = SetupStyles();
|
|
211
|
+
const overrides = orgDefault({ fontScale: 'huge' as unknown as 'large' });
|
|
212
|
+
expect(ApplyStyleOverrides(input, overrides)).toBe(input);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it('holds a floor so small cannot render text illegible', () => {
|
|
216
|
+
const base = SetupStyles();
|
|
217
|
+
base.typography.fontSize = { xs: '9px', sm: '12px', md: '14px', lg: '16px', xl: '20px' };
|
|
218
|
+
const styles = ApplyStyleOverrides(base, orgDefault({ fontScale: 'small' }));
|
|
219
|
+
expect(styles.typography.fontSize.xs).toBe('10px');
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('leaves sizes not expressed in px alone rather than guessing', () => {
|
|
223
|
+
const base = SetupStyles();
|
|
224
|
+
base.typography.fontSize = { sm: '0.875rem', md: '14px', lg: 'clamp(1rem, 2vw, 2rem)', xl: '20px' };
|
|
225
|
+
const styles = ApplyStyleOverrides(base, orgDefault({ fontScale: 'large' }));
|
|
226
|
+
expect(styles.typography.fontSize).toEqual({
|
|
227
|
+
sm: '0.875rem', md: '18px', lg: 'clamp(1rem, 2vw, 2rem)', xl: '25px',
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('keeps fontFamily, weights, spacing and colors untouched', () => {
|
|
232
|
+
const input = SetupStyles();
|
|
233
|
+
const styles = ApplyStyleOverrides(input, orgDefault({ fontScale: 'large' }));
|
|
234
|
+
expect(styles.typography.fontFamily).toBe(input.typography.fontFamily);
|
|
235
|
+
expect(styles.typography.fontWeight).toEqual(input.typography.fontWeight);
|
|
236
|
+
expect(styles.spacing).toEqual(input.spacing);
|
|
237
|
+
expect(styles.colors.primary).toBe(input.colors.primary);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('does not mutate the base ladder', () => {
|
|
241
|
+
const input = SetupStyles();
|
|
242
|
+
ApplyStyleOverrides(input, orgDefault({ fontScale: 'large' }));
|
|
243
|
+
expect(input.typography.fontSize.md).toBe('14px');
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('combines with a color override in one pass', () => {
|
|
247
|
+
const styles = ApplyStyleOverrides(
|
|
248
|
+
SetupStyles(), orgDefault({ fontScale: 'small', chartPalette: ['#00f', '#fc0'] }));
|
|
249
|
+
expect(styles.chartPalette).toEqual(['#00f', '#fc0']);
|
|
250
|
+
expect(styles.typography.fontSize.md).toBe('12px');
|
|
251
|
+
});
|
|
252
|
+
});
|