@khanacademy/wonder-blocks-tokens
Advanced tools
| export declare const spacing: { | ||
| readonly xxxxSmall_2: 2; | ||
| readonly xxxSmall_4: 4; | ||
| readonly xxSmall_6: 6; | ||
| readonly xSmall_8: 8; | ||
| readonly small_12: 12; | ||
| readonly medium_16: 16; | ||
| readonly large_24: 24; | ||
| readonly xLarge_32: 32; | ||
| readonly xxLarge_48: 48; | ||
| readonly xxxLarge_64: 64; | ||
| }; | ||
| export type VALID_PRIMARY_SPACING = 4 | 8 | 16 | 32 | 64; | ||
| export type VALID_SECONDARY_SPACING = 6 | 12 | 24 | 48; | ||
| export type VALID_SPACING = VALID_PRIMARY_SPACING | VALID_SECONDARY_SPACING; |
| /** | ||
| * A color manipulation library useful for dynamically | ||
| * mixing colors together. | ||
| */ | ||
| export declare const fade: (color: string, percentage: number) => string; | ||
| export declare const mix: (color: string, background: string) => string; |
| export const spacing = { | ||
| // Named | ||
| xxxxSmall_2: 2, | ||
| xxxSmall_4: 4, | ||
| xxSmall_6: 6, | ||
| xSmall_8: 8, | ||
| small_12: 12, | ||
| medium_16: 16, | ||
| large_24: 24, | ||
| xLarge_32: 32, | ||
| xxLarge_48: 48, | ||
| xxxLarge_64: 64, | ||
| } as const; | ||
| export type VALID_PRIMARY_SPACING = 4 | 8 | 16 | 32 | 64; | ||
| export type VALID_SECONDARY_SPACING = 6 | 12 | 24 | 48; | ||
| export type VALID_SPACING = VALID_PRIMARY_SPACING | VALID_SECONDARY_SPACING; |
Sorry, the diff of this file is not supported yet
| import {fade, mix} from "../utils"; | ||
| const INVALID_COLORS = ["#NOTVALID", "#12345", "#12", "#ABCDEFG", ""]; | ||
| describe("mix", () => { | ||
| test("color is not a string, throws", () => { | ||
| // Arrange | ||
| // @ts-expect-error [FEI-5019] - TS2352 - Conversion of type 'null' to type 'string' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. | ||
| const color = null as string; | ||
| // Act | ||
| const underTest = () => mix(color, "#FFF"); | ||
| // Assert | ||
| expect(underTest).toThrowErrorMatchingSnapshot(); | ||
| }); | ||
| test("background is not a string, throws", () => { | ||
| // Arrange | ||
| // @ts-expect-error [FEI-5019] - TS2352 - Conversion of type 'null' to type 'string' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. | ||
| const background = null as string; | ||
| // Act | ||
| const underTest = () => mix("#FFF", background); | ||
| // Assert | ||
| expect(underTest).toThrowErrorMatchingSnapshot(); | ||
| }); | ||
| test("color is not a valid string format, throws", () => { | ||
| // Arrange | ||
| const testpoints = INVALID_COLORS; | ||
| // Act | ||
| for (const testpoint of testpoints) { | ||
| const underTest = () => mix(testpoint, "#FFF"); | ||
| expect(underTest).toThrowErrorMatchingSnapshot(); | ||
| } | ||
| }); | ||
| test("background is not a valid string format, throws", () => { | ||
| // Arrange | ||
| const testpoints = INVALID_COLORS; | ||
| // Act | ||
| for (const testpoint of testpoints) { | ||
| const underTest = () => mix("#FFF", testpoint); | ||
| expect(underTest).toThrowErrorMatchingSnapshot(); | ||
| } | ||
| }); | ||
| test("color has no alpha, returns color with background alpha", () => { | ||
| // Arrange | ||
| const testpoints = [ | ||
| ["#000", "#abc", "#000000"], | ||
| ["#FFFFFF", "rgba(10,20,30,0.5)", "rgba(255,255,255,0.50)"], | ||
| ["rgb(200,200,190)", "rgba(0,0,0,0.23)", "rgba(200,200,190,0.23)"], | ||
| ["rgba(0,0,0,1)", "#1D3baa", "#000000"], | ||
| ["#ABC", "rgba(0,0,0,1)", "#aabbcc"], | ||
| ]; | ||
| for (const [color, background, expectation] of testpoints) { | ||
| // Act | ||
| const result = mix(color, background); | ||
| // Assert | ||
| expect(result).toBe(expectation); | ||
| } | ||
| }); | ||
| test("color has alpha, returns mix with background alpha", () => { | ||
| // Arrange | ||
| const testpoints = [ | ||
| ["rgba(100,100,100,0.2)", "#FFF", "#e0e0e0"], | ||
| ["rgba(100,100,100,0.2)", "rgba(0,0,0,0.5)", "rgba(20,20,20,0.50)"], | ||
| ["rgba(0,0,0,0.25)", "#fFfFfF", "#bfbfbf"], | ||
| ["rgba(0,0,0,0.25)", "rgb(255,255,0)", "#bfbf00"], | ||
| ["rgba(100,200,100,0.25)", "rgb(255,255,0)", "#d8f119"], | ||
| ["rgba(33,36,44,0.32)", "#00a60e", "#0b7c18"], | ||
| ]; | ||
| for (const [color, background, expectation] of testpoints) { | ||
| // Act | ||
| const result = mix(color, background); | ||
| // Assert | ||
| expect(result).toBe(expectation); | ||
| } | ||
| }); | ||
| }); | ||
| describe("fade", () => { | ||
| test("color is not a string, throws", () => { | ||
| // Arrange | ||
| // @ts-expect-error [FEI-5019] - TS2352 - Conversion of type 'null' to type 'string' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. | ||
| const color = null as string; | ||
| // Act | ||
| const underTest = () => fade(color, 0.2); | ||
| // Assert | ||
| expect(underTest).toThrowErrorMatchingSnapshot(); | ||
| }); | ||
| test("color is not a valid string format, throws", () => { | ||
| // Arrange | ||
| const testpoints = INVALID_COLORS; | ||
| // Act | ||
| for (const testpoint of testpoints) { | ||
| const underTest = () => fade(testpoint, 0.5); | ||
| expect(underTest).toThrowErrorMatchingSnapshot(); | ||
| } | ||
| }); | ||
| test("percentage is negative, throws", () => { | ||
| // Arrange | ||
| const percentage = -1; | ||
| // Act | ||
| const underTest = () => fade("#FFFFFF", percentage); | ||
| // Assert | ||
| expect(underTest).toThrowErrorMatchingSnapshot(); | ||
| }); | ||
| test("percentage is greater than 1, throws", () => { | ||
| // Arrange | ||
| const percentage = 1.1; | ||
| // Act | ||
| const underTest = () => fade("#FFFFFF", percentage); | ||
| // Assert | ||
| expect(underTest).toThrowErrorMatchingSnapshot(); | ||
| }); | ||
| test("3 digit # color, returns faded color", () => { | ||
| // Arrange | ||
| const color = "#ABC"; | ||
| // Act | ||
| const result = fade(color, 0.5); | ||
| // Assert | ||
| expect(result).toBe("rgba(170,187,204,0.50)"); | ||
| }); | ||
| test("6 digit # color, returns faded color", () => { | ||
| // Arrange | ||
| const color = "#AABBCC"; | ||
| // Act | ||
| const result = fade(color, 0.5); | ||
| // Assert | ||
| expect(result).toBe("rgba(170,187,204,0.50)"); | ||
| }); | ||
| test("rgb color, returns faded color", () => { | ||
| // Arrange | ||
| const color = "rgb(100,200,0)"; | ||
| // Act | ||
| const result = fade(color, 0.5); | ||
| // Assert | ||
| expect(result).toBe("rgba(100,200,0,0.50)"); | ||
| }); | ||
| test("rgba color without 100% alpha, returns faded color", () => { | ||
| // Arrange | ||
| const color = "rgba(100,200,0, 1)"; | ||
| // Act | ||
| const result = fade(color, 0.5); | ||
| // Assert | ||
| expect(result).toBe("rgba(100,200,0,0.50)"); | ||
| }); | ||
| test("rgba color with less than 100% alpha, returns faded color", () => { | ||
| // Arrange | ||
| const color = "rgba(100,200,0, 0.6)"; | ||
| // Act | ||
| const result = fade(color, 0.5); | ||
| // Assert | ||
| expect(result).toBe("rgba(100,200,0,0.30)"); | ||
| }); | ||
| }); |
| /** | ||
| * A color manipulation library useful for dynamically | ||
| * mixing colors together. | ||
| */ | ||
| const color6Regexp = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i; | ||
| const color3Regexp = /^#([0-9a-f])([0-9a-f])([0-9a-f])$/i; | ||
| const rgbaRegexp = /^rgba?\(\s*(\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\s*\)$/i; | ||
| type Color = { | ||
| r: number; | ||
| g: number; | ||
| b: number; | ||
| a: number; | ||
| }; | ||
| // Parse a color in #abcdef, rgb(...), or rgba(...) form into an object | ||
| // with r,g,b,a keys. | ||
| const parse = (color: string): Color => { | ||
| if (typeof color !== "string") { | ||
| throw new Error(`Failed to parse color: ${color}`); | ||
| } | ||
| const color3Match = color.match(color3Regexp); | ||
| if (color3Match) { | ||
| return { | ||
| r: parseInt(`${color3Match[1]}${color3Match[1]}`, 16), | ||
| g: parseInt(`${color3Match[2]}${color3Match[2]}`, 16), | ||
| b: parseInt(`${color3Match[3]}${color3Match[3]}`, 16), | ||
| a: 1, | ||
| }; | ||
| } | ||
| const color6Match = color.match(color6Regexp); | ||
| if (color6Match) { | ||
| return { | ||
| r: parseInt(color6Match[1], 16), | ||
| g: parseInt(color6Match[2], 16), | ||
| b: parseInt(color6Match[3], 16), | ||
| a: 1, | ||
| }; | ||
| } | ||
| const rgbaMatch = color.match(rgbaRegexp); | ||
| if (rgbaMatch) { | ||
| return { | ||
| r: parseFloat(rgbaMatch[1]), | ||
| g: parseFloat(rgbaMatch[2]), | ||
| b: parseFloat(rgbaMatch[3]), | ||
| a: rgbaMatch[4] ? parseFloat(rgbaMatch[4]) : 1, | ||
| }; | ||
| } | ||
| throw new Error(`Failed to parse color: ${color}`); | ||
| }; | ||
| // Stringify the color in an `rgba()` or `#abcdef` format. | ||
| const format = (color: Color): string => { | ||
| const r = Math.round(color.r); | ||
| const g = Math.round(color.g); | ||
| const b = Math.round(color.b); | ||
| if (color.a === 1) { | ||
| const _s = (c: number) => { | ||
| const asString = c.toString(16); | ||
| return asString.length === 1 ? `0${asString}` : asString; | ||
| }; | ||
| return `#${_s(r)}${_s(g)}${_s(b)}`; | ||
| } else { | ||
| return `rgba(${r},${g},${b},${color.a.toFixed(2)})`; | ||
| } | ||
| }; | ||
| // Adjust the alpha value of a color. | ||
| export const fade = (color: string, percentage: number): string => { | ||
| if (percentage < 0 || percentage > 1) { | ||
| throw new Error("Percentage must be between 0 and 1"); | ||
| } | ||
| const components = parse(color); | ||
| return format({ | ||
| ...components, | ||
| a: components.a * percentage, | ||
| }); | ||
| }; | ||
| // Mix a color into a background color, using the alpha channel of the base | ||
| // color to determine the linear blend. | ||
| export const mix = (color: string, background: string): string => { | ||
| const colorObj = parse(color); | ||
| const bgObj = parse(background); | ||
| return format({ | ||
| r: colorObj.r * colorObj.a + bgObj.r * (1 - colorObj.a), | ||
| g: colorObj.g * colorObj.a + bgObj.g * (1 - colorObj.a), | ||
| b: colorObj.b * colorObj.a + bgObj.b * (1 - colorObj.a), | ||
| a: bgObj.a, | ||
| }); | ||
| }; |
+11
-0
| # @khanacademy/wonder-blocks-tokens | ||
| ## 1.2.0 | ||
| ### Minor Changes | ||
| - 874081aa: Add fade and mix functions | ||
| ### Patch Changes | ||
| - 874081aa: Remove wonder-blocks-color dependency in favor of wonder-blocks-tokens | ||
| - a9bf603a: Move spacing tokens to wb-tokens | ||
| ## 1.1.0 | ||
@@ -4,0 +15,0 @@ |
+126
-23
@@ -1,4 +0,1 @@ | ||
| export { default as spacing } from '@khanacademy/wonder-blocks-spacing'; | ||
| import Color, { fade, mix } from '@khanacademy/wonder-blocks-color'; | ||
| const border = { | ||
@@ -36,21 +33,114 @@ radius: { | ||
| const fadedColorWithWhite = (color, alpha) => mix(fade(color, alpha), Color.white); | ||
| const color = _extends({}, Color, { | ||
| white32: fade(Color.white, 0.32), | ||
| activeBlue: mix(Color.offBlack32, Color.blue), | ||
| fadedBlue: fadedColorWithWhite(Color.blue, 0.32), | ||
| fadedBlue24: fadedColorWithWhite(Color.blue, 0.24), | ||
| fadedBlue16: fadedColorWithWhite(Color.blue, 0.16), | ||
| fadedBlue8: fadedColorWithWhite(Color.blue, 0.08), | ||
| activeRed: mix(Color.offBlack32, Color.red), | ||
| fadedRed: fadedColorWithWhite(Color.red, 0.32), | ||
| fadedRed24: fadedColorWithWhite(Color.red, 0.24), | ||
| fadedRed16: fadedColorWithWhite(Color.red, 0.16), | ||
| fadedRed8: fadedColorWithWhite(Color.red, 0.08), | ||
| fadedGreen24: fadedColorWithWhite(Color.green, 0.24), | ||
| fadedGreen16: fadedColorWithWhite(Color.green, 0.16), | ||
| fadedGold24: fadedColorWithWhite(Color.gold, 0.24), | ||
| fadedGold16: fadedColorWithWhite(Color.gold, 0.16), | ||
| fadedPurple24: fadedColorWithWhite(Color.purple, 0.24), | ||
| fadedPurple16: fadedColorWithWhite(Color.purple, 0.16), | ||
| const color6Regexp = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i; | ||
| const color3Regexp = /^#([0-9a-f])([0-9a-f])([0-9a-f])$/i; | ||
| const rgbaRegexp = /^rgba?\(\s*(\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\s*\)$/i; | ||
| const parse = color => { | ||
| if (typeof color !== "string") { | ||
| throw new Error(`Failed to parse color: ${color}`); | ||
| } | ||
| const color3Match = color.match(color3Regexp); | ||
| if (color3Match) { | ||
| return { | ||
| r: parseInt(`${color3Match[1]}${color3Match[1]}`, 16), | ||
| g: parseInt(`${color3Match[2]}${color3Match[2]}`, 16), | ||
| b: parseInt(`${color3Match[3]}${color3Match[3]}`, 16), | ||
| a: 1 | ||
| }; | ||
| } | ||
| const color6Match = color.match(color6Regexp); | ||
| if (color6Match) { | ||
| return { | ||
| r: parseInt(color6Match[1], 16), | ||
| g: parseInt(color6Match[2], 16), | ||
| b: parseInt(color6Match[3], 16), | ||
| a: 1 | ||
| }; | ||
| } | ||
| const rgbaMatch = color.match(rgbaRegexp); | ||
| if (rgbaMatch) { | ||
| return { | ||
| r: parseFloat(rgbaMatch[1]), | ||
| g: parseFloat(rgbaMatch[2]), | ||
| b: parseFloat(rgbaMatch[3]), | ||
| a: rgbaMatch[4] ? parseFloat(rgbaMatch[4]) : 1 | ||
| }; | ||
| } | ||
| throw new Error(`Failed to parse color: ${color}`); | ||
| }; | ||
| const format = color => { | ||
| const r = Math.round(color.r); | ||
| const g = Math.round(color.g); | ||
| const b = Math.round(color.b); | ||
| if (color.a === 1) { | ||
| const _s = c => { | ||
| const asString = c.toString(16); | ||
| return asString.length === 1 ? `0${asString}` : asString; | ||
| }; | ||
| return `#${_s(r)}${_s(g)}${_s(b)}`; | ||
| } else { | ||
| return `rgba(${r},${g},${b},${color.a.toFixed(2)})`; | ||
| } | ||
| }; | ||
| const fade = (color, percentage) => { | ||
| if (percentage < 0 || percentage > 1) { | ||
| throw new Error("Percentage must be between 0 and 1"); | ||
| } | ||
| const components = parse(color); | ||
| return format(_extends({}, components, { | ||
| a: components.a * percentage | ||
| })); | ||
| }; | ||
| const mix = (color, background) => { | ||
| const colorObj = parse(color); | ||
| const bgObj = parse(background); | ||
| return format({ | ||
| r: colorObj.r * colorObj.a + bgObj.r * (1 - colorObj.a), | ||
| g: colorObj.g * colorObj.a + bgObj.g * (1 - colorObj.a), | ||
| b: colorObj.b * colorObj.a + bgObj.b * (1 - colorObj.a), | ||
| a: bgObj.a | ||
| }); | ||
| }; | ||
| const offBlack = "#21242c"; | ||
| const white = "#ffffff"; | ||
| const baseColors = { | ||
| blue: "#1865f2", | ||
| purple: "#9059ff", | ||
| green: "#00a60e", | ||
| gold: "#ffb100", | ||
| red: "#d92916", | ||
| offBlack, | ||
| offBlack64: fade(offBlack, 0.64), | ||
| offBlack50: fade(offBlack, 0.5), | ||
| offBlack32: fade(offBlack, 0.32), | ||
| offBlack16: fade(offBlack, 0.16), | ||
| offBlack8: fade(offBlack, 0.08), | ||
| offWhite: "#f7f8fa", | ||
| white, | ||
| white64: fade(white, 0.64), | ||
| white50: fade(white, 0.5), | ||
| darkBlue: "#0b2149", | ||
| teal: "#14bf96", | ||
| lightBlue: "#37c5fd", | ||
| pink: "#fa50ae" | ||
| }; | ||
| const fadedColorWithWhite = (color, alpha) => mix(fade(color, alpha), baseColors.white); | ||
| const color = _extends({}, baseColors, { | ||
| white32: fade(baseColors.white, 0.32), | ||
| activeBlue: mix(baseColors.offBlack32, baseColors.blue), | ||
| fadedBlue: fadedColorWithWhite(baseColors.blue, 0.32), | ||
| fadedBlue24: fadedColorWithWhite(baseColors.blue, 0.24), | ||
| fadedBlue16: fadedColorWithWhite(baseColors.blue, 0.16), | ||
| fadedBlue8: fadedColorWithWhite(baseColors.blue, 0.08), | ||
| activeRed: mix(baseColors.offBlack32, baseColors.red), | ||
| fadedRed: fadedColorWithWhite(baseColors.red, 0.32), | ||
| fadedRed24: fadedColorWithWhite(baseColors.red, 0.24), | ||
| fadedRed16: fadedColorWithWhite(baseColors.red, 0.16), | ||
| fadedRed8: fadedColorWithWhite(baseColors.red, 0.08), | ||
| fadedGreen24: fadedColorWithWhite(baseColors.green, 0.24), | ||
| fadedGreen16: fadedColorWithWhite(baseColors.green, 0.16), | ||
| fadedGold24: fadedColorWithWhite(baseColors.gold, 0.24), | ||
| fadedGold16: fadedColorWithWhite(baseColors.gold, 0.16), | ||
| fadedPurple24: fadedColorWithWhite(baseColors.purple, 0.24), | ||
| fadedPurple16: fadedColorWithWhite(baseColors.purple, 0.16), | ||
| eggplant: "#5f1e5c" | ||
@@ -90,2 +180,15 @@ }); | ||
| export { border, color, font }; | ||
| const spacing = { | ||
| xxxxSmall_2: 2, | ||
| xxxSmall_4: 4, | ||
| xxSmall_6: 6, | ||
| xSmall_8: 8, | ||
| small_12: 12, | ||
| medium_16: 16, | ||
| large_24: 24, | ||
| xLarge_32: 32, | ||
| xxLarge_48: 48, | ||
| xxxLarge_64: 64 | ||
| }; | ||
| export { border, color, fade, font, mix, spacing }; |
+8
-2
@@ -1,8 +0,14 @@ | ||
| import spacing from "@khanacademy/wonder-blocks-spacing"; | ||
| import { border } from "./tokens/border"; | ||
| import { color } from "./tokens/color"; | ||
| import { font } from "./tokens/font"; | ||
| import { spacing } from "./tokens/spacing"; | ||
| import { mix, fade } from "./util/utils"; | ||
| export { | ||
| /** | ||
| * Core tokens for the Wonder Blocks design system. | ||
| */ | ||
| export { border, color, font, spacing }; | ||
| border, color, font, spacing, | ||
| /** | ||
| * Utility functions for working with colors. | ||
| */ | ||
| mix, fade, }; |
+128
-31
@@ -5,10 +5,2 @@ 'use strict'; | ||
| var wonderBlocksSpacing = require('@khanacademy/wonder-blocks-spacing'); | ||
| var Color = require('@khanacademy/wonder-blocks-color'); | ||
| function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
| var wonderBlocksSpacing__default = /*#__PURE__*/_interopDefaultLegacy(wonderBlocksSpacing); | ||
| var Color__default = /*#__PURE__*/_interopDefaultLegacy(Color); | ||
| const border = { | ||
@@ -46,21 +38,114 @@ radius: { | ||
| const fadedColorWithWhite = (color, alpha) => Color.mix(Color.fade(color, alpha), Color__default["default"].white); | ||
| const color = _extends({}, Color__default["default"], { | ||
| white32: Color.fade(Color__default["default"].white, 0.32), | ||
| activeBlue: Color.mix(Color__default["default"].offBlack32, Color__default["default"].blue), | ||
| fadedBlue: fadedColorWithWhite(Color__default["default"].blue, 0.32), | ||
| fadedBlue24: fadedColorWithWhite(Color__default["default"].blue, 0.24), | ||
| fadedBlue16: fadedColorWithWhite(Color__default["default"].blue, 0.16), | ||
| fadedBlue8: fadedColorWithWhite(Color__default["default"].blue, 0.08), | ||
| activeRed: Color.mix(Color__default["default"].offBlack32, Color__default["default"].red), | ||
| fadedRed: fadedColorWithWhite(Color__default["default"].red, 0.32), | ||
| fadedRed24: fadedColorWithWhite(Color__default["default"].red, 0.24), | ||
| fadedRed16: fadedColorWithWhite(Color__default["default"].red, 0.16), | ||
| fadedRed8: fadedColorWithWhite(Color__default["default"].red, 0.08), | ||
| fadedGreen24: fadedColorWithWhite(Color__default["default"].green, 0.24), | ||
| fadedGreen16: fadedColorWithWhite(Color__default["default"].green, 0.16), | ||
| fadedGold24: fadedColorWithWhite(Color__default["default"].gold, 0.24), | ||
| fadedGold16: fadedColorWithWhite(Color__default["default"].gold, 0.16), | ||
| fadedPurple24: fadedColorWithWhite(Color__default["default"].purple, 0.24), | ||
| fadedPurple16: fadedColorWithWhite(Color__default["default"].purple, 0.16), | ||
| const color6Regexp = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i; | ||
| const color3Regexp = /^#([0-9a-f])([0-9a-f])([0-9a-f])$/i; | ||
| const rgbaRegexp = /^rgba?\(\s*(\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\s*\)$/i; | ||
| const parse = color => { | ||
| if (typeof color !== "string") { | ||
| throw new Error(`Failed to parse color: ${color}`); | ||
| } | ||
| const color3Match = color.match(color3Regexp); | ||
| if (color3Match) { | ||
| return { | ||
| r: parseInt(`${color3Match[1]}${color3Match[1]}`, 16), | ||
| g: parseInt(`${color3Match[2]}${color3Match[2]}`, 16), | ||
| b: parseInt(`${color3Match[3]}${color3Match[3]}`, 16), | ||
| a: 1 | ||
| }; | ||
| } | ||
| const color6Match = color.match(color6Regexp); | ||
| if (color6Match) { | ||
| return { | ||
| r: parseInt(color6Match[1], 16), | ||
| g: parseInt(color6Match[2], 16), | ||
| b: parseInt(color6Match[3], 16), | ||
| a: 1 | ||
| }; | ||
| } | ||
| const rgbaMatch = color.match(rgbaRegexp); | ||
| if (rgbaMatch) { | ||
| return { | ||
| r: parseFloat(rgbaMatch[1]), | ||
| g: parseFloat(rgbaMatch[2]), | ||
| b: parseFloat(rgbaMatch[3]), | ||
| a: rgbaMatch[4] ? parseFloat(rgbaMatch[4]) : 1 | ||
| }; | ||
| } | ||
| throw new Error(`Failed to parse color: ${color}`); | ||
| }; | ||
| const format = color => { | ||
| const r = Math.round(color.r); | ||
| const g = Math.round(color.g); | ||
| const b = Math.round(color.b); | ||
| if (color.a === 1) { | ||
| const _s = c => { | ||
| const asString = c.toString(16); | ||
| return asString.length === 1 ? `0${asString}` : asString; | ||
| }; | ||
| return `#${_s(r)}${_s(g)}${_s(b)}`; | ||
| } else { | ||
| return `rgba(${r},${g},${b},${color.a.toFixed(2)})`; | ||
| } | ||
| }; | ||
| const fade = (color, percentage) => { | ||
| if (percentage < 0 || percentage > 1) { | ||
| throw new Error("Percentage must be between 0 and 1"); | ||
| } | ||
| const components = parse(color); | ||
| return format(_extends({}, components, { | ||
| a: components.a * percentage | ||
| })); | ||
| }; | ||
| const mix = (color, background) => { | ||
| const colorObj = parse(color); | ||
| const bgObj = parse(background); | ||
| return format({ | ||
| r: colorObj.r * colorObj.a + bgObj.r * (1 - colorObj.a), | ||
| g: colorObj.g * colorObj.a + bgObj.g * (1 - colorObj.a), | ||
| b: colorObj.b * colorObj.a + bgObj.b * (1 - colorObj.a), | ||
| a: bgObj.a | ||
| }); | ||
| }; | ||
| const offBlack = "#21242c"; | ||
| const white = "#ffffff"; | ||
| const baseColors = { | ||
| blue: "#1865f2", | ||
| purple: "#9059ff", | ||
| green: "#00a60e", | ||
| gold: "#ffb100", | ||
| red: "#d92916", | ||
| offBlack, | ||
| offBlack64: fade(offBlack, 0.64), | ||
| offBlack50: fade(offBlack, 0.5), | ||
| offBlack32: fade(offBlack, 0.32), | ||
| offBlack16: fade(offBlack, 0.16), | ||
| offBlack8: fade(offBlack, 0.08), | ||
| offWhite: "#f7f8fa", | ||
| white, | ||
| white64: fade(white, 0.64), | ||
| white50: fade(white, 0.5), | ||
| darkBlue: "#0b2149", | ||
| teal: "#14bf96", | ||
| lightBlue: "#37c5fd", | ||
| pink: "#fa50ae" | ||
| }; | ||
| const fadedColorWithWhite = (color, alpha) => mix(fade(color, alpha), baseColors.white); | ||
| const color = _extends({}, baseColors, { | ||
| white32: fade(baseColors.white, 0.32), | ||
| activeBlue: mix(baseColors.offBlack32, baseColors.blue), | ||
| fadedBlue: fadedColorWithWhite(baseColors.blue, 0.32), | ||
| fadedBlue24: fadedColorWithWhite(baseColors.blue, 0.24), | ||
| fadedBlue16: fadedColorWithWhite(baseColors.blue, 0.16), | ||
| fadedBlue8: fadedColorWithWhite(baseColors.blue, 0.08), | ||
| activeRed: mix(baseColors.offBlack32, baseColors.red), | ||
| fadedRed: fadedColorWithWhite(baseColors.red, 0.32), | ||
| fadedRed24: fadedColorWithWhite(baseColors.red, 0.24), | ||
| fadedRed16: fadedColorWithWhite(baseColors.red, 0.16), | ||
| fadedRed8: fadedColorWithWhite(baseColors.red, 0.08), | ||
| fadedGreen24: fadedColorWithWhite(baseColors.green, 0.24), | ||
| fadedGreen16: fadedColorWithWhite(baseColors.green, 0.16), | ||
| fadedGold24: fadedColorWithWhite(baseColors.gold, 0.24), | ||
| fadedGold16: fadedColorWithWhite(baseColors.gold, 0.16), | ||
| fadedPurple24: fadedColorWithWhite(baseColors.purple, 0.24), | ||
| fadedPurple16: fadedColorWithWhite(baseColors.purple, 0.16), | ||
| eggplant: "#5f1e5c" | ||
@@ -100,8 +185,20 @@ }); | ||
| Object.defineProperty(exports, 'spacing', { | ||
| enumerable: true, | ||
| get: function () { return wonderBlocksSpacing__default["default"]; } | ||
| }); | ||
| const spacing = { | ||
| xxxxSmall_2: 2, | ||
| xxxSmall_4: 4, | ||
| xxSmall_6: 6, | ||
| xSmall_8: 8, | ||
| small_12: 12, | ||
| medium_16: 16, | ||
| large_24: 24, | ||
| xLarge_32: 32, | ||
| xxLarge_48: 48, | ||
| xxxLarge_64: 64 | ||
| }; | ||
| exports.border = border; | ||
| exports.color = color; | ||
| exports.fade = fade; | ||
| exports.font = font; | ||
| exports.mix = mix; | ||
| exports.spacing = spacing; |
+2
-5
| { | ||
| "name": "@khanacademy/wonder-blocks-tokens", | ||
| "version": "1.1.0", | ||
| "version": "1.2.0", | ||
| "description": "Core primitive design tokens for Web Wonder Blocks", | ||
@@ -16,6 +16,3 @@ "main": "dist/index.js", | ||
| }, | ||
| "dependencies": { | ||
| "@khanacademy/wonder-blocks-color": "^3.0.0", | ||
| "@khanacademy/wonder-blocks-spacing": "^4.0.1" | ||
| }, | ||
| "dependencies": {}, | ||
| "devDependencies": { | ||
@@ -22,0 +19,0 @@ "@khanacademy/wb-dev-build-settings": "^1.0.0" |
+17
-7
@@ -1,11 +0,21 @@ | ||
| // TODO(WB-1643): Move wonder-blocks-spacing to tokens | ||
| import spacing from "@khanacademy/wonder-blocks-spacing"; | ||
| import {border} from "./tokens/border"; | ||
| import {color} from "./tokens/color"; | ||
| import {font} from "./tokens/font"; | ||
| import {spacing} from "./tokens/spacing"; | ||
| /** | ||
| * Core tokens for the Wonder Blocks design system. | ||
| */ | ||
| export {border, color, font, spacing}; | ||
| import {mix, fade} from "./util/utils"; | ||
| export { | ||
| /** | ||
| * Core tokens for the Wonder Blocks design system. | ||
| */ | ||
| border, | ||
| color, | ||
| font, | ||
| spacing, | ||
| /** | ||
| * Utility functions for working with colors. | ||
| */ | ||
| mix, | ||
| fade, | ||
| }; |
+76
-21
@@ -1,35 +0,90 @@ | ||
| // TODO(WB-1642): Move wonder-blocks-color to tokens | ||
| import Color, {fade, mix} from "@khanacademy/wonder-blocks-color"; | ||
| import {fade, mix} from "../util/utils"; | ||
| const offBlack = "#21242c"; | ||
| const white = "#ffffff"; | ||
| type ColorType = { | ||
| // Product | ||
| blue: string; | ||
| purple: string; | ||
| green: string; | ||
| gold: string; | ||
| red: string; | ||
| // Neutral | ||
| offBlack: string; | ||
| offBlack64: string; | ||
| offBlack50: string; | ||
| offBlack32: string; | ||
| offBlack16: string; | ||
| offBlack8: string; | ||
| offWhite: string; | ||
| white: string; | ||
| white64: string; | ||
| white50: string; | ||
| // Brand | ||
| darkBlue: string; | ||
| teal: string; | ||
| lightBlue: string; | ||
| pink: string; | ||
| }; | ||
| const baseColors: ColorType = { | ||
| // Product | ||
| blue: "#1865f2", | ||
| purple: "#9059ff", | ||
| green: "#00a60e", | ||
| gold: "#ffb100", | ||
| red: "#d92916", | ||
| // Neutral | ||
| offBlack, | ||
| offBlack64: fade(offBlack, 0.64), | ||
| offBlack50: fade(offBlack, 0.5), | ||
| offBlack32: fade(offBlack, 0.32), | ||
| offBlack16: fade(offBlack, 0.16), | ||
| offBlack8: fade(offBlack, 0.08), | ||
| offWhite: "#f7f8fa", | ||
| white, | ||
| white64: fade(white, 0.64), | ||
| white50: fade(white, 0.5), | ||
| // Brand | ||
| darkBlue: "#0b2149", | ||
| teal: "#14bf96", | ||
| lightBlue: "#37c5fd", | ||
| pink: "#fa50ae", | ||
| }; | ||
| const fadedColorWithWhite = (color: string, alpha: number) => | ||
| mix(fade(color, alpha), Color.white); | ||
| mix(fade(color, alpha), baseColors.white); | ||
| export const color = { | ||
| // Wonder Blocks base colors | ||
| ...Color, | ||
| ...baseColors, | ||
| // Additional colors | ||
| white32: fade(Color.white, 0.32), | ||
| white32: fade(baseColors.white, 0.32), | ||
| // Blue shades | ||
| activeBlue: mix(Color.offBlack32, Color.blue), | ||
| fadedBlue: fadedColorWithWhite(Color.blue, 0.32), | ||
| fadedBlue24: fadedColorWithWhite(Color.blue, 0.24), | ||
| fadedBlue16: fadedColorWithWhite(Color.blue, 0.16), | ||
| fadedBlue8: fadedColorWithWhite(Color.blue, 0.08), | ||
| activeBlue: mix(baseColors.offBlack32, baseColors.blue), | ||
| fadedBlue: fadedColorWithWhite(baseColors.blue, 0.32), | ||
| fadedBlue24: fadedColorWithWhite(baseColors.blue, 0.24), | ||
| fadedBlue16: fadedColorWithWhite(baseColors.blue, 0.16), | ||
| fadedBlue8: fadedColorWithWhite(baseColors.blue, 0.08), | ||
| // Red shades | ||
| activeRed: mix(Color.offBlack32, Color.red), | ||
| fadedRed: fadedColorWithWhite(Color.red, 0.32), | ||
| fadedRed24: fadedColorWithWhite(Color.red, 0.24), | ||
| fadedRed16: fadedColorWithWhite(Color.red, 0.16), | ||
| fadedRed8: fadedColorWithWhite(Color.red, 0.08), | ||
| activeRed: mix(baseColors.offBlack32, baseColors.red), | ||
| fadedRed: fadedColorWithWhite(baseColors.red, 0.32), | ||
| fadedRed24: fadedColorWithWhite(baseColors.red, 0.24), | ||
| fadedRed16: fadedColorWithWhite(baseColors.red, 0.16), | ||
| fadedRed8: fadedColorWithWhite(baseColors.red, 0.08), | ||
| // Green shades | ||
| fadedGreen24: fadedColorWithWhite(Color.green, 0.24), | ||
| fadedGreen16: fadedColorWithWhite(Color.green, 0.16), | ||
| fadedGreen24: fadedColorWithWhite(baseColors.green, 0.24), | ||
| fadedGreen16: fadedColorWithWhite(baseColors.green, 0.16), | ||
| // Gold shades | ||
| fadedGold24: fadedColorWithWhite(Color.gold, 0.24), | ||
| fadedGold16: fadedColorWithWhite(Color.gold, 0.16), | ||
| fadedGold24: fadedColorWithWhite(baseColors.gold, 0.24), | ||
| fadedGold16: fadedColorWithWhite(baseColors.gold, 0.16), | ||
| // Purple shades | ||
| fadedPurple24: fadedColorWithWhite(Color.purple, 0.24), | ||
| fadedPurple16: fadedColorWithWhite(Color.purple, 0.16), | ||
| fadedPurple24: fadedColorWithWhite(baseColors.purple, 0.24), | ||
| fadedPurple16: fadedColorWithWhite(baseColors.purple, 0.16), | ||
| // Khanmigo | ||
| eggplant: "#5f1e5c", | ||
| }; |
@@ -10,10 +10,3 @@ { | ||
| }, | ||
| "references": [ | ||
| { | ||
| "path": "../wonder-blocks-color/tsconfig-build.json" | ||
| }, | ||
| { | ||
| "path": "../wonder-blocks-spacing/tsconfig-build.json" | ||
| } | ||
| ] | ||
| "references": [] | ||
| } |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
77865
31.78%0
-100%20
42.86%907
140.58%1
Infinity%- Removed
- Removed