UNPKG

wave-ui

Version:

A UI framework for Vue.js 3 (and 2) with only the bright side. :sunny:

624 lines (595 loc) 22.6 kB
import { consoleError } from './console' /** * Generates the color shades for each custom color and status colors for the current theme (only), * and save it in the config object. * * @param {Object} config */ export const generateColorShades = config => { // Add color shades for each custom color and status color of each theme. ['light', 'dark'].forEach(theme => { const themeOfColors = config.colors[theme] themeOfColors.shades = {} for (const label in themeOfColors) { if (label === 'shades') continue // Skip if item is the `shades` container. // Account for string colors and the fine tuned shaded colors. const colorInfo = themeOfColors[label] const color = { label, color: (themeOfColors[label]?.color ?? themeOfColors[label])?.replace?.('#', '') } const col = color.color if (!col) continue // Don't break if a color is only set for one of the themes. if (col.length === 3) color.color = col[0] + '' + col[0] + col[1] + col[1] + col[2] + col[2] for (let i = 1; i <= 6; i++) { const lighterColor = lighten(`#${color.color}`, i * (colorInfo?.lightIncrement ?? 16) + (colorInfo?.lightOffset ?? 0)) const darkerColor = darken(`#${color.color}`, i * (colorInfo?.darkIncrement ?? 12.4) + (colorInfo?.darkOffset ?? 0)) // Adding the shades to the config object to generate the CSS from w-app. themeOfColors.shades[`${color.label}-light${i}`] = lighterColor themeOfColors.shades[`${color.label}-dark${i}`] = darkerColor } } }) } export const flattenColors = (themeColors, colorPalette) => { const colors = { ...colorPalette.reduce((obj, color) => { obj[color.label] = color.color const shades = (color.shades || []).reduce((obj, color) => { obj[color.label] = color.color return obj }, {}) return { ...obj, ...shades } }, { ...themeColors, ...themeColors.shades }) } delete colors.shades return colors } /** * Clamp a value between a minimum and maximum value. * * @param {number} value - Value to clamp * @param {number} min - Minimum possible value * @param {number} max - Maximum possible value * @returns {number} The clamped value */ export function clamp (value, min, max) { return Math.min(Math.max(value, min), max) } /** * Convert a number to a hexadecimal string. * * @param {number} value - The number to convert * @throws {Error} - If the value is not in the range 0~255 * @returns {string} The hexadecimal string */ export function toHexString (value) { const trimmedValue = value.toString(16) return ( (trimmedValue.length === 1 && `0${trimmedValue}`) || (trimmedValue.length === 2 && trimmedValue) || consoleError(`expected value from 0~255, got: ${value}`) || '' ) } /** * Determines if a string is a valid hex color * * Valid long hex colors formats: * - #ffffff, * - #00000033 * * @param {string} str - The string to test * @returns {boolean} - Whether the string is a valid hex color */ export function isValidHex (str) { return /^#[0-9a-f]{6}([0-9a-f]{2})?$/i.test(str) } /** * Determines if a string is a short hex color * * Valid short hex colors formats: * - #fff, * - #0003 * * @param {string} str - The string to test * @returns {boolean} - Whether the string is a short hex color */ export function isShortHex (str) { return /^#[0-9a-f]{3}([0-9a-f])?$/i.test(str) } /** * Expands a short hex color to a full hex color * * @param {string} str - The short hex color to expand such as '#fff' or '#0003' with an alpha value * @returns {string} - The expanded hex color such as '#ffffff' or '#00000033' with an alpha value */ export function expandShortHex (str) { return `#${str.substring(1).split('').map(char => `${char}${char}`).join('')}` } /** * Parse a color string into a full length hex string * * @param {string} str - The color string to parse, either a full hex color or short hex color e.g. '#fff' or '#001122'. * This can also include an alpha value e.g. '#00112233' or '#0003'. * @throws {Error} - If the string is not a valid color * @returns {string} - The full parsed hex color for example, with alpha: '#00112233' */ function getColorFullHex (str) { return (isValidHex(str) && str) || (isShortHex(str) && expandShortHex(str)) || consoleError(`expected color hex string, got '${str}'`) || '' } /** * Break a hex color string into it's components * * @param {string} color - The color string to parse * @returns {{ red, green, blue, alpha, hasAlpha: boolean }} - The color components */ function getColorComponents (color) { const hex = getColorFullHex(color) const red = parseInt(hex.substring(1, 3), 16) const green = parseInt(hex.substring(3, 5), 16) const blue = parseInt(hex.substring(5, 7), 16) // Compare against length 9 because the full hex string will have the `#` at the beginning of it const alpha = hex.length === 9 ? parseInt(hex.substring(7, 9), 16) / 255 : 1.0 return { red, green, blue, alpha, hasAlpha: hex.length === 9 } } /** * Convert RGB components to a hex color string * * @param {number} r - red * @param {number} g - green * @param {number} b - blue * @param {number} [a] - alpha * @returns {string} - The hex color string for example: '#001122' or with alpha: '#00112233' */ export function hexFromRGB (r, g, b, a) { return `#${toHexString(r)}${toHexString(g)}${toHexString(b)}${a ? toHexString(Math.floor(a * 255)) : ''}` } /** * Mix two colors together. The same way that SCSS does it * * Valid hex colors formats: * - #fff * - #0003 * - #ffffff * - #00000033 * * @param {string} color1 - Color 1 as a hex * @param {string} color2 - Color 2 as a hex * @param {number} [weight] - The percentage to mix them at. Default: 50 * @returns {string} - The new mixed color as a hex for example: '#001122' or with alpha: '#00112233' * * @see https://gist.github.com/ktnyt/2573047b5b4c7c775f2be22326ebf6a8 for the original Typescript implementation */ export function mixColors (color1, color2, weight = 50) { const c1 = getColorComponents(color1) const c2 = getColorComponents(color2) const percentage = clamp(weight, 0, 100) / 100 const alphaWeight = 2 * percentage - 1 const alphaDiff = c1.alpha - c2.alpha const c1Weight = ( ( alphaWeight * alphaDiff === -1 ? alphaWeight : (alphaWeight + alphaDiff) / (1 + alphaWeight * alphaDiff) ) + 1 ) / 2 const c2Weight = 1 - c1Weight const red = clamp(Math.round(c1.red * c1Weight + c2.red * c2Weight), 0, 255) const green = clamp(Math.round(c1.green * c1Weight + c2.green * c2Weight), 0, 255) const blue = clamp(Math.round(c1.blue * c1Weight + c2.blue * c2Weight), 0, 255) const alpha = c1.alpha * percentage + c2.alpha * (1 - percentage) return c1.hasAlpha || c2.hasAlpha || alpha !== 1 ? hexFromRGB(red, green, blue, alpha) : hexFromRGB(red, green, blue) } /** * Lighten a color by a percentage * * Valid hex colors formats: * - #fff * - #0003 * - #ffffff * - #00000033 * * @param {string} color - The hex color to lighten * @param {number} [weight] - The amount to lighten by. * Default: `15` to match the SCSS `light-increment` value of `7.5` * the way the math is handled here we double the weight to match the SCSS result * @returns {string} - The new lightened color as a full hex string, potentially with alpha */ export function lighten (color, weight = 15) { return mixColors('#ffffff', color, weight) } /** * Darken a color by a percentage * * Valid hex colors formats: * - #fff * - #0003 * - #ffffff * - #00000033 * * @param {string} color - The hex color to darken * @param {number} [weight] - The amount to darken by. * Default: `12.4` to match the SCSS `dark-increment` value of `6.2` * the way the math is handled here we double the weight to match the SCSS result * @returns {string} - The new darkened color as a full hex string, potentially with alpha */ export function darken (color, weight = 12.4) { return mixColors('#000000', color, weight) } /** * Generate a color palette from a color info object * * @param {Record<string,{color: string, lightOffset: number, lightIncrement: number, darkOffset: number, darkIncrement: number}>} colorInfo - Colors to generate the palette from * @returns {Array<{label: string, color: string, shades: Array<{label: string, color: string}>}>} - The color palette */ export function generateColorPalette (colorInfo) { return Object.keys(colorInfo).map(label => { const color = colorInfo[label]?.color ?? colorInfo[label] return { label, color, shades: [6, 5, 4, 3, 2, 1, -1, -2, -3, -4, -5, -6].map(i => ({ label: `${label}-${i > 0 ? 'light' : 'dark'}${Math.abs(i)}`, color: i > 0 ? lighten(color, (i * (colorInfo[label]?.lightIncrement ?? 15)) - (colorInfo[label]?.lightOffset ?? 0)) : darken(color, (-i * (colorInfo[label]?.darkIncrement ?? 12.4)) - (colorInfo[label]?.darkOffset ?? 0)) })) } }) } export const colorPalette = [ { label: 'pink', color: '#e91e63', shades: [ { label: 'pink-light6', color: '#fdebf1' }, { label: 'pink-light5', color: '#faccdc' }, { label: 'pink-light4', color: '#f7adc6' }, { label: 'pink-light3', color: '#f48eb1' }, { label: 'pink-light2', color: '#f16f9b' }, { label: 'pink-light1', color: '#ee5085' }, { label: 'pink-dark1', color: '#d31555' }, { label: 'pink-dark2', color: '#b6124a' }, { label: 'pink-dark3', color: '#990f3e' }, { label: 'pink-dark4', color: '#7c0c32' }, { label: 'pink-dark5', color: '#600927' }, { label: 'pink-dark6', color: '#43071b' } ] }, { label: 'purple', color: '#a741b9', shades: [ { label: 'purple-light6', color: '#f9f2fa' }, { label: 'purple-light5', color: '#eed9f2' }, { label: 'purple-light4', color: '#e3c1e9' }, { label: 'purple-light3', color: '#d8a8e1' }, { label: 'purple-light2', color: '#cd90d8' }, { label: 'purple-light1', color: '#c277cf' }, { label: 'purple-dark1', color: '#9239a2' }, { label: 'purple-dark2', color: '#7d318a' }, { label: 'purple-dark3', color: '#682873' }, { label: 'purple-dark4', color: '#53205b' }, { label: 'purple-dark5', color: '#3d1844' }, { label: 'purple-dark6', color: '#28102d' } ] }, { label: 'deep-purple', color: '#673ab7', shades: [ { label: 'deep-purple-light6', color: '#f1edf9' }, { label: 'deep-purple-light5', color: '#daceef' }, { label: 'deep-purple-light4', color: '#c2afe6' }, { label: 'deep-purple-light3', color: '#ab90dc' }, { label: 'deep-purple-light2', color: '#9471d2' }, { label: 'deep-purple-light1', color: '#7c52c8' }, { label: 'deep-purple-dark1', color: '#5b33a1' }, { label: 'deep-purple-dark2', color: '#4e2c8b' }, { label: 'deep-purple-dark3', color: '#422575' }, { label: 'deep-purple-dark4', color: '#351e5f' }, { label: 'deep-purple-dark5', color: '#291749' }, { label: 'deep-purple-dark6', color: '#1c1033' } ] }, { label: 'indigo', color: '#3f51b5', shades: [ { label: 'indigo-light6', color: '#eff1fa' }, { label: 'indigo-light5', color: '#d1d6ef' }, { label: 'indigo-light4', color: '#b3bae4' }, { label: 'indigo-light3', color: '#949fda' }, { label: 'indigo-light2', color: '#7684cf' }, { label: 'indigo-light1', color: '#5869c5' }, { label: 'indigo-dark1', color: '#37479f' }, { label: 'indigo-dark2', color: '#303e8a' }, { label: 'indigo-dark3', color: '#283474' }, { label: 'indigo-dark4', color: '#212a5f' }, { label: 'indigo-dark5', color: '#192149' }, { label: 'indigo-dark6', color: '#121734' } ] }, { label: 'blue', color: '#2196f3', shades: [ { label: 'blue-light6', color: '#e6f3fe' }, { label: 'blue-light5', color: '#c6e4fc' }, { label: 'blue-light4', color: '#a5d4fa' }, { label: 'blue-light3', color: '#84c5f8' }, { label: 'blue-light2', color: '#63b5f7' }, { label: 'blue-light1', color: '#42a6f5' }, { label: 'blue-dark1', color: '#0c85e5' }, { label: 'blue-dark2', color: '#0b72c4' }, { label: 'blue-dark3', color: '#095fa3' }, { label: 'blue-dark4', color: '#074c82' }, { label: 'blue-dark5', color: '#053961' }, { label: 'blue-dark6', color: '#032540' } ] }, { label: 'light-blue', color: '#03a9f4', shades: [ { label: 'light-blue-light6', color: '#e7f7ff' }, { label: 'light-blue-light5', color: '#c0ebfe' }, { label: 'light-blue-light4', color: '#98defe' }, { label: 'light-blue-light3', color: '#71d2fd' }, { label: 'light-blue-light2', color: '#4ac5fd' }, { label: 'light-blue-light1', color: '#22b9fc' }, { label: 'light-blue-dark1', color: '#0393d5' }, { label: 'light-blue-dark2', color: '#027eb6' }, { label: 'light-blue-dark3', color: '#026896' }, { label: 'light-blue-dark4', color: '#015277' }, { label: 'light-blue-dark5', color: '#013d58' }, { label: 'light-blue-dark6', color: '#012739' } ] }, { label: 'cyan', color: '#04cbe5', shades: [ { label: 'cyan-light6', color: '#e9fcff' }, { label: 'cyan-light5', color: '#baf6fe' }, { label: 'cyan-light4', color: '#8bf0fd' }, { label: 'cyan-light3', color: '#5ceafc' }, { label: 'cyan-light2', color: '#2ce3fb' }, { label: 'cyan-light1', color: '#04d8f4' }, { label: 'cyan-dark1', color: '#04b2c8' }, { label: 'cyan-dark2', color: '#0398ac' }, { label: 'cyan-dark3', color: '#037f8f' }, { label: 'cyan-dark4', color: '#026673' }, { label: 'cyan-dark5', color: '#024c56' }, { label: 'cyan-dark6', color: '#01333a' } ] }, { label: 'teal', color: '#1db3a8', shades: [ { label: 'teal-light6', color: '#e2faf9' }, { label: 'teal-light5', color: '#b8f3ef' }, { label: 'teal-light4', color: '#8eede6' }, { label: 'teal-light3', color: '#64e6dc' }, { label: 'teal-light2', color: '#39dfd3' }, { label: 'teal-light1', color: '#20c7bb' }, { label: 'teal-dark1', color: '#199b92' }, { label: 'teal-dark2', color: '#15847c' }, { label: 'teal-dark3', color: '#116c65' }, { label: 'teal-dark4', color: '#0e544f' }, { label: 'teal-dark5', color: '#0a3c39' }, { label: 'teal-dark6', color: '#062523' } ] }, { label: 'green', color: '#4caf50', shades: [ { label: 'green-light6', color: '#edf7ed' }, { label: 'green-light5', color: '#d2ebd3' }, { label: 'green-light4', color: '#b7e0b8' }, { label: 'green-light3', color: '#9bd49e' }, { label: 'green-light2', color: '#80c883' }, { label: 'green-light1', color: '#65bc69' }, { label: 'green-dark1', color: '#439b47' }, { label: 'green-dark2', color: '#3a863d' }, { label: 'green-dark3', color: '#327234' }, { label: 'green-dark4', color: '#295e2b' }, { label: 'green-dark5', color: '#204a22' }, { label: 'green-dark6', color: '#173518' } ] }, { label: 'light-green', color: '#90d73f', shades: [ { label: 'light-green-light6', color: '#f4fbec' }, { label: 'light-green-light5', color: '#e5f6d3' }, { label: 'light-green-light4', color: '#d7f1b9' }, { label: 'light-green-light3', color: '#c8eba0' }, { label: 'light-green-light2', color: '#b9e687' }, { label: 'light-green-light1', color: '#abe16d' }, { label: 'light-green-dark1', color: '#80cc2a' }, { label: 'light-green-dark2', color: '#70b225' }, { label: 'light-green-dark3', color: '#609820' }, { label: 'light-green-dark4', color: '#4f7d1a' }, { label: 'light-green-dark5', color: '#3f6315' }, { label: 'light-green-dark6', color: '#2e490f' } ] }, { label: 'lime', color: '#cee029', shades: [ { label: 'lime-light6', color: '#fafce9' }, { label: 'lime-light5', color: '#f4f8ce' }, { label: 'lime-light4', color: '#edf4b2' }, { label: 'lime-light3', color: '#e7f097' }, { label: 'lime-light2', color: '#e1ec7b' }, { label: 'lime-light1', color: '#dae85f' }, { label: 'lime-dark1', color: '#bbcc1e' }, { label: 'lime-dark2', color: '#a1b01a' }, { label: 'lime-dark3', color: '#889516' }, { label: 'lime-dark4', color: '#6f7912' }, { label: 'lime-dark5', color: '#565d0e' }, { label: 'lime-dark6', color: '#3c420a' } ] }, { label: 'yellow', color: '#ffe70f', shades: [ { label: 'yellow-light6', color: '#fffce0' }, { label: 'yellow-light5', color: '#fff9c4' }, { label: 'yellow-light4', color: '#fff6a8' }, { label: 'yellow-light3', color: '#fff38c' }, { label: 'yellow-light2', color: '#fff170' }, { label: 'yellow-light1', color: '#ffee54' }, { label: 'yellow-dark1', color: '#eed700' }, { label: 'yellow-dark2', color: '#cfba00' }, { label: 'yellow-dark3', color: '#af9e00' }, { label: 'yellow-dark4', color: '#908100' }, { label: 'yellow-dark5', color: '#706500' }, { label: 'yellow-dark6', color: '#504800' } ] }, { label: 'amber', color: '#ffc107', shades: [ { label: 'amber-light6', color: '#fffaed' }, { label: 'amber-light5', color: '#fff1c6' }, { label: 'amber-light4', color: '#ffe7a0' }, { label: 'amber-light3', color: '#ffde7a' }, { label: 'amber-light2', color: '#ffd454' }, { label: 'amber-light1', color: '#ffcb2d' }, { label: 'amber-dark1', color: '#e6ad00' }, { label: 'amber-dark2', color: '#c79500' }, { label: 'amber-dark3', color: '#a77d00' }, { label: 'amber-dark4', color: '#886600' }, { label: 'amber-dark5', color: '#684e00' }, { label: 'amber-dark6', color: '#483600' } ] }, { label: 'orange', color: '#ff9800', shades: [ { label: 'orange-light6', color: '#fff5e6' }, { label: 'orange-light5', color: '#ffe5bf' }, { label: 'orange-light4', color: '#ffd699' }, { label: 'orange-light3', color: '#ffc673' }, { label: 'orange-light2', color: '#ffb74d' }, { label: 'orange-light1', color: '#ffa726' }, { label: 'orange-dark1', color: '#df8500' }, { label: 'orange-dark2', color: '#c07200' }, { label: 'orange-dark3', color: '#a05f00' }, { label: 'orange-dark4', color: '#814d00' }, { label: 'orange-dark5', color: '#613a00' }, { label: 'orange-dark6', color: '#412700' } ] }, { label: 'deep-orange', color: '#ff6825', shades: [ { label: 'deep-orange-light6', color: '#fff0e9' }, { label: 'deep-orange-light5', color: '#ffd9c8' }, { label: 'deep-orange-light4', color: '#ffc2a8' }, { label: 'deep-orange-light3', color: '#ffac87' }, { label: 'deep-orange-light2', color: '#ff9566' }, { label: 'deep-orange-light1', color: '#ff7f46' }, { label: 'deep-orange-dark1', color: '#ff5205' }, { label: 'deep-orange-dark2', color: '#e54600' }, { label: 'deep-orange-dark3', color: '#c53d00' }, { label: 'deep-orange-dark4', color: '#a63300' }, { label: 'deep-orange-dark5', color: '#862900' }, { label: 'deep-orange-dark6', color: '#661f00' } ] }, { label: 'red', color: '#fa3317', shades: [ { label: 'red-light6', color: '#fee3df' }, { label: 'red-light5', color: '#fec6be' }, { label: 'red-light4', color: '#fdaa9e' }, { label: 'red-light3', color: '#fc8d7d' }, { label: 'red-light2', color: '#fc705d' }, { label: 'red-light1', color: '#fb543c' }, { label: 'red-dark1', color: '#ec2205' }, { label: 'red-dark2', color: '#cd1d04' }, { label: 'red-dark3', color: '#ae1904' }, { label: 'red-dark4', color: '#8f1403' }, { label: 'red-dark5', color: '#701002' }, { label: 'red-dark6', color: '#520c02' } ] }, { label: 'brown', color: '#845848', shades: [ { label: 'brown-light6', color: '#f2eae7' }, { label: 'brown-light5', color: '#e2d1ca' }, { label: 'brown-light4', color: '#d2b7ad' }, { label: 'brown-light3', color: '#c39e90' }, { label: 'brown-light2', color: '#b38473' }, { label: 'brown-light1', color: '#a16b58' }, { label: 'brown-dark1', color: '#744d3f' }, { label: 'brown-dark2', color: '#634236' }, { label: 'brown-dark3', color: '#53372d' }, { label: 'brown-dark4', color: '#422c24' }, { label: 'brown-dark5', color: '#32211b' }, { label: 'brown-dark6', color: '#211612' } ] }, { label: 'blue-grey', color: '#6c8693', shades: [ { label: 'blue-grey-light6', color: '#f0f3f4' }, { label: 'blue-grey-light5', color: '#dae1e4' }, { label: 'blue-grey-light4', color: '#c4cfd4' }, { label: 'blue-grey-light3', color: '#aebcc4' }, { label: 'blue-grey-light2', color: '#98aab3' }, { label: 'blue-grey-light1', color: '#8298a3' }, { label: 'blue-grey-dark1', color: '#5f7581' }, { label: 'blue-grey-dark2', color: '#51656f' }, { label: 'blue-grey-dark3', color: '#44545c' }, { label: 'blue-grey-dark4', color: '#36444a' }, { label: 'blue-grey-dark5', color: '#293338' }, { label: 'blue-grey-dark6', color: '#1c2226' } ] }, { label: 'grey', color: '#848484', shades: [ { label: 'grey-light6', color: '#f7f7f7' }, { label: 'grey-light5', color: '#e4e4e4' }, { label: 'grey-light4', color: '#d1d1d1' }, { label: 'grey-light3', color: '#bdbdbd' }, { label: 'grey-light2', color: '#aaaaaa' }, { label: 'grey-light1', color: '#979797' }, { label: 'grey-dark1', color: '#747474' }, { label: 'grey-dark2', color: '#646464' }, { label: 'grey-dark3', color: '#555555' }, { label: 'grey-dark4', color: '#454545' }, { label: 'grey-dark5', color: '#353535' }, { label: 'grey-dark6', color: '#252525' } ] }, { label: 'black', color: '#000' }, { label: 'white', color: '#fff' }, { label: 'transparent', color: 'transparent' }, { label: 'inherit', color: 'inherit' } ]