UNPKG

mdui

Version:

实现 material you 设计规范的 Web Components 组件库

134 lines (130 loc) 5.35 kB
import { blueFromArgb, greenFromArgb, redFromArgb, customColor, argbFromHex, Scheme, CorePalette, } from '@material/material-color-utilities'; import { getDocument } from 'ssr-window'; import { $ } from '@mdui/jq/$.js'; import { unique } from '@mdui/jq/functions/unique.js'; import '@mdui/jq/methods/addClass.js'; import '@mdui/jq/methods/append.js'; import '@mdui/jq/methods/get.js'; import '@mdui/jq/methods/remove.js'; import '@mdui/jq/methods/removeClass.js'; import { toKebabCase } from '@mdui/jq/shared/helper.js'; const themeArr = ['light', 'dark']; const prefix = 'mdui-custom-color-scheme-'; // 类名前缀 let themeIndex = 0; const rgbFromArgb = (source) => { const red = redFromArgb(source); const green = greenFromArgb(source); const blue = blueFromArgb(source); return [red, green, blue].join(', '); }; /** * 移除指定元素上的配色方案 * @param target */ export const remove = (target) => { const $target = $(target); // 找出指定元素上所有的配色方案 CSS class let classNames = $target .get() .map((element) => Array.from(element.classList)) .flat(); classNames = unique(classNames).filter((className) => className.startsWith(prefix)); // 移除 CSS class $target.removeClass(classNames.join(' ')); // 找出没有被其他元素使用的 CSS class const unusedClassNames = classNames.filter((className) => $(`.${className}`).length === 0); // 移除对应的 <style> 元素 $(unusedClassNames.map((i) => `#${i}`).join(',')).remove(); }; /** * 设置配色方案 * 在 head 中插入一个 <style id="mdui-custom-color-scheme-${source}"> 元素, * 并在 target 元素上添加 class="mdui-custom-color-scheme-${source}" * * 自定义颜色的 css 变量 * --mdui-color-red * --mdui-color-on-red * --mdui-color-red-container * --mdui-color-on-red-container * * @param source * @param options */ export const setFromSource = (source, options) => { const document = getDocument(); const $target = $(options?.target || document.documentElement); // 生成配色方案 const schemes = { light: Scheme.light(source).toJSON(), dark: Scheme.dark(source).toJSON(), }; // todo 目前 @material/material-color-utilities 库缺失了 8 种颜色,等官方库加上后,可以删除这段代码 // https://github.com/material-foundation/material-color-utilities/issues/98 const palette = CorePalette.of(source); Object.assign(schemes.light, { 'surface-dim': palette.n1.tone(87), 'surface-bright': palette.n1.tone(98), 'surface-container-lowest': palette.n1.tone(100), 'surface-container-low': palette.n1.tone(96), 'surface-container': palette.n1.tone(94), 'surface-container-high': palette.n1.tone(92), 'surface-container-highest': palette.n1.tone(90), 'surface-tint-color': schemes.light.primary, }); Object.assign(schemes.dark, { 'surface-dim': palette.n1.tone(6), 'surface-bright': palette.n1.tone(24), 'surface-container-lowest': palette.n1.tone(4), 'surface-container-low': palette.n1.tone(10), 'surface-container': palette.n1.tone(12), 'surface-container-high': palette.n1.tone(17), 'surface-container-highest': palette.n1.tone(22), 'surface-tint-color': schemes.dark.primary, }); // 扩充自定义颜色 (options?.customColors || []).map((color) => { const name = toKebabCase(color.name); const custom = customColor(source, { name, value: argbFromHex(color.value), blend: true, }); themeArr.forEach((theme) => { schemes[theme][name] = custom[theme].color; schemes[theme][`on-${name}`] = custom[theme].onColor; schemes[theme][`${name}-container`] = custom[theme].colorContainer; schemes[theme][`on-${name}-container`] = custom[theme].onColorContainer; }); }); // 根据配色方案生成 css 变量 const colorVar = (theme, callback) => { return Object.entries(schemes[theme]) .map(([key, value]) => callback(toKebabCase(key), rgbFromArgb(value))) .join(''); }; const className = prefix + `${source}-${themeIndex++}`; // CSS 文本 const cssText = `.${className} { ${colorVar('light', (token, rgb) => `--mdui-color-${token}-light: ${rgb};`)} ${colorVar('dark', (token, rgb) => `--mdui-color-${token}-dark: ${rgb};`)} ${colorVar('light', (token) => `--mdui-color-${token}: var(--mdui-color-${token}-light);`)} color: rgb(var(--mdui-color-on-background)); background-color: rgb(var(--mdui-color-background)); } .mdui-theme-dark .${className}, .mdui-theme-dark.${className} { ${colorVar('dark', (token) => `--mdui-color-${token}: var(--mdui-color-${token}-dark);`)} } @media (prefers-color-scheme: dark) { .mdui-theme-auto .${className}, .mdui-theme-auto.${className} { ${colorVar('dark', (token) => `--mdui-color-${token}: var(--mdui-color-${token}-dark);`)} } }`; // 移除旧的配色方案 remove($target); // 创建 <style> 元素,添加到 head 中 $(document.head).append(`<style id="${className}">${cssText}</style>`); // 添加新配色方案 $target.addClass(className); };