@windijs/helpers
Version:
@windijs/helpers
1,284 lines (1,266 loc) • 44.7 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var shared = require('@windijs/shared');
// https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types
// pre-defined keywords
const initial = "initial";
const inherit = "inherit";
const unset = "unset";
const none = "none";
/**
* Merge two object and their nested children
*/
function mergeObject(a, b) {
return Object.entries(b).reduce((o, [k, v]) => {
o[k] =
v && typeof v === "object"
? mergeObject((o[k] = o[k] || (Array.isArray(v) ? [] : {})), v)
: v;
return o;
}, a);
}
const SymbolCSS = Symbol.for("css");
const SymbolMeta = Symbol.for("meta");
const SymbolData = Symbol.for("data");
const SymbolProxy = Symbol.for("proxy");
function isProxy(i) {
return i != null && SymbolProxy in i;
}
function isStyleObject(i) {
return i != null && (typeof i === "object" || typeof i === "function") && i[SymbolCSS] != null;
}
function isStyleArray(i) {
return Array.isArray(i) && i.find(o => isStyleObject(o) || isStyleArray(o));
}
function getStyleVariants(style) {
return style[SymbolMeta].variants;
}
function getStyleProps(style) {
const { uid, children, props } = style[SymbolMeta];
if (Array.isArray(children))
style = children[0];
return [uid, ...(props ?? [])].filter(i => i != null);
}
function getStyleIdent(style) {
return (getStyleVariants(style)
.map(i => i + ":")
.join("") + getStyleProps(style).join("."));
}
function getFirstVar(style) {
const css = style[SymbolCSS];
for (const [k, v] of shared.entries(css))
if (k.startsWith("--w-"))
return [k, v];
return undefined;
}
function applyVariant(utility) {
let css = utility[SymbolCSS];
for (const variant of utility[SymbolMeta].variants)
css = {
[variant]: css,
};
return css;
}
function useArrayHelper() {
// eslint-disable-next-line no-extend-native
Array.prototype.toString = function () {
return this.join(isStyleArray(this) ? " " : ",");
};
}
/**
* Bundle all utilities to a single css object.
* @param utilities - Utilities and Variants
* @returns CSSObject
*/
function bundle(utilities) {
let vcss;
const css = new Map();
for (const utility of utilities.flat().filter(i => i != null)) {
vcss = applyVariant(utility);
for (const [k, v] of shared.entries(vcss))
if (v != null)
css.set(k, css.has(k) && typeof v === "object" ? mergeObject(css.get(k), v) : v);
}
return css;
}
const prop = (strings, ...expr) => strings.map((string, i) => string + (expr[i] || "")).join("");
// https://drafts.csswg.org/cssom/#serialize-an-identifier
function escapeCSS(str) {
const length = str.length;
let index = -1;
let codeUnit;
let result = "";
const firstCodeUnit = str.charCodeAt(0);
while (++index < length) {
codeUnit = str.charCodeAt(index);
// Note: there’s no need to special-case astral symbols, surrogate
// pairs, or lone surrogates.
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER
// (U+FFFD).
if (codeUnit === 0x0000) {
result += "\uFFFD";
continue;
}
// Comma
if (codeUnit === 44) {
result += "\\2c ";
continue;
}
if (
// If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
// U+007F, […]
(codeUnit >= 0x0001 && codeUnit <= 0x001f) ||
codeUnit === 0x007f ||
// If the character is the first character and is in the range [0-9]
// (U+0030 to U+0039), […]
(index === 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
// If the character is the second character and is in the range [0-9]
// (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
(index === 1 && codeUnit >= 0x0030 && codeUnit <= 0x0039 && firstCodeUnit === 0x002d)) {
// https://drafts.csswg.org/cssom/#escape-a-character-as-code-point
result += "\\" + codeUnit.toString(16) + " ";
continue;
}
if (
// If the character is the first character and is a `-` (U+002D), and
// there is no second character, […]
index === 0 &&
length === 1 &&
codeUnit === 0x002d) {
result += "\\" + str.charAt(index);
continue;
}
// If the character is not handled by one of the above rules and is
// greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or
// is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to
// U+005A), or [a-z] (U+0061 to U+007A), […]
if (codeUnit >= 0x0080 ||
codeUnit === 0x002d ||
codeUnit === 0x005f ||
(codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
(codeUnit >= 0x0041 && codeUnit <= 0x005a) ||
(codeUnit >= 0x0061 && codeUnit <= 0x007a)) {
// the character itself
result += str.charAt(index);
continue;
}
// Otherwise, the escaped character.
// https://drafts.csswg.org/cssom/#escape-a-character
result += "\\" + str.charAt(index);
}
return result;
}
// eslint-disable-next-line @typescript-eslint/no-use-before-define
let CURRENT_NAMER = alphaNamer;
let MINI_COUNT = 0;
const MINI_MAP = {};
// a, b, c ... a0, a1, ...
function alphaCount(n) {
if (n < 26)
return String.fromCharCode(n + 97);
const x = (n - 26) % 36;
return alphaCount(Math.floor((n - 26) / 36)) + (x < 10 ? x.toString() : String.fromCharCode(x + 87));
}
function alphaNamer(style) {
const key = getStyleIdent(style);
if (key in MINI_MAP)
return MINI_MAP[key];
return (MINI_MAP[key] = alphaCount(MINI_COUNT++));
}
function atomicNamer(style) {
// TODO: apply varaint for this
return escapeCSS(getStyleProps(style).join("."));
}
function hashNamer(style) {
return "w-" + shared.hash(getStyleIdent(style));
}
function useNamer(f) {
CURRENT_NAMER = f;
}
function nameStyle(style) {
return CURRENT_NAMER(style);
}
function inline(x, ...utilities) {
const isGet = isStyleObject(x);
const styles = [];
for (const [key, value] of Object.entries(bundle(utilities)))
if (typeof value === "string")
isGet ? styles.push(key + ":" + value) : x.style.setProperty(key, value);
if (isGet)
return styles.join(";");
}
function cssBlock(selector, body = [], rootIndent = 0, childIndent = rootIndent + 2) {
const statements = [];
for (const item of body)
if (typeof item === "string")
statements.push(shared.indent(item, childIndent));
else
statements.push(cssBlock(item.selector, item.body, childIndent + 2));
return [shared.indent(selector, rootIndent) + " {", ...statements, shared.indent("}", rootIndent)].join("\n");
}
function createRules(css, selector) {
const rules = [];
const rootRule = { selector, children: [] };
for (const [key, value] of shared.entries(css))
if (typeof value === "string" || value instanceof String)
rootRule.children.push({ property: key, value: value });
else if (typeof value === "number")
rootRule.children.push({ property: key, value: value.toString() });
else if (Array.isArray(value))
value.map(i => rootRule.children.push({ property: key, value: i }));
else if (typeof value === "object" && value != null) {
if (rootRule.children[0])
rules.push({ ...rootRule });
rootRule.children = [];
const children = selector.charCodeAt(0) === 64 /* @ */ ? { [selector]: value } : value;
if (key.charCodeAt(0) === 64 /* @ */)
rules.push({ rule: key, children: createRules(children, selector) });
else
rules.push(...createRules(children, key.replace(/&/g, selector)));
}
rootRule.children[0] && rules.push(rootRule);
return rules;
}
function buildDecl({ value, property }) {
if (Array.isArray(value))
return value.map(i => property + ": " + i + ";");
return property.startsWith("webkit") ? "-" : "" + shared.camelToDash(property) + ": " + value + ";";
}
function buildRule({ selector, children }, indent = 0) {
return cssBlock(selector, children.map(i => buildDecl(i)).flat(), indent);
}
function buildAtRule({ rule, children }, indent = 0) {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
return cssBlock(rule, createBlockBody(children, indent + 2), indent, 0);
}
function createBlockBody(rules, indent = 0) {
const blocks = [];
for (const rule of rules)
if ("selector" in rule)
blocks.push(buildRule(rule, indent));
else
blocks.push(buildAtRule(rule, indent));
return blocks;
}
function buildRules(rules) {
return createBlockBody(rules).join("\n\n");
}
function dedupRules(rules) {
const styles = [];
const atRules = {};
for (const r of rules)
if ("selector" in r)
styles.push(r);
else if (r.rule in atRules)
atRules[r.rule].children.push(...r.children);
else
atRules[r.rule] = r;
return [...styles, ...Object.values(atRules)];
}
/** build a single StyleObject to css */
function buildStyle(className, style) {
return buildRules(createRules(applyVariant(style), "." + className));
}
function atomic(...utilities) {
const rules = [];
for (const utility of utilities.flat().filter(i => i != null))
rules.push(...createRules(applyVariant(utility), "." + nameStyle(utility)));
return buildRules(dedupRules(rules));
}
const _unify = (selector, utilities) => buildRules(createRules(bundle(utilities), selector));
function unify(...params) {
if (typeof params[0] === "string")
return _unify(params[0], params.slice(1));
const map = Object.assign({}, ...params);
return Object.entries(map)
.map(([k, v]) => (Array.isArray(v) ? _unify(k, v) : _unify(k, [v])))
.join("\n\n");
}
function build(...utilities) {
const rules = [];
for (const utility of utilities.flat().filter(i => i != null)) {
const selector = utility[SymbolMeta].selector;
if (typeof selector === "string")
rules.push(...createRules(applyVariant(utility), selector));
}
return buildRules(dedupRules(rules));
}
function defineConfig(config) {
return config;
}
// TODO: should return object, like CSSPercentage/CSSDimension...
// TODO: support multiple add/sub/mul/div
function sub(left, right) {
if (typeof left === "object" && typeof right === "object")
if (left.type === right.type)
return left.value - right.value + (left.type === "percent" ? "%" : left.type);
return left + " - " + right;
}
function add(left, right) {
if (typeof left === "object" && typeof right === "object")
if (left.type === right.type)
return left.value + right.value + (left.type === "percent" ? "%" : left.type);
return left + " + " + right;
}
function mul(left, right) {
if (typeof left === "number" && typeof right === "object")
return left * right.value + (right.type === "percent" ? "%" : right.type);
if (typeof left === "object" && typeof right === "number")
return left.value * right + (left.type === "percent" ? "%" : left.type);
if (typeof left === "number" && typeof right === "number")
return left * right + "";
return left + " * " + right;
}
function div(left, right) {
if (typeof left === "object" && typeof right === "number")
return left.value / right + (left.type === "percent" ? "%" : left.type);
if (typeof left === "number" && typeof right === "number")
return left / right + "";
return left + " / " + right;
}
const WindiPrecision = 10;
function prec(n) {
return +n.toFixed(WindiPrecision);
}
/* eslint-disable @typescript-eslint/no-this-alias */
function digitToHEX(d) {
let hex = d.toString(16);
hex = "00".slice(0, 2 - hex.length) + hex;
return hex;
}
function rgbToHEX(rgba) {
const rgb = rgba.slice(0, 3);
return "#" + rgb.map(digitToHEX).join("").toLowerCase();
}
function hexToRGB(hex) {
if (hex.length === 4)
hex = "#" + [hex[1], hex[1], hex[2], hex[2], hex[3], hex[3]].join("");
else if (hex.length === 5)
hex = "#" + [hex[1], hex[1], hex[2], hex[2], hex[3], hex[3], hex[4], hex[4]].join("");
const c = +("0x" + hex.substring(1));
if (hex.length === 9)
return [(c >> 24) & 255, (c >> 16) & 255, (c >> 8) & 255, (c & 255) / 256];
return [(c >> 16) & 255, (c >> 8) & 255, c & 255, 1];
}
function sliceColor(str) {
const params = str.slice(str.indexOf("(") + 1, str.indexOf(")"));
return params.indexOf(",") !== -1 ? params.split(/,\s*/) : params.split(/\s+\/?\s*/);
}
function rgbToHSL(rgba) {
const r = rgba[0] / 255;
const g = rgba[1] / 255;
const b = rgba[2] / 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
let h;
let s;
const l = (max + min) / 2;
const d = max - min;
const huecalc = {
[r]: () => (60 * (g - b)) / d + (g < b ? 360 : 0),
[g]: () => (60 * (b - r)) / d + 120,
[b]: () => (60 * (r - g)) / d + 240,
};
if (d === 0)
h = s = 0; // grayscaled color
else {
s = l < 0.5 ? d / (max + min) : d / (2 - max - min);
h = huecalc[max]();
}
return [h, s * 100, l * 100].concat([rgba[3]]);
}
function hueToRGB(p, q, t) {
if (t < 0)
t += 1;
if (t > 1)
t -= 1;
if (t < 1 / 6)
return p + (q - p) * 6 * t;
if (t < 1 / 2)
return q;
if (t < 2 / 3)
return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
function hslToRGB(hsla) {
let r;
let g;
let b;
const h = hsla[0] / 360;
const s = hsla[1] / 100;
const l = hsla[2] / 100;
if (s === 0)
r = g = b = l; // grayscaled color
else {
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
r = hueToRGB(p, q, h + 1 / 3);
g = hueToRGB(p, q, h);
b = hueToRGB(p, q, h - 1 / 3);
}
return [r, g, b]
.map(function (c) {
return Math.round(c * 255);
})
.concat([hsla[3]]);
}
function hwbToRGB(hue, whiteness, blackness, alpha = 1) {
const scaledHue = (hue % 360) / 360;
let scaledWhiteness = whiteness / 100;
let scaledBlackness = blackness / 100;
const sum = scaledWhiteness + scaledBlackness;
if (sum > 1) {
scaledWhiteness /= sum;
scaledBlackness /= sum;
}
const factor = 1 - scaledWhiteness - scaledBlackness;
function toRgb(hue) {
const channel = hueToRGB(0, 1, hue) * factor + scaledWhiteness;
return Math.round(channel * 255);
}
return [toRgb(scaledHue + 1 / 3), toRgb(scaledHue), toRgb(scaledHue - 1 / 3), alpha];
}
function adjustWithScale(rgba, deg, scale = 0, index = 0, len = 100) {
rgba = [...rgba];
rgba[index] = deg
? Math.max(Math.min(rgba[index] + deg, len), 0)
: scale >= 0
? Math.floor(((len - rgba[index]) * scale) / 100 + rgba[index])
: Math.floor(rgba[index] - (rgba[index] * Math.abs(scale)) / 100);
return rgba;
}
function adjustHue(hsla, deg) {
hsla = [...hsla];
hsla[0] = hsla[0] + deg;
return hsla;
}
const adjustSaturation = (hsla, deg, scale = 0) => adjustWithScale(hsla, deg, scale, 1);
const adjustLightness = (hsla, deg, scale = 0) => adjustWithScale(hsla, deg, scale, 2);
const adjustRed = (rgba, deg, scale = 0) => adjustWithScale(rgba, deg, scale, 0, 255);
const adjustGreen = (rgba, deg, scale = 0) => adjustWithScale(rgba, deg, scale, 1, 255);
const adjustBlue = (rgba, deg, scale = 0) => adjustWithScale(rgba, deg, scale, 2, 255);
const adjustAlpha = (hsla, deg, scale = 0) => {
hsla = [...hsla];
hsla[3] = deg
? Math.round(Math.max(Math.min(hsla[3] + deg, 1), 0) * 100) / 100
: scale >= 0
? Math.floor((1 - hsla[3]) * scale + hsla[3] * 100) / 100
: Math.floor(hsla[3] * (100 + scale)) / 100;
return hsla;
};
function mixColor(color1, color2, w = 50) {
const weightScale = w / 100;
const normalizedWeight = weightScale * 2 - 1;
const alphaDistance = color1[3] - color2[3];
const combinedWeight1 = normalizedWeight * alphaDistance === -1 ? normalizedWeight : (normalizedWeight + alphaDistance) / (1 + normalizedWeight * alphaDistance);
const weight1 = (combinedWeight1 + 1) / 2;
const weight2 = 1 - weight1;
return [
Math.round(color1[0] * weight1 + color2[0] * weight2),
Math.round(color1[1] * weight1 + color2[1] * weight2),
Math.round(color1[2] * weight1 + color2[2] * weight2),
color1[3] * weightScale + color2[3] * (1 - weightScale),
];
}
function subMixColor(color1, color2, w = 50) {
return color1.map((c, i) => (i === 3 ? color2[i] + (c - color2[i]) * (w / 100) : Math.floor(color2[i] + (c - color2[i]) * (w / 100))));
}
class Color {
constructor(hexval, rgbaval, hslaval) {
if (Array.isArray(hexval)) {
if (hexval[3] == null)
hexval.push(1);
this.rgbaval = hexval;
this.hexval = rgbToHEX(this.rgbaval);
}
else {
this.hexval = hexval;
this.rgbaval = rgbaval ?? hexToRGB(hexval);
}
this.hslaval = hslaval ?? rgbToHSL(this.rgbaval);
}
static hex(str) {
const hexval = str.toLowerCase();
const rgbaval = hexToRGB(hexval);
const hslaval = rgbToHSL(rgbaval);
return new Color(hexval, rgbaval, hslaval);
}
static rgb(r, g, b, a = 1) {
return Color.rgba(r, g, b, a);
}
static rgba(r, g, b, a) {
const rgbaval = [r, g, b, a];
const hexval = rgbToHEX(rgbaval);
const hslaval = rgbToHSL(rgbaval);
return new Color(hexval, rgbaval, hslaval);
}
static hsl(h, s, l, a = 1) {
return Color.hsla(h, s, l, a);
}
static hsla(h, s, l, a) {
const hslaval = [h, s, l, a];
const rgbaval = hslToRGB(hslaval);
const hexval = rgbToHEX(rgbaval);
return new Color(hexval, rgbaval, hslaval);
}
static hwb(hue, whiteness, blackness, alpha = 1) {
return Color.rgba(...hwbToRGB(hue, whiteness, blackness, alpha));
}
get hex() {
const v = this.hexval;
return v[1] === v[2] && v[3] === v[4] && v[5] === v[6] ? "#" + v[1] + v[3] + v[5] : v;
}
get rgb() {
return this.rgba.slice(0, 3);
}
get rgba() {
return this.rgbaval;
}
get hsl() {
return this.hsla.slice(0, 3);
}
get hsla() {
return this.hslaval.map(i => prec(i));
}
get hwb() {
return [this.hue, this.whiteness, this.blackness];
}
static mix(c1, c2, w = 50) {
return Color.rgba(...mixColor(c1.rgbaval, c2.rgbaval, w));
}
static subcolormix(c1, c2, w = 50) {
return Color.rgba(...subMixColor(c1.rgbaval, c2.rgbaval, w));
}
get red() {
return this.rgbaval[0];
}
get green() {
return this.rgbaval[1];
}
get blue() {
return this.rgbaval[2];
}
get hue() {
return prec(this.hslaval[0]);
}
get saturation() {
return prec(this.hslaval[1]);
}
get lightness() {
return prec(this.hslaval[2]);
}
get alpha() {
return this.rgbaval[3];
}
get opacity() {
return this.alpha;
}
get whiteness() {
const [r, g, b] = this.rgbaval;
return prec((Math.min(Math.min(r, g), b) / 255) * 100);
}
get blackness() {
const [r, g, b] = this.rgbaval;
return prec(100 - (Math.max(Math.max(r, g), b) / 255) * 100);
}
get ieHexStr() {
return "#" + (digitToHEX(this.alpha * 255) + this.hexval.slice(1)).toUpperCase();
}
get rgbStr() {
return `rgb(${this.rgb.join(", ")})`;
}
get rgbaStr() {
return `rgba(${this.rgba.join(", ")})`;
}
get hslStr() {
const [h, s, l] = this.hsl;
return `hsl(${h}, ${s}%, ${l}%)`;
}
get hslaStr() {
const [h, s, l, a] = this.hsla;
return `hsla(${h}, ${s}%, ${l}%, ${a})`;
}
get hwbStr() {
const [h, w, b] = this.hwb;
const a = this.opacity;
return a < 1 ? `hwb(${h} ${w}% ${b}% / ${a})` : `hwb(${h} ${w}% ${b}%)`;
}
invert(weight = 100) {
const inverted = this.rgba.map((c, i) => (i === 3 ? c : Math.round(255 - c)));
return Color.mix(new Color(rgbToHEX(inverted), inverted, rgbToHSL(inverted).concat([inverted[3]])), this, weight);
}
adjustRed(deg, scale = 0) {
return Color.rgba(...adjustRed(this.rgbaval, deg, scale));
}
adjustGreen(deg, scale = 0) {
return Color.rgba(...adjustGreen(this.rgbaval, deg, scale));
}
adjustBlue(deg, scale = 0) {
return Color.rgba(...adjustBlue(this.rgbaval, deg, scale));
}
adjustHue(deg) {
return Color.hsla(...adjustHue(this.hslaval, deg));
}
adjustSaturation(deg, scale = 0) {
return Color.hsla(...adjustSaturation(this.hslaval, deg, scale));
}
adjustLightness(deg, scale = 0) {
return Color.hsla(...adjustLightness(this.hslaval, deg, scale));
}
adjustAlpha(deg, scale = 0) {
return Color.hsla(...adjustAlpha(this.hslaval, deg, scale));
}
complement() {
return this.adjustHue(180);
}
saturate(deg) {
return this.adjustSaturation(deg);
}
desaturate(deg) {
return this.adjustSaturation(-deg);
}
grayscale() {
return this.adjustSaturation(-100);
}
lighten(amount) {
return this.adjustLightness(amount);
}
darken(amount) {
return this.adjustLightness(-amount);
}
opacify(deg) {
return this.adjustAlpha(deg);
}
transparentize(deg) {
return this.adjustAlpha(-deg);
}
fadeIn(deg) {
return this.adjustAlpha(deg);
}
fadeOut(deg) {
return this.adjustAlpha(-deg);
}
adjust(opt) {
let color = this;
for (const [k, v] of Object.entries(opt))
color = color[("adjust" + k[0].toUpperCase() + k.slice(1))](v);
return color;
}
scale(opt) {
let color = this;
for (const [k, v] of Object.entries(opt))
color = color[("adjust" + k[0].toUpperCase() + k.slice(1))](undefined, v);
return color;
}
change(opt) {
let rgba = this.rgba;
let hsla = this.hsla;
for (const [k, v] of Object.entries(opt))
switch (k) {
case "red":
rgba[0] = v;
hsla = rgbToHSL(rgba);
break;
case "green":
rgba[1] = v;
hsla = rgbToHSL(rgba);
break;
case "blue":
rgba[2] = v;
hsla = rgbToHSL(rgba);
break;
case "hue":
hsla[0] = v;
rgba = hslToRGB(hsla);
break;
case "saturation":
hsla[1] = v;
rgba = hslToRGB(hsla);
break;
case "lightness":
hsla[2] = v;
rgba = hslToRGB(hsla);
break;
case "alpha":
rgba[3] = v;
hsla[3] = v;
break;
}
return new Color(rgbToHEX(rgba), rgba, hsla);
}
// Color Sets
lightenSet(n) {
return [this].concat(shared.range(1, n).map(i => this.adjustLightness(undefined, (100 / n) * i)));
}
darkenSet(n) {
return [this].concat(shared.range(1, n).map(i => this.adjustLightness(undefined, -((100 / n) * i))));
}
desaturateSet(n) {
return [this].concat(shared.range(1, n).map(i => this.adjustSaturation(undefined, -((100 / n) * i))));
}
complementSet(n) {
const comp = this.complement();
return shared.range(0, n)
.reverse()
.map(i => (i === n - 1 ? this : i === 0 ? comp : Color.subcolormix(this, comp, (100 / (n - 1)) * i)));
}
invertSet(n) {
const inv = this.invert();
return shared.range(0, n)
.reverse()
.map(i => (i === n - 1 ? this : i === 0 ? inv : Color.subcolormix(this, inv, (100 / (n - 1)) * i)));
}
}
function colorLuminance(color) {
const rgb = color.rgb.map(i => i / 255).map(v => (v < 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2));
return prec(rgb[0] * 0.2126 + rgb[1] * 0.7152 + rgb[2] * 0.0722);
}
function getLightColor(color, lightness = 96) {
return color.change({ lightness: color.lightness > 96 ? color.lightness : lightness });
}
function getDarkColor(color, lightness = 29) {
return color.change({
lightness: Math.max(lightness, Math.round(lightness + (0.53 - colorLuminance(color)) * 53)),
});
}
let CurrentMeta;
function resetMeta(uid = "css", type = "css", props = [], variants = []) {
CurrentMeta = { uid, type, props, variants };
}
resetMeta();
function getMeta() {
return CurrentMeta;
}
function getUid() {
return CurrentMeta.uid;
}
function pushMetaProp(prop) {
return CurrentMeta.props.push(prop);
}
function updateMetaType(type) {
CurrentMeta.type = type;
}
function resetStyleMeta(style, meta = CurrentMeta) {
style[SymbolMeta] = meta;
return style;
}
const baseStyleTarget = (css, meta, data) => {
if (data != null)
// push func prop, for example bg.red.opacity(50) -> [..., opacity(50)]
for (const [k, v] of Object.entries(data))
if (typeof v === "function")
data[k] = (...args) => {
pushMetaProp(shared.parenWrap(k, args.toString()));
return v(...args);
};
return {
[SymbolProxy]: true,
[SymbolCSS]: css,
[SymbolMeta]: meta,
[SymbolData]: data,
};
};
const baseStyleHandler = (target, prop, receiver) => {
if (prop === "css")
return Reflect.get(target, SymbolCSS, receiver);
if (prop === "meta")
return Reflect.get(target, SymbolMeta, receiver);
const data = Reflect.get(target, SymbolData, receiver);
if (data && prop in data)
return data[prop];
return Reflect.get(target, prop, receiver);
};
let CurrentLoader = (css, meta, data) => new Proxy(baseStyleTarget(css, meta, data), { get: baseStyleHandler });
function useStyleLoader(loader) {
CurrentLoader = loader;
}
function css(css, data, meta) {
return CurrentLoader(css, meta ?? getMeta(), data);
}
const BUILDED_CLASSES = [];
function injectCSS(css) {
const container = document.getElementById("windijs");
if (container)
container.textContent += "\n" + css;
else {
const el = document.createElement("style");
el.id = "windijs";
el.setAttribute("type", "text/css");
el.textContent = css;
document.head.appendChild(el);
}
}
/** Create a styleLoader */
function createStyleLoader(inject) {
return (css, meta, data) => {
const baseStyle = baseStyleTarget(css, meta, data);
const className = nameStyle(baseStyle);
return new Proxy({
[className]: true,
...baseStyle,
}, {
get(target, prop, receiver) {
// for react, svelte...
if (prop === "toString")
return () => {
inject(className, baseStyle);
return Object.keys(target).join(" ");
};
// for vue
if (prop === className) {
inject(className, baseStyle);
return Reflect.get(target, prop, receiver);
}
return baseStyleHandler(target, prop, receiver);
},
});
};
}
/** CSS-In-JS Loader */
const cssInJsLoader = createStyleLoader((className, style) => {
if (!BUILDED_CLASSES.includes(className)) {
BUILDED_CLASSES.push(className);
injectCSS(buildStyle(className, style));
}
});
const SSR_CLASSES = [];
const SSR_CSS_LIST = [];
/** SSR Loader */
const ssrLoader = createStyleLoader((className, style) => {
if (!SSR_CLASSES.includes(className)) {
SSR_CLASSES.push(className);
SSR_CSS_LIST.push(buildStyle(className, style));
}
});
/** Mount server side generated css */
function mountCSS() {
return SSR_CSS_LIST.join("\n");
}
function apply(selector, ...utilities) {
return css(bundle(utilities), undefined, {
uid: "apply",
type: "css",
props: [selector],
variants: [],
selector,
});
}
function funcProxy(f) {
return new Proxy(f, {
get(target, p) {
return Reflect.apply(target, undefined, [p]);
},
apply(target, thisArg, argArray) {
return Reflect.apply(target, thisArg, argArray);
},
});
}
let GLOBAL_STYLES = [];
function queryStyles(selector) {
for (let i = GLOBAL_STYLES.length - 1; i >= 0; i--)
if (GLOBAL_STYLES[i].selector === selector)
return GLOBAL_STYLES[i].children;
}
function globalApply(selector, ...utilities) {
const style = apply(selector, ...utilities);
GLOBAL_STYLES.push({
selector,
children: utilities.flat().filter(i => i != null),
style,
});
return style;
}
function createDollarCall(selector) {
return new Proxy(globalApply, {
get(target, p) {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
if (p === "ATTR")
return createAttrProxy(selector);
if (p === "styles")
return queryStyles(selector) ?? [];
if (p === "$")
selector += ", ";
else if (p === "$$")
selector += " > ";
else if (p === "_")
selector += " ";
else if (p === "__")
selector += " + ";
else if (p === "_$_")
selector += " ~ ";
else if (p.charCodeAt(0) < 91)
selector += p.toLowerCase(); // HTML Elements
// eslint-disable-next-line @typescript-eslint/no-unused-vars
else
selector += "." + p;
return createDollarCall(selector);
},
apply(target, thisArg, argArray) {
return Reflect.apply(target, thisArg, [selector, ...argArray]);
},
});
}
const attrMatches = {
match: "=",
hyphenMatch: "|=",
contains: "~=",
includes: "*=",
startsWith: "^=",
endsWith: "$=",
};
const createAttrProxy = (selector) => funcProxy(function (attribute) {
return new Proxy(globalApply, {
get(target, p) {
if (p in attrMatches)
return funcProxy(function (v) {
selector += `[${attribute}${attrMatches[p]}${JSON.stringify(v)}]`;
return createDollarCall(selector);
});
return Reflect.get(createDollarCall(selector), p);
},
apply(target, thisArg, argArray) {
selector += `[${attribute}]`;
return Reflect.apply(target, thisArg, [selector, ...argArray]);
},
});
});
const $ = new Proxy(globalApply, {
get(target, p) {
if (p === "call")
return (thisArg, ...args) => Reflect.apply(target, thisArg, args);
if (p === "init")
return () => (GLOBAL_STYLES = []);
if (p === "exports")
return GLOBAL_STYLES;
if (p === "styles")
return new Proxy(GLOBAL_STYLES.map(i => i.children).flat(), {
get(target, p) {
if (Reflect.has(target, p))
return Reflect.get(target, p);
return queryStyles(p);
},
});
let selector = "";
if (p === "ID")
return funcProxy(function (id) {
selector += "#" + id;
return createDollarCall(selector);
});
if (p === "ATTR")
return createAttrProxy(selector);
if (p === "All")
selector += "*";
else if (p === "Root")
selector += ":root";
// TODO: support :host(.selector)
else if (p === "Host")
selector += ":host";
else if (p.charCodeAt(0) < 91)
selector += p.toLowerCase(); // HTML Elements
// eslint-disable-next-line @typescript-eslint/no-unused-vars
else
selector += "." + p;
return createDollarCall(selector);
},
});
function quote(str) {
return `${JSON.stringify(str).replace(/\\\\/g, "\\")}`;
}
// https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions
// TODO: more detailed help documentation for css functions
// TODO: support var as type & param
// TODO: support calc as type & param
// reference functionns
function attr(name, type, fallback) {
const defaultValue = fallback != null ? ", " + fallback : "";
if (!type)
return shared.parenWrap("attr", name + defaultValue);
return shared.parenWrap("attr", name + " " + type + defaultValue);
}
function url(url, base64 = false, dataType = "image/png") {
return shared.parenWrap("url", base64 ? `data:${dataType};base64,` + url : url);
}
function $var(name, defaultValue) {
return defaultValue ? `var(--${name}, ${defaultValue})` : `var(--${name})`;
}
// shape functions
function path(path, fillRule) {
return shared.parenWrap("path", fillRule ? fillRule + ", " + JSON.stringify(path) : JSON.stringify(path));
}
// color functions
/** Creates a Color from hue, white and black. */
function hwb(hue, whiteness, blackness, alpha) {
return shared.parenWrap("hwb", [hue, whiteness, blackness].join(" ") + (alpha ? " / " + alpha : ""));
}
// filter functions
function dropShadow(offsetX, offsetY, blurRadius, color) {
return shared.parenWrap("drop-shadow", [offsetX, offsetY, blurRadius, color].join(" "));
}
function counters(name, char, style) {
return shared.parenWrap("counters", [name, JSON.stringify(char), style].filter(i => i != null).join(", "));
}
// shape functions
function circle(shapeRadius, positon) {
return shared.parenWrap("circle", positon == null ? shapeRadius.toString() : shapeRadius + " at " + (Array.isArray(positon) ? positon.join(" ") : positon));
}
function ellipse(shapeRadiusX, shapeRadiusY, positon) {
const shapeRadius = [shapeRadiusX, shapeRadiusY].join(" ");
return shared.parenWrap("ellipse", positon == null ? shapeRadius : shapeRadius + " at " + (Array.isArray(positon) ? positon.join(" ") : positon));
}
function round(radius, radius2, radius3, radius4) {
if (Array.isArray(radius) || Array.isArray(radius2))
return [radius, radius2].map(i => (Array.isArray(i) ? i.join(" ") : i)).join(" / ");
return [radius, radius2, radius3, radius4].filter(i => i != null).join(" ");
}
class Inset {
constructor(values) {
this.values = [];
this.values = values;
this.round = ((a, b, c, d) => shared.parenWrap("inset", this.values.filter(i => i != null).join(" ") + " round " + round(a, b, c, d)));
}
toString() {
return shared.parenWrap("inset", this.values.filter(i => i != null).join(" "));
}
}
function inset(lengthOrPercent, lengthOrPercent2, lengthOrPercent3, lengthOrPercent4) {
return new Inset([lengthOrPercent, lengthOrPercent2, lengthOrPercent3, lengthOrPercent4]);
}
function polygon(fillRule, ...lengthOrPercent) {
return shared.parenWrap("polygon", [fillRule, ...lengthOrPercent]
.filter(i => i != null)
.map(i => (Array.isArray(i) ? i.join(" ") : i))
.join(", "));
}
const { matrix, matrix3d, perspective, rotate, rotate3d, rotateX, rotateY, rotateZ, scale, scale3d, scaleX, scaleY, scaleZ, skew, skewX, skewY, translate, translate3d, translateX, translateY, translateZ, steps, calc, clamp, max, min, abs, sign, blur, brightness, contrast, grayscale, invert, opacity, saturate, sepia, rgb, rgba, hsl, hsla, counter, env, minmax, repeat, } = new Proxy({}, {
get(_, p) {
return (...args) => p + "(" + args.filter(i => i != null).join(", ") + ")";
},
});
const { hueRotate, fitContent, cubicBezier, linearGradient, radialGradient, conicGradient, repeatingConicGradient, repeatingLinearGradient, repeatingRadialGradient, } = new Proxy({}, {
get(_, p) {
return (...args) => shared.camelToDash(p) +
"(" +
args
.map(i => (Array.isArray(i) ? i.join(" ") : i))
.filter(i => i != null)
.join(", ") +
")";
},
});
const filters = {
blur,
brightness,
contrast,
dropShadow,
grayscale,
hueRotate,
invert,
saturate,
sepia,
};
// export const transforms = { rotate, rotate3d, rotateX, rotateY, rotateZ, scale, scale3d, scaleX, scaleY, scaleZ, skew, skewX, skewY, translate, translate3d, translateX, translateY, translateZ };
const transforms = { rotate, scale, skew, translate };
// Color
const color = new Proxy({}, {
get: (_, v) => {
const map = { var: $var, calc, rgb, rgba, hsl, hsla, hwb };
return v in map ? map[v] : v;
},
});
function dimension(type, suffix = type) {
return new Proxy({}, {
get: (_, value) => Object.create({
value: +value,
type,
valueOf: () => value + suffix,
toString: () => value + suffix,
}),
});
}
const percent = dimension("percent", "%");
const { deg, grad, rad, turn } = new Proxy({}, { get: (_, k) => dimension(k) });
const { s, ms } = new Proxy({}, { get: (_, k) => dimension(k) });
const fr = dimension("fr");
const $in = dimension("in");
const { dpi, dpcm, dppx, x } = new Proxy({}, { get: (_, k) => dimension(k) });
const { px, pc, pt, cm, mm, Q, ch, ex, em, rem, vw, vh, vmax, vmin } = new Proxy({}, {
get: (_, k) => dimension(k),
});
exports.$ = $;
exports.$in = $in;
exports.$var = $var;
exports.Color = Color;
exports.Q = Q;
exports.SymbolCSS = SymbolCSS;
exports.SymbolData = SymbolData;
exports.SymbolMeta = SymbolMeta;
exports.SymbolProxy = SymbolProxy;
exports.abs = abs;
exports.add = add;
exports.adjustAlpha = adjustAlpha;
exports.adjustBlue = adjustBlue;
exports.adjustGreen = adjustGreen;
exports.adjustHue = adjustHue;
exports.adjustLightness = adjustLightness;
exports.adjustRed = adjustRed;
exports.adjustSaturation = adjustSaturation;
exports.alphaCount = alphaCount;
exports.alphaNamer = alphaNamer;
exports.apply = apply;
exports.applyVariant = applyVariant;
exports.atomic = atomic;
exports.atomicNamer = atomicNamer;
exports.attr = attr;
exports.baseStyleHandler = baseStyleHandler;
exports.baseStyleTarget = baseStyleTarget;
exports.blur = blur;
exports.brightness = brightness;
exports.build = build;
exports.buildAtRule = buildAtRule;
exports.buildDecl = buildDecl;
exports.buildRule = buildRule;
exports.buildRules = buildRules;
exports.buildStyle = buildStyle;
exports.bundle = bundle;
exports.calc = calc;
exports.ch = ch;
exports.circle = circle;
exports.clamp = clamp;
exports.cm = cm;
exports.color = color;
exports.colorLuminance = colorLuminance;
exports.conicGradient = conicGradient;
exports.contrast = contrast;
exports.counter = counter;
exports.counters = counters;
exports.createRules = createRules;
exports.createStyleLoader = createStyleLoader;
exports.css = css;
exports.cssInJsLoader = cssInJsLoader;
exports.cubicBezier = cubicBezier;
exports.dedupRules = dedupRules;
exports.defineConfig = defineConfig;
exports.deg = deg;
exports.digitToHEX = digitToHEX;
exports.div = div;
exports.dpcm = dpcm;
exports.dpi = dpi;
exports.dppx = dppx;
exports.dropShadow = dropShadow;
exports.ellipse = ellipse;
exports.em = em;
exports.env = env;
exports.escapeCSS = escapeCSS;
exports.ex = ex;
exports.filters = filters;
exports.fitContent = fitContent;
exports.fr = fr;
exports.getDarkColor = getDarkColor;
exports.getFirstVar = getFirstVar;
exports.getLightColor = getLightColor;
exports.getMeta = getMeta;
exports.getStyleIdent = getStyleIdent;
exports.getStyleProps = getStyleProps;
exports.getStyleVariants = getStyleVariants;
exports.getUid = getUid;
exports.grad = grad;
exports.grayscale = grayscale;
exports.hashNamer = hashNamer;
exports.hexToRGB = hexToRGB;
exports.hsl = hsl;
exports.hslToRGB = hslToRGB;
exports.hsla = hsla;
exports.hueRotate = hueRotate;
exports.hueToRGB = hueToRGB;
exports.hwb = hwb;
exports.hwbToRGB = hwbToRGB;
exports.inherit = inherit;
exports.initial = initial;
exports.injectCSS = injectCSS;
exports.inline = inline;
exports.inset = inset;
exports.invert = invert;
exports.isProxy = isProxy;
exports.isStyleArray = isStyleArray;
exports.isStyleObject = isStyleObject;
exports.linearGradient = linearGradient;
exports.matrix = matrix;
exports.matrix3d = matrix3d;
exports.max = max;
exports.mergeObject = mergeObject;
exports.min = min;
exports.minmax = minmax;
exports.mixColor = mixColor;
exports.mm = mm;
exports.mountCSS = mountCSS;
exports.ms = ms;
exports.mul = mul;
exports.nameStyle = nameStyle;
exports.none = none;
exports.opacity = opacity;
exports.path = path;
exports.pc = pc;
exports.percent = percent;
exports.perspective = perspective;
exports.polygon = polygon;
exports.prec = prec;
exports.prop = prop;
exports.pt = pt;
exports.pushMetaProp = pushMetaProp;
exports.px = px;
exports.queryStyles = queryStyles;
exports.quote = quote;
exports.rad = rad;
exports.radialGradient = radialGradient;
exports.rem = rem;
exports.repeat = repeat;
exports.repeatingConicGradient = repeatingConicGradient;
exports.repeatingLinearGradient = repeatingLinearGradient;
exports.repeatingRadialGradient = repeatingRadialGradient;
exports.resetMeta = resetMeta;
exports.resetStyleMeta = resetStyleMeta;
exports.rgb = rgb;
exports.rgbToHEX = rgbToHEX;
exports.rgbToHSL = rgbToHSL;
exports.rgba = rgba;
exports.rotate = rotate;
exports.rotate3d = rotate3d;
exports.rotateX = rotateX;
exports.rotateY = rotateY;
exports.rotateZ = rotateZ;
exports.s = s;
exports.saturate = saturate;
exports.scale = scale;
exports.scale3d = scale3d;
exports.scaleX = scaleX;
exports.scaleY = scaleY;
exports.scaleZ = scaleZ;
exports.sepia = sepia;
exports.sign = sign;
exports.skew = skew;
exports.skewX = skewX;
exports.skewY = skewY;
exports.sliceColor = sliceColor;
exports.ssrLoader = ssrLoader;
exports.steps = steps;
exports.sub = sub;
exports.subMixColor = subMixColor;
exports.transforms = transforms;
exports.translate = translate;
exports.translate3d = translate3d;
exports.translateX = translateX;
exports.translateY = translateY;
exports.translateZ = translateZ;
exports.turn = turn;
exports.unify = unify;
exports.unset = unset;
exports.updateMetaType = updateMetaType;
exports.url = url;
exports.useArrayHelper = useArrayHelper;
exports.useNamer = useNamer;
exports.useStyleLoader = useStyleLoader;
exports.vh = vh;
exports.vmax = vmax;
exports.vmin = vmin;
exports.vw = vw;
exports.x = x;