UNPKG

@clerk/themes

Version:

Themes for the Clerk auth components

331 lines (330 loc) • 9.23 kB
"use strict"; /* eslint-disable no-useless-escape */ /** * These helpers have been extracted from the following libraries, * converted to Typescript and adapted to our needs. * * https://github.com/Qix-/color-convert * https://github.com/Qix-/color-name * https://github.com/Qix-/color */ Object.defineProperty(exports, "__esModule", { value: true }); exports.colors = void 0; const abbrRegex = /^#([a-f0-9]{3,4})$/i; const hexRegex = /^#([a-f0-9]{6})([a-f0-9]{2})?$/i; const rgbaRegex = /^rgba?\(\s*([+-]?\d+)(?=[\s,])\s*(?:,\s*)?([+-]?\d+)(?=[\s,])\s*(?:,\s*)?([+-]?\d+)\s*(?:[,|\/]\s*([+-]?[\d\.]+)(%?)\s*)?\)$/; const perRegex = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,?\s*([+-]?[\d\.]+)\%\s*,?\s*([+-]?[\d\.]+)\%\s*(?:[,|\/]\s*([+-]?[\d\.]+)(%?)\s*)?\)$/; const hslRegex = /^hsla?\(\s*([+-]?(?:\d{0,3}\.)?\d+)(?:deg)?\s*,?\s*([+-]?[\d\.]+)%\s*,?\s*([+-]?[\d\.]+)%\s*(?:[,|\/]\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/; const hwbRegex = /^hwb\(\s*([+-]?\d{0,3}(?:\.\d+)?)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/; // List of common css keywords. // https://github.com/colorjs/color-name const keywords = { black: [0, 0, 0, 1], blue: [0, 0, 255, 1], red: [255, 0, 0, 1], green: [0, 128, 0, 1], grey: [128, 128, 128, 1], gray: [128, 128, 128, 1], white: [255, 255, 255, 1], yellow: [255, 255, 0, 1], transparent: [0, 0, 0, 0], }; const clamp = (num, min, max) => Math.min(Math.max(min, num), max); const parseRgb = (str) => { if (!str) { return null; } const rgb = [0, 0, 0, 1]; let match; let i; let hexAlpha; if ((match = str.match(hexRegex))) { hexAlpha = match[2]; match = match[1]; for (i = 0; i < 3; i++) { const i2 = i * 2; rgb[i] = parseInt(match.slice(i2, i2 + 2), 16); } if (hexAlpha) { rgb[3] = parseInt(hexAlpha, 16) / 255; } } else if ((match = str.match(abbrRegex))) { match = match[1]; hexAlpha = match[3]; for (i = 0; i < 3; i++) { rgb[i] = parseInt(match[i] + match[i], 16); } if (hexAlpha) { rgb[3] = parseInt(hexAlpha + hexAlpha, 16) / 255; } } else if ((match = str.match(rgbaRegex))) { for (i = 0; i < 3; i++) { rgb[i] = parseInt(match[i + 1], 0); } if (match[4]) { if (match[5]) { rgb[3] = parseFloat(match[4]) * 0.01; } else { rgb[3] = parseFloat(match[4]); } } } else if ((match = str.match(perRegex))) { for (i = 0; i < 3; i++) { rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55); } if (match[4]) { if (match[5]) { rgb[3] = parseFloat(match[4]) * 0.01; } else { rgb[3] = parseFloat(match[4]); } } } else if (str in keywords) { return keywords[str]; } else { return null; } for (i = 0; i < 3; i++) { rgb[i] = clamp(rgb[i], 0, 255); } rgb[3] = clamp(rgb[3], 0, 1); return rgb; }; const parseHsl = (str) => { if (!str) { return null; } const match = str.match(hslRegex); return match ? transformHslOrHwb(match) : null; }; const parseHwb = function (str) { if (!str) { return null; } const match = str.match(hwbRegex); return match ? transformHslOrHwb(match) : null; }; const transformHslOrHwb = (match) => { const alpha = parseFloat(match[4]); const hh = ((parseFloat(match[1]) % 360) + 360) % 360; const sw = clamp(parseFloat(match[2]), 0, 100); const lb = clamp(parseFloat(match[3]), 0, 100); const aa = clamp(isNaN(alpha) ? 1 : alpha, 0, 1); return [hh, sw, lb, aa]; }; const hslaTupleToHslaColor = (hsla) => { var _a; return { h: hsla[0], s: hsla[1], l: hsla[2], a: (_a = hsla[3]) !== null && _a !== void 0 ? _a : 1 }; }; const hwbTupleToRgbTuple = (hwb) => { var _a; const h = hwb[0] / 360; let wh = hwb[1] / 100; let bl = hwb[2] / 100; const a = (_a = hwb[3]) !== null && _a !== void 0 ? _a : 1; const ratio = wh + bl; let f; // Wh + bl cant be > 1 if (ratio > 1) { wh /= ratio; bl /= ratio; } const i = Math.floor(6 * h); const v = 1 - bl; f = 6 * h - i; if ((i & 0x01) !== 0) { f = 1 - f; } const n = wh + f * (v - wh); // Linear interpolation let r; let g; let b; switch (i) { default: case 6: case 0: r = v; g = n; b = wh; break; case 1: r = n; g = v; b = wh; break; case 2: r = wh; g = v; b = n; break; case 3: r = wh; g = n; b = v; break; case 4: r = n; g = wh; b = v; break; case 5: r = v; g = wh; b = n; break; } return [r * 255, g * 255, b * 255, a]; }; const rgbaTupleToHslaColor = (rgb) => { var _a; const r = rgb[0] / 255; const g = rgb[1] / 255; const b = rgb[2] / 255; const a = (_a = rgb[3]) !== null && _a !== void 0 ? _a : 1; const min = Math.min(r, g, b); const max = Math.max(r, g, b); const delta = max - min; let h; let s; if (max === min) { h = 0; } else if (r === max) { h = (g - b) / delta; } else if (g === max) { h = 2 + (b - r) / delta; } else if (b === max) { h = 4 + (r - g) / delta; } // @ts-ignore h = Math.min(h * 60, 360); if (h < 0) { h += 360; } const l = (min + max) / 2; if (max === min) { s = 0; } else if (l <= 0.5) { s = delta / (max + min); } else { s = delta / (2 - max - min); } return { h: Math.floor(h), s: Math.floor(s * 100), l: Math.floor(l * 100), a }; }; const hwbTupleToHslaColor = (hwb) => { return rgbaTupleToHslaColor(hwbTupleToRgbTuple(hwb)); }; const hslaColorToHslaString = ({ h, s, l, a }) => { return `hsla(${h}, ${s}%, ${l}%, ${a !== null && a !== void 0 ? a : 1})`; }; const parse = (str) => { const prefix = str.substr(0, 3).toLowerCase(); let res; if (prefix === 'hsl') { res = { model: 'hsl', value: parseHsl(str) }; } else if (prefix === 'hwb') { res = { model: 'hwb', value: parseHwb(str) }; } else { res = { model: 'rgb', value: parseRgb(str) }; } if (!res || !res.value) { throw new Error(`Clerk: "${str}" cannot be used as a color within 'variables'. You can pass one of: - any valid hsl or hsla color - any valid rgb or rgba color - any valid hex color - any valid hwb color - ${Object.keys(keywords).join(', ')} `); } return res; }; const toHslaColor = (str) => { const { model, value } = parse(str); switch (model) { case 'hsl': return hslaTupleToHslaColor(value); case 'hwb': return hwbTupleToHslaColor(value); case 'rgb': return rgbaTupleToHslaColor(value); } }; const toHslaString = (hsla) => { return typeof hsla === 'string' ? hslaColorToHslaString(toHslaColor(hsla)) : hslaColorToHslaString(hsla); }; const changeHslaLightness = (color, num) => { return { ...color, l: color.l + num }; }; const setHslaAlpha = (color, num) => { return { ...color, a: num }; }; const changeHslaAlpha = (color, num) => { return { ...color, a: color.a ? color.a - num : undefined }; }; const lighten = (color, percentage = 0) => { if (!color) { return undefined; } const hsla = toHslaColor(color); return toHslaString(changeHslaLightness(hsla, hsla.l * percentage)); }; const makeSolid = (color) => { if (!color) { return undefined; } return toHslaString({ ...toHslaColor(color), a: 1 }); }; const makeTransparent = (color, percentage = 0) => { var _a; if (!color || color.toString() === '') { return undefined; } const hsla = toHslaColor(color); return toHslaString(changeHslaAlpha(hsla, ((_a = hsla.a) !== null && _a !== void 0 ? _a : 1) * percentage)); }; const setAlpha = (color, alpha) => { if (!color.toString()) { return color; } return toHslaString(setHslaAlpha(toHslaColor(color), alpha)); }; const adjustForLightness = (color, lightness = 5) => { if (!color) { return undefined; } const hsla = exports.colors.toHslaColor(color); if (!hsla) { return color; } if (hsla.l === 100) { hsla.l = 95; } else { hsla.l = Math.min(hsla.l + 2 * lightness, 100); } return exports.colors.toHslaString(hsla); }; exports.colors = { toHslaColor, toHslaString, adjustForLightness, changeHslaLightness, setHslaAlpha, lighten, makeTransparent, makeSolid, setAlpha, };