Skip to content

Commit 9caa94f

Browse files
author
Brad Cornes
committed
add initial @Variants completions
1 parent 12fd0e9 commit 9caa94f

File tree

2 files changed

+86
-7
lines changed

2 files changed

+86
-7
lines changed

packages/tailwindcss-class-names/src/getVariants.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,30 @@ export default function getVariants({ config, version, postcss }) {
66
semver.gte(version, '0.3.0') && variants.push('focus', 'group-hover')
77
semver.gte(version, '0.5.0') && variants.push('active')
88
semver.gte(version, '0.7.0') && variants.push('focus-within')
9+
semver.gte(version, '1.0.0-beta.1') && variants.push('default')
910
semver.gte(version, '1.1.0') &&
1011
variants.push('first', 'last', 'odd', 'even', 'disabled', 'visited')
1112

1213
let plugins = config.plugins
1314
if (!Array.isArray(plugins)) {
1415
plugins = []
1516
}
16-
plugins.forEach(plugin => {
17+
plugins.forEach((plugin) => {
1718
try {
1819
;(plugin.handler || plugin)({
1920
addUtilities: () => {},
2021
addComponents: () => {},
2122
addBase: () => {},
22-
addVariant: name => {
23+
addVariant: (name) => {
2324
variants.push(name)
2425
},
25-
e: x => x,
26-
prefix: x => x,
26+
e: (x) => x,
27+
prefix: (x) => x,
2728
theme: (path, defaultValue) =>
2829
dlv(config, `theme.${path}`, defaultValue),
2930
variants: () => [],
3031
config: (path, defaultValue) => dlv(config, path, defaultValue),
31-
postcss
32+
postcss,
3233
})
3334
} catch (_) {
3435
console.error(_)

packages/tailwindcss-language-server/src/providers/completionProvider.ts

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,79 @@ function provideCssHelperCompletions(
286286
}
287287
}
288288

289+
function provideVariantsDirectiveCompletions(
290+
state: State,
291+
{ position, textDocument }: CompletionParams
292+
): CompletionList {
293+
let doc = state.editor.documents.get(textDocument.uri)
294+
295+
if (!isCssContext(doc, position)) {
296+
return null
297+
}
298+
299+
let text = doc.getText({
300+
start: { line: position.line, character: 0 },
301+
end: position,
302+
})
303+
304+
const match = text.match(/^\s*@variants\s+(?<partial>[^}]*)$/i)
305+
306+
if (match === null) return null
307+
308+
const parts = match.groups.partial.split(/\s*,\s*/)
309+
310+
if (/\s+/.test(parts[parts.length - 1])) return null
311+
312+
// TODO: move this to tailwindcss-class-names?
313+
let variants = dlv(
314+
state.config,
315+
['variants'],
316+
dlv(state.config, ['modules'], {})
317+
)
318+
if (!isObject(variants) && !Array.isArray(variants)) {
319+
variants = []
320+
}
321+
let enabledVariants: string[]
322+
if (Array.isArray(variants)) {
323+
enabledVariants = variants
324+
} else {
325+
const uniqueVariants: Set<string> = new Set()
326+
for (const mod in variants) {
327+
if (!Array.isArray(variants[mod])) continue
328+
variants[mod].forEach((v: string) => uniqueVariants.add(v))
329+
}
330+
enabledVariants = [...uniqueVariants]
331+
}
332+
333+
enabledVariants = state.variants.filter(
334+
(x) => enabledVariants.indexOf(x) !== -1 || x === 'default'
335+
)
336+
337+
const existingVariants = parts.slice(0, parts.length - 1)
338+
339+
return {
340+
isIncomplete: false,
341+
items: enabledVariants
342+
.filter((v) => existingVariants.indexOf(v) === -1)
343+
.map((variant) => ({
344+
// TODO: detail
345+
label: variant,
346+
kind: CompletionItemKind.Constant,
347+
data: 'variant',
348+
textEdit: {
349+
newText: variant,
350+
range: {
351+
start: {
352+
line: position.line,
353+
character: position.character - parts[parts.length - 1].length,
354+
},
355+
end: position,
356+
},
357+
},
358+
})),
359+
}
360+
}
361+
289362
function provideScreenDirectiveCompletions(
290363
state: State,
291364
{ position, textDocument }: CompletionParams
@@ -424,15 +497,20 @@ export function provideCompletions(
424497
provideClassNameCompletions(state, params) ||
425498
provideCssHelperCompletions(state, params) ||
426499
provideCssDirectiveCompletions(state, params) ||
427-
provideScreenDirectiveCompletions(state, params)
500+
provideScreenDirectiveCompletions(state, params) ||
501+
provideVariantsDirectiveCompletions(state, params)
428502
)
429503
}
430504

431505
export function resolveCompletionItem(
432506
state: State,
433507
item: CompletionItem
434508
): CompletionItem {
435-
if (item.data === 'helper' || item.data === 'directive') {
509+
if (
510+
item.data === 'helper' ||
511+
item.data === 'directive' ||
512+
item.data === 'variant'
513+
) {
436514
return item
437515
}
438516

0 commit comments

Comments
 (0)