@unocss/preset-mini 0.16.4 → 0.18.1

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.
@@ -113,14 +113,18 @@ const variantSpace = (matcher) => {
113
113
  }
114
114
  };
115
115
 
116
- const variants = [
116
+ const variants = (options) => [
117
117
  variantSpace,
118
118
  variantNegative,
119
119
  variantImportant,
120
120
  variantBreakpoints,
121
121
  ...variantCombinators,
122
122
  pseudo.variantPseudoClasses,
123
- pseudo.variantPseudoElements
123
+ pseudo.variantPseudoClassFunctions,
124
+ pseudo.variantTaggedPseudoClasses(options),
125
+ pseudo.variantPseudoElements,
126
+ pseudo.partClasses,
127
+ ...options.dark === "media" ? variantColorsMedia : variantColorsClass
124
128
  ];
125
129
 
126
130
  exports.variantBreakpoints = variantBreakpoints;
@@ -1,5 +1,5 @@
1
1
  import { v as variantMatcher } from './variants.mjs';
2
- import { v as variantPseudoClasses, a as variantPseudoElements } from './pseudo.mjs';
2
+ import { v as variantPseudoClasses, a as variantPseudoClassFunctions, b as variantTaggedPseudoClasses, c as variantPseudoElements, p as partClasses } from './pseudo.mjs';
3
3
 
4
4
  const regexCache = {};
5
5
  const variantBreakpoints = (matcher, _, theme) => {
@@ -111,14 +111,18 @@ const variantSpace = (matcher) => {
111
111
  }
112
112
  };
113
113
 
114
- const variants = [
114
+ const variants = (options) => [
115
115
  variantSpace,
116
116
  variantNegative,
117
117
  variantImportant,
118
118
  variantBreakpoints,
119
119
  ...variantCombinators,
120
120
  variantPseudoClasses,
121
- variantPseudoElements
121
+ variantPseudoClassFunctions,
122
+ variantTaggedPseudoClasses(options),
123
+ variantPseudoElements,
124
+ partClasses,
125
+ ...options.dark === "media" ? variantColorsMedia : variantColorsClass
122
126
  ];
123
127
 
124
- export { variantColorsMedia as a, variantColorsClass as b, variantBreakpoints as c, variantCombinators as d, variantImportant as e, variantNegative as f, variantSpace as g, variants as v };
128
+ export { variantBreakpoints as a, variantCombinators as b, variantColorsClass as c, variantColorsMedia as d, variantImportant as e, variantNegative as f, variantSpace as g, variants as v };
@@ -40,18 +40,46 @@ const PseudoClasses = Object.fromEntries([
40
40
  "only-of-type"
41
41
  ].map(core.toArray));
42
42
  const PseudoElements = [
43
+ "placeholder",
43
44
  "before",
44
45
  "after",
45
46
  "first-letter",
46
47
  "first-line",
47
48
  "selection"
48
49
  ];
50
+ const PseudoClassFunctions = [
51
+ "not",
52
+ "is",
53
+ "where",
54
+ "has"
55
+ ];
56
+ const PartClassesRE = /(part-\[(.+)]:)(.+)/;
49
57
  const PseudoElementsRE = new RegExp(`^(${PseudoElements.join("|")})[:-]`);
50
58
  const PseudoClassesStr = Object.keys(PseudoClasses).join("|");
59
+ const PseudoClassFunctionsStr = PseudoClassFunctions.join("|");
51
60
  const PseudoClassesRE = new RegExp(`^(${PseudoClassesStr})[:-]`);
52
- const PseudoClassesNotRE = new RegExp(`^not-(${PseudoClassesStr})[:-]`);
53
- const PseudoClassesGroupRE = new RegExp(`^group-((not-)?(${PseudoClassesStr}))[:-]`);
54
- const PseudoClassesPeerRE = new RegExp(`^peer-((not-)?(${PseudoClassesStr}))[:-]`);
61
+ const PseudoClassFunctionsRE = new RegExp(`^(${PseudoClassFunctionsStr})-(${PseudoClassesStr})[:-]`);
62
+ function shouldAdd(entires) {
63
+ return !entires.find((i) => i[0] === CONTROL_BYPASS_PSEUDO_CLASS) || void 0;
64
+ }
65
+ const taggedPseudoClassMatcher = (tag, parent, combinator) => {
66
+ const re = new RegExp(`^${tag}-((?:(${PseudoClassFunctionsStr})-)?(${PseudoClassesStr}))[:-]`);
67
+ const rawRe = new RegExp(`^${core.escapeRegExp(parent)}:`);
68
+ return (input) => {
69
+ const match = input.match(re);
70
+ if (match) {
71
+ let pseudo = PseudoClasses[match[3]] || match[3];
72
+ if (match[2])
73
+ pseudo = `${match[2]}(:${pseudo})`;
74
+ return {
75
+ matcher: input.slice(match[1].length + tag.length + 2),
76
+ selector: (s, body) => {
77
+ return shouldAdd(body) && rawRe.test(s) ? s.replace(rawRe, `${parent}:${pseudo}:`) : `${parent}:${pseudo}${combinator}${s}`;
78
+ }
79
+ };
80
+ }
81
+ };
82
+ };
55
83
  const variantPseudoElements = (input) => {
56
84
  const match = input.match(PseudoElementsRE);
57
85
  if (match) {
@@ -61,12 +89,9 @@ const variantPseudoElements = (input) => {
61
89
  };
62
90
  }
63
91
  };
64
- function shouldAdd(entires) {
65
- return !entires.find((i) => i[0] === CONTROL_BYPASS_PSEUDO_CLASS) || void 0;
66
- }
67
92
  const variantPseudoClasses = {
68
93
  match: (input) => {
69
- let match = input.match(PseudoClassesRE);
94
+ const match = input.match(PseudoClassesRE);
70
95
  if (match) {
71
96
  const pseudo = PseudoClasses[match[1]] || match[1];
72
97
  return {
@@ -74,32 +99,45 @@ const variantPseudoClasses = {
74
99
  selector: (s, body) => shouldAdd(body) && `${s}:${pseudo}`
75
100
  };
76
101
  }
77
- match = input.match(PseudoClassesNotRE);
78
- if (match) {
79
- const pseudo = PseudoClasses[match[1]] || match[1];
80
- return {
81
- matcher: input.slice(match[1].length + 5),
82
- selector: (s, body) => shouldAdd(body) && `${s}:not(:${pseudo})`
83
- };
84
- }
85
- match = input.match(PseudoClassesGroupRE);
102
+ },
103
+ multiPass: true
104
+ };
105
+ const variantPseudoClassFunctions = {
106
+ match: (input) => {
107
+ const match = input.match(PseudoClassFunctionsRE);
86
108
  if (match) {
87
- let pseudo = PseudoClasses[match[3]] || match[3];
88
- if (match[2])
89
- pseudo = `not(:${pseudo})`;
109
+ const fn = match[1];
110
+ const pseudo = PseudoClasses[match[2]] || match[2];
90
111
  return {
91
- matcher: input.slice(match[1].length + 7),
92
- selector: (s, body) => shouldAdd(body) && s.includes(".group:") ? s.replace(/\.group:/, `.group:${pseudo}:`) : `.group:${pseudo} ${s}`
112
+ matcher: input.slice(match[1].length + match[2].length + 2),
113
+ selector: (s, body) => shouldAdd(body) && `${s}:${fn}(:${pseudo})`
93
114
  };
94
115
  }
95
- match = input.match(PseudoClassesPeerRE);
116
+ },
117
+ multiPass: true
118
+ };
119
+ const variantTaggedPseudoClasses = (options = {}) => ({
120
+ match: (input) => {
121
+ const attributify = !!options?.attributifyPseudo;
122
+ const g = taggedPseudoClassMatcher("group", attributify ? '[group=""]' : ".group", " ")(input);
123
+ if (g)
124
+ return g;
125
+ const p = taggedPseudoClassMatcher("peer", attributify ? '[peer=""]' : ".peer", "~")(input);
126
+ if (p)
127
+ return p;
128
+ },
129
+ multiPass: true
130
+ });
131
+ const partClasses = {
132
+ match: (input) => {
133
+ const match = input.match(PartClassesRE);
96
134
  if (match) {
97
- let pseudo = PseudoClasses[match[3]] || match[3];
98
- if (match[2])
99
- pseudo = `not(:${pseudo})`;
135
+ const part = `part(${match[2]})`;
100
136
  return {
101
- matcher: input.slice(match[1].length + 6),
102
- selector: (s, body) => shouldAdd(body) && s.includes(".peer:") ? s.replace(/\.peer:/, `.peer:${pseudo}:`) : `.peer:${pseudo}~${s}`
137
+ matcher: input.slice(match[1].length),
138
+ selector: (s, body) => {
139
+ return shouldAdd(body) && `${s}::${part}`;
140
+ }
103
141
  };
104
142
  }
105
143
  },
@@ -107,6 +145,8 @@ const variantPseudoClasses = {
107
145
  };
108
146
 
109
147
  exports.CONTROL_BYPASS_PSEUDO_CLASS = CONTROL_BYPASS_PSEUDO_CLASS;
110
- exports.PseudoClasses = PseudoClasses;
148
+ exports.partClasses = partClasses;
149
+ exports.variantPseudoClassFunctions = variantPseudoClassFunctions;
111
150
  exports.variantPseudoClasses = variantPseudoClasses;
112
151
  exports.variantPseudoElements = variantPseudoElements;
152
+ exports.variantTaggedPseudoClasses = variantTaggedPseudoClasses;
@@ -1,4 +1,4 @@
1
- import { toArray } from '@unocss/core';
1
+ import { toArray, escapeRegExp } from '@unocss/core';
2
2
 
3
3
  const CONTROL_BYPASS_PSEUDO_CLASS = "$$no-pseudo";
4
4
  const PseudoClasses = Object.fromEntries([
@@ -38,18 +38,46 @@ const PseudoClasses = Object.fromEntries([
38
38
  "only-of-type"
39
39
  ].map(toArray));
40
40
  const PseudoElements = [
41
+ "placeholder",
41
42
  "before",
42
43
  "after",
43
44
  "first-letter",
44
45
  "first-line",
45
46
  "selection"
46
47
  ];
48
+ const PseudoClassFunctions = [
49
+ "not",
50
+ "is",
51
+ "where",
52
+ "has"
53
+ ];
54
+ const PartClassesRE = /(part-\[(.+)]:)(.+)/;
47
55
  const PseudoElementsRE = new RegExp(`^(${PseudoElements.join("|")})[:-]`);
48
56
  const PseudoClassesStr = Object.keys(PseudoClasses).join("|");
57
+ const PseudoClassFunctionsStr = PseudoClassFunctions.join("|");
49
58
  const PseudoClassesRE = new RegExp(`^(${PseudoClassesStr})[:-]`);
50
- const PseudoClassesNotRE = new RegExp(`^not-(${PseudoClassesStr})[:-]`);
51
- const PseudoClassesGroupRE = new RegExp(`^group-((not-)?(${PseudoClassesStr}))[:-]`);
52
- const PseudoClassesPeerRE = new RegExp(`^peer-((not-)?(${PseudoClassesStr}))[:-]`);
59
+ const PseudoClassFunctionsRE = new RegExp(`^(${PseudoClassFunctionsStr})-(${PseudoClassesStr})[:-]`);
60
+ function shouldAdd(entires) {
61
+ return !entires.find((i) => i[0] === CONTROL_BYPASS_PSEUDO_CLASS) || void 0;
62
+ }
63
+ const taggedPseudoClassMatcher = (tag, parent, combinator) => {
64
+ const re = new RegExp(`^${tag}-((?:(${PseudoClassFunctionsStr})-)?(${PseudoClassesStr}))[:-]`);
65
+ const rawRe = new RegExp(`^${escapeRegExp(parent)}:`);
66
+ return (input) => {
67
+ const match = input.match(re);
68
+ if (match) {
69
+ let pseudo = PseudoClasses[match[3]] || match[3];
70
+ if (match[2])
71
+ pseudo = `${match[2]}(:${pseudo})`;
72
+ return {
73
+ matcher: input.slice(match[1].length + tag.length + 2),
74
+ selector: (s, body) => {
75
+ return shouldAdd(body) && rawRe.test(s) ? s.replace(rawRe, `${parent}:${pseudo}:`) : `${parent}:${pseudo}${combinator}${s}`;
76
+ }
77
+ };
78
+ }
79
+ };
80
+ };
53
81
  const variantPseudoElements = (input) => {
54
82
  const match = input.match(PseudoElementsRE);
55
83
  if (match) {
@@ -59,12 +87,9 @@ const variantPseudoElements = (input) => {
59
87
  };
60
88
  }
61
89
  };
62
- function shouldAdd(entires) {
63
- return !entires.find((i) => i[0] === CONTROL_BYPASS_PSEUDO_CLASS) || void 0;
64
- }
65
90
  const variantPseudoClasses = {
66
91
  match: (input) => {
67
- let match = input.match(PseudoClassesRE);
92
+ const match = input.match(PseudoClassesRE);
68
93
  if (match) {
69
94
  const pseudo = PseudoClasses[match[1]] || match[1];
70
95
  return {
@@ -72,36 +97,49 @@ const variantPseudoClasses = {
72
97
  selector: (s, body) => shouldAdd(body) && `${s}:${pseudo}`
73
98
  };
74
99
  }
75
- match = input.match(PseudoClassesNotRE);
76
- if (match) {
77
- const pseudo = PseudoClasses[match[1]] || match[1];
78
- return {
79
- matcher: input.slice(match[1].length + 5),
80
- selector: (s, body) => shouldAdd(body) && `${s}:not(:${pseudo})`
81
- };
82
- }
83
- match = input.match(PseudoClassesGroupRE);
100
+ },
101
+ multiPass: true
102
+ };
103
+ const variantPseudoClassFunctions = {
104
+ match: (input) => {
105
+ const match = input.match(PseudoClassFunctionsRE);
84
106
  if (match) {
85
- let pseudo = PseudoClasses[match[3]] || match[3];
86
- if (match[2])
87
- pseudo = `not(:${pseudo})`;
107
+ const fn = match[1];
108
+ const pseudo = PseudoClasses[match[2]] || match[2];
88
109
  return {
89
- matcher: input.slice(match[1].length + 7),
90
- selector: (s, body) => shouldAdd(body) && s.includes(".group:") ? s.replace(/\.group:/, `.group:${pseudo}:`) : `.group:${pseudo} ${s}`
110
+ matcher: input.slice(match[1].length + match[2].length + 2),
111
+ selector: (s, body) => shouldAdd(body) && `${s}:${fn}(:${pseudo})`
91
112
  };
92
113
  }
93
- match = input.match(PseudoClassesPeerRE);
114
+ },
115
+ multiPass: true
116
+ };
117
+ const variantTaggedPseudoClasses = (options = {}) => ({
118
+ match: (input) => {
119
+ const attributify = !!options?.attributifyPseudo;
120
+ const g = taggedPseudoClassMatcher("group", attributify ? '[group=""]' : ".group", " ")(input);
121
+ if (g)
122
+ return g;
123
+ const p = taggedPseudoClassMatcher("peer", attributify ? '[peer=""]' : ".peer", "~")(input);
124
+ if (p)
125
+ return p;
126
+ },
127
+ multiPass: true
128
+ });
129
+ const partClasses = {
130
+ match: (input) => {
131
+ const match = input.match(PartClassesRE);
94
132
  if (match) {
95
- let pseudo = PseudoClasses[match[3]] || match[3];
96
- if (match[2])
97
- pseudo = `not(:${pseudo})`;
133
+ const part = `part(${match[2]})`;
98
134
  return {
99
- matcher: input.slice(match[1].length + 6),
100
- selector: (s, body) => shouldAdd(body) && s.includes(".peer:") ? s.replace(/\.peer:/, `.peer:${pseudo}:`) : `.peer:${pseudo}~${s}`
135
+ matcher: input.slice(match[1].length),
136
+ selector: (s, body) => {
137
+ return shouldAdd(body) && `${s}::${part}`;
138
+ }
101
139
  };
102
140
  }
103
141
  },
104
142
  multiPass: true
105
143
  };
106
144
 
107
- export { CONTROL_BYPASS_PSEUDO_CLASS as C, PseudoClasses as P, variantPseudoElements as a, variantPseudoClasses as v };
145
+ export { CONTROL_BYPASS_PSEUDO_CLASS as C, variantPseudoClassFunctions as a, variantTaggedPseudoClasses as b, variantPseudoElements as c, partClasses as p, variantPseudoClasses as v };
@@ -36,12 +36,64 @@ const xyzMap = {
36
36
  "": ["-x", "-y"]
37
37
  };
38
38
 
39
+ const cssBasicProps = [
40
+ "color",
41
+ "border-color",
42
+ "background-color",
43
+ "flex-grow",
44
+ "flex",
45
+ "flex-shrink",
46
+ "caret-color",
47
+ "font",
48
+ "gap",
49
+ "opacity",
50
+ "visibility",
51
+ "z-index",
52
+ "font-weight",
53
+ "zoom",
54
+ "text-shadow",
55
+ "transform",
56
+ "box-shadow"
57
+ ];
58
+ const cssPositionProps = [
59
+ "backround-position",
60
+ "left",
61
+ "right",
62
+ "top",
63
+ "bottom",
64
+ "object-position"
65
+ ];
66
+ const cssSizeProps = [
67
+ "max-height",
68
+ "min-height",
69
+ "max-width",
70
+ "min-width",
71
+ "height",
72
+ "width",
73
+ "border-width",
74
+ "margin",
75
+ "padding",
76
+ "outline-width",
77
+ "outline-offset",
78
+ "font-size",
79
+ "line-height",
80
+ "text-indent",
81
+ "vertical-align",
82
+ "border-spacing",
83
+ "letter-spacing",
84
+ "word-spacing"
85
+ ];
86
+ const cssEnhanceProps = ["stroke", "filter", "backdrop-filter", "fill", "mask", "mask-size", "mask-border", "clip-path", "clip"];
87
+ const cssProps = [
88
+ ...cssBasicProps,
89
+ ...cssPositionProps,
90
+ ...cssSizeProps,
91
+ ...cssEnhanceProps
92
+ ];
39
93
  const numberWithUnitRE = /^(-?[0-9.]+)(px|pt|pc|rem|em|%|vh|vw|in|cm|mm|ex|ch|vmin|vmax)?$/i;
40
94
  const numberRE = /^(-?[0-9.]+)$/i;
41
95
  const unitOnlyRE = /^(px)$/i;
42
96
  function numberWithUnit(str) {
43
- if (str === "auto" || str === "a")
44
- return "auto";
45
97
  const match = str.match(numberWithUnitRE);
46
98
  if (!match)
47
99
  return;
@@ -49,9 +101,11 @@ function numberWithUnit(str) {
49
101
  if (unit)
50
102
  return str;
51
103
  }
52
- function rem(str) {
104
+ function auto(str) {
53
105
  if (str === "auto" || str === "a")
54
106
  return "auto";
107
+ }
108
+ function rem(str) {
55
109
  if (str.match(unitOnlyRE))
56
110
  return `1${str}`;
57
111
  const match = str.match(numberWithUnitRE);
@@ -122,10 +176,20 @@ function global(str) {
122
176
  if (["inherit", "initial", "revert", "unset"].includes(str))
123
177
  return str;
124
178
  }
179
+ function properties(str) {
180
+ if (str === void 0)
181
+ return;
182
+ for (const prop of str.split(",")) {
183
+ if (!cssProps.includes(prop))
184
+ return;
185
+ }
186
+ return str;
187
+ }
125
188
 
126
189
  const valueHandlers = {
127
190
  __proto__: null,
128
191
  numberWithUnit: numberWithUnit,
192
+ auto: auto,
129
193
  rem: rem,
130
194
  px: px,
131
195
  number: number,
@@ -134,7 +198,8 @@ const valueHandlers = {
134
198
  bracket: bracket,
135
199
  cssvar: cssvar,
136
200
  time: time,
137
- global: global
201
+ global: global,
202
+ properties: properties
138
203
  };
139
204
 
140
205
  const handler = core.createValueHandler(valueHandlers);
@@ -143,17 +208,87 @@ const h = handler;
143
208
  function capitalize(str) {
144
209
  return str.charAt(0).toUpperCase() + str.slice(1);
145
210
  }
146
- const directionSize = (prefix) => ([_, direction, size]) => {
147
- const v = handler.bracket.rem.fraction.cssvar(size);
148
- if (v)
149
- return directionMap[direction].map((i) => [prefix + i, v]);
211
+ const directionSize = (propertyPrefix) => ([_, direction, size]) => {
212
+ const v = handler.bracket.auto.rem.fraction.cssvar(size);
213
+ if (v !== void 0)
214
+ return directionMap[direction].map((i) => [`${propertyPrefix}${i}`, v]);
215
+ };
216
+ const getThemeColor = (theme, colors) => theme.colors?.[colors.join("-").replace(/(-[a-z])/g, (n) => n.slice(1).toUpperCase())];
217
+ const parseColor = (body, theme) => {
218
+ const [main, opacity] = body.split(/(?:\/|:)/);
219
+ const colors = main.replace(/([a-z])([0-9])/g, "$1-$2").split(/-/g);
220
+ const [name] = colors;
221
+ if (!name)
222
+ return;
223
+ let color;
224
+ const bracket = handler.bracket(main);
225
+ const bracketOrMain = bracket || main;
226
+ if (bracketOrMain.startsWith("#"))
227
+ color = bracketOrMain.slice(1);
228
+ if (bracketOrMain.startsWith("hex-"))
229
+ color = bracketOrMain.slice(4);
230
+ color = color || bracket;
231
+ let no = "DEFAULT";
232
+ if (!color) {
233
+ let colorData;
234
+ const [scale] = colors.slice(-1);
235
+ if (scale.match(/^\d+$/)) {
236
+ no = scale;
237
+ colorData = getThemeColor(theme, colors.slice(0, -1));
238
+ } else {
239
+ colorData = getThemeColor(theme, colors);
240
+ if (!colorData) {
241
+ [, no = no] = colors;
242
+ colorData = getThemeColor(theme, [name]);
243
+ }
244
+ }
245
+ if (typeof colorData === "string")
246
+ color = colorData;
247
+ else if (no && colorData)
248
+ color = colorData[no];
249
+ }
250
+ return {
251
+ opacity,
252
+ name,
253
+ no,
254
+ color,
255
+ rgba: core.hex2rgba(color)
256
+ };
257
+ };
258
+ const colorResolver = (property, varName) => ([, body], { theme }) => {
259
+ const data = parseColor(body, theme);
260
+ if (!data)
261
+ return;
262
+ const { opacity, color, rgba } = data;
263
+ if (!color)
264
+ return;
265
+ const a = opacity ? opacity[0] === "[" ? handler.bracket.percent(opacity) : parseFloat(opacity) / 100 : rgba?.[3];
266
+ if (rgba) {
267
+ if (a != null && !Number.isNaN(a)) {
268
+ rgba[3] = typeof a === "string" && !a.includes("%") ? parseFloat(a) : a;
269
+ return {
270
+ [property]: `rgba(${rgba.join(",")})`
271
+ };
272
+ } else {
273
+ return {
274
+ [`--un-${varName}-opacity`]: 1,
275
+ [property]: `rgba(${rgba.slice(0, 3).join(",")},var(--un-${varName}-opacity))`
276
+ };
277
+ }
278
+ } else {
279
+ return {
280
+ [property]: color.replace("%alpha", `${a || 1}`)
281
+ };
282
+ }
150
283
  };
151
284
 
152
285
  exports.capitalize = capitalize;
286
+ exports.colorResolver = colorResolver;
153
287
  exports.cornerMap = cornerMap;
154
288
  exports.directionMap = directionMap;
155
289
  exports.directionSize = directionSize;
156
290
  exports.h = h;
157
291
  exports.handler = handler;
292
+ exports.parseColor = parseColor;
158
293
  exports.valueHandlers = valueHandlers;
159
294
  exports.xyzMap = xyzMap;