tailwindcss 0.0.0-insiders.ef325ea → 0.0.0-insiders.f267d91

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/CHANGELOG.md CHANGED
@@ -15,6 +15,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
15
15
 
16
16
  - Add `placeholder` variant ([#6106](https://github.com/tailwindlabs/tailwindcss/pull/6106))
17
17
  - Add tuple syntax for configuring screens while guaranteeing order ([#5956](https://github.com/tailwindlabs/tailwindcss/pull/5956))
18
+ - Add combinable `touch-action` support ([#6115](https://github.com/tailwindlabs/tailwindcss/pull/6115))
19
+ - Add support for "arbitrary properties" ([#6161](https://github.com/tailwindlabs/tailwindcss/pull/6161))
20
+ - Add `portrait` and `landscape` variants ([#6046](https://github.com/tailwindlabs/tailwindcss/pull/6046))
21
+ - Add `aspect-attrs` utility by default ([#6178](https://github.com/tailwindlabs/tailwindcss/pull/6178))
22
+ - Add `text-decoration-style`, `text-decoration-thickness`, and `text-underline-offset` utilities ([#6004](https://github.com/tailwindlabs/tailwindcss/pull/6004))
23
+
24
+ ### Changed
25
+
26
+ - Deprecate `decoration-slice` and `decoration-break` in favor `box-decoration-slice` and `box-decoration-break` _(non-breaking)_ ([#6004](https://github.com/tailwindlabs/tailwindcss/pull/6004))
18
27
 
19
28
  ## [3.0.0-alpha.2] - 2021-11-08
20
29
 
@@ -126,6 +126,9 @@ var _default = [
126
126
  "textOpacity",
127
127
  "textDecoration",
128
128
  "textDecorationColor",
129
+ "textDecorationStyle",
130
+ "textDecorationThickness",
131
+ "textUnderlineOffset",
129
132
  "fontSmoothing",
130
133
  "placeholderColor",
131
134
  "placeholderOpacity",
@@ -203,6 +203,10 @@ let variantPlugins = {
203
203
  let query = (0, _buildMediaQuery).default(screen);
204
204
  addVariant(screen.name, `@media ${query}`);
205
205
  }
206
+ },
207
+ orientationVariants: ({ addVariant })=>{
208
+ addVariant('portrait', '@media (orientation: portrait)');
209
+ addVariant('landscape', '@media (orientation: landscape)');
206
210
  }
207
211
  };
208
212
  exports.variantPlugins = variantPlugins;
@@ -995,7 +999,15 @@ let corePlugins1 = {
995
999
  });
996
1000
  },
997
1001
  cursor: (0, _createUtilityPlugin).default('cursor'),
998
- touchAction: ({ addUtilities })=>{
1002
+ touchAction: ({ addBase , addUtilities })=>{
1003
+ addBase({
1004
+ '@defaults touch-action': {
1005
+ '--tw-pan-x': 'var(--tw-empty,/*!*/ /*!*/)',
1006
+ '--tw-pan-y': 'var(--tw-empty,/*!*/ /*!*/)',
1007
+ '--tw-pinch-zoom': 'var(--tw-empty,/*!*/ /*!*/)',
1008
+ '--tw-touch-action': 'var(--tw-pan-x) var(--tw-pan-y) var(--tw-pinch-zoom)'
1009
+ }
1010
+ });
999
1011
  addUtilities({
1000
1012
  '.touch-auto': {
1001
1013
  'touch-action': 'auto'
@@ -1004,25 +1016,46 @@ let corePlugins1 = {
1004
1016
  'touch-action': 'none'
1005
1017
  },
1006
1018
  '.touch-pan-x': {
1007
- 'touch-action': 'pan-x'
1019
+ '@defaults touch-action': {
1020
+ },
1021
+ '--tw-pan-x': 'pan-x',
1022
+ 'touch-action': 'var(--tw-touch-action)'
1008
1023
  },
1009
1024
  '.touch-pan-left': {
1010
- 'touch-action': 'pan-left'
1025
+ '@defaults touch-action': {
1026
+ },
1027
+ '--tw-pan-x': 'pan-left',
1028
+ 'touch-action': 'var(--tw-touch-action)'
1011
1029
  },
1012
1030
  '.touch-pan-right': {
1013
- 'touch-action': 'pan-right'
1031
+ '@defaults touch-action': {
1032
+ },
1033
+ '--tw-pan-x': 'pan-right',
1034
+ 'touch-action': 'var(--tw-touch-action)'
1014
1035
  },
1015
1036
  '.touch-pan-y': {
1016
- 'touch-action': 'pan-y'
1037
+ '@defaults touch-action': {
1038
+ },
1039
+ '--tw-pan-y': 'pan-y',
1040
+ 'touch-action': 'var(--tw-touch-action)'
1017
1041
  },
1018
1042
  '.touch-pan-up': {
1019
- 'touch-action': 'pan-up'
1043
+ '@defaults touch-action': {
1044
+ },
1045
+ '--tw-pan-y': 'pan-up',
1046
+ 'touch-action': 'var(--tw-touch-action)'
1020
1047
  },
1021
1048
  '.touch-pan-down': {
1022
- 'touch-action': 'pan-down'
1049
+ '@defaults touch-action': {
1050
+ },
1051
+ '--tw-pan-y': 'pan-down',
1052
+ 'touch-action': 'var(--tw-touch-action)'
1023
1053
  },
1024
1054
  '.touch-pinch-zoom': {
1025
- 'touch-action': 'pinch-zoom'
1055
+ '@defaults touch-action': {
1056
+ },
1057
+ '--tw-pinch-zoom': 'pinch-zoom',
1058
+ 'touch-action': 'var(--tw-touch-action)'
1026
1059
  },
1027
1060
  '.touch-manipulation': {
1028
1061
  'touch-action': 'manipulation'
@@ -2282,6 +2315,12 @@ let corePlugins1 = {
2282
2315
  },
2283
2316
  '.decoration-clone': {
2284
2317
  'box-decoration-break': 'clone'
2318
+ },
2319
+ '.box-decoration-slice': {
2320
+ 'box-decoration-break': 'slice'
2321
+ },
2322
+ '.box-decoration-clone': {
2323
+ 'box-decoration-break': 'clone'
2285
2324
  }
2286
2325
  });
2287
2326
  },
@@ -2753,6 +2792,9 @@ let corePlugins1 = {
2753
2792
  '.underline': {
2754
2793
  'text-decoration': 'underline'
2755
2794
  },
2795
+ '.overline': {
2796
+ 'text-decoration': 'overline'
2797
+ },
2756
2798
  '.line-through': {
2757
2799
  'text-decoration': 'line-through'
2758
2800
  },
@@ -2771,11 +2813,55 @@ let corePlugins1 = {
2771
2813
  }, {
2772
2814
  values: (0, _flattenColorPalette).default(theme('textDecorationColor')),
2773
2815
  type: [
2774
- 'color',
2775
- 'any'
2816
+ 'color'
2776
2817
  ]
2777
2818
  });
2778
2819
  },
2820
+ textDecorationStyle: ({ addUtilities })=>{
2821
+ addUtilities({
2822
+ '.decoration-solid': {
2823
+ 'text-decoration-style': 'solid'
2824
+ },
2825
+ '.decoration-double': {
2826
+ 'text-decoration-style': 'double'
2827
+ },
2828
+ '.decoration-dotted': {
2829
+ 'text-decoration-style': 'dotted'
2830
+ },
2831
+ '.decoration-dashed': {
2832
+ 'text-decoration-style': 'dashed'
2833
+ },
2834
+ '.decoration-wavy': {
2835
+ 'text-decoration-style': 'wavy'
2836
+ }
2837
+ });
2838
+ },
2839
+ textDecorationThickness: (0, _createUtilityPlugin).default('textDecorationThickness', [
2840
+ [
2841
+ 'decoration',
2842
+ [
2843
+ 'text-decoration-thickness'
2844
+ ]
2845
+ ]
2846
+ ], {
2847
+ type: [
2848
+ 'length',
2849
+ 'percentage'
2850
+ ]
2851
+ }),
2852
+ textUnderlineOffset: (0, _createUtilityPlugin).default('textUnderlineOffset', [
2853
+ [
2854
+ 'underline-offset',
2855
+ [
2856
+ 'text-underline-offset'
2857
+ ]
2858
+ ]
2859
+ ], {
2860
+ type: [
2861
+ 'length',
2862
+ 'percentage'
2863
+ ]
2864
+ }),
2779
2865
  fontSmoothing: ({ addUtilities })=>{
2780
2866
  addUtilities({
2781
2867
  '.antialiased': {
@@ -288,7 +288,8 @@ legend {
288
288
  }
289
289
 
290
290
  ol,
291
- ul {
291
+ ul,
292
+ menu {
292
293
  list-style: none;
293
294
  margin: 0;
294
295
  padding: 0;
@@ -46,6 +46,8 @@ const PATTERNS = [
46
46
  /([^<>"'`\s]*\[\w*\("[^'`\s]*"\)\])/.source,
47
47
  /([^<>"'`\s]*\['[^"'`\s]*'\])/.source,
48
48
  /([^<>"'`\s]*\["[^"'`\s]*"\])/.source,
49
+ /([^<>"'`\s]*\[[^<>"'`\s]*:'[^"'`\s]*'\])/.source,
50
+ /([^<>"'`\s]*\[[^<>"'`\s]*:"[^"'`\s]*"\])/.source,
49
51
  /([^<>"'`\s]*\[[^"'`\s]+\][^<>"'`\s]*)/.source,
50
52
  /([^<>"'`\s]*[^"'`\s:])/.source
51
53
  ].join('|');
@@ -11,6 +11,9 @@ var _prefixSelector = _interopRequireDefault(require("../util/prefixSelector"));
11
11
  var _pluginUtils = require("../util/pluginUtils");
12
12
  var _log = _interopRequireDefault(require("../util/log"));
13
13
  var _formatVariantSelector = require("../util/formatVariantSelector");
14
+ var _nameClass = require("../util/nameClass");
15
+ var _dataTypes = require("../util/dataTypes");
16
+ var _isValidArbitraryValue = _interopRequireDefault(require("../util/isValidArbitraryValue"));
14
17
  function _interopRequireDefault(obj) {
15
18
  return obj && obj.__esModule ? obj : {
16
19
  default: obj
@@ -250,6 +253,31 @@ function parseRules(rule, cache, options = {
250
253
  options
251
254
  ];
252
255
  }
256
+ function extractArbitraryProperty(classCandidate, context) {
257
+ var ref;
258
+ let [, property, value] = (ref = classCandidate.match(/^\[([a-zA-Z0-9-_]+):(\S+)\]$/)) !== null && ref !== void 0 ? ref : [];
259
+ if (value === undefined) {
260
+ return null;
261
+ }
262
+ let normalized = (0, _dataTypes).normalize(value);
263
+ if (!(0, _isValidArbitraryValue).default(normalized)) {
264
+ return null;
265
+ }
266
+ return [
267
+ [
268
+ {
269
+ sort: context.arbitraryPropertiesSort,
270
+ layer: 'utilities'
271
+ },
272
+ ()=>({
273
+ [(0, _nameClass).asClass(classCandidate)]: {
274
+ [property]: normalized
275
+ }
276
+ })
277
+ ,
278
+ ],
279
+ ];
280
+ }
253
281
  function* resolveMatchedPlugins(classCandidate, context) {
254
282
  if (context.candidateRuleMap.has(classCandidate)) {
255
283
  yield [
@@ -257,6 +285,14 @@ function* resolveMatchedPlugins(classCandidate, context) {
257
285
  'DEFAULT'
258
286
  ];
259
287
  }
288
+ yield* (function*(arbitraryPropertyRule) {
289
+ if (arbitraryPropertyRule !== null) {
290
+ yield [
291
+ arbitraryPropertyRule,
292
+ 'DEFAULT'
293
+ ];
294
+ }
295
+ })(extractArbitraryProperty(classCandidate, context));
260
296
  let candidatePrefix = classCandidate;
261
297
  let negative = false;
262
298
  const twConfigPrefix = context.tailwindConfig.prefix;
@@ -23,6 +23,7 @@ var sharedState = _interopRequireWildcard(require("./sharedState"));
23
23
  var _toPath = require("../util/toPath");
24
24
  var _log = _interopRequireDefault(require("../util/log"));
25
25
  var _negateValue = _interopRequireDefault(require("../util/negateValue"));
26
+ var _isValidArbitraryValue = _interopRequireDefault(require("../util/isValidArbitraryValue"));
26
27
  function _interopRequireDefault(obj) {
27
28
  return obj && obj.__esModule ? obj : {
28
29
  default: obj
@@ -160,68 +161,6 @@ function withIdentifiers(styles) {
160
161
  });
161
162
  });
162
163
  }
163
- let matchingBrackets = new Map([
164
- [
165
- '{',
166
- '}'
167
- ],
168
- [
169
- '[',
170
- ']'
171
- ],
172
- [
173
- '(',
174
- ')'
175
- ],
176
- ]);
177
- let inverseMatchingBrackets = new Map(Array.from(matchingBrackets.entries()).map(([k, v])=>[
178
- v,
179
- k
180
- ]
181
- ));
182
- let quotes = new Set([
183
- '"',
184
- "'",
185
- '`'
186
- ]);
187
- // Arbitrary values must contain balanced brackets (), [] and {}. Escaped
188
- // values don't count, and brackets inside quotes also don't count.
189
- //
190
- // E.g.: w-[this-is]w-[weird-and-invalid]
191
- // E.g.: w-[this-is\\]w-\\[weird-but-valid]
192
- // E.g.: content-['this-is-also-valid]-weirdly-enough']
193
- function isValidArbitraryValue(value) {
194
- let stack = [];
195
- let inQuotes = false;
196
- for(let i = 0; i < value.length; i++){
197
- let char = value[i];
198
- // Non-escaped quotes allow us to "allow" anything in between
199
- if (quotes.has(char) && value[i - 1] !== '\\') {
200
- inQuotes = !inQuotes;
201
- }
202
- if (inQuotes) continue;
203
- if (value[i - 1] === '\\') continue; // Escaped
204
- if (matchingBrackets.has(char)) {
205
- stack.push(char);
206
- } else if (inverseMatchingBrackets.has(char)) {
207
- let inverse = inverseMatchingBrackets.get(char);
208
- // Nothing to pop from, therefore it is unbalanced
209
- if (stack.length <= 0) {
210
- return false;
211
- }
212
- // Popped value must match the inverse value, otherwise it is unbalanced
213
- if (stack.pop() !== inverse) {
214
- return false;
215
- }
216
- }
217
- }
218
- // If there is still something on the stack, it is also unbalanced
219
- if (stack.length > 0) {
220
- return false;
221
- }
222
- // All good, totally balanced!
223
- return true;
224
- }
225
164
  function buildPluginApi(tailwindConfig, context, { variantList , variantMap , offsets , classList }) {
226
165
  function getConfigValue(path, defaultValue) {
227
166
  return path ? (0, _dlv).default(tailwindConfig, path, defaultValue) : tailwindConfig;
@@ -409,7 +348,7 @@ function buildPluginApi(tailwindConfig, context, { variantList , variantMap , of
409
348
  if (!type.includes(coercedType) && !isOnlyPlugin) {
410
349
  return [];
411
350
  }
412
- if (!isValidArbitraryValue(value)) {
351
+ if (!(0, _isValidArbitraryValue).default(value)) {
413
352
  return [];
414
353
  }
415
354
  let ruleSets = [].concat(rule(value)).filter(Boolean).map((declaration)=>({
@@ -466,7 +405,7 @@ function buildPluginApi(tailwindConfig, context, { variantList , variantMap , of
466
405
  return [];
467
406
  }
468
407
  }
469
- if (!isValidArbitraryValue(value)) {
408
+ if (!(0, _isValidArbitraryValue).default(value)) {
470
409
  return [];
471
410
  }
472
411
  let ruleSets = [].concat(rule(value)).filter(Boolean).map((declaration)=>({
@@ -608,7 +547,8 @@ function resolvePlugins(context, root) {
608
547
  _corePlugins.variantPlugins['reducedMotionVariants'],
609
548
  _corePlugins.variantPlugins['darkVariants'],
610
549
  _corePlugins.variantPlugins['printVariant'],
611
- _corePlugins.variantPlugins['screenVariants'],
550
+ _corePlugins.variantPlugins['screenVariants'],
551
+ _corePlugins.variantPlugins['orientationVariants'],
612
552
  ];
613
553
  return [
614
554
  ...corePluginList,
@@ -652,6 +592,9 @@ function registerPlugins(plugins, context) {
652
592
  offsets.user,
653
593
  ]);
654
594
  let reservedBits = BigInt(highestOffset.toString(2).length);
595
+ // A number one less than the top range of the highest offset area
596
+ // so arbitrary properties are always sorted at the end.
597
+ context.arbitraryPropertiesSort = (1n << reservedBits << 0n) - 1n;
655
598
  context.layerOrder = {
656
599
  base: 1n << reservedBits << 0n,
657
600
  components: 1n << reservedBits << 1n,
@@ -40,7 +40,16 @@ function formatVariantSelector(current, ...others) {
40
40
  function finalizeSelector(format, { selector: selector1 , candidate , context }) {
41
41
  var ref, ref1;
42
42
  var ref2;
43
- let base = candidate.split((ref2 = context === null || context === void 0 ? void 0 : (ref = context.tailwindConfig) === null || ref === void 0 ? void 0 : ref.separator) !== null && ref2 !== void 0 ? ref2 : ':').pop();
43
+ let separator = (ref2 = context === null || context === void 0 ? void 0 : (ref = context.tailwindConfig) === null || ref === void 0 ? void 0 : ref.separator) !== null && ref2 !== void 0 ? ref2 : ':';
44
+ // Split by the separator, but ignore the separator inside square brackets:
45
+ //
46
+ // E.g.: dark:lg:hover:[paint-order:markers]
47
+ // ┬ ┬ ┬ ┬
48
+ // │ │ │ ╰── We will not split here
49
+ // ╰──┴─────┴─────────────── We will split here
50
+ //
51
+ let splitter = new RegExp(`\\${separator}(?![^[]*\\])`);
52
+ let base = candidate.split(splitter).pop();
44
53
  if (context === null || context === void 0 ? void 0 : (ref1 = context.tailwindConfig) === null || ref1 === void 0 ? void 0 : ref1.prefix) {
45
54
  format = (0, _prefixSelector).default(context.tailwindConfig.prefix, format);
46
55
  }
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ exports.default = isValidArbitraryValue;
6
+ let matchingBrackets = new Map([
7
+ [
8
+ '{',
9
+ '}'
10
+ ],
11
+ [
12
+ '[',
13
+ ']'
14
+ ],
15
+ [
16
+ '(',
17
+ ')'
18
+ ],
19
+ ]);
20
+ let inverseMatchingBrackets = new Map(Array.from(matchingBrackets.entries()).map(([k, v])=>[
21
+ v,
22
+ k
23
+ ]
24
+ ));
25
+ let quotes = new Set([
26
+ '"',
27
+ "'",
28
+ '`'
29
+ ]);
30
+ function isValidArbitraryValue(value) {
31
+ let stack = [];
32
+ let inQuotes = false;
33
+ for(let i = 0; i < value.length; i++){
34
+ let char = value[i];
35
+ if (char === ':' && !inQuotes && stack.length === 0) {
36
+ return false;
37
+ }
38
+ // Non-escaped quotes allow us to "allow" anything in between
39
+ if (quotes.has(char) && value[i - 1] !== '\\') {
40
+ inQuotes = !inQuotes;
41
+ }
42
+ if (inQuotes) continue;
43
+ if (value[i - 1] === '\\') continue; // Escaped
44
+ if (matchingBrackets.has(char)) {
45
+ stack.push(char);
46
+ } else if (inverseMatchingBrackets.has(char)) {
47
+ let inverse = inverseMatchingBrackets.get(char);
48
+ // Nothing to pop from, therefore it is unbalanced
49
+ if (stack.length <= 0) {
50
+ return false;
51
+ }
52
+ // Popped value must match the inverse value, otherwise it is unbalanced
53
+ if (stack.pop() !== inverse) {
54
+ return false;
55
+ }
56
+ }
57
+ }
58
+ // If there is still something on the stack, it is also unbalanced
59
+ if (stack.length > 0) {
60
+ return false;
61
+ }
62
+ // All good, totally balanced!
63
+ return true;
64
+ }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
+ exports.asClass = asClass;
5
6
  exports.default = nameClass;
6
7
  exports.formatClass = formatClass;
7
8
  var _escapeClassName = _interopRequireDefault(require("./escapeClassName"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tailwindcss",
3
- "version": "0.0.0-insiders.ef325ea",
3
+ "version": "0.0.0-insiders.f267d91",
4
4
  "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
5
5
  "license": "MIT",
6
6
  "main": "lib/index.js",
@@ -1 +1 @@
1
- export default ["preflight","container","accessibility","pointerEvents","visibility","position","inset","isolation","zIndex","order","gridColumn","gridColumnStart","gridColumnEnd","gridRow","gridRowStart","gridRowEnd","float","clear","margin","boxSizing","display","aspectRatio","height","maxHeight","minHeight","width","minWidth","maxWidth","flex","flexShrink","flexGrow","flexBasis","tableLayout","borderCollapse","transformOrigin","translate","rotate","skew","scale","transform","animation","cursor","touchAction","userSelect","resize","scrollSnapType","scrollSnapAlign","scrollSnapStop","scrollMargin","scrollPadding","listStylePosition","listStyleType","appearance","columns","breakBefore","breakInside","breakAfter","gridAutoColumns","gridAutoFlow","gridAutoRows","gridTemplateColumns","gridTemplateRows","flexDirection","flexWrap","placeContent","placeItems","alignContent","alignItems","justifyContent","justifyItems","gap","space","divideWidth","divideStyle","divideColor","divideOpacity","placeSelf","alignSelf","justifySelf","overflow","overscrollBehavior","scrollBehavior","textOverflow","whitespace","wordBreak","borderRadius","borderWidth","borderStyle","borderColor","borderOpacity","backgroundColor","backgroundOpacity","backgroundImage","gradientColorStops","boxDecorationBreak","backgroundSize","backgroundAttachment","backgroundClip","backgroundPosition","backgroundRepeat","backgroundOrigin","fill","stroke","strokeWidth","objectFit","objectPosition","padding","textAlign","textIndent","verticalAlign","fontFamily","fontSize","fontWeight","textTransform","fontStyle","fontVariantNumeric","lineHeight","letterSpacing","textColor","textOpacity","textDecoration","textDecorationColor","fontSmoothing","placeholderColor","placeholderOpacity","caretColor","accentColor","opacity","backgroundBlendMode","mixBlendMode","boxShadow","boxShadowColor","outlineStyle","outlineWidth","outlineOffset","outlineColor","ringWidth","ringColor","ringOpacity","ringOffsetWidth","ringOffsetColor","blur","brightness","contrast","dropShadow","grayscale","hueRotate","invert","saturate","sepia","filter","backdropBlur","backdropBrightness","backdropContrast","backdropGrayscale","backdropHueRotate","backdropInvert","backdropOpacity","backdropSaturate","backdropSepia","backdropFilter","transitionProperty","transitionDelay","transitionDuration","transitionTimingFunction","willChange","content"]
1
+ export default ["preflight","container","accessibility","pointerEvents","visibility","position","inset","isolation","zIndex","order","gridColumn","gridColumnStart","gridColumnEnd","gridRow","gridRowStart","gridRowEnd","float","clear","margin","boxSizing","display","aspectRatio","height","maxHeight","minHeight","width","minWidth","maxWidth","flex","flexShrink","flexGrow","flexBasis","tableLayout","borderCollapse","transformOrigin","translate","rotate","skew","scale","transform","animation","cursor","touchAction","userSelect","resize","scrollSnapType","scrollSnapAlign","scrollSnapStop","scrollMargin","scrollPadding","listStylePosition","listStyleType","appearance","columns","breakBefore","breakInside","breakAfter","gridAutoColumns","gridAutoFlow","gridAutoRows","gridTemplateColumns","gridTemplateRows","flexDirection","flexWrap","placeContent","placeItems","alignContent","alignItems","justifyContent","justifyItems","gap","space","divideWidth","divideStyle","divideColor","divideOpacity","placeSelf","alignSelf","justifySelf","overflow","overscrollBehavior","scrollBehavior","textOverflow","whitespace","wordBreak","borderRadius","borderWidth","borderStyle","borderColor","borderOpacity","backgroundColor","backgroundOpacity","backgroundImage","gradientColorStops","boxDecorationBreak","backgroundSize","backgroundAttachment","backgroundClip","backgroundPosition","backgroundRepeat","backgroundOrigin","fill","stroke","strokeWidth","objectFit","objectPosition","padding","textAlign","textIndent","verticalAlign","fontFamily","fontSize","fontWeight","textTransform","fontStyle","fontVariantNumeric","lineHeight","letterSpacing","textColor","textOpacity","textDecoration","textDecorationColor","textDecorationStyle","textDecorationThickness","textUnderlineOffset","fontSmoothing","placeholderColor","placeholderOpacity","caretColor","accentColor","opacity","backgroundBlendMode","mixBlendMode","boxShadow","boxShadowColor","outlineStyle","outlineWidth","outlineOffset","outlineColor","ringWidth","ringColor","ringOpacity","ringOffsetWidth","ringOffsetColor","blur","brightness","contrast","dropShadow","grayscale","hueRotate","invert","saturate","sepia","filter","backdropBlur","backdropBrightness","backdropContrast","backdropGrayscale","backdropHueRotate","backdropInvert","backdropOpacity","backdropSaturate","backdropSepia","backdropFilter","transitionProperty","transitionDelay","transitionDuration","transitionTimingFunction","willChange","content"]
@@ -165,6 +165,11 @@ export let variantPlugins = {
165
165
  addVariant(screen.name, `@media ${query}`)
166
166
  }
167
167
  },
168
+
169
+ orientationVariants: ({ addVariant }) => {
170
+ addVariant('portrait', '@media (orientation: portrait)')
171
+ addVariant('landscape', '@media (orientation: landscape)')
172
+ },
168
173
  }
169
174
 
170
175
  export let corePlugins = {
@@ -602,17 +607,54 @@ export let corePlugins = {
602
607
 
603
608
  cursor: createUtilityPlugin('cursor'),
604
609
 
605
- touchAction: ({ addUtilities }) => {
610
+ touchAction: ({ addBase, addUtilities }) => {
611
+ addBase({
612
+ '@defaults touch-action': {
613
+ '--tw-pan-x': 'var(--tw-empty,/*!*/ /*!*/)',
614
+ '--tw-pan-y': 'var(--tw-empty,/*!*/ /*!*/)',
615
+ '--tw-pinch-zoom': 'var(--tw-empty,/*!*/ /*!*/)',
616
+ '--tw-touch-action': 'var(--tw-pan-x) var(--tw-pan-y) var(--tw-pinch-zoom)',
617
+ },
618
+ })
619
+
606
620
  addUtilities({
607
621
  '.touch-auto': { 'touch-action': 'auto' },
608
622
  '.touch-none': { 'touch-action': 'none' },
609
- '.touch-pan-x': { 'touch-action': 'pan-x' },
610
- '.touch-pan-left': { 'touch-action': 'pan-left' },
611
- '.touch-pan-right': { 'touch-action': 'pan-right' },
612
- '.touch-pan-y': { 'touch-action': 'pan-y' },
613
- '.touch-pan-up': { 'touch-action': 'pan-up' },
614
- '.touch-pan-down': { 'touch-action': 'pan-down' },
615
- '.touch-pinch-zoom': { 'touch-action': 'pinch-zoom' },
623
+ '.touch-pan-x': {
624
+ '@defaults touch-action': {},
625
+ '--tw-pan-x': 'pan-x',
626
+ 'touch-action': 'var(--tw-touch-action)',
627
+ },
628
+ '.touch-pan-left': {
629
+ '@defaults touch-action': {},
630
+ '--tw-pan-x': 'pan-left',
631
+ 'touch-action': 'var(--tw-touch-action)',
632
+ },
633
+ '.touch-pan-right': {
634
+ '@defaults touch-action': {},
635
+ '--tw-pan-x': 'pan-right',
636
+ 'touch-action': 'var(--tw-touch-action)',
637
+ },
638
+ '.touch-pan-y': {
639
+ '@defaults touch-action': {},
640
+ '--tw-pan-y': 'pan-y',
641
+ 'touch-action': 'var(--tw-touch-action)',
642
+ },
643
+ '.touch-pan-up': {
644
+ '@defaults touch-action': {},
645
+ '--tw-pan-y': 'pan-up',
646
+ 'touch-action': 'var(--tw-touch-action)',
647
+ },
648
+ '.touch-pan-down': {
649
+ '@defaults touch-action': {},
650
+ '--tw-pan-y': 'pan-down',
651
+ 'touch-action': 'var(--tw-touch-action)',
652
+ },
653
+ '.touch-pinch-zoom': {
654
+ '@defaults touch-action': {},
655
+ '--tw-pinch-zoom': 'pinch-zoom',
656
+ 'touch-action': 'var(--tw-touch-action)',
657
+ },
616
658
  '.touch-manipulation': { 'touch-action': 'manipulation' },
617
659
  })
618
660
  },
@@ -1354,8 +1396,10 @@ export let corePlugins = {
1354
1396
 
1355
1397
  boxDecorationBreak: ({ addUtilities }) => {
1356
1398
  addUtilities({
1357
- '.decoration-slice': { 'box-decoration-break': 'slice' },
1358
- '.decoration-clone': { 'box-decoration-break': 'clone' },
1399
+ '.decoration-slice': { 'box-decoration-break': 'slice' }, // Deprecated
1400
+ '.decoration-clone': { 'box-decoration-break': 'clone' }, // Deprecated
1401
+ '.box-decoration-slice': { 'box-decoration-break': 'slice' },
1402
+ '.box-decoration-clone': { 'box-decoration-break': 'clone' },
1359
1403
  })
1360
1404
  },
1361
1405
 
@@ -1613,6 +1657,7 @@ export let corePlugins = {
1613
1657
  textDecoration: ({ addUtilities }) => {
1614
1658
  addUtilities({
1615
1659
  '.underline': { 'text-decoration': 'underline' },
1660
+ '.overline': { 'text-decoration': 'overline' },
1616
1661
  '.line-through': { 'text-decoration': 'line-through' },
1617
1662
  '.no-underline': { 'text-decoration': 'none' },
1618
1663
  })
@@ -1625,10 +1670,32 @@ export let corePlugins = {
1625
1670
  return { 'text-decoration-color': toColorValue(value) }
1626
1671
  },
1627
1672
  },
1628
- { values: flattenColorPalette(theme('textDecorationColor')), type: ['color', 'any'] }
1673
+ { values: flattenColorPalette(theme('textDecorationColor')), type: ['color'] }
1629
1674
  )
1630
1675
  },
1631
1676
 
1677
+ textDecorationStyle: ({ addUtilities }) => {
1678
+ addUtilities({
1679
+ '.decoration-solid': { 'text-decoration-style': 'solid' },
1680
+ '.decoration-double': { 'text-decoration-style': 'double' },
1681
+ '.decoration-dotted': { 'text-decoration-style': 'dotted' },
1682
+ '.decoration-dashed': { 'text-decoration-style': 'dashed' },
1683
+ '.decoration-wavy': { 'text-decoration-style': 'wavy' },
1684
+ })
1685
+ },
1686
+
1687
+ textDecorationThickness: createUtilityPlugin(
1688
+ 'textDecorationThickness',
1689
+ [['decoration', ['text-decoration-thickness']]],
1690
+ { type: ['length', 'percentage'] }
1691
+ ),
1692
+
1693
+ textUnderlineOffset: createUtilityPlugin(
1694
+ 'textUnderlineOffset',
1695
+ [['underline-offset', ['text-underline-offset']]],
1696
+ { type: ['length', 'percentage'] }
1697
+ ),
1698
+
1632
1699
  fontSmoothing: ({ addUtilities }) => {
1633
1700
  addUtilities({
1634
1701
  '.antialiased': {
@@ -288,7 +288,8 @@ legend {
288
288
  }
289
289
 
290
290
  ol,
291
- ul {
291
+ ul,
292
+ menu {
292
293
  list-style: none;
293
294
  margin: 0;
294
295
  padding: 0;
@@ -15,6 +15,8 @@ const PATTERNS = [
15
15
  /([^<>"'`\s]*\[\w*\("[^'`\s]*"\)\])/.source, // bg-[url("..."),url("...")]
16
16
  /([^<>"'`\s]*\['[^"'`\s]*'\])/.source, // `content-['hello']` but not `content-['hello']']`
17
17
  /([^<>"'`\s]*\["[^"'`\s]*"\])/.source, // `content-["hello"]` but not `content-["hello"]"]`
18
+ /([^<>"'`\s]*\[[^<>"'`\s]*:'[^"'`\s]*'\])/.source, // `[content:'hello']` but not `[content:"hello"]`
19
+ /([^<>"'`\s]*\[[^<>"'`\s]*:"[^"'`\s]*"\])/.source, // `[content:"hello"]` but not `[content:'hello']`
18
20
  /([^<>"'`\s]*\[[^"'`\s]+\][^<>"'`\s]*)/.source, // `fill-[#bada55]`, `fill-[#bada55]/50`
19
21
  /([^<>"'`\s]*[^"'`\s:])/.source, // `px-1.5`, `uppercase` but not `uppercase:`
20
22
  ].join('|')
@@ -6,6 +6,9 @@ import prefixSelector from '../util/prefixSelector'
6
6
  import { updateAllClasses } from '../util/pluginUtils'
7
7
  import log from '../util/log'
8
8
  import { formatVariantSelector, finalizeSelector } from '../util/formatVariantSelector'
9
+ import { asClass } from '../util/nameClass'
10
+ import { normalize } from '../util/dataTypes'
11
+ import isValidArbitraryValue from '../util/isValidArbitraryValue'
9
12
 
10
13
  let classNameParser = selectorParser((selectors) => {
11
14
  return selectors.first.filter(({ type }) => type === 'class').pop().value
@@ -245,11 +248,42 @@ function parseRules(rule, cache, options = {}) {
245
248
  return [cache.get(rule), options]
246
249
  }
247
250
 
251
+ function extractArbitraryProperty(classCandidate, context) {
252
+ let [, property, value] = classCandidate.match(/^\[([a-zA-Z0-9-_]+):(\S+)\]$/) ?? []
253
+
254
+ if (value === undefined) {
255
+ return null
256
+ }
257
+
258
+ let normalized = normalize(value)
259
+
260
+ if (!isValidArbitraryValue(normalized)) {
261
+ return null
262
+ }
263
+
264
+ return [
265
+ [
266
+ { sort: context.arbitraryPropertiesSort, layer: 'utilities' },
267
+ () => ({
268
+ [asClass(classCandidate)]: {
269
+ [property]: normalized,
270
+ },
271
+ }),
272
+ ],
273
+ ]
274
+ }
275
+
248
276
  function* resolveMatchedPlugins(classCandidate, context) {
249
277
  if (context.candidateRuleMap.has(classCandidate)) {
250
278
  yield [context.candidateRuleMap.get(classCandidate), 'DEFAULT']
251
279
  }
252
280
 
281
+ yield* (function* (arbitraryPropertyRule) {
282
+ if (arbitraryPropertyRule !== null) {
283
+ yield [arbitraryPropertyRule, 'DEFAULT']
284
+ }
285
+ })(extractArbitraryProperty(classCandidate, context))
286
+
253
287
  let candidatePrefix = classCandidate
254
288
  let negative = false
255
289
 
@@ -18,6 +18,7 @@ import { env } from './sharedState'
18
18
  import { toPath } from '../util/toPath'
19
19
  import log from '../util/log'
20
20
  import negateValue from '../util/negateValue'
21
+ import isValidArbitraryValue from '../util/isValidArbitraryValue'
21
22
 
22
23
  function parseVariantFormatString(input) {
23
24
  if (input.includes('{')) {
@@ -130,64 +131,6 @@ function withIdentifiers(styles) {
130
131
  })
131
132
  }
132
133
 
133
- let matchingBrackets = new Map([
134
- ['{', '}'],
135
- ['[', ']'],
136
- ['(', ')'],
137
- ])
138
- let inverseMatchingBrackets = new Map(
139
- Array.from(matchingBrackets.entries()).map(([k, v]) => [v, k])
140
- )
141
-
142
- let quotes = new Set(['"', "'", '`'])
143
-
144
- // Arbitrary values must contain balanced brackets (), [] and {}. Escaped
145
- // values don't count, and brackets inside quotes also don't count.
146
- //
147
- // E.g.: w-[this-is]w-[weird-and-invalid]
148
- // E.g.: w-[this-is\\]w-\\[weird-but-valid]
149
- // E.g.: content-['this-is-also-valid]-weirdly-enough']
150
- function isValidArbitraryValue(value) {
151
- let stack = []
152
- let inQuotes = false
153
-
154
- for (let i = 0; i < value.length; i++) {
155
- let char = value[i]
156
-
157
- // Non-escaped quotes allow us to "allow" anything in between
158
- if (quotes.has(char) && value[i - 1] !== '\\') {
159
- inQuotes = !inQuotes
160
- }
161
-
162
- if (inQuotes) continue
163
- if (value[i - 1] === '\\') continue // Escaped
164
-
165
- if (matchingBrackets.has(char)) {
166
- stack.push(char)
167
- } else if (inverseMatchingBrackets.has(char)) {
168
- let inverse = inverseMatchingBrackets.get(char)
169
-
170
- // Nothing to pop from, therefore it is unbalanced
171
- if (stack.length <= 0) {
172
- return false
173
- }
174
-
175
- // Popped value must match the inverse value, otherwise it is unbalanced
176
- if (stack.pop() !== inverse) {
177
- return false
178
- }
179
- }
180
- }
181
-
182
- // If there is still something on the stack, it is also unbalanced
183
- if (stack.length > 0) {
184
- return false
185
- }
186
-
187
- // All good, totally balanced!
188
- return true
189
- }
190
-
191
134
  function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offsets, classList }) {
192
135
  function getConfigValue(path, defaultValue) {
193
136
  return path ? dlv(tailwindConfig, path, defaultValue) : tailwindConfig
@@ -575,6 +518,7 @@ function resolvePlugins(context, root) {
575
518
  variantPlugins['darkVariants'],
576
519
  variantPlugins['printVariant'],
577
520
  variantPlugins['screenVariants'],
521
+ variantPlugins['orientationVariants'],
578
522
  ]
579
523
 
580
524
  return [...corePluginList, ...beforeVariants, ...userPlugins, ...afterVariants, ...layerPlugins]
@@ -617,6 +561,10 @@ function registerPlugins(plugins, context) {
617
561
  ])
618
562
  let reservedBits = BigInt(highestOffset.toString(2).length)
619
563
 
564
+ // A number one less than the top range of the highest offset area
565
+ // so arbitrary properties are always sorted at the end.
566
+ context.arbitraryPropertiesSort = ((1n << reservedBits) << 0n) - 1n
567
+
620
568
  context.layerOrder = {
621
569
  base: (1n << reservedBits) << 0n,
622
570
  components: (1n << reservedBits) << 1n,
@@ -30,7 +30,17 @@ export function formatVariantSelector(current, ...others) {
30
30
  }
31
31
 
32
32
  export function finalizeSelector(format, { selector, candidate, context }) {
33
- let base = candidate.split(context?.tailwindConfig?.separator ?? ':').pop()
33
+ let separator = context?.tailwindConfig?.separator ?? ':'
34
+
35
+ // Split by the separator, but ignore the separator inside square brackets:
36
+ //
37
+ // E.g.: dark:lg:hover:[paint-order:markers]
38
+ // ┬ ┬ ┬ ┬
39
+ // │ │ │ ╰── We will not split here
40
+ // ╰──┴─────┴─────────────── We will split here
41
+ //
42
+ let splitter = new RegExp(`\\${separator}(?![^[]*\\])`)
43
+ let base = candidate.split(splitter).pop()
34
44
 
35
45
  if (context?.tailwindConfig?.prefix) {
36
46
  format = prefixSelector(context.tailwindConfig.prefix, format)
@@ -0,0 +1,61 @@
1
+ let matchingBrackets = new Map([
2
+ ['{', '}'],
3
+ ['[', ']'],
4
+ ['(', ')'],
5
+ ])
6
+ let inverseMatchingBrackets = new Map(
7
+ Array.from(matchingBrackets.entries()).map(([k, v]) => [v, k])
8
+ )
9
+
10
+ let quotes = new Set(['"', "'", '`'])
11
+
12
+ // Arbitrary values must contain balanced brackets (), [] and {}. Escaped
13
+ // values don't count, and brackets inside quotes also don't count.
14
+ //
15
+ // E.g.: w-[this-is]w-[weird-and-invalid]
16
+ // E.g.: w-[this-is\\]w-\\[weird-but-valid]
17
+ // E.g.: content-['this-is-also-valid]-weirdly-enough']
18
+ export default function isValidArbitraryValue(value) {
19
+ let stack = []
20
+ let inQuotes = false
21
+
22
+ for (let i = 0; i < value.length; i++) {
23
+ let char = value[i]
24
+
25
+ if (char === ':' && !inQuotes && stack.length === 0) {
26
+ return false
27
+ }
28
+
29
+ // Non-escaped quotes allow us to "allow" anything in between
30
+ if (quotes.has(char) && value[i - 1] !== '\\') {
31
+ inQuotes = !inQuotes
32
+ }
33
+
34
+ if (inQuotes) continue
35
+ if (value[i - 1] === '\\') continue // Escaped
36
+
37
+ if (matchingBrackets.has(char)) {
38
+ stack.push(char)
39
+ } else if (inverseMatchingBrackets.has(char)) {
40
+ let inverse = inverseMatchingBrackets.get(char)
41
+
42
+ // Nothing to pop from, therefore it is unbalanced
43
+ if (stack.length <= 0) {
44
+ return false
45
+ }
46
+
47
+ // Popped value must match the inverse value, otherwise it is unbalanced
48
+ if (stack.pop() !== inverse) {
49
+ return false
50
+ }
51
+ }
52
+ }
53
+
54
+ // If there is still something on the stack, it is also unbalanced
55
+ if (stack.length > 0) {
56
+ return false
57
+ }
58
+
59
+ // All good, totally balanced!
60
+ return true
61
+ }
@@ -1,7 +1,7 @@
1
1
  import escapeClassName from './escapeClassName'
2
2
  import escapeCommas from './escapeCommas'
3
3
 
4
- function asClass(name) {
4
+ export function asClass(name) {
5
5
  return escapeCommas(`.${escapeClassName(name)}`)
6
6
  }
7
7
 
@@ -115,6 +115,7 @@ module.exports = {
115
115
  auto: 'auto',
116
116
  square: '1 / 1',
117
117
  video: '16 / 9',
118
+ attrs: 'attr(width) / attr(height)'
118
119
  },
119
120
  backdropBlur: ({ theme }) => theme('blur'),
120
121
  backdropBrightness: ({ theme }) => theme('brightness'),
@@ -797,6 +798,23 @@ module.exports = {
797
798
  },
798
799
  textColor: ({ theme }) => theme('colors'),
799
800
  textDecorationColor: ({ theme }) => theme('colors'),
801
+ textDecorationThickness: {
802
+ auto: 'auto',
803
+ 'from-font': 'from-font',
804
+ 0: '0px',
805
+ 1: '1px',
806
+ 2: '2px',
807
+ 4: '4px',
808
+ 8: '8px',
809
+ },
810
+ textUnderlineOffset: {
811
+ auto: 'auto',
812
+ 0: '0px',
813
+ 1: '1px',
814
+ 2: '2px',
815
+ 4: '4px',
816
+ 8: '8px',
817
+ },
800
818
  textIndent: ({ theme }) => ({
801
819
  ...theme('spacing'),
802
820
  }),