tailwindcss 3.0.0-alpha.1 → 3.0.2

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.
Files changed (73) hide show
  1. package/colors.js +2 -1
  2. package/defaultConfig.js +2 -1
  3. package/defaultTheme.js +2 -1
  4. package/lib/cli.js +39 -35
  5. package/lib/constants.js +1 -1
  6. package/lib/corePluginList.js +10 -1
  7. package/lib/corePlugins.js +393 -259
  8. package/lib/css/preflight.css +14 -1
  9. package/lib/featureFlags.js +12 -7
  10. package/lib/lib/collapseDuplicateDeclarations.js +29 -0
  11. package/lib/lib/detectNesting.js +17 -2
  12. package/lib/lib/evaluateTailwindFunctions.js +9 -5
  13. package/lib/lib/expandApplyAtRules.js +26 -9
  14. package/lib/lib/expandTailwindAtRules.js +4 -1
  15. package/lib/lib/generateRules.js +151 -19
  16. package/lib/lib/resolveDefaultsAtRules.js +67 -56
  17. package/lib/lib/setupContextUtils.js +80 -80
  18. package/lib/lib/setupWatchingContext.js +5 -1
  19. package/lib/lib/sharedState.js +2 -2
  20. package/lib/lib/substituteScreenAtRules.js +7 -4
  21. package/lib/processTailwindFeatures.js +4 -0
  22. package/lib/util/buildMediaQuery.js +13 -24
  23. package/lib/util/createUtilityPlugin.js +5 -5
  24. package/lib/util/dataTypes.js +38 -7
  25. package/lib/util/formatVariantSelector.js +186 -0
  26. package/lib/util/isValidArbitraryValue.js +64 -0
  27. package/lib/util/nameClass.js +2 -1
  28. package/lib/util/negateValue.js +3 -1
  29. package/lib/util/normalizeConfig.js +22 -8
  30. package/lib/util/normalizeScreens.js +61 -0
  31. package/lib/util/parseBoxShadowValue.js +77 -0
  32. package/lib/util/pluginUtils.js +62 -158
  33. package/lib/util/prefixSelector.js +1 -3
  34. package/lib/util/resolveConfig.js +17 -13
  35. package/lib/util/transformThemeValue.js +23 -13
  36. package/package.json +15 -15
  37. package/peers/index.js +4456 -5450
  38. package/plugin.js +2 -1
  39. package/resolveConfig.js +2 -1
  40. package/src/.DS_Store +0 -0
  41. package/src/cli.js +9 -2
  42. package/src/corePluginList.js +1 -1
  43. package/src/corePlugins.js +392 -404
  44. package/src/css/preflight.css +14 -1
  45. package/src/featureFlags.js +14 -4
  46. package/src/lib/collapseDuplicateDeclarations.js +28 -0
  47. package/src/lib/detectNesting.js +22 -3
  48. package/src/lib/evaluateTailwindFunctions.js +5 -2
  49. package/src/lib/expandApplyAtRules.js +29 -2
  50. package/src/lib/expandTailwindAtRules.js +5 -2
  51. package/src/lib/generateRules.js +155 -11
  52. package/src/lib/resolveDefaultsAtRules.js +67 -50
  53. package/src/lib/setupContextUtils.js +77 -67
  54. package/src/lib/setupWatchingContext.js +7 -0
  55. package/src/lib/sharedState.js +1 -1
  56. package/src/lib/substituteScreenAtRules.js +6 -3
  57. package/src/processTailwindFeatures.js +5 -0
  58. package/src/util/buildMediaQuery.js +14 -18
  59. package/src/util/createUtilityPlugin.js +2 -2
  60. package/src/util/dataTypes.js +43 -11
  61. package/src/util/formatVariantSelector.js +196 -0
  62. package/src/util/isValidArbitraryValue.js +61 -0
  63. package/src/util/nameClass.js +2 -2
  64. package/src/util/negateValue.js +4 -2
  65. package/src/util/normalizeConfig.js +17 -1
  66. package/src/util/normalizeScreens.js +45 -0
  67. package/src/util/parseBoxShadowValue.js +71 -0
  68. package/src/util/pluginUtils.js +50 -146
  69. package/src/util/prefixSelector.js +1 -4
  70. package/src/util/resolveConfig.js +7 -1
  71. package/src/util/transformThemeValue.js +22 -7
  72. package/stubs/defaultConfig.stub.js +118 -58
  73. package/CHANGELOG.md +0 -1759
@@ -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
 
@@ -14,7 +14,7 @@ export function formatClass(classPrefix, key) {
14
14
  return classPrefix
15
15
  }
16
16
 
17
- if (key === '-') {
17
+ if (key === '-' || key === '-DEFAULT') {
18
18
  return `-${classPrefix}`
19
19
  }
20
20
 
@@ -1,6 +1,10 @@
1
1
  export default function (value) {
2
2
  value = `${value}`
3
3
 
4
+ if (value === '0') {
5
+ return '0'
6
+ }
7
+
4
8
  // Flip sign of numbers
5
9
  if (/^[+-]?(\d+|\d*\.\d+)(e[+-]?\d+)?(%|\w+)?$/.test(value)) {
6
10
  return value.replace(/^[+-]?/, (sign) => (sign === '-' ? '' : '-'))
@@ -9,6 +13,4 @@ export default function (value) {
9
13
  if (value.includes('var(') || value.includes('calc(')) {
10
14
  return `calc(${value} * -1)`
11
15
  }
12
-
13
- return value
14
16
  }
@@ -140,6 +140,18 @@ export function normalizeConfig(config) {
140
140
  return []
141
141
  })()
142
142
 
143
+ // Normalize prefix option
144
+ if (typeof config.prefix === 'function') {
145
+ log.warn('prefix-function', [
146
+ 'As of Tailwind CSS v3.0, `prefix` cannot be a function.',
147
+ 'Update `prefix` in your configuration to be a string to eliminate this warning.',
148
+ // TODO: Add https://tw.wtf/prefix-function
149
+ ])
150
+ config.prefix = ''
151
+ } else {
152
+ config.prefix = config.prefix ?? ''
153
+ }
154
+
143
155
  // Normalize the `content`
144
156
  config.content = {
145
157
  files: (() => {
@@ -170,7 +182,7 @@ export function normalizeConfig(config) {
170
182
 
171
183
  let extractors = {}
172
184
 
173
- extractors.DEFAULT = (() => {
185
+ let defaultExtractor = (() => {
174
186
  if (config.purge?.options?.defaultExtractor) {
175
187
  return config.purge.options.defaultExtractor
176
188
  }
@@ -182,6 +194,10 @@ export function normalizeConfig(config) {
182
194
  return undefined
183
195
  })()
184
196
 
197
+ if (defaultExtractor !== undefined) {
198
+ extractors.DEFAULT = defaultExtractor
199
+ }
200
+
185
201
  // Functions
186
202
  if (typeof extract === 'function') {
187
203
  extractors.DEFAULT = extract
@@ -0,0 +1,45 @@
1
+ /**
2
+ * A function that normalizes the various forms that the screens object can be
3
+ * provided in.
4
+ *
5
+ * Input(s):
6
+ * - ['100px', '200px'] // Raw strings
7
+ * - { sm: '100px', md: '200px' } // Object with string values
8
+ * - { sm: { min: '100px' }, md: { max: '100px' } } // Object with object values
9
+ * - { sm: [{ min: '100px' }, { max: '200px' }] } // Object with object array (multiple values)
10
+ *
11
+ * Output(s):
12
+ * - [{ name: 'sm', values: [{ min: '100px', max: '200px' }] }] // List of objects, that contains multiple values
13
+ */
14
+ export function normalizeScreens(screens, root = true) {
15
+ if (Array.isArray(screens)) {
16
+ return screens.map((screen) => {
17
+ if (root && Array.isArray(screen)) {
18
+ throw new Error('The tuple syntax is not supported for `screens`.')
19
+ }
20
+
21
+ if (typeof screen === 'string') {
22
+ return { name: screen.toString(), values: [{ min: screen, max: undefined }] }
23
+ }
24
+
25
+ let [name, options] = screen
26
+ name = name.toString()
27
+
28
+ if (typeof options === 'string') {
29
+ return { name, values: [{ min: options, max: undefined }] }
30
+ }
31
+
32
+ if (Array.isArray(options)) {
33
+ return { name, values: options.map((option) => resolveValue(option)) }
34
+ }
35
+
36
+ return { name, values: [resolveValue(options)] }
37
+ })
38
+ }
39
+
40
+ return normalizeScreens(Object.entries(screens ?? {}), false)
41
+ }
42
+
43
+ function resolveValue({ 'min-width': _minWidth, min = _minWidth, max, raw } = {}) {
44
+ return { min, max, raw }
45
+ }
@@ -0,0 +1,71 @@
1
+ let KEYWORDS = new Set(['inset', 'inherit', 'initial', 'revert', 'unset'])
2
+ let COMMA = /\,(?![^(]*\))/g // Comma separator that is not located between brackets. E.g.: `cubiz-bezier(a, b, c)` these don't count.
3
+ let SPACE = /\ +(?![^(]*\))/g // Similar to the one above, but with spaces instead.
4
+ let LENGTH = /^-?(\d+)(.*?)$/g
5
+
6
+ export function parseBoxShadowValue(input) {
7
+ let shadows = input.split(COMMA)
8
+ return shadows.map((shadow) => {
9
+ let value = shadow.trim()
10
+ let result = { raw: value }
11
+ let parts = value.split(SPACE)
12
+ let seen = new Set()
13
+
14
+ for (let part of parts) {
15
+ // Reset index, since the regex is stateful.
16
+ LENGTH.lastIndex = 0
17
+
18
+ // Keyword
19
+ if (!seen.has('KEYWORD') && KEYWORDS.has(part)) {
20
+ result.keyword = part
21
+ seen.add('KEYWORD')
22
+ }
23
+
24
+ // Length value
25
+ else if (LENGTH.test(part)) {
26
+ if (!seen.has('X')) {
27
+ result.x = part
28
+ seen.add('X')
29
+ } else if (!seen.has('Y')) {
30
+ result.y = part
31
+ seen.add('Y')
32
+ } else if (!seen.has('BLUR')) {
33
+ result.blur = part
34
+ seen.add('BLUR')
35
+ } else if (!seen.has('SPREAD')) {
36
+ result.spread = part
37
+ seen.add('SPREAD')
38
+ }
39
+ }
40
+
41
+ // Color or unknown
42
+ else {
43
+ if (!result.color) {
44
+ result.color = part
45
+ } else {
46
+ if (!result.unknown) result.unknown = []
47
+ result.unknown.push(part)
48
+ }
49
+ }
50
+ }
51
+
52
+ // Check if valid
53
+ result.valid = result.x !== undefined && result.y !== undefined
54
+
55
+ return result
56
+ })
57
+ }
58
+
59
+ export function formatBoxShadowValue(shadows) {
60
+ return shadows
61
+ .map((shadow) => {
62
+ if (!shadow.valid) {
63
+ return shadow.raw
64
+ }
65
+
66
+ return [shadow.keyword, shadow.x, shadow.y, shadow.blur, shadow.spread, shadow.color]
67
+ .filter(Boolean)
68
+ .join(' ')
69
+ })
70
+ .join(', ')
71
+ }
@@ -1,7 +1,6 @@
1
1
  import selectorParser from 'postcss-selector-parser'
2
2
  import escapeCommas from './escapeCommas'
3
3
  import { withAlphaValue } from './withAlphaVariable'
4
- import isKeyframeRule from './isKeyframeRule'
5
4
  import {
6
5
  normalize,
7
6
  length,
@@ -16,36 +15,14 @@ import {
16
15
  relativeSize,
17
16
  position,
18
17
  lineWidth,
18
+ shadow,
19
19
  } from './dataTypes'
20
-
21
- export function applyStateToMarker(selector, marker, state, join) {
22
- let markerIdx = selector.search(new RegExp(`${marker}[:[]`))
23
-
24
- if (markerIdx === -1) {
25
- return join(marker + state, selector)
26
- }
27
-
28
- let markerSelector = selector.slice(markerIdx, selector.indexOf(' ', markerIdx))
29
-
30
- return join(
31
- marker + state + markerSelector.slice(markerIdx + marker.length),
32
- selector.replace(markerSelector, '')
33
- )
34
- }
20
+ import negateValue from './negateValue'
35
21
 
36
22
  export function updateAllClasses(selectors, updateClass) {
37
23
  let parser = selectorParser((selectors) => {
38
24
  selectors.walkClasses((sel) => {
39
- let updatedClass = updateClass(sel.value, {
40
- withAttr(className, attr) {
41
- sel.parent.insertAfter(sel, selectorParser.attribute({ attribute: attr.slice(1, -1) }))
42
- return className
43
- },
44
- withPseudo(className, pseudo) {
45
- sel.parent.insertAfter(sel, selectorParser.pseudo({ value: pseudo }))
46
- return className
47
- },
48
- })
25
+ let updatedClass = updateClass(sel.value)
49
26
  sel.value = updatedClass
50
27
  if (sel.raws && sel.raws.value) {
51
28
  sel.raws.value = escapeCommas(sel.raws.value)
@@ -58,133 +35,50 @@ export function updateAllClasses(selectors, updateClass) {
58
35
  return result
59
36
  }
60
37
 
61
- export function updateLastClasses(selectors, updateClass) {
62
- let parser = selectorParser((selectors) => {
63
- selectors.each((sel) => {
64
- let lastClass = sel.filter(({ type }) => type === 'class').pop()
65
-
66
- if (lastClass === undefined) {
67
- return
68
- }
69
-
70
- let updatedClass = updateClass(lastClass.value, {
71
- withPseudo(className, pseudo) {
72
- lastClass.parent.insertAfter(lastClass, selectorParser.pseudo({ value: `${pseudo}` }))
73
- return className
74
- },
75
- })
76
- lastClass.value = updatedClass
77
- if (lastClass.raws && lastClass.raws.value) {
78
- lastClass.raws.value = escapeCommas(lastClass.raws.value)
79
- }
80
- })
81
- })
82
- let result = parser.processSync(selectors)
83
-
84
- return result
85
- }
86
-
87
- function splitByNotEscapedCommas(str) {
88
- let chunks = []
89
- let currentChunk = ''
90
- for (let i = 0; i < str.length; i++) {
91
- if (str[i] === ',' && str[i - 1] !== '\\') {
92
- chunks.push(currentChunk)
93
- currentChunk = ''
94
- } else {
95
- currentChunk += str[i]
96
- }
38
+ function resolveArbitraryValue(modifier, validate) {
39
+ if (!isArbitraryValue(modifier)) {
40
+ return undefined
97
41
  }
98
- chunks.push(currentChunk)
99
- return chunks
100
- }
101
42
 
102
- export function transformAllSelectors(transformSelector, { wrap, withRule } = {}) {
103
- return ({ container }) => {
104
- container.walkRules((rule) => {
105
- if (isKeyframeRule(rule)) {
106
- return rule
107
- }
108
- let transformed = splitByNotEscapedCommas(rule.selector).map(transformSelector).join(',')
109
- rule.selector = transformed
110
- if (withRule) {
111
- withRule(rule)
112
- }
113
- return rule
114
- })
43
+ let value = modifier.slice(1, -1)
115
44
 
116
- if (wrap) {
117
- let wrapper = wrap()
118
- let nodes = container.nodes
119
- container.removeAll()
120
- wrapper.append(nodes)
121
- container.append(wrapper)
122
- }
45
+ if (!validate(value)) {
46
+ return undefined
123
47
  }
48
+
49
+ return normalize(value)
124
50
  }
125
51
 
126
- export function transformAllClasses(transformClass, { wrap, withRule } = {}) {
127
- return ({ container }) => {
128
- container.walkRules((rule) => {
129
- let selector = rule.selector
130
- let variantSelector = updateAllClasses(selector, transformClass)
131
- rule.selector = variantSelector
132
- if (withRule) {
133
- withRule(rule)
134
- }
135
- return rule
136
- })
52
+ function asNegativeValue(modifier, lookup = {}, validate) {
53
+ let positiveValue = lookup[modifier]
137
54
 
138
- if (wrap) {
139
- let wrapper = wrap()
140
- let nodes = container.nodes
141
- container.removeAll()
142
- wrapper.append(nodes)
143
- container.append(wrapper)
144
- }
55
+ if (positiveValue !== undefined) {
56
+ return negateValue(positiveValue)
145
57
  }
146
- }
147
58
 
148
- export function transformLastClasses(transformClass, { wrap, withRule } = {}) {
149
- return ({ container }) => {
150
- container.walkRules((rule) => {
151
- let selector = rule.selector
152
- let variantSelector = updateLastClasses(selector, transformClass)
153
- rule.selector = variantSelector
154
- if (withRule) {
155
- withRule(rule)
156
- }
157
- return rule
158
- })
59
+ if (isArbitraryValue(modifier)) {
60
+ let resolved = resolveArbitraryValue(modifier, validate)
159
61
 
160
- if (wrap) {
161
- let wrapper = wrap()
162
- let nodes = container.nodes
163
- container.removeAll()
164
- wrapper.append(nodes)
165
- container.append(wrapper)
62
+ if (resolved === undefined) {
63
+ return undefined
166
64
  }
65
+
66
+ return negateValue(resolved)
167
67
  }
168
68
  }
169
69
 
170
- export function asValue(modifier, lookup = {}, { validate = () => true } = {}) {
171
- let value = lookup[modifier]
70
+ export function asValue(modifier, options = {}, { validate = () => true } = {}) {
71
+ let value = options.values?.[modifier]
172
72
 
173
73
  if (value !== undefined) {
174
74
  return value
175
75
  }
176
76
 
177
- if (!isArbitraryValue(modifier)) {
178
- return undefined
179
- }
180
-
181
- value = modifier.slice(1, -1)
182
-
183
- if (!validate(value)) {
184
- return undefined
77
+ if (options.supportsNegativeValues && modifier.startsWith('-')) {
78
+ return asNegativeValue(modifier.slice(1), options.values, validate)
185
79
  }
186
80
 
187
- return normalize(value)
81
+ return resolveArbitraryValue(modifier, validate)
188
82
  }
189
83
 
190
84
  function isArbitraryValue(input) {
@@ -201,16 +95,16 @@ function splitAlpha(modifier) {
201
95
  return [modifier.slice(0, slashIdx), modifier.slice(slashIdx + 1)]
202
96
  }
203
97
 
204
- export function asColor(modifier, lookup = {}, tailwindConfig = {}) {
205
- if (lookup[modifier] !== undefined) {
206
- return lookup[modifier]
98
+ export function asColor(modifier, options = {}, { tailwindConfig = {} } = {}) {
99
+ if (options.values?.[modifier] !== undefined) {
100
+ return options.values?.[modifier]
207
101
  }
208
102
 
209
103
  let [color, alpha] = splitAlpha(modifier)
210
104
 
211
105
  if (alpha !== undefined) {
212
106
  let normalizedColor =
213
- lookup[color] ?? (isArbitraryValue(color) ? color.slice(1, -1) : undefined)
107
+ options.values?.[color] ?? (isArbitraryValue(color) ? color.slice(1, -1) : undefined)
214
108
 
215
109
  if (normalizedColor === undefined) {
216
110
  return undefined
@@ -227,16 +121,16 @@ export function asColor(modifier, lookup = {}, tailwindConfig = {}) {
227
121
  return withAlphaValue(normalizedColor, tailwindConfig.theme.opacity[alpha])
228
122
  }
229
123
 
230
- return asValue(modifier, lookup, { validate: validateColor })
124
+ return asValue(modifier, options, { validate: validateColor })
231
125
  }
232
126
 
233
- export function asLookupValue(modifier, lookup = {}) {
234
- return lookup[modifier]
127
+ export function asLookupValue(modifier, options = {}) {
128
+ return options.values?.[modifier]
235
129
  }
236
130
 
237
131
  function guess(validate) {
238
- return (modifier, lookup) => {
239
- return asValue(modifier, lookup, { validate })
132
+ return (modifier, options) => {
133
+ return asValue(modifier, options, { validate })
240
134
  }
241
135
  }
242
136
 
@@ -255,6 +149,7 @@ let typeMap = {
255
149
  'line-width': guess(lineWidth),
256
150
  'absolute-size': guess(absoluteSize),
257
151
  'relative-size': guess(relativeSize),
152
+ shadow: guess(shadow),
258
153
  }
259
154
 
260
155
  let supportedTypes = Object.keys(typeMap)
@@ -265,22 +160,31 @@ function splitAtFirst(input, delim) {
265
160
  return [input.slice(0, idx), input.slice(idx + 1)]
266
161
  }
267
162
 
268
- export function coerceValue(types, modifier, values, tailwindConfig) {
163
+ export function coerceValue(types, modifier, options, tailwindConfig) {
269
164
  if (isArbitraryValue(modifier)) {
270
- let [explicitType, value] = splitAtFirst(modifier.slice(1, -1), ':')
165
+ let arbitraryValue = modifier.slice(1, -1)
166
+ let [explicitType, value] = splitAtFirst(arbitraryValue, ':')
167
+
168
+ // It could be that this resolves to `url(https` which is not a valid
169
+ // identifier. We currently only support "simple" words with dashes or
170
+ // underscores. E.g.: family-name
171
+ if (!/^[\w-_]+$/g.test(explicitType)) {
172
+ value = arbitraryValue
173
+ }
271
174
 
272
- if (explicitType !== undefined && !supportedTypes.includes(explicitType)) {
175
+ //
176
+ else if (explicitType !== undefined && !supportedTypes.includes(explicitType)) {
273
177
  return []
274
178
  }
275
179
 
276
180
  if (value.length > 0 && supportedTypes.includes(explicitType)) {
277
- return [asValue(`[${value}]`, values, tailwindConfig), explicitType]
181
+ return [asValue(`[${value}]`, options), explicitType]
278
182
  }
279
183
  }
280
184
 
281
185
  // Find first matching type
282
186
  for (let type of [].concat(types)) {
283
- let result = typeMap[type](modifier, values, tailwindConfig)
187
+ let result = typeMap[type](modifier, options, { tailwindConfig })
284
188
  if (result) return [result, type]
285
189
  }
286
190
 
@@ -2,13 +2,10 @@ import parser from 'postcss-selector-parser'
2
2
  import { tap } from './tap'
3
3
 
4
4
  export default function (prefix, selector) {
5
- const getPrefix =
6
- typeof prefix === 'function' ? prefix : () => (prefix === undefined ? '' : prefix)
7
-
8
5
  return parser((selectors) => {
9
6
  selectors.walkClasses((classSelector) => {
10
7
  tap(classSelector.value, (baseClass) => {
11
- classSelector.value = `${getPrefix('.' + baseClass)}${baseClass}`
8
+ classSelector.value = `${prefix}${baseClass}`
12
9
  })
13
10
  })
14
11
  }).processSync(selector)
@@ -40,10 +40,16 @@ function mergeWith(target, ...sources) {
40
40
  const configUtils = {
41
41
  colors,
42
42
  negative(scale) {
43
+ // TODO: Log that this function isn't really needed anymore?
43
44
  return Object.keys(scale)
44
45
  .filter((key) => scale[key] !== '0')
45
46
  .reduce((negativeScale, key) => {
46
- negativeScale[`-${key}`] = negateValue(scale[key])
47
+ let negativeValue = negateValue(scale[key])
48
+
49
+ if (negativeValue !== undefined) {
50
+ negativeScale[`-${key}`] = negativeValue
51
+ }
52
+
47
53
  return negativeScale
48
54
  }, {})
49
55
  },
@@ -2,7 +2,12 @@ import postcss from 'postcss'
2
2
 
3
3
  export default function transformThemeValue(themeSection) {
4
4
  if (['fontSize', 'outline'].includes(themeSection)) {
5
- return (value) => (Array.isArray(value) ? value[0] : value)
5
+ return (value) => {
6
+ if (typeof value === 'function') value = value({})
7
+ if (Array.isArray(value)) value = value[0]
8
+
9
+ return value
10
+ }
6
11
  }
7
12
 
8
13
  if (
@@ -20,18 +25,28 @@ export default function transformThemeValue(themeSection) {
20
25
  'animation',
21
26
  ].includes(themeSection)
22
27
  ) {
23
- return (value) => (Array.isArray(value) ? value.join(', ') : value)
28
+ return (value) => {
29
+ if (typeof value === 'function') value = value({})
30
+ if (Array.isArray(value)) value = value.join(', ')
31
+
32
+ return value
33
+ }
24
34
  }
25
35
 
26
36
  // For backwards compatibility reasons, before we switched to underscores
27
37
  // instead of commas for arbitrary values.
28
38
  if (['gridTemplateColumns', 'gridTemplateRows', 'objectPosition'].includes(themeSection)) {
29
- return (value) => (typeof value === 'string' ? postcss.list.comma(value).join(' ') : value)
30
- }
39
+ return (value) => {
40
+ if (typeof value === 'function') value = value({})
41
+ if (typeof value === 'string') value = postcss.list.comma(value).join(' ')
31
42
 
32
- if (themeSection === 'colors') {
33
- return (value) => (typeof value === 'function' ? value({}) : value)
43
+ return value
44
+ }
34
45
  }
35
46
 
36
- return (value) => value
47
+ return (value) => {
48
+ if (typeof value === 'function') value = value({})
49
+
50
+ return value
51
+ }
37
52
  }