UNPKG

@pchmn/expo-material3-theme

Version:

Manage Material 3 theme in your React Native App

125 lines 5.25 kB
import { argbFromHex, CorePalette, Hct, Scheme, SchemeFidelity, themeFromSourceColor as themeFromSourceColorOriginal, } from '@material/material-color-utilities'; import color from 'color'; const opacity = { level1: 0.08, level2: 0.12, level3: 0.16, level4: 0.38, }; const elevations = ['transparent', 0.05, 0.08, 0.11, 0.12, 0.14]; export function createThemeFromSystemSchemes(schemes) { const { light, dark, palettes } = generateSchemesFromSourceColor(schemes.light.primary); schemes = { light: { ...light, ...schemes.light }, dark: { ...dark, ...schemes.dark }, }; return { light: { ...schemes.light, ...generateMissingFields(schemes.light, palettes, 'light') }, dark: { ...schemes.dark, ...generateMissingFields(schemes.dark, palettes, 'dark') }, }; } export function createThemeFromSourceColor(sourceColor, options) { const { light, dark, palettes } = generateSchemesFromSourceColor(sourceColor, options); return { light: { ...light, ...generateMissingFields(light, palettes, 'light') }, dark: { ...dark, ...generateMissingFields(dark, palettes, 'dark') }, }; } function generateMissingFields(scheme, palettes, colorScheme) { const elevation = elevations.reduce((acc, value, index) => ({ ...acc, [`level${index}`]: index === 0 ? value : color(scheme.surface).mix(color(scheme.primary), Number(value)).hex(), }), {}); const customColors = { surfaceDisabled: color(scheme.onSurface).alpha(opacity.level2).rgb().string(), onSurfaceDisabled: color(scheme.onSurface).alpha(opacity.level4).rgb().string(), backdrop: color(palettes.neutralVariant.tone(20)).alpha(0.4).rgb().string(), surfaceContainer: color(palettes.neutral.tone(colorScheme === 'dark' ? 12 : 94)).hex(), surfaceContainerLow: color(palettes.neutral.tone(colorScheme === 'dark' ? 10 : 96)).hex(), surfaceContainerLowest: color(palettes.neutral.tone(colorScheme === 'dark' ? 4 : 100)).hex(), surfaceContainerHigh: color(palettes.neutral.tone(colorScheme === 'dark' ? 17 : 92)).hex(), surfaceContainerHighest: color(palettes.neutral.tone(colorScheme === 'dark' ? 22 : 90)).hex(), surfaceBright: color(palettes.neutral.tone(colorScheme === 'dark' ? 24 : 98)).hex(), surfaceDim: color(palettes.neutral.tone(colorScheme === 'dark' ? 6 : 87)).hex(), surfaceTint: scheme.primary, }; return { elevation, ...customColors }; } function generateSchemesFromSourceColor(sourceColor, options) { const { schemes, palettes } = themeFromSourceColor(argbFromHex(sourceColor), options); return { light: transformScheme(schemes.light), dark: transformScheme(schemes.dark), palettes, }; } function transformScheme(scheme) { const jsonScheme = schemeToJson(scheme); return Object.entries(jsonScheme).reduce((acc, [key, value]) => { return { ...acc, [key]: color(value).hex(), }; }, {}); } function schemeToJson(scheme) { if (scheme instanceof Scheme) { return scheme.toJSON(); } return { primary: scheme.primary, onPrimary: scheme.onPrimary, primaryContainer: scheme.primaryContainer, onPrimaryContainer: scheme.onPrimaryContainer, secondary: scheme.secondary, onSecondary: scheme.onSecondary, secondaryContainer: scheme.secondaryContainer, onSecondaryContainer: scheme.onSecondaryContainer, tertiary: scheme.tertiary, onTertiary: scheme.onTertiary, tertiaryContainer: scheme.tertiaryContainer, onTertiaryContainer: scheme.onTertiaryContainer, error: scheme.error, onError: scheme.onError, errorContainer: scheme.errorContainer, onErrorContainer: scheme.onErrorContainer, background: scheme.background, onBackground: scheme.onBackground, surface: scheme.surface, onSurface: scheme.onSurface, surfaceVariant: scheme.surfaceVariant, onSurfaceVariant: scheme.onSurfaceVariant, outline: scheme.outline, outlineVariant: scheme.outlineVariant, shadow: scheme.shadow, scrim: scheme.scrim, inverseSurface: scheme.inverseSurface, inverseOnSurface: scheme.inverseOnSurface, inversePrimary: scheme.inversePrimary, }; } function themeFromSourceColor(sourceColor, options) { const { colorFidelity } = options || {}; const sourceColorHct = Hct.fromInt(sourceColor); if (!colorFidelity) { return themeFromSourceColorOriginal(sourceColor); } const palette = CorePalette.of(sourceColor); const lightScheme = new SchemeFidelity(sourceColorHct, false, 0); const darkScheme = new SchemeFidelity(sourceColorHct, true, 0); return { schemes: { light: lightScheme, dark: darkScheme, }, palettes: { primary: palette.a1, secondary: palette.a2, tertiary: palette.a3, neutral: palette.n1, neutralVariant: palette.n2, error: palette.error, }, }; } //# sourceMappingURL=createMaterial3Theme.js.map