@tenphi/tasty 2.6.5 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{collector-c00_hT9R.js → collector-BEF4F_PE.js} +3 -3
- package/dist/{collector-c00_hT9R.js.map → collector-BEF4F_PE.js.map} +1 -1
- package/dist/{collector-osfWTeRd.d.ts → collector-CpU85p2G.d.ts} +2 -2
- package/dist/{config-BoZDUHW5.d.ts → config-3h7BtX4l.d.ts} +2 -2
- package/dist/{config-IzenlK2R.js → config-BDnvK42H.js} +308 -74
- package/dist/config-BDnvK42H.js.map +1 -0
- package/dist/core/index.d.ts +5 -5
- package/dist/core/index.js +6 -6
- package/dist/{core-J9U8fXzr.js → core-BiFQGi4v.js} +5 -5
- package/dist/{core-J9U8fXzr.js.map → core-BiFQGi4v.js.map} +1 -1
- package/dist/{css-writer-CCyaR6ZM.js → css-writer-4IMPW4i1.js} +3 -3
- package/dist/{css-writer-CCyaR6ZM.js.map → css-writer-4IMPW4i1.js.map} +1 -1
- package/dist/{format-rules-CCb7qNPt.js → format-rules-DrpEA0CZ.js} +2 -2
- package/dist/{format-rules-CCb7qNPt.js.map → format-rules-DrpEA0CZ.js.map} +1 -1
- package/dist/{hydrate-DEsdmcdy.js → hydrate-DItCQmmZ.js} +2 -2
- package/dist/{hydrate-DEsdmcdy.js.map → hydrate-DItCQmmZ.js.map} +1 -1
- package/dist/{index-tcHuMPFt.d.ts → index-BsJz5xBF.d.ts} +2 -2
- package/dist/{index-D-OA_O6i.d.ts → index-C_SRmAWj.d.ts} +193 -163
- package/dist/index.d.ts +5 -5
- package/dist/index.js +7 -7
- package/dist/{keyframes-DxAp6xwG.js → keyframes-DYGxQPjN.js} +2 -2
- package/dist/{keyframes-DxAp6xwG.js.map → keyframes-DYGxQPjN.js.map} +1 -1
- package/dist/{merge-styles-BMWcH6MF.d.ts → merge-styles-BzOwGOGC.d.ts} +2 -2
- package/dist/{merge-styles-Ugifi570.js → merge-styles-oU4CfZY7.js} +2 -2
- package/dist/{merge-styles-Ugifi570.js.map → merge-styles-oU4CfZY7.js.map} +1 -1
- package/dist/{resolve-recipes-DEmQhiop.js → resolve-recipes-PwM-R6Jc.js} +3 -3
- package/dist/{resolve-recipes-DEmQhiop.js.map → resolve-recipes-PwM-R6Jc.js.map} +1 -1
- package/dist/ssr/astro-client.js +1 -1
- package/dist/ssr/astro.js +3 -3
- package/dist/ssr/index.d.ts +1 -1
- package/dist/ssr/index.js +3 -3
- package/dist/ssr/next.d.ts +1 -1
- package/dist/ssr/next.js +4 -4
- package/dist/static/index.d.ts +2 -2
- package/dist/static/index.js +1 -1
- package/dist/zero/babel.d.ts +1 -1
- package/dist/zero/babel.js +4 -4
- package/dist/zero/index.d.ts +1 -1
- package/dist/zero/index.js +1 -1
- package/docs/dsl.md +110 -1
- package/docs/pipeline.md +40 -2
- package/package.json +5 -5
- package/dist/config-IzenlK2R.js.map +0 -1
|
@@ -453,7 +453,19 @@ const K2 = .03;
|
|
|
453
453
|
const K3 = (1 + K1) / (1 + K2);
|
|
454
454
|
const clamp$1 = (value, min, max) => Math.max(Math.min(value, max), min);
|
|
455
455
|
const constrainAngle = (angle) => (angle % 360 + 360) % 360;
|
|
456
|
+
const toe = (x) => .5 * (K3 * x - K1 + Math.sqrt((K3 * x - K1) * (K3 * x - K1) + 4 * K2 * K3 * x));
|
|
456
457
|
const toeInv = (x) => (x ** 2 + K1 * x) / (K3 * (x + K2));
|
|
458
|
+
const OKHST_REF_EPS = .05;
|
|
459
|
+
function yToL(y) {
|
|
460
|
+
return toe(Math.cbrt(Math.max(0, y)));
|
|
461
|
+
}
|
|
462
|
+
function yFromTone(t, eps = OKHST_REF_EPS) {
|
|
463
|
+
const den = Math.log(1 + eps) - Math.log(eps);
|
|
464
|
+
return Math.exp(t / 100 * den + Math.log(eps)) - eps;
|
|
465
|
+
}
|
|
466
|
+
function fromTone(t, eps = OKHST_REF_EPS) {
|
|
467
|
+
return yToL(yFromTone(t, eps));
|
|
468
|
+
}
|
|
457
469
|
const oklabToLinearSrgb = (lab) => {
|
|
458
470
|
const L = lab[0];
|
|
459
471
|
const a = lab[1];
|
|
@@ -745,6 +757,16 @@ function okhslToSrgb(h, s, l) {
|
|
|
745
757
|
];
|
|
746
758
|
}
|
|
747
759
|
/**
|
|
760
|
+
* OKHST to sRGB (0-1 range).
|
|
761
|
+
* @param h - Hue in degrees (0-360)
|
|
762
|
+
* @param s - Saturation (0-1)
|
|
763
|
+
* @param t - Tone (0-1)
|
|
764
|
+
* @returns sRGB values in 0-1 range, clamped to gamut
|
|
765
|
+
*/
|
|
766
|
+
function okhstToSrgb(h, s, t) {
|
|
767
|
+
return okhslToSrgb(h, clamp$1(s, 0, 1), clamp$1(fromTone(t * 100), 0, 1));
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
748
770
|
* OKLCH to sRGB (0-255 range).
|
|
749
771
|
* @param L - Lightness (0-1)
|
|
750
772
|
* @param C - Chroma (typically 0-0.4)
|
|
@@ -1024,7 +1046,7 @@ function getRgbValuesFromRgbaString(str) {
|
|
|
1024
1046
|
}
|
|
1025
1047
|
/**
|
|
1026
1048
|
* Convert any recognized color string to an `rgb()` CSS string.
|
|
1027
|
-
* Handles hex, `okhsl()`, `hsl()`/`hsla()`, named CSS colors,
|
|
1049
|
+
* Handles hex, `okhsl()`, `okhst()`, `hsl()`/`hsla()`, named CSS colors,
|
|
1028
1050
|
* and `rgb()`/`rgba()` pass-through.
|
|
1029
1051
|
*/
|
|
1030
1052
|
function strToRgb(color, _ignoreAlpha = false) {
|
|
@@ -1033,6 +1055,7 @@ function strToRgb(color, _ignoreAlpha = false) {
|
|
|
1033
1055
|
if (color.startsWith("#")) return hexToRgb(color);
|
|
1034
1056
|
if (color.startsWith("oklch(")) return oklchStringToRgb(color);
|
|
1035
1057
|
if (color.startsWith("okhsl(")) return okhslStringToRgb(color);
|
|
1058
|
+
if (color.startsWith("okhst(")) return okhstStringToRgb(color);
|
|
1036
1059
|
if (color.startsWith("hsl")) return hslStringToRgb(color);
|
|
1037
1060
|
const namedHex = getNamedColorHex().get(color.toLowerCase());
|
|
1038
1061
|
if (namedHex) return hexToRgb(namedHex);
|
|
@@ -1097,6 +1120,34 @@ function okhslStringToRgb(okhslStr) {
|
|
|
1097
1120
|
return `rgb(${r255} ${g255} ${b255})`;
|
|
1098
1121
|
}
|
|
1099
1122
|
/**
|
|
1123
|
+
* Convert an `okhst()` color string to an `rgb()`/`rgba()` CSS string.
|
|
1124
|
+
* Supports deg/turn/rad hue units and percentage saturation/tone.
|
|
1125
|
+
*/
|
|
1126
|
+
function okhstStringToRgb(okhstStr) {
|
|
1127
|
+
const match = okhstStr.match(/okhst\(([^)]+)\)/i);
|
|
1128
|
+
if (!match) return null;
|
|
1129
|
+
const [colorPart, alphaPart] = match[1].trim().split("/");
|
|
1130
|
+
const parts = colorPart.trim().split(/[,\s]+/).filter(Boolean);
|
|
1131
|
+
if (parts.length < 3) return null;
|
|
1132
|
+
let h = parseFloat(parts[0]);
|
|
1133
|
+
const hueStr = parts[0].toLowerCase();
|
|
1134
|
+
if (hueStr.endsWith("turn")) h = parseFloat(hueStr) * 360;
|
|
1135
|
+
else if (hueStr.endsWith("rad")) h = parseFloat(hueStr) * 180 / Math.PI;
|
|
1136
|
+
else if (hueStr.endsWith("deg")) h = parseFloat(hueStr);
|
|
1137
|
+
const parsePercent = (val) => {
|
|
1138
|
+
const num = parseFloat(val);
|
|
1139
|
+
return val.includes("%") ? num / 100 : num;
|
|
1140
|
+
};
|
|
1141
|
+
const s = Math.max(0, Math.min(1, parsePercent(parts[1])));
|
|
1142
|
+
const t = Math.max(0, Math.min(1, parsePercent(parts[2])));
|
|
1143
|
+
const [r, g, b] = okhstToSrgb(h, s, t);
|
|
1144
|
+
const r255 = Math.round(Math.max(0, Math.min(1, r)) * 255);
|
|
1145
|
+
const g255 = Math.round(Math.max(0, Math.min(1, g)) * 255);
|
|
1146
|
+
const b255 = Math.round(Math.max(0, Math.min(1, b)) * 255);
|
|
1147
|
+
if (alphaPart) return `rgba(${r255}, ${g255}, ${b255}, ${parseFloat(alphaPart.trim())})`;
|
|
1148
|
+
return `rgb(${r255} ${g255} ${b255})`;
|
|
1149
|
+
}
|
|
1150
|
+
/**
|
|
1100
1151
|
* Convert an `oklch()` color string to an `rgb()`/`rgba()` CSS string.
|
|
1101
1152
|
* Supports deg/turn/rad hue units and percentage lightness.
|
|
1102
1153
|
*/
|
|
@@ -1269,6 +1320,17 @@ function resolveToRgbaValues(color) {
|
|
|
1269
1320
|
parsed.alpha
|
|
1270
1321
|
];
|
|
1271
1322
|
}
|
|
1323
|
+
if (trimmed.startsWith("okhst(")) {
|
|
1324
|
+
const parsed = parseColorFuncArgs(trimmed, "okhst");
|
|
1325
|
+
if (!parsed) return null;
|
|
1326
|
+
const [r, g, b] = okhstToSrgb(parseHue(parsed.parts[0]), clamp01(parsePercent(parsed.parts[1])), clamp01(parsePercent(parsed.parts[2])));
|
|
1327
|
+
return [
|
|
1328
|
+
clamp01(r) * 255,
|
|
1329
|
+
clamp01(g) * 255,
|
|
1330
|
+
clamp01(b) * 255,
|
|
1331
|
+
parsed.alpha
|
|
1332
|
+
];
|
|
1333
|
+
}
|
|
1272
1334
|
const fallback = strToRgb(trimmed);
|
|
1273
1335
|
if (fallback) {
|
|
1274
1336
|
if (fallback !== trimmed) return resolveToRgbaValues(fallback);
|
|
@@ -1602,7 +1664,7 @@ function classify(raw, opts, recurse) {
|
|
|
1602
1664
|
if (baseToken in predefinedTokens) {
|
|
1603
1665
|
const resolvedValue = predefinedTokens[baseToken];
|
|
1604
1666
|
if (resolvedValue.startsWith("#")) return classify(`${resolvedValue.toLowerCase()}.${rawAlpha}`, opts, recurse);
|
|
1605
|
-
const funcMatch = resolvedValue.match(/^(rgba?|hsla?|hwb|oklab|oklch|lab|lch|color|okhsl|device-cmyk|gray|color-mix|color-contrast)\((.+)\)$/i);
|
|
1667
|
+
const funcMatch = resolvedValue.match(/^(rgba?|hsla?|hwb|oklab|oklch|lab|lch|color|okhsl|okhst|device-cmyk|gray|color-mix|color-contrast)\((.+)\)$/i);
|
|
1606
1668
|
if (funcMatch) {
|
|
1607
1669
|
const [, funcName, args] = funcMatch;
|
|
1608
1670
|
let alpha;
|
|
@@ -1983,20 +2045,7 @@ var StyleParser = class {
|
|
|
1983
2045
|
}
|
|
1984
2046
|
};
|
|
1985
2047
|
//#endregion
|
|
1986
|
-
//#region src/plugins/
|
|
1987
|
-
/**
|
|
1988
|
-
* OKHSL Plugin for Tasty
|
|
1989
|
-
*
|
|
1990
|
-
* Converts OKHSL color syntax to RGB notation.
|
|
1991
|
-
* Supports angle units: deg, turn, rad, or unitless (degrees).
|
|
1992
|
-
*
|
|
1993
|
-
* Examples:
|
|
1994
|
-
* okhsl(240.5 50% 50%)
|
|
1995
|
-
* okhsl(240.5deg 50% 50%)
|
|
1996
|
-
* okhsl(0.25turn 50% 50%)
|
|
1997
|
-
* okhsl(1.57rad 50% 50%)
|
|
1998
|
-
*/
|
|
1999
|
-
const conversionCache = new Lru(500);
|
|
2048
|
+
//#region src/plugins/color-func.ts
|
|
2000
2049
|
const clamp = (value, min, max) => Math.max(Math.min(value, max), min);
|
|
2001
2050
|
/**
|
|
2002
2051
|
* Parse an angle value with optional unit.
|
|
@@ -2022,32 +2071,56 @@ const parsePercentage = (value) => {
|
|
|
2022
2071
|
return value.includes("%") ? num / 100 : num;
|
|
2023
2072
|
};
|
|
2024
2073
|
/**
|
|
2074
|
+
* Creates a color function handler for the tasty parser.
|
|
2075
|
+
* @param name The name of the color space (e.g., 'okhsl', 'okhst')
|
|
2076
|
+
* @param channelLabel The label for the channels in warnings (e.g., 'H S L')
|
|
2077
|
+
* @param convert A function that converts the parsed H, C2, C3 values to sRGB [r, g, b] (0-1)
|
|
2078
|
+
*/
|
|
2079
|
+
function createColorFunc(name, channelLabel, convert) {
|
|
2080
|
+
const conversionCache = new Lru(500);
|
|
2081
|
+
return (groups) => {
|
|
2082
|
+
if (groups.length === 0 || groups[0].all.length < 3) {
|
|
2083
|
+
console.warn(`[${name}] Expected 3 values (${channelLabel}), got:`, groups);
|
|
2084
|
+
return "rgb(0% 0% 0%)";
|
|
2085
|
+
}
|
|
2086
|
+
const group = groups[0];
|
|
2087
|
+
const tokens = group.all;
|
|
2088
|
+
const alpha = group.parts.length > 1 && group.parts[1].all.length > 0 ? group.parts[1].output : void 0;
|
|
2089
|
+
const cacheKey = tokens.slice(0, 3).join(" ") + (alpha ? ` / ${alpha}` : "");
|
|
2090
|
+
const cached = conversionCache.get(cacheKey);
|
|
2091
|
+
if (cached) return cached;
|
|
2092
|
+
const h = parseAngle(tokens[0]);
|
|
2093
|
+
const c2 = parsePercentage(tokens[1]);
|
|
2094
|
+
const c3 = parsePercentage(tokens[2]);
|
|
2095
|
+
const [r, g, b] = convert(h, clamp(c2, 0, 1), clamp(c3, 0, 1));
|
|
2096
|
+
const format = (n) => {
|
|
2097
|
+
const pct = n * 100;
|
|
2098
|
+
return parseFloat(pct.toFixed(1)).toString() + "%";
|
|
2099
|
+
};
|
|
2100
|
+
const result = alpha ? `rgb(${format(r)} ${format(g)} ${format(b)} / ${alpha})` : `rgb(${format(r)} ${format(g)} ${format(b)})`;
|
|
2101
|
+
conversionCache.set(cacheKey, result);
|
|
2102
|
+
return result;
|
|
2103
|
+
};
|
|
2104
|
+
}
|
|
2105
|
+
//#endregion
|
|
2106
|
+
//#region src/plugins/okhsl-plugin.ts
|
|
2107
|
+
/**
|
|
2108
|
+
* OKHSL Plugin for Tasty
|
|
2109
|
+
*
|
|
2110
|
+
* Converts OKHSL color syntax to RGB notation.
|
|
2111
|
+
* Supports angle units: deg, turn, rad, or unitless (degrees).
|
|
2112
|
+
*
|
|
2113
|
+
* Examples:
|
|
2114
|
+
* okhsl(240.5 50% 50%)
|
|
2115
|
+
* okhsl(240.5deg 50% 50%)
|
|
2116
|
+
* okhsl(0.25turn 50% 50%)
|
|
2117
|
+
* okhsl(1.57rad 50% 50%)
|
|
2118
|
+
*/
|
|
2119
|
+
/**
|
|
2025
2120
|
* The okhsl function handler for tasty parser.
|
|
2026
2121
|
* Receives parsed style groups and returns an RGB color string.
|
|
2027
2122
|
*/
|
|
2028
|
-
const okhslFunc = (
|
|
2029
|
-
if (groups.length === 0 || groups[0].all.length < 3) {
|
|
2030
|
-
console.warn("[okhsl] Expected 3 values (H S L), got:", groups);
|
|
2031
|
-
return "rgb(0% 0% 0%)";
|
|
2032
|
-
}
|
|
2033
|
-
const group = groups[0];
|
|
2034
|
-
const tokens = group.all;
|
|
2035
|
-
const alpha = group.parts.length > 1 && group.parts[1].all.length > 0 ? group.parts[1].output : void 0;
|
|
2036
|
-
const cacheKey = tokens.slice(0, 3).join(" ") + (alpha ? ` / ${alpha}` : "");
|
|
2037
|
-
const cached = conversionCache.get(cacheKey);
|
|
2038
|
-
if (cached) return cached;
|
|
2039
|
-
const h = parseAngle(tokens[0]);
|
|
2040
|
-
const s = parsePercentage(tokens[1]);
|
|
2041
|
-
const l = parsePercentage(tokens[2]);
|
|
2042
|
-
const [r, g, b] = okhslToSrgb(h, clamp(s, 0, 1), clamp(l, 0, 1));
|
|
2043
|
-
const format = (n) => {
|
|
2044
|
-
const pct = n * 100;
|
|
2045
|
-
return parseFloat(pct.toFixed(1)).toString() + "%";
|
|
2046
|
-
};
|
|
2047
|
-
const result = alpha ? `rgb(${format(r)} ${format(g)} ${format(b)} / ${alpha})` : `rgb(${format(r)} ${format(g)} ${format(b)})`;
|
|
2048
|
-
conversionCache.set(cacheKey, result);
|
|
2049
|
-
return result;
|
|
2050
|
-
};
|
|
2123
|
+
const okhslFunc = createColorFunc("okhsl", "H S L", okhslToSrgb);
|
|
2051
2124
|
/**
|
|
2052
2125
|
* OKHSL Plugin for Tasty.
|
|
2053
2126
|
*
|
|
@@ -2075,6 +2148,52 @@ const okhslPlugin = () => ({
|
|
|
2075
2148
|
funcs: { okhsl: okhslFunc }
|
|
2076
2149
|
});
|
|
2077
2150
|
//#endregion
|
|
2151
|
+
//#region src/plugins/okhst-plugin.ts
|
|
2152
|
+
/**
|
|
2153
|
+
* OKHST Plugin for Tasty
|
|
2154
|
+
*
|
|
2155
|
+
* Converts OKHST color syntax to RGB notation.
|
|
2156
|
+
* OKHST is OKHSL with the lightness axis replaced by a contrast-uniform tone axis.
|
|
2157
|
+
* Supports angle units: deg, turn, rad, or unitless (degrees).
|
|
2158
|
+
*
|
|
2159
|
+
* Examples:
|
|
2160
|
+
* okhst(240.5 50% 50%)
|
|
2161
|
+
* okhst(240.5deg 50% 50%)
|
|
2162
|
+
* okhst(0.25turn 50% 50%)
|
|
2163
|
+
* okhst(1.57rad 50% 50%)
|
|
2164
|
+
*/
|
|
2165
|
+
/**
|
|
2166
|
+
* The okhst function handler for tasty parser.
|
|
2167
|
+
* Receives parsed style groups and returns an RGB color string.
|
|
2168
|
+
*/
|
|
2169
|
+
const okhstFunc = createColorFunc("okhst", "H S T", okhstToSrgb);
|
|
2170
|
+
/**
|
|
2171
|
+
* OKHST Plugin for Tasty.
|
|
2172
|
+
*
|
|
2173
|
+
* Adds support for the `okhst()` color function in tasty styles.
|
|
2174
|
+
*
|
|
2175
|
+
* @example
|
|
2176
|
+
* ```ts
|
|
2177
|
+
* import { configure } from '@tenphi/tasty';
|
|
2178
|
+
* import { okhstPlugin } from '@tenphi/tasty';
|
|
2179
|
+
*
|
|
2180
|
+
* configure({
|
|
2181
|
+
* plugins: [okhstPlugin()],
|
|
2182
|
+
* });
|
|
2183
|
+
*
|
|
2184
|
+
* // Now you can use okhst in styles:
|
|
2185
|
+
* const Box = tasty({
|
|
2186
|
+
* styles: {
|
|
2187
|
+
* fill: 'okhst(240 50% 50%)',
|
|
2188
|
+
* },
|
|
2189
|
+
* });
|
|
2190
|
+
* ```
|
|
2191
|
+
*/
|
|
2192
|
+
const okhstPlugin = () => ({
|
|
2193
|
+
name: "okhst",
|
|
2194
|
+
funcs: { okhst: okhstFunc }
|
|
2195
|
+
});
|
|
2196
|
+
//#endregion
|
|
2078
2197
|
//#region src/utils/styles.ts
|
|
2079
2198
|
/**
|
|
2080
2199
|
* Normalize a color token value.
|
|
@@ -2101,7 +2220,7 @@ function isSimpleColorFast(val) {
|
|
|
2101
2220
|
case 114: return val.charCodeAt(1) === 103 && val.charCodeAt(2) === 98;
|
|
2102
2221
|
case 104: return val.charCodeAt(1) === 115 && val.charCodeAt(2) === 108;
|
|
2103
2222
|
case 108: return val.charCodeAt(1) === 99 && val.charCodeAt(2) === 104;
|
|
2104
|
-
case 111: return val.startsWith("oklch(") || val.startsWith("okhsl(");
|
|
2223
|
+
case 111: return val.startsWith("oklch(") || val.startsWith("okhsl(") || val.startsWith("okhst(");
|
|
2105
2224
|
case 118: return RE_VAR_COLOR.test(val);
|
|
2106
2225
|
case 99: return val === "currentColor" || val === "currentcolor";
|
|
2107
2226
|
case 116: return val === "transparent";
|
|
@@ -2134,7 +2253,10 @@ function getOrCreateParser() {
|
|
|
2134
2253
|
}
|
|
2135
2254
|
return __tastyParser;
|
|
2136
2255
|
}
|
|
2137
|
-
const __tastyFuncs = {
|
|
2256
|
+
const __tastyFuncs = {
|
|
2257
|
+
okhsl: okhslFunc,
|
|
2258
|
+
okhst: okhstFunc
|
|
2259
|
+
};
|
|
2138
2260
|
function customFunc(name, fn) {
|
|
2139
2261
|
__tastyFuncs[name] = fn;
|
|
2140
2262
|
getOrCreateParser().setFuncs(__tastyFuncs);
|
|
@@ -7442,6 +7564,18 @@ function wrapInIsOrNot(args, negated) {
|
|
|
7442
7564
|
return `${negated ? ":not" : ":is"}(${args.sort().join(", ")})`;
|
|
7443
7565
|
}
|
|
7444
7566
|
/**
|
|
7567
|
+
* Wrap a non-empty selector fragment in `:where(...)` to zero its
|
|
7568
|
+
* specificity. Tasty anchors specificity solely on the doubled class
|
|
7569
|
+
* (`.tXX.tXX`) and `data-element` attributes; every stateful selector
|
|
7570
|
+
* (modifiers, pseudos, :is()/:not() groups, root/parent context) is wrapped
|
|
7571
|
+
* so it contributes nothing to specificity and the cascade is decided by
|
|
7572
|
+
* source order alone. Empty input passes through unchanged.
|
|
7573
|
+
*/
|
|
7574
|
+
function wrapWhere(inner) {
|
|
7575
|
+
if (!inner) return "";
|
|
7576
|
+
return `:where(${inner})`;
|
|
7577
|
+
}
|
|
7578
|
+
/**
|
|
7445
7579
|
* Convert a selector group to a CSS selector fragment.
|
|
7446
7580
|
*
|
|
7447
7581
|
* Single-branch groups are unwrapped (no :is() wrapper).
|
|
@@ -7545,7 +7679,7 @@ function rootGroupsToCSS(groups) {
|
|
|
7545
7679
|
if (optimized.length === 0) return void 0;
|
|
7546
7680
|
let prefix = ":root";
|
|
7547
7681
|
for (const group of optimized) prefix += selectorGroupToCSS(group);
|
|
7548
|
-
return prefix;
|
|
7682
|
+
return wrapWhere(prefix);
|
|
7549
7683
|
}
|
|
7550
7684
|
/**
|
|
7551
7685
|
* Convert parent groups to CSS selector fragments (for final output).
|
|
@@ -7557,7 +7691,8 @@ function parentGroupsToCSS(groups) {
|
|
|
7557
7691
|
for (const group of groups) {
|
|
7558
7692
|
const combinator = group.direct ? " > *" : " *";
|
|
7559
7693
|
const args = group.branches.map((branch) => branchToCSS(branch) + combinator);
|
|
7560
|
-
|
|
7694
|
+
const inner = group.negated ? `:not(${args.sort().join(", ")})` : args.sort().join(", ");
|
|
7695
|
+
result += wrapWhere(inner);
|
|
7561
7696
|
}
|
|
7562
7697
|
return result;
|
|
7563
7698
|
}
|
|
@@ -8227,6 +8362,21 @@ function buildAtRulesFromVariant(variant) {
|
|
|
8227
8362
|
return atRules;
|
|
8228
8363
|
}
|
|
8229
8364
|
//#endregion
|
|
8365
|
+
//#region src/pipeline/warnings.ts
|
|
8366
|
+
const defaultWarningHandler = (warning) => {
|
|
8367
|
+
console.warn(`[Tasty] ${warning.message}`);
|
|
8368
|
+
};
|
|
8369
|
+
let warningHandler = defaultWarningHandler;
|
|
8370
|
+
/**
|
|
8371
|
+
* Emit a structured pipeline warning via the configured handler.
|
|
8372
|
+
*/
|
|
8373
|
+
function emitWarning(code, message) {
|
|
8374
|
+
warningHandler({
|
|
8375
|
+
code,
|
|
8376
|
+
message
|
|
8377
|
+
});
|
|
8378
|
+
}
|
|
8379
|
+
//#endregion
|
|
8230
8380
|
//#region src/pipeline/exclusive.ts
|
|
8231
8381
|
/**
|
|
8232
8382
|
* Build exclusive conditions for a list of parsed style entries.
|
|
@@ -8255,7 +8405,12 @@ function buildAtRulesFromVariant(variant) {
|
|
|
8255
8405
|
function buildExclusiveConditions(entries) {
|
|
8256
8406
|
const result = [];
|
|
8257
8407
|
const priorConditions = [];
|
|
8408
|
+
const floors = [];
|
|
8258
8409
|
for (const entry of entries) {
|
|
8410
|
+
if (entry.floor) {
|
|
8411
|
+
floors.push(entry);
|
|
8412
|
+
continue;
|
|
8413
|
+
}
|
|
8259
8414
|
let exclusive = entry.condition;
|
|
8260
8415
|
for (const prior of priorConditions) {
|
|
8261
8416
|
if (prior.kind === "true") continue;
|
|
@@ -8270,6 +8425,10 @@ function buildExclusiveConditions(entries) {
|
|
|
8270
8425
|
});
|
|
8271
8426
|
if (entry.condition.kind !== "true") priorConditions.push(entry.condition);
|
|
8272
8427
|
}
|
|
8428
|
+
for (const floor of floors) result.push({
|
|
8429
|
+
...floor,
|
|
8430
|
+
exclusiveCondition: floor.condition
|
|
8431
|
+
});
|
|
8273
8432
|
return result;
|
|
8274
8433
|
}
|
|
8275
8434
|
/**
|
|
@@ -8282,19 +8441,85 @@ function buildExclusiveConditions(entries) {
|
|
|
8282
8441
|
*/
|
|
8283
8442
|
function parseStyleEntries(styleKey, valueMap, parseCondition) {
|
|
8284
8443
|
const entries = [];
|
|
8285
|
-
|
|
8444
|
+
let floorEntry = null;
|
|
8445
|
+
Object.keys(valueMap).forEach((stateKey) => {
|
|
8286
8446
|
const value = valueMap[stateKey];
|
|
8447
|
+
if (stateKey === "_") {
|
|
8448
|
+
floorEntry = {
|
|
8449
|
+
styleKey,
|
|
8450
|
+
stateKey,
|
|
8451
|
+
value,
|
|
8452
|
+
condition: trueCondition(),
|
|
8453
|
+
priority: 0,
|
|
8454
|
+
floor: true
|
|
8455
|
+
};
|
|
8456
|
+
return;
|
|
8457
|
+
}
|
|
8458
|
+
if (isMisusedFallbackKey(stateKey)) {
|
|
8459
|
+
emitWarning("INVALID_FALLBACK_KEY", `Style key "${stateKey}" (in "${styleKey}") combines the fallback "_" with other state logic. "_" can only be used on its own as a map-wide fallback floor. The key has been ignored.`);
|
|
8460
|
+
return;
|
|
8461
|
+
}
|
|
8287
8462
|
const condition = stateKey === "" ? trueCondition() : parseCondition(stateKey);
|
|
8288
8463
|
entries.push({
|
|
8289
8464
|
styleKey,
|
|
8290
8465
|
stateKey,
|
|
8291
8466
|
value,
|
|
8292
8467
|
condition,
|
|
8293
|
-
priority:
|
|
8468
|
+
priority: 0
|
|
8294
8469
|
});
|
|
8295
8470
|
});
|
|
8296
|
-
|
|
8297
|
-
|
|
8471
|
+
if (floorEntry !== null) {
|
|
8472
|
+
const hasOtherStates = entries.some((e) => e.condition.kind !== "true");
|
|
8473
|
+
const hasDefault = entries.some((e) => e.condition.kind === "true");
|
|
8474
|
+
if (!hasOtherStates && hasDefault) {
|
|
8475
|
+
emitWarning("REDUNDANT_DEFAULT_STATE", `Style "${styleKey}" defines both a "_" fallback and a "" default with no other states. The "" default is redundant (always superseded by "_"); the "_" value is used and the "" default is ignored.`);
|
|
8476
|
+
entries.length = 0;
|
|
8477
|
+
}
|
|
8478
|
+
}
|
|
8479
|
+
const normalized = normalizeDefaultStates(entries, styleKey);
|
|
8480
|
+
const ordered = floorEntry !== null ? [floorEntry, ...normalized] : normalized;
|
|
8481
|
+
ordered.forEach((entry, index) => {
|
|
8482
|
+
entry.priority = index;
|
|
8483
|
+
});
|
|
8484
|
+
ordered.reverse();
|
|
8485
|
+
return ordered;
|
|
8486
|
+
}
|
|
8487
|
+
/**
|
|
8488
|
+
* Detect a misused standalone `_` fallback key: a key that is not exactly
|
|
8489
|
+
* `_` but contains `_` as a standalone atom among state-logic operators
|
|
8490
|
+
* (`&`, `|`, `^`, `,`) or grouping parens. A `_` embedded in a longer token
|
|
8491
|
+
* (e.g. a modifier named `_private`) is not a misuse.
|
|
8492
|
+
*/
|
|
8493
|
+
function isMisusedFallbackKey(stateKey) {
|
|
8494
|
+
if (stateKey === "_" || !stateKey.includes("_")) return false;
|
|
8495
|
+
return /(?:^|[\s&|^,(])_(?:[\s&|^,)]|$)/.test(stateKey);
|
|
8496
|
+
}
|
|
8497
|
+
/**
|
|
8498
|
+
* Resolve the bare `''` default state (`condition.kind === 'true'`) in a
|
|
8499
|
+
* style value map.
|
|
8500
|
+
*
|
|
8501
|
+
* The bare default only behaves correctly as the **first** (lowest-priority)
|
|
8502
|
+
* key. When it appears later, `buildExclusiveConditions` processes it first
|
|
8503
|
+
* (after the reverse), never adds it to the prior list, and never negates it
|
|
8504
|
+
* — so it silently overrides every state authored before it.
|
|
8505
|
+
*
|
|
8506
|
+
* This function, given entries in authored order, moves a misplaced bare
|
|
8507
|
+
* default to the front (lowest priority), preserving the relative order of
|
|
8508
|
+
* all other entries, and emits a `MISPLACED_DEFAULT_STATE` warning.
|
|
8509
|
+
*
|
|
8510
|
+
* The `_` fallback floor is pulled out before this runs (see
|
|
8511
|
+
* `parseStyleEntries`), so only the bare `''` default is considered here.
|
|
8512
|
+
*/
|
|
8513
|
+
function normalizeDefaultStates(entries, styleKey) {
|
|
8514
|
+
const defaultPos = entries.findIndex((e) => e.condition.kind === "true");
|
|
8515
|
+
if (defaultPos <= 0) return entries;
|
|
8516
|
+
const defaultEntry = entries[defaultPos];
|
|
8517
|
+
emitWarning("MISPLACED_DEFAULT_STATE", `Style "${styleKey}" defines the default state "${defaultEntry.stateKey}" after other states. A bare default ("") must be the first key, otherwise it overrides the states above it. It has been moved to the first position. Define default states first.`);
|
|
8518
|
+
return [
|
|
8519
|
+
defaultEntry,
|
|
8520
|
+
...entries.slice(0, defaultPos),
|
|
8521
|
+
...entries.slice(defaultPos + 1)
|
|
8522
|
+
];
|
|
8298
8523
|
}
|
|
8299
8524
|
/**
|
|
8300
8525
|
* Merge parsed entries that share the same value.
|
|
@@ -8417,8 +8642,9 @@ function extractCompoundStates(valueMap) {
|
|
|
8417
8642
|
const keys = Object.keys(valueMap);
|
|
8418
8643
|
if (keys.length < 3 || !keys.some((k) => k.includes("&"))) return valueMap;
|
|
8419
8644
|
const entries = keys.map((key) => {
|
|
8645
|
+
const atoms = splitTopLevelAnd(key);
|
|
8420
8646
|
return {
|
|
8421
|
-
atoms:
|
|
8647
|
+
atoms: atoms === null || atoms.includes("_") ? [key] : atoms,
|
|
8422
8648
|
value: valueMap[key]
|
|
8423
8649
|
};
|
|
8424
8650
|
});
|
|
@@ -8723,21 +8949,6 @@ function transformSelectorContent(content) {
|
|
|
8723
8949
|
return content.replace(ELEMENT_NAME_RE, (_, prefix, name) => `${prefix}[data-element="${name}"]`);
|
|
8724
8950
|
}
|
|
8725
8951
|
//#endregion
|
|
8726
|
-
//#region src/pipeline/warnings.ts
|
|
8727
|
-
const defaultWarningHandler = (warning) => {
|
|
8728
|
-
console.warn(`[Tasty] ${warning.message}`);
|
|
8729
|
-
};
|
|
8730
|
-
let warningHandler = defaultWarningHandler;
|
|
8731
|
-
/**
|
|
8732
|
-
* Emit a structured pipeline warning via the configured handler.
|
|
8733
|
-
*/
|
|
8734
|
-
function emitWarning(code, message) {
|
|
8735
|
-
warningHandler({
|
|
8736
|
-
code,
|
|
8737
|
-
message
|
|
8738
|
-
});
|
|
8739
|
-
}
|
|
8740
|
-
//#endregion
|
|
8741
8952
|
//#region src/pipeline/parseStateKey.ts
|
|
8742
8953
|
/**
|
|
8743
8954
|
* State Key Parser
|
|
@@ -9252,7 +9463,17 @@ function runPipeline(styles, parserContext) {
|
|
|
9252
9463
|
const starting = [];
|
|
9253
9464
|
for (const rule of dedupedRules) if (rule.startingStyle) starting.push(rule);
|
|
9254
9465
|
else normal.push(rule);
|
|
9255
|
-
return normal.concat(starting);
|
|
9466
|
+
return stableSortByOrder(normal).concat(stableSortByOrder(starting));
|
|
9467
|
+
}
|
|
9468
|
+
/**
|
|
9469
|
+
* Stable sort CSS rules by their `order` hint ascending. Rules without an
|
|
9470
|
+
* `order` are treated as 0. `Array.prototype.sort` is stable (ES2019+,
|
|
9471
|
+
* Node >= 20), so equal-order rules keep their emission order — the `_`
|
|
9472
|
+
* fallback floor (low order) stays before the overrides that layer over it.
|
|
9473
|
+
*/
|
|
9474
|
+
function stableSortByOrder(rules) {
|
|
9475
|
+
if (rules.length <= 1) return rules;
|
|
9476
|
+
return [...rules].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
9256
9477
|
}
|
|
9257
9478
|
/**
|
|
9258
9479
|
* Process styles at a given nesting level.
|
|
@@ -9360,7 +9581,8 @@ function invokeHandler(handler, stateSnapshots, selectorSuffix) {
|
|
|
9360
9581
|
for (const suffix of suffixes) computedRules.push({
|
|
9361
9582
|
condition: snapshot.condition,
|
|
9362
9583
|
declarations,
|
|
9363
|
-
selectorSuffix: suffix
|
|
9584
|
+
selectorSuffix: suffix,
|
|
9585
|
+
order: snapshot.order
|
|
9364
9586
|
});
|
|
9365
9587
|
}
|
|
9366
9588
|
}
|
|
@@ -9778,10 +10000,15 @@ function computeStateCombinations(exclusiveByStyle, lookupStyles) {
|
|
|
9778
10000
|
const simplified = simplifyCondition(and(...combo.map((e) => e.exclusiveCondition)));
|
|
9779
10001
|
if (simplified.kind === "false") continue;
|
|
9780
10002
|
const values = {};
|
|
9781
|
-
|
|
10003
|
+
let order = 0;
|
|
10004
|
+
for (const entry of combo) {
|
|
10005
|
+
values[entry.styleKey] = entry.value;
|
|
10006
|
+
if (entry.priority > order) order = entry.priority;
|
|
10007
|
+
}
|
|
9782
10008
|
snapshots.push({
|
|
9783
10009
|
condition: simplified,
|
|
9784
|
-
values
|
|
10010
|
+
values,
|
|
10011
|
+
order
|
|
9785
10012
|
});
|
|
9786
10013
|
}
|
|
9787
10014
|
return snapshots;
|
|
@@ -9829,10 +10056,13 @@ function mergeByValue(rules) {
|
|
|
9829
10056
|
for (const [, groupRules] of groups) if (groupRules.length === 1) merged.push(groupRules[0]);
|
|
9830
10057
|
else {
|
|
9831
10058
|
const mergedCondition = simplifyCondition(or(...groupRules.map((r) => r.condition)));
|
|
10059
|
+
let order = groupRules[0].order;
|
|
10060
|
+
for (const r of groupRules) if (r.order < order) order = r.order;
|
|
9832
10061
|
merged.push({
|
|
9833
10062
|
condition: mergedCondition,
|
|
9834
10063
|
declarations: groupRules[0].declarations,
|
|
9835
|
-
selectorSuffix: groupRules[0].selectorSuffix
|
|
10064
|
+
selectorSuffix: groupRules[0].selectorSuffix,
|
|
10065
|
+
order
|
|
9836
10066
|
});
|
|
9837
10067
|
}
|
|
9838
10068
|
return merged;
|
|
@@ -9842,12 +10072,15 @@ function mergeByValue(rules) {
|
|
|
9842
10072
|
*/
|
|
9843
10073
|
function buildSelectorFromVariant(variant, selectorSuffix) {
|
|
9844
10074
|
let selector = "";
|
|
9845
|
-
|
|
9846
|
-
for (const group of variant.selectorGroups)
|
|
10075
|
+
let rootSegment = branchToCSS([...variant.modifierConditions, ...variant.pseudoConditions]);
|
|
10076
|
+
for (const group of variant.selectorGroups) rootSegment += selectorGroupToCSS(group);
|
|
10077
|
+
selector += wrapWhere(rootSegment);
|
|
9847
10078
|
if (variant.parentGroups.length > 0) selector += parentGroupsToCSS(variant.parentGroups);
|
|
9848
10079
|
selector += selectorSuffix;
|
|
9849
10080
|
const ownOptimized = optimizeGroups(variant.ownGroups);
|
|
9850
|
-
|
|
10081
|
+
let ownSegment = "";
|
|
10082
|
+
for (const group of ownOptimized) ownSegment += selectorGroupToCSS(group);
|
|
10083
|
+
selector += wrapWhere(ownSegment);
|
|
9851
10084
|
return selector;
|
|
9852
10085
|
}
|
|
9853
10086
|
/**
|
|
@@ -9882,7 +10115,8 @@ function materializeComputedRule(rule) {
|
|
|
9882
10115
|
const selectorFragments = mergeVariantsIntoSelectorGroups(group.variants).map((v) => buildSelectorFromVariant(v, rule.selectorSuffix));
|
|
9883
10116
|
const cssRule = {
|
|
9884
10117
|
selector: selectorFragments.length === 1 ? selectorFragments[0] : selectorFragments,
|
|
9885
|
-
declarations
|
|
10118
|
+
declarations,
|
|
10119
|
+
order: rule.order
|
|
9886
10120
|
};
|
|
9887
10121
|
if (group.atRules.length > 0) cssRule.atRules = group.atRules;
|
|
9888
10122
|
if (group.rootPrefix) cssRule.rootPrefix = group.rootPrefix;
|
|
@@ -10594,6 +10828,6 @@ function resetConfig() {
|
|
|
10594
10828
|
delete storage[GLOBAL_INJECTOR_KEY];
|
|
10595
10829
|
}
|
|
10596
10830
|
//#endregion
|
|
10597
|
-
export { parseColor as $, StyleInjector as A,
|
|
10831
|
+
export { parseColor as $, StyleInjector as A, extractLocalProperties as At, styleHandlers as B, parseStateKey as C, getComponentPropertySyntax as Ct, extractPredefinedStateRefs as D, hslToRgbValues as Dt, extractLocalPredefinedStates as E, hexToRgb as Et, fontFaceContentHash as F, CUSTOM_UNITS as G, warn as H, formatFontFaceRule as I, filterMods as J, DIRECTIONS as K, hasLocalFontFace as L, formatCounterStyleRule as M, hasLocalProperties as Mt, hasLocalCounterStyle as N, parsePropertyToken as Nt, getGlobalPredefinedStates as O, strToRgb as Ot, extractLocalFontFace as P, normalizeColorTokenValue as Q, SheetManager as R, renderStyles as S, getColorSpaceSuffix as St, createStateParserContext as T, getRgbValuesFromRgbaString as Tt, createStyle as U, deprecationWarning as V, PropertyTypeResolver as W, getGlobalParser as X, getGlobalFuncs as Y, getGlobalPredefinedTokens as Z, markStylesGenerated as _, isDevEnv as _t, getGlobalCounterStyle as a, okhstPlugin as at, hasPipelineCacheEntry as b, getColorSpaceComponents as bt, getGlobalKeyframes as c, StyleParser as ct, getNamePrefix as d, DEFAULT_ZERO_NAME_PREFIX as dt, parseStyle as et, hasGlobalKeyframes as f, makeClassName as ft, isTestEnvironment as g, validateNamePrefix as gt, isConfigLocked as h, tastyClassRegex as ht, getGlobalConfigTokens as i, okhstFunc as it, extractLocalCounterStyle as j, getEffectiveDefinition as jt, setGlobalPredefinedStates as k, Lru as kt, getGlobalRecipes as l, Bucket as lt, hasStylesGenerated as m, makeKeyframeName as mt, getConfig as n, setGlobalPredefinedTokens as nt, getGlobalFontFace as o, okhslFunc as ot, hasGlobalRecipes as p, makeCounterStyleName as pt, customFunc as q, getEffectiveProperties as r, stringifyStyles as rt, getGlobalInjector as s, okhslPlugin as st, configure as t, resetGlobalPredefinedTokens as tt, getGlobalStyles as u, DEFAULT_NAME_PREFIX as ut, resetConfig as v, hashString as vt, camelToKebab as w, getNamedColorHex as wt, isSelector as x, getColorSpaceFunc as xt, generateTypographyTokens as y, colorInitialValueToComponents as yt, STYLE_HANDLER_MAP as z };
|
|
10598
10832
|
|
|
10599
|
-
//# sourceMappingURL=config-
|
|
10833
|
+
//# sourceMappingURL=config-BDnvK42H.js.map
|