UNPKG

@poupe/material-color-utilities

Version:

Algorithms and utilities that power the Material Design 3 (M3) color system, including choosing theme colors from images and creating tones of colors; all in a new color space.

128 lines 4.26 kB
/** * @license * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { Blend } from '../blend/blend.js'; import { CorePalette } from '../palettes/core_palette.js'; import { Scheme } from '../scheme/scheme.js'; import { sourceColorFromImage } from './image_utils.js'; import { hexFromArgb } from './string_utils.js'; /** * Generate a theme from a source color * * @param source Source color * @param customColors Array of custom colors * @return Theme object */ export function themeFromSourceColor(source, customColors = []) { const palette = CorePalette.of(source); return { source, schemes: { light: Scheme.light(source), dark: Scheme.dark(source), }, palettes: { primary: palette.a1, secondary: palette.a2, tertiary: palette.a3, neutral: palette.n1, neutralVariant: palette.n2, error: palette.error, }, customColors: customColors.map((c) => customColor(source, c)), }; } /** * Generate a theme from an image source * * @param image Image element * @param customColors Array of custom colors * @return Theme object */ export async function themeFromImage(image, customColors = []) { const source = await sourceColorFromImage(image); return themeFromSourceColor(source, customColors); } /** * Generate custom color group from source and target color * * @param source Source color * @param color Custom color * @return Custom color group * * @link https://m3.material.io/styles/color/the-color-system/color-roles */ export function customColor(source, color) { let value = color.value; const from = value; const to = source; if (color.blend) { value = Blend.harmonize(from, to); } const palette = CorePalette.of(value); const tones = palette.a1; return { color, value, light: { color: tones.tone(40), onColor: tones.tone(100), colorContainer: tones.tone(90), onColorContainer: tones.tone(10), }, dark: { color: tones.tone(80), onColor: tones.tone(20), colorContainer: tones.tone(30), onColorContainer: tones.tone(90), }, }; } /** * Apply a theme to an element * * @param theme Theme object * @param options Options */ export function applyTheme(theme, options) { const target = options?.target || document.body; const isDark = options?.dark ?? false; const scheme = isDark ? theme.schemes.dark : theme.schemes.light; setSchemeProperties(target, scheme); if (options?.brightnessSuffix) { setSchemeProperties(target, theme.schemes.dark, '-dark'); setSchemeProperties(target, theme.schemes.light, '-light'); } if (options?.paletteTones) { const tones = options?.paletteTones ?? []; for (const [key, palette] of Object.entries(theme.palettes)) { const paletteKey = key.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); for (const tone of tones) { const token = `--md-ref-palette-${paletteKey}-${paletteKey}${tone}`; const color = hexFromArgb(palette.tone(tone)); target.style.setProperty(token, color); } } } } function setSchemeProperties(target, scheme, suffix = '') { for (const [key, value] of Object.entries(scheme.toJSON())) { const token = key.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); const color = hexFromArgb(value); target.style.setProperty(`--md-sys-color-${token}${suffix}`, color); } } //# sourceMappingURL=theme_utils.js.map