mcp-tailwindcss 1.2.0 → 1.3.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/auto-updater.d.ts +16 -0
- package/dist/auto-updater.d.ts.map +1 -1
- package/dist/auto-updater.js +121 -0
- package/dist/auto-updater.js.map +1 -1
- package/dist/constants.d.ts +4 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +21 -0
- package/dist/constants.js.map +1 -0
- package/dist/formatters.d.ts +7 -0
- package/dist/formatters.d.ts.map +1 -0
- package/dist/formatters.js +147 -0
- package/dist/formatters.js.map +1 -0
- package/dist/index.js +23 -3842
- package/dist/index.js.map +1 -1
- package/dist/tools/ast-tools.d.ts +3 -0
- package/dist/tools/ast-tools.d.ts.map +1 -0
- package/dist/tools/ast-tools.js +311 -0
- package/dist/tools/ast-tools.js.map +1 -0
- package/dist/tools/content-tools.d.ts +3 -0
- package/dist/tools/content-tools.d.ts.map +1 -0
- package/dist/tools/content-tools.js +2910 -0
- package/dist/tools/content-tools.js.map +1 -0
- package/dist/tools/repo-tools.d.ts +4 -0
- package/dist/tools/repo-tools.d.ts.map +1 -0
- package/dist/tools/repo-tools.js +205 -0
- package/dist/tools/repo-tools.js.map +1 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,38 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
3
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
-
import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
5
4
|
import { createRequire } from 'node:module';
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { checkAndUpdate, checkForUpdates, getRepositoryStatus, scheduleUpdateCheck, ensureRepository, } from './auto-updater.js';
|
|
11
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
-
const __dirname = path.dirname(__filename);
|
|
5
|
+
import { ensureRepository, checkForUpdates, scheduleUpdateCheck, checkPackageUpdate, schedulePackageUpdateCheck, } from './auto-updater.js';
|
|
6
|
+
import { registerAstTools } from './tools/ast-tools.js';
|
|
7
|
+
import { registerRepoTools, registerResources } from './tools/repo-tools.js';
|
|
8
|
+
import { registerContentTools } from './tools/content-tools.js';
|
|
13
9
|
const require = createRequire(import.meta.url);
|
|
14
10
|
const APP_VERSION = require('../package.json').version ?? '0.0.0';
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
interface: '📋',
|
|
18
|
-
type: '📝',
|
|
19
|
-
enum: '🔢',
|
|
20
|
-
function: '⚡',
|
|
21
|
-
class: '🏛️',
|
|
22
|
-
variable: '📦',
|
|
23
|
-
namespace: '📁',
|
|
24
|
-
're-export': '🔗',
|
|
25
|
-
};
|
|
26
|
-
const CATEGORY_LABELS = {
|
|
27
|
-
interface: 'Interfaces',
|
|
28
|
-
type: 'Type Aliases',
|
|
29
|
-
enum: 'Enumerations',
|
|
30
|
-
function: 'Functions',
|
|
31
|
-
class: 'Classes',
|
|
32
|
-
variable: 'Variables/Constants',
|
|
33
|
-
namespace: 'Namespaces',
|
|
34
|
-
're-export': 'Re-exports',
|
|
35
|
-
};
|
|
11
|
+
const AUTO_UPDATE_INTERVAL = parseInt(process.env.AUTO_UPDATE_INTERVAL || '3600000', 10);
|
|
12
|
+
const AUTO_UPDATE_ENABLED = process.env.AUTO_UPDATE_ENABLED !== 'false';
|
|
36
13
|
const mcpServer = new McpServer({
|
|
37
14
|
name: 'mcp-tailwindcss',
|
|
38
15
|
version: APP_VERSION,
|
|
@@ -42,3834 +19,38 @@ const mcpServer = new McpServer({
|
|
|
42
19
|
resources: {},
|
|
43
20
|
},
|
|
44
21
|
});
|
|
45
|
-
function getDirectoryTree(dirPath, prefix = '') {
|
|
46
|
-
let result = '';
|
|
47
|
-
const items = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
48
|
-
const dirs = items.filter((i) => i.isDirectory() && !i.name.startsWith('.'));
|
|
49
|
-
const files = items.filter((i) => i.isFile() && (i.name.endsWith('.ts') || i.name.endsWith('.js')));
|
|
50
|
-
for (const file of files) {
|
|
51
|
-
result += `${prefix}├── ${file.name}\n`;
|
|
52
|
-
}
|
|
53
|
-
for (let i = 0; i < dirs.length; i++) {
|
|
54
|
-
const dir = dirs[i];
|
|
55
|
-
const isLast = i === dirs.length - 1;
|
|
56
|
-
result += `${prefix}${isLast ? '└── ' : '├── '}${dir.name}/\n`;
|
|
57
|
-
result += getDirectoryTree(path.join(dirPath, dir.name), prefix + (isLast ? ' ' : '│ '));
|
|
58
|
-
}
|
|
59
|
-
return result;
|
|
60
|
-
}
|
|
61
|
-
function formatProperty(prop) {
|
|
62
|
-
if (prop.isMethod || prop.isCallSignature) {
|
|
63
|
-
const params = prop.parameters?.join(', ') || '';
|
|
64
|
-
return `${prop.name}(${params}): ${prop.returnType || prop.type}`;
|
|
65
|
-
}
|
|
66
|
-
if (prop.isIndexSignature) {
|
|
67
|
-
return `${prop.name}: ${prop.type}`;
|
|
68
|
-
}
|
|
69
|
-
const optional = prop.optional ? '?' : '';
|
|
70
|
-
const readonly = prop.readonly ? 'readonly ' : '';
|
|
71
|
-
return `${readonly}${prop.name}${optional}: ${prop.type}`;
|
|
72
|
-
}
|
|
73
|
-
function formatExtractedType(type, detailed = false) {
|
|
74
|
-
let result = `### ${CATEGORY_EMOJI[type.kind]} ${type.kind}: \`${type.name}\`\n\n`;
|
|
75
|
-
result += `**Arquivo:** \`${type.file}\`${type.lineNumber ? ` (linha ${type.lineNumber})` : ''}\n`;
|
|
76
|
-
result += `**Módulo:** ${type.module}\n\n`;
|
|
77
|
-
if (type.docs) {
|
|
78
|
-
result += `> ${type.docs}\n\n`;
|
|
79
|
-
}
|
|
80
|
-
result += '```typescript\n' + type.signature + '\n```\n\n';
|
|
81
|
-
if (detailed) {
|
|
82
|
-
if (type.typeParameters && type.typeParameters.length > 0) {
|
|
83
|
-
result += '**Type Parameters:**\n';
|
|
84
|
-
for (const tp of type.typeParameters) {
|
|
85
|
-
result += `- \`${tp.name}\``;
|
|
86
|
-
if (tp.constraint)
|
|
87
|
-
result += ` extends \`${tp.constraint}\``;
|
|
88
|
-
if (tp.default)
|
|
89
|
-
result += ` = \`${tp.default}\``;
|
|
90
|
-
result += '\n';
|
|
91
|
-
}
|
|
92
|
-
result += '\n';
|
|
93
|
-
}
|
|
94
|
-
if (type.extends && type.extends.length > 0) {
|
|
95
|
-
result += `**Extends:** ${type.extends.map((e) => `\`${e}\``).join(', ')}\n\n`;
|
|
96
|
-
}
|
|
97
|
-
if (type.implements && type.implements.length > 0) {
|
|
98
|
-
result += `**Implements:** ${type.implements.map((i) => `\`${i}\``).join(', ')}\n\n`;
|
|
99
|
-
}
|
|
100
|
-
if (type.properties && type.properties.length > 0) {
|
|
101
|
-
result += '**Properties:**\n';
|
|
102
|
-
for (const prop of type.properties.slice(0, 15)) {
|
|
103
|
-
result += `- \`${formatProperty(prop)}\`\n`;
|
|
104
|
-
if (prop.docs)
|
|
105
|
-
result += ` > ${prop.docs}\n`;
|
|
106
|
-
}
|
|
107
|
-
if (type.properties.length > 15) {
|
|
108
|
-
result += `- ... e mais ${type.properties.length - 15} propriedades\n`;
|
|
109
|
-
}
|
|
110
|
-
result += '\n';
|
|
111
|
-
}
|
|
112
|
-
if (type.methods && type.methods.length > 0) {
|
|
113
|
-
result += '**Methods:**\n';
|
|
114
|
-
for (const method of type.methods.slice(0, 15)) {
|
|
115
|
-
result += `- \`${formatProperty(method)}\`\n`;
|
|
116
|
-
if (method.docs)
|
|
117
|
-
result += ` > ${method.docs}\n`;
|
|
118
|
-
}
|
|
119
|
-
if (type.methods.length > 15) {
|
|
120
|
-
result += `- ... e mais ${type.methods.length - 15} métodos\n`;
|
|
121
|
-
}
|
|
122
|
-
result += '\n';
|
|
123
|
-
}
|
|
124
|
-
if (type.members && type.members.length > 0) {
|
|
125
|
-
result += '**Members:**\n';
|
|
126
|
-
for (const member of type.members.slice(0, 20)) {
|
|
127
|
-
result += `- \`${member}\`\n`;
|
|
128
|
-
}
|
|
129
|
-
if (type.members.length > 20) {
|
|
130
|
-
result += `- ... e mais ${type.members.length - 20} membros\n`;
|
|
131
|
-
}
|
|
132
|
-
result += '\n';
|
|
133
|
-
}
|
|
134
|
-
if (type.value) {
|
|
135
|
-
result += `**Value:** \`${type.value}\`\n\n`;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
return result;
|
|
139
|
-
}
|
|
140
|
-
function formatStatistics(stats) {
|
|
141
|
-
let result = '# 📊 Estatísticas da Biblioteca Tailwind CSS\n\n';
|
|
142
|
-
result += `**Total de Declarações:** ${stats.totalDeclarations}\n\n`;
|
|
143
|
-
result += '## Por Categoria\n\n';
|
|
144
|
-
result += '| Categoria | Quantidade | % |\n';
|
|
145
|
-
result += '|-----------|------------|---|\n';
|
|
146
|
-
for (const [kind, count] of Object.entries(stats.byKind)) {
|
|
147
|
-
const percentage = ((count / stats.totalDeclarations) * 100).toFixed(1);
|
|
148
|
-
result += `| ${CATEGORY_EMOJI[kind]} ${CATEGORY_LABELS[kind]} | ${count} | ${percentage}% |\n`;
|
|
149
|
-
}
|
|
150
|
-
result += '\n## Por Módulo\n\n';
|
|
151
|
-
result += '| Módulo | Total | Interfaces | Types | Functions | Enums | Variables | Classes |\n';
|
|
152
|
-
result += '|--------|-------|------------|-------|-----------|-------|-----------|----------|\n';
|
|
153
|
-
for (const mod of stats.byModule) {
|
|
154
|
-
result += `| **${mod.module}** | ${mod.total} | ${mod.interfaces} | ${mod.types} | ${mod.functions} | ${mod.enums} | ${mod.variables} | ${mod.classes} |\n`;
|
|
155
|
-
}
|
|
156
|
-
result += '\n## Top Interfaces\n';
|
|
157
|
-
for (const name of stats.topInterfaces) {
|
|
158
|
-
result += `- \`${name}\`\n`;
|
|
159
|
-
}
|
|
160
|
-
result += '\n## Top Types\n';
|
|
161
|
-
for (const name of stats.topTypes) {
|
|
162
|
-
result += `- \`${name}\`\n`;
|
|
163
|
-
}
|
|
164
|
-
result += '\n## Top Functions\n';
|
|
165
|
-
for (const name of stats.topFunctions) {
|
|
166
|
-
result += `- \`${name}\`\n`;
|
|
167
|
-
}
|
|
168
|
-
return result;
|
|
169
|
-
}
|
|
170
|
-
function formatDependencies(deps) {
|
|
171
|
-
let result = '# 🔗 Análise de Dependências\n\n';
|
|
172
|
-
for (const dep of deps) {
|
|
173
|
-
result += `## 📁 ${dep.module}\n\n`;
|
|
174
|
-
if (dep.exports.length > 0) {
|
|
175
|
-
result += `**Exports (${dep.exports.length}):** `;
|
|
176
|
-
result += dep.exports.slice(0, 10).map((e) => `\`${e}\``).join(', ');
|
|
177
|
-
if (dep.exports.length > 10) {
|
|
178
|
-
result += `, ... (+${dep.exports.length - 10})`;
|
|
179
|
-
}
|
|
180
|
-
result += '\n\n';
|
|
181
|
-
}
|
|
182
|
-
if (dep.reExportsFrom.length > 0) {
|
|
183
|
-
result += `**Re-exports from:** ${dep.reExportsFrom.map((r) => `\`${r}\``).join(', ')}\n\n`;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
return result;
|
|
187
|
-
}
|
|
188
|
-
mcpServer.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
189
|
-
return {
|
|
190
|
-
tools: [
|
|
191
|
-
{
|
|
192
|
-
name: 'tailwind_estrutura',
|
|
193
|
-
description: 'Lista a estrutura de arquivos do pacote Tailwind CSS (packages/tailwindcss/src). Útil para entender a organização do código.',
|
|
194
|
-
inputSchema: {
|
|
195
|
-
type: 'object',
|
|
196
|
-
properties: {
|
|
197
|
-
subpasta: {
|
|
198
|
-
type: 'string',
|
|
199
|
-
description: 'Subpasta específica para listar (ex: utils, compat). Deixe vazio para listar tudo.',
|
|
200
|
-
},
|
|
201
|
-
},
|
|
202
|
-
required: [],
|
|
203
|
-
},
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
name: 'tailwind_ler_arquivo',
|
|
207
|
-
description: 'Lê o conteúdo de um arquivo específico da biblioteca Tailwind CSS.',
|
|
208
|
-
inputSchema: {
|
|
209
|
-
type: 'object',
|
|
210
|
-
properties: {
|
|
211
|
-
caminho: {
|
|
212
|
-
type: 'string',
|
|
213
|
-
description: 'Caminho relativo do arquivo dentro de src/ (ex: utils/resolve-config.ts)',
|
|
214
|
-
},
|
|
215
|
-
},
|
|
216
|
-
required: ['caminho'],
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
name: 'tailwind_extrair_tipos',
|
|
221
|
-
description: 'Extrai interfaces, types, enums, funções, classes, variáveis e namespaces exportados do Tailwind usando análise de AST. Economiza tokens mostrando apenas assinaturas.',
|
|
222
|
-
inputSchema: {
|
|
223
|
-
type: 'object',
|
|
224
|
-
properties: {
|
|
225
|
-
modulo: {
|
|
226
|
-
type: 'string',
|
|
227
|
-
description: 'Nome do módulo para extrair tipos (ex: utils, compat, intellisense). Deixe vazio para todos.',
|
|
228
|
-
},
|
|
229
|
-
apenas_kind: {
|
|
230
|
-
type: 'string',
|
|
231
|
-
enum: ['interface', 'type', 'enum', 'function', 'class', 'variable', 'namespace', 're-export'],
|
|
232
|
-
description: 'Filtrar por tipo específico de declaração.',
|
|
233
|
-
},
|
|
234
|
-
},
|
|
235
|
-
required: [],
|
|
236
|
-
},
|
|
237
|
-
},
|
|
238
|
-
{
|
|
239
|
-
name: 'tailwind_buscar_tipo',
|
|
240
|
-
description: 'Busca a definição de um tipo específico do Tailwind pelo nome. Retorna assinatura completa, propriedades, métodos e documentação.',
|
|
241
|
-
inputSchema: {
|
|
242
|
-
type: 'object',
|
|
243
|
-
properties: {
|
|
244
|
-
nome: {
|
|
245
|
-
type: 'string',
|
|
246
|
-
description: 'Nome do tipo a buscar (ex: Config, PluginCreator, ThemeValue)',
|
|
247
|
-
},
|
|
248
|
-
},
|
|
249
|
-
required: ['nome'],
|
|
250
|
-
},
|
|
251
|
-
},
|
|
252
|
-
{
|
|
253
|
-
name: 'tailwind_buscar_fuzzy',
|
|
254
|
-
description: 'Busca tipos do Tailwind usando correspondência aproximada. Útil quando não sabe o nome exato.',
|
|
255
|
-
inputSchema: {
|
|
256
|
-
type: 'object',
|
|
257
|
-
properties: {
|
|
258
|
-
query: {
|
|
259
|
-
type: 'string',
|
|
260
|
-
description: 'Termo de busca (ex: "message send", "auth state", "socket config")',
|
|
261
|
-
},
|
|
262
|
-
limite: {
|
|
263
|
-
type: 'number',
|
|
264
|
-
description: 'Número máximo de resultados (default: 20)',
|
|
265
|
-
},
|
|
266
|
-
},
|
|
267
|
-
required: ['query'],
|
|
268
|
-
},
|
|
269
|
-
},
|
|
270
|
-
{
|
|
271
|
-
name: 'tailwind_listar_exports',
|
|
272
|
-
description: 'Lista todos os exports públicos do Tailwind, agrupados por módulo e categoria.',
|
|
273
|
-
inputSchema: {
|
|
274
|
-
type: 'object',
|
|
275
|
-
properties: {},
|
|
276
|
-
required: [],
|
|
277
|
-
},
|
|
278
|
-
},
|
|
279
|
-
{
|
|
280
|
-
name: 'tailwind_categorias',
|
|
281
|
-
description: 'Lista declarações de uma categoria específica (interfaces, types, enums, functions, classes, variables, namespaces) do Tailwind.',
|
|
282
|
-
inputSchema: {
|
|
283
|
-
type: 'object',
|
|
284
|
-
properties: {
|
|
285
|
-
categoria: {
|
|
286
|
-
type: 'string',
|
|
287
|
-
enum: ['interface', 'type', 'enum', 'function', 'class', 'variable', 'namespace', 're-export'],
|
|
288
|
-
description: 'Categoria de declarações para listar.',
|
|
289
|
-
},
|
|
290
|
-
modulo: {
|
|
291
|
-
type: 'string',
|
|
292
|
-
description: 'Filtrar por módulo específico (opcional).',
|
|
293
|
-
},
|
|
294
|
-
},
|
|
295
|
-
required: ['categoria'],
|
|
296
|
-
},
|
|
297
|
-
},
|
|
298
|
-
{
|
|
299
|
-
name: 'tailwind_constantes',
|
|
300
|
-
description: 'Lista todas as constantes e variáveis exportadas do Tailwind (configurações, defaults, etc).',
|
|
301
|
-
inputSchema: {
|
|
302
|
-
type: 'object',
|
|
303
|
-
properties: {
|
|
304
|
-
modulo: {
|
|
305
|
-
type: 'string',
|
|
306
|
-
description: 'Filtrar por módulo específico (ex: Defaults, WABinary).',
|
|
307
|
-
},
|
|
308
|
-
},
|
|
309
|
-
required: [],
|
|
310
|
-
},
|
|
311
|
-
},
|
|
312
|
-
{
|
|
313
|
-
name: 'tailwind_hierarquia',
|
|
314
|
-
description: 'Mostra a hierarquia de herança de um tipo (extends/implements, pais e filhos).',
|
|
315
|
-
inputSchema: {
|
|
316
|
-
type: 'object',
|
|
317
|
-
properties: {
|
|
318
|
-
nome: {
|
|
319
|
-
type: 'string',
|
|
320
|
-
description: 'Nome do tipo para analisar hierarquia.',
|
|
321
|
-
},
|
|
322
|
-
},
|
|
323
|
-
required: ['nome'],
|
|
324
|
-
},
|
|
325
|
-
},
|
|
326
|
-
{
|
|
327
|
-
name: 'tailwind_estatisticas',
|
|
328
|
-
description: 'Retorna estatísticas detalhadas do Tailwind: contagem por categoria, por módulo, top tipos.',
|
|
329
|
-
inputSchema: {
|
|
330
|
-
type: 'object',
|
|
331
|
-
properties: {},
|
|
332
|
-
required: [],
|
|
333
|
-
},
|
|
334
|
-
},
|
|
335
|
-
{
|
|
336
|
-
name: 'tailwind_dependencias',
|
|
337
|
-
description: 'Analisa as dependências entre módulos do Tailwind: o que cada módulo exporta e re-exporta.',
|
|
338
|
-
inputSchema: {
|
|
339
|
-
type: 'object',
|
|
340
|
-
properties: {},
|
|
341
|
-
required: [],
|
|
342
|
-
},
|
|
343
|
-
},
|
|
344
|
-
{
|
|
345
|
-
name: 'tailwind_enums',
|
|
346
|
-
description: 'Lista todas as enumerações exportadas do Tailwind com seus valores.',
|
|
347
|
-
inputSchema: {
|
|
348
|
-
type: 'object',
|
|
349
|
-
properties: {},
|
|
350
|
-
required: [],
|
|
351
|
-
},
|
|
352
|
-
},
|
|
353
|
-
{
|
|
354
|
-
name: 'tailwind_interfaces',
|
|
355
|
-
description: 'Lista todas as interfaces do Tailwind com suas propriedades e métodos.',
|
|
356
|
-
inputSchema: {
|
|
357
|
-
type: 'object',
|
|
358
|
-
properties: {
|
|
359
|
-
modulo: {
|
|
360
|
-
type: 'string',
|
|
361
|
-
description: 'Filtrar por módulo específico.',
|
|
362
|
-
},
|
|
363
|
-
detalhado: {
|
|
364
|
-
type: 'boolean',
|
|
365
|
-
description: 'Incluir propriedades e métodos (default: false).',
|
|
366
|
-
},
|
|
367
|
-
},
|
|
368
|
-
required: [],
|
|
369
|
-
},
|
|
370
|
-
},
|
|
371
|
-
{
|
|
372
|
-
name: 'tailwind_funcoes',
|
|
373
|
-
description: 'Lista todas as funções exportadas do Tailwind com suas assinaturas.',
|
|
374
|
-
inputSchema: {
|
|
375
|
-
type: 'object',
|
|
376
|
-
properties: {
|
|
377
|
-
modulo: {
|
|
378
|
-
type: 'string',
|
|
379
|
-
description: 'Filtrar por módulo específico (ex: Utils, Socket).',
|
|
380
|
-
},
|
|
381
|
-
},
|
|
382
|
-
required: [],
|
|
383
|
-
},
|
|
384
|
-
},
|
|
385
|
-
{
|
|
386
|
-
name: 'tailwind_check_updates',
|
|
387
|
-
description: 'Verifica se há atualizações disponíveis no repositório oficial do Tailwind CSS (GitHub). Não aplica atualizações, apenas verifica.',
|
|
388
|
-
inputSchema: {
|
|
389
|
-
type: 'object',
|
|
390
|
-
properties: {},
|
|
391
|
-
required: [],
|
|
392
|
-
},
|
|
393
|
-
},
|
|
394
|
-
{
|
|
395
|
-
name: 'tailwind_update',
|
|
396
|
-
description: 'Atualiza o repositório local do Tailwind CSS para a versão mais recente do GitHub. Executa git pull automaticamente.',
|
|
397
|
-
inputSchema: {
|
|
398
|
-
type: 'object',
|
|
399
|
-
properties: {},
|
|
400
|
-
required: [],
|
|
401
|
-
},
|
|
402
|
-
},
|
|
403
|
-
{
|
|
404
|
-
name: 'tailwind_status',
|
|
405
|
-
description: 'Mostra o status atual do repositório Tailwind: SHA do commit, se há atualizações pendentes, caminho do repositório.',
|
|
406
|
-
inputSchema: {
|
|
407
|
-
type: 'object',
|
|
408
|
-
properties: {},
|
|
409
|
-
required: [],
|
|
410
|
-
},
|
|
411
|
-
},
|
|
412
|
-
{
|
|
413
|
-
name: 'tailwind_integracoes',
|
|
414
|
-
description: 'Passo a passo e snippets para integrar Tailwind CSS com frameworks (Vite, Next.js, Nuxt, SvelteKit, Remix, Astro, Vue, React).',
|
|
415
|
-
inputSchema: {
|
|
416
|
-
type: 'object',
|
|
417
|
-
properties: {
|
|
418
|
-
framework: {
|
|
419
|
-
type: 'string',
|
|
420
|
-
description: 'Framework alvo (vite, next, nuxt, sveltekit, remix, astro, vue, react).',
|
|
421
|
-
},
|
|
422
|
-
},
|
|
423
|
-
required: ['framework'],
|
|
424
|
-
},
|
|
425
|
-
},
|
|
426
|
-
{
|
|
427
|
-
name: 'tailwind_utilities',
|
|
428
|
-
description: 'Lista completa de classes utilitárias do Tailwind CSS organizadas por categoria (layout, flexbox, grid, spacing, sizing, typography, backgrounds, borders, effects, filters, transitions, transforms). Inclui sintaxe e CSS gerado.',
|
|
429
|
-
inputSchema: {
|
|
430
|
-
type: 'object',
|
|
431
|
-
properties: {
|
|
432
|
-
categoria: {
|
|
433
|
-
type: 'string',
|
|
434
|
-
enum: ['layout', 'flexbox', 'grid', 'spacing', 'sizing', 'typography', 'backgrounds', 'borders', 'effects', 'filters', 'transitions', 'transforms', 'interactivity', 'svg', 'tables', 'accessibility'],
|
|
435
|
-
description: 'Categoria de utilities para listar. Se omitido, lista todas as categorias disponíveis.',
|
|
436
|
-
},
|
|
437
|
-
},
|
|
438
|
-
required: [],
|
|
439
|
-
},
|
|
440
|
-
},
|
|
441
|
-
{
|
|
442
|
-
name: 'tailwind_variants',
|
|
443
|
-
description: 'Lista completa de variants (modificadores) do Tailwind CSS: pseudo-classes (hover, focus, active), pseudo-elements (before, after), media queries (sm, md, lg), estados (disabled, checked), dark mode, e variants compostos (group-hover, peer-focus).',
|
|
444
|
-
inputSchema: {
|
|
445
|
-
type: 'object',
|
|
446
|
-
properties: {
|
|
447
|
-
tipo: {
|
|
448
|
-
type: 'string',
|
|
449
|
-
enum: ['pseudo-classes', 'pseudo-elements', 'responsive', 'dark-mode', 'state', 'compound', 'aria', 'data'],
|
|
450
|
-
description: 'Tipo de variant para listar. Se omitido, lista todos os tipos.',
|
|
451
|
-
},
|
|
452
|
-
},
|
|
453
|
-
required: [],
|
|
454
|
-
},
|
|
455
|
-
},
|
|
456
|
-
{
|
|
457
|
-
name: 'tailwind_cores',
|
|
458
|
-
description: 'Paleta completa de cores do Tailwind CSS v4 com valores em OKLCH e equivalentes hex. Inclui todas as escalas (50-950) para cada cor (slate, gray, red, orange, yellow, green, blue, indigo, purple, pink).',
|
|
459
|
-
inputSchema: {
|
|
460
|
-
type: 'object',
|
|
461
|
-
properties: {
|
|
462
|
-
cor: {
|
|
463
|
-
type: 'string',
|
|
464
|
-
description: 'Nome da cor específica (slate, gray, zinc, neutral, stone, red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose). Se omitido, lista todas.',
|
|
465
|
-
},
|
|
466
|
-
},
|
|
467
|
-
required: [],
|
|
468
|
-
},
|
|
469
|
-
},
|
|
470
|
-
{
|
|
471
|
-
name: 'tailwind_spacing',
|
|
472
|
-
description: 'Escala completa de espaçamento do Tailwind CSS. Mostra todos os valores de spacing (0, 0.5, 1, 1.5, 2, ... 96, px) com seus valores em rem/px. Usado para margin, padding, gap, width, height, etc.',
|
|
473
|
-
inputSchema: {
|
|
474
|
-
type: 'object',
|
|
475
|
-
properties: {},
|
|
476
|
-
required: [],
|
|
477
|
-
},
|
|
478
|
-
},
|
|
479
|
-
{
|
|
480
|
-
name: 'tailwind_breakpoints',
|
|
481
|
-
description: 'Breakpoints responsivos do Tailwind CSS com valores e exemplos de uso. Mostra sm, md, lg, xl, 2xl e como usar min-*, max-* e container queries (@sm, @md, etc).',
|
|
482
|
-
inputSchema: {
|
|
483
|
-
type: 'object',
|
|
484
|
-
properties: {},
|
|
485
|
-
required: [],
|
|
486
|
-
},
|
|
487
|
-
},
|
|
488
|
-
{
|
|
489
|
-
name: 'tailwind_receitas',
|
|
490
|
-
description: 'Receitas e exemplos prontos de componentes comuns com Tailwind CSS: buttons, cards, forms, modals, navbars, footers, heroes, grids responsivos. Código HTML+classes pronto para copiar.',
|
|
491
|
-
inputSchema: {
|
|
492
|
-
type: 'object',
|
|
493
|
-
properties: {
|
|
494
|
-
componente: {
|
|
495
|
-
type: 'string',
|
|
496
|
-
enum: ['button', 'card', 'form', 'input', 'modal', 'navbar', 'footer', 'hero', 'grid', 'alert', 'badge', 'avatar', 'dropdown', 'tabs', 'breadcrumb', 'pagination', 'skeleton'],
|
|
497
|
-
description: 'Componente específico para ver a receita.',
|
|
498
|
-
},
|
|
499
|
-
},
|
|
500
|
-
required: ['componente'],
|
|
501
|
-
},
|
|
502
|
-
},
|
|
503
|
-
{
|
|
504
|
-
name: 'tailwind_migracao_v4',
|
|
505
|
-
description: 'Guia completo de migração do Tailwind CSS v3 para v4. Mudanças de sintaxe, novas features, breaking changes, e exemplos de código antes/depois.',
|
|
506
|
-
inputSchema: {
|
|
507
|
-
type: 'object',
|
|
508
|
-
properties: {
|
|
509
|
-
topico: {
|
|
510
|
-
type: 'string',
|
|
511
|
-
enum: ['overview', 'css-first', 'theme-config', 'utilities', 'variants', 'plugins', 'breaking-changes', 'postcss-vite'],
|
|
512
|
-
description: 'Tópico específico da migração. Se omitido, mostra overview completo.',
|
|
513
|
-
},
|
|
514
|
-
},
|
|
515
|
-
required: [],
|
|
516
|
-
},
|
|
517
|
-
},
|
|
518
|
-
{
|
|
519
|
-
name: 'tailwind_boas_praticas',
|
|
520
|
-
description: 'Boas práticas e dicas para usar Tailwind CSS de forma eficiente: organização de classes, extração de componentes, performance, acessibilidade, responsive design, dark mode.',
|
|
521
|
-
inputSchema: {
|
|
522
|
-
type: 'object',
|
|
523
|
-
properties: {
|
|
524
|
-
topico: {
|
|
525
|
-
type: 'string',
|
|
526
|
-
enum: ['organizacao', 'componentes', 'performance', 'acessibilidade', 'responsivo', 'dark-mode', 'animacoes', 'forms'],
|
|
527
|
-
description: 'Tópico específico. Se omitido, mostra dicas gerais.',
|
|
528
|
-
},
|
|
529
|
-
},
|
|
530
|
-
required: [],
|
|
531
|
-
},
|
|
532
|
-
},
|
|
533
|
-
],
|
|
534
|
-
};
|
|
535
|
-
});
|
|
536
|
-
mcpServer.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
537
|
-
const { name, arguments: args } = request.params;
|
|
538
|
-
try {
|
|
539
|
-
switch (name) {
|
|
540
|
-
case 'tailwind_estrutura': {
|
|
541
|
-
const subpasta = args?.subpasta;
|
|
542
|
-
const targetPath = subpasta ? path.join(TAILWIND_SRC_PATH, subpasta) : TAILWIND_SRC_PATH;
|
|
543
|
-
if (!fs.existsSync(targetPath)) {
|
|
544
|
-
return {
|
|
545
|
-
content: [{ type: 'text', text: `❌ Pasta não encontrada: ${subpasta || 'src'}` }],
|
|
546
|
-
isError: true,
|
|
547
|
-
};
|
|
548
|
-
}
|
|
549
|
-
const tree = getDirectoryTree(targetPath);
|
|
550
|
-
return {
|
|
551
|
-
content: [
|
|
552
|
-
{
|
|
553
|
-
type: 'text',
|
|
554
|
-
text: `# 📁 Estrutura de ${subpasta || 'tailwindcss/packages/tailwindcss/src'}\n\n\`\`\`\n${tree}\`\`\``,
|
|
555
|
-
},
|
|
556
|
-
],
|
|
557
|
-
};
|
|
558
|
-
}
|
|
559
|
-
case 'tailwind_ler_arquivo': {
|
|
560
|
-
const caminho = args.caminho;
|
|
561
|
-
const fullPath = path.join(TAILWIND_SRC_PATH, caminho);
|
|
562
|
-
if (!fs.existsSync(fullPath)) {
|
|
563
|
-
return {
|
|
564
|
-
content: [{ type: 'text', text: `❌ Arquivo não encontrado: ${caminho}` }],
|
|
565
|
-
isError: true,
|
|
566
|
-
};
|
|
567
|
-
}
|
|
568
|
-
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
569
|
-
const ext = path.extname(caminho).slice(1) || 'typescript';
|
|
570
|
-
return {
|
|
571
|
-
content: [
|
|
572
|
-
{
|
|
573
|
-
type: 'text',
|
|
574
|
-
text: `# 📄 ${caminho}\n\n\`\`\`${ext}\n${content}\n\`\`\``,
|
|
575
|
-
},
|
|
576
|
-
],
|
|
577
|
-
};
|
|
578
|
-
}
|
|
579
|
-
case 'tailwind_extrair_tipos': {
|
|
580
|
-
const { modulo, apenas_kind } = args;
|
|
581
|
-
const parser = new AstParser(TAILWIND_SRC_PATH);
|
|
582
|
-
let types;
|
|
583
|
-
if (modulo) {
|
|
584
|
-
types = parser.getTypesFromModule(modulo);
|
|
585
|
-
}
|
|
586
|
-
else {
|
|
587
|
-
types = parser.extractAllTypes();
|
|
588
|
-
}
|
|
589
|
-
if (apenas_kind) {
|
|
590
|
-
types = types.filter((t) => t.kind === apenas_kind);
|
|
591
|
-
}
|
|
592
|
-
const grouped = {};
|
|
593
|
-
for (const type of types) {
|
|
594
|
-
if (!grouped[type.module])
|
|
595
|
-
grouped[type.module] = [];
|
|
596
|
-
grouped[type.module].push(type);
|
|
597
|
-
}
|
|
598
|
-
let result = `# 📚 Tipos Exportados${modulo ? ` (${modulo})` : ''}${apenas_kind ? ` - ${CATEGORY_LABELS[apenas_kind]}` : ''}\n\n`;
|
|
599
|
-
result += `**Total:** ${types.length} declarações\n\n`;
|
|
600
|
-
for (const [mod, moduleTypes] of Object.entries(grouped)) {
|
|
601
|
-
result += `## 📁 ${mod}\n\n`;
|
|
602
|
-
for (const type of moduleTypes) {
|
|
603
|
-
result += formatExtractedType(type, false);
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
return {
|
|
607
|
-
content: [{ type: 'text', text: result }],
|
|
608
|
-
};
|
|
609
|
-
}
|
|
610
|
-
case 'tailwind_buscar_tipo': {
|
|
611
|
-
const nome = args.nome;
|
|
612
|
-
const parser = new AstParser(TAILWIND_SRC_PATH);
|
|
613
|
-
const found = parser.searchType(nome);
|
|
614
|
-
if (!found) {
|
|
615
|
-
const fuzzyResults = parser.fuzzySearch(nome, 5);
|
|
616
|
-
let suggestion = '';
|
|
617
|
-
if (fuzzyResults.length > 0) {
|
|
618
|
-
suggestion = '\n\n**Você quis dizer:**\n' + fuzzyResults.map((t) => `- \`${t.name}\` (${t.kind})`).join('\n');
|
|
619
|
-
}
|
|
620
|
-
return {
|
|
621
|
-
content: [
|
|
622
|
-
{
|
|
623
|
-
type: 'text',
|
|
624
|
-
text: `❌ Tipo "${nome}" não encontrado.${suggestion}`,
|
|
625
|
-
},
|
|
626
|
-
],
|
|
627
|
-
isError: true,
|
|
628
|
-
};
|
|
629
|
-
}
|
|
630
|
-
return {
|
|
631
|
-
content: [{ type: 'text', text: formatExtractedType(found, true) }],
|
|
632
|
-
};
|
|
633
|
-
}
|
|
634
|
-
case 'tailwind_buscar_fuzzy': {
|
|
635
|
-
const { query, limite } = args;
|
|
636
|
-
const parser = new AstParser(TAILWIND_SRC_PATH);
|
|
637
|
-
const results = parser.fuzzySearch(query, limite || 20);
|
|
638
|
-
if (results.length === 0) {
|
|
639
|
-
return {
|
|
640
|
-
content: [{ type: 'text', text: `❌ Nenhum resultado encontrado para "${query}"` }],
|
|
641
|
-
isError: true,
|
|
642
|
-
};
|
|
643
|
-
}
|
|
644
|
-
let result = `# 🔍 Resultados para "${query}"\n\n`;
|
|
645
|
-
result += `**Encontrados:** ${results.length} tipos\n\n`;
|
|
646
|
-
for (const type of results) {
|
|
647
|
-
result += `- ${CATEGORY_EMOJI[type.kind]} **\`${type.name}\`** (${type.kind}) - \`${type.file}\`\n`;
|
|
648
|
-
if (type.docs)
|
|
649
|
-
result += ` > ${type.docs.substring(0, 100)}...\n`;
|
|
650
|
-
}
|
|
651
|
-
return {
|
|
652
|
-
content: [{ type: 'text', text: result }],
|
|
653
|
-
};
|
|
654
|
-
}
|
|
655
|
-
case 'tailwind_listar_exports': {
|
|
656
|
-
const parser = new AstParser(TAILWIND_SRC_PATH);
|
|
657
|
-
const types = parser.extractAllTypes();
|
|
658
|
-
const byModule = {};
|
|
659
|
-
for (const type of types) {
|
|
660
|
-
if (!byModule[type.module]) {
|
|
661
|
-
byModule[type.module] = {};
|
|
662
|
-
}
|
|
663
|
-
if (!byModule[type.module][type.kind]) {
|
|
664
|
-
byModule[type.module][type.kind] = [];
|
|
665
|
-
}
|
|
666
|
-
byModule[type.module][type.kind].push(type.name);
|
|
667
|
-
}
|
|
668
|
-
let result = '# 📚 Exports da Biblioteca Tailwind CSS\n\n';
|
|
669
|
-
result += `**Total:** ${types.length} declarações exportadas\n\n`;
|
|
670
|
-
for (const [module, kinds] of Object.entries(byModule)) {
|
|
671
|
-
const total = Object.values(kinds).flat().length;
|
|
672
|
-
result += `## 📁 ${module} (${total})\n\n`;
|
|
673
|
-
for (const [kind, names] of Object.entries(kinds)) {
|
|
674
|
-
result += `### ${CATEGORY_EMOJI[kind]} ${CATEGORY_LABELS[kind]} (${names.length})\n`;
|
|
675
|
-
for (const name of names.slice(0, 10)) {
|
|
676
|
-
result += `- \`${name}\`\n`;
|
|
677
|
-
}
|
|
678
|
-
if (names.length > 10) {
|
|
679
|
-
result += `- ... e mais ${names.length - 10}\n`;
|
|
680
|
-
}
|
|
681
|
-
result += '\n';
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
return {
|
|
685
|
-
content: [{ type: 'text', text: result }],
|
|
686
|
-
};
|
|
687
|
-
}
|
|
688
|
-
case 'tailwind_categorias': {
|
|
689
|
-
const { categoria, modulo } = args;
|
|
690
|
-
const parser = new AstParser(TAILWIND_SRC_PATH);
|
|
691
|
-
let types = parser.getTypesByKind(categoria);
|
|
692
|
-
if (modulo) {
|
|
693
|
-
types = types.filter((t) => t.module.toLowerCase() === modulo.toLowerCase());
|
|
694
|
-
}
|
|
695
|
-
let result = `# ${CATEGORY_EMOJI[categoria]} ${CATEGORY_LABELS[categoria]}\n\n`;
|
|
696
|
-
result += `**Total:** ${types.length}\n\n`;
|
|
697
|
-
for (const type of types) {
|
|
698
|
-
result += formatExtractedType(type, categoria === 'enum' || categoria === 'interface');
|
|
699
|
-
}
|
|
700
|
-
return {
|
|
701
|
-
content: [{ type: 'text', text: result }],
|
|
702
|
-
};
|
|
703
|
-
}
|
|
704
|
-
case 'tailwind_constantes': {
|
|
705
|
-
const { modulo } = args;
|
|
706
|
-
const parser = new AstParser(TAILWIND_SRC_PATH);
|
|
707
|
-
let constants = parser.getConstants();
|
|
708
|
-
if (modulo) {
|
|
709
|
-
constants = constants.filter((c) => c.module.toLowerCase() === modulo.toLowerCase());
|
|
710
|
-
}
|
|
711
|
-
let result = '# 📦 Constantes e Variáveis Exportadas\n\n';
|
|
712
|
-
result += `**Total:** ${constants.length}\n\n`;
|
|
713
|
-
const byModule = {};
|
|
714
|
-
for (const c of constants) {
|
|
715
|
-
if (!byModule[c.module])
|
|
716
|
-
byModule[c.module] = [];
|
|
717
|
-
byModule[c.module].push(c);
|
|
718
|
-
}
|
|
719
|
-
for (const [mod, vars] of Object.entries(byModule)) {
|
|
720
|
-
result += `## 📁 ${mod}\n\n`;
|
|
721
|
-
for (const v of vars) {
|
|
722
|
-
result += `### \`${v.name}\`\n`;
|
|
723
|
-
result += `**Tipo:** \`${v.signature.replace(`const ${v.name}: `, '')}\`\n`;
|
|
724
|
-
if (v.value) {
|
|
725
|
-
result += `**Valor:** \`${v.value}\`\n`;
|
|
726
|
-
}
|
|
727
|
-
result += '\n';
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
return {
|
|
731
|
-
content: [{ type: 'text', text: result }],
|
|
732
|
-
};
|
|
733
|
-
}
|
|
734
|
-
case 'tailwind_hierarquia': {
|
|
735
|
-
const { nome } = args;
|
|
736
|
-
const parser = new AstParser(TAILWIND_SRC_PATH);
|
|
737
|
-
const hierarchy = parser.getTypeHierarchy(nome);
|
|
738
|
-
if (!hierarchy) {
|
|
739
|
-
return {
|
|
740
|
-
content: [{ type: 'text', text: `❌ Tipo "${nome}" não encontrado.` }],
|
|
741
|
-
isError: true,
|
|
742
|
-
};
|
|
743
|
-
}
|
|
744
|
-
let result = `# 🌳 Hierarquia de \`${hierarchy.type.name}\`\n\n`;
|
|
745
|
-
result += formatExtractedType(hierarchy.type, false);
|
|
746
|
-
if (hierarchy.parents.length > 0) {
|
|
747
|
-
result += '## ⬆️ Herda de (Parents)\n\n';
|
|
748
|
-
for (const parent of hierarchy.parents) {
|
|
749
|
-
result += `- \`${parent}\`\n`;
|
|
750
|
-
}
|
|
751
|
-
result += '\n';
|
|
752
|
-
}
|
|
753
|
-
if (hierarchy.children.length > 0) {
|
|
754
|
-
result += '## ⬇️ Herdado por (Children)\n\n';
|
|
755
|
-
for (const child of hierarchy.children) {
|
|
756
|
-
result += `- \`${child}\`\n`;
|
|
757
|
-
}
|
|
758
|
-
result += '\n';
|
|
759
|
-
}
|
|
760
|
-
if (hierarchy.parents.length === 0 && hierarchy.children.length === 0) {
|
|
761
|
-
result += '*Este tipo não possui relacionamentos de herança.*\n';
|
|
762
|
-
}
|
|
763
|
-
return {
|
|
764
|
-
content: [{ type: 'text', text: result }],
|
|
765
|
-
};
|
|
766
|
-
}
|
|
767
|
-
case 'tailwind_estatisticas': {
|
|
768
|
-
const parser = new AstParser(TAILWIND_SRC_PATH);
|
|
769
|
-
const stats = parser.getStatistics();
|
|
770
|
-
return {
|
|
771
|
-
content: [{ type: 'text', text: formatStatistics(stats) }],
|
|
772
|
-
};
|
|
773
|
-
}
|
|
774
|
-
case 'tailwind_dependencias': {
|
|
775
|
-
const parser = new AstParser(TAILWIND_SRC_PATH);
|
|
776
|
-
const deps = parser.analyzeDependencies();
|
|
777
|
-
return {
|
|
778
|
-
content: [{ type: 'text', text: formatDependencies(deps) }],
|
|
779
|
-
};
|
|
780
|
-
}
|
|
781
|
-
case 'tailwind_enums': {
|
|
782
|
-
const parser = new AstParser(TAILWIND_SRC_PATH);
|
|
783
|
-
const enums = parser.getEnums();
|
|
784
|
-
let result = '# 🔢 Enumerações da Biblioteca\n\n';
|
|
785
|
-
result += `**Total:** ${enums.length}\n\n`;
|
|
786
|
-
for (const e of enums) {
|
|
787
|
-
result += `## \`${e.name}\`\n\n`;
|
|
788
|
-
result += `**Arquivo:** \`${e.file}\`\n\n`;
|
|
789
|
-
if (e.docs)
|
|
790
|
-
result += `> ${e.docs}\n\n`;
|
|
791
|
-
if (e.members && e.members.length > 0) {
|
|
792
|
-
result += '**Valores:**\n';
|
|
793
|
-
for (const member of e.members) {
|
|
794
|
-
result += `- \`${member}\`\n`;
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
result += '\n';
|
|
798
|
-
}
|
|
799
|
-
return {
|
|
800
|
-
content: [{ type: 'text', text: result }],
|
|
801
|
-
};
|
|
802
|
-
}
|
|
803
|
-
case 'tailwind_interfaces': {
|
|
804
|
-
const { modulo, detalhado } = args;
|
|
805
|
-
const parser = new AstParser(TAILWIND_SRC_PATH);
|
|
806
|
-
let interfaces = parser.getInterfaces();
|
|
807
|
-
if (modulo) {
|
|
808
|
-
interfaces = interfaces.filter((i) => i.module.toLowerCase() === modulo.toLowerCase());
|
|
809
|
-
}
|
|
810
|
-
let result = '# 📋 Interfaces da Biblioteca\n\n';
|
|
811
|
-
result += `**Total:** ${interfaces.length}\n\n`;
|
|
812
|
-
for (const iface of interfaces) {
|
|
813
|
-
result += formatExtractedType(iface, detalhado || false);
|
|
814
|
-
}
|
|
815
|
-
return {
|
|
816
|
-
content: [{ type: 'text', text: result }],
|
|
817
|
-
};
|
|
818
|
-
}
|
|
819
|
-
case 'tailwind_funcoes': {
|
|
820
|
-
const { modulo } = args;
|
|
821
|
-
const parser = new AstParser(TAILWIND_SRC_PATH);
|
|
822
|
-
let functions = parser.getFunctions();
|
|
823
|
-
if (modulo) {
|
|
824
|
-
functions = functions.filter((f) => f.module.toLowerCase() === modulo.toLowerCase());
|
|
825
|
-
}
|
|
826
|
-
let result = '# ⚡ Funções da Biblioteca\n\n';
|
|
827
|
-
result += `**Total:** ${functions.length}\n\n`;
|
|
828
|
-
const byModule = {};
|
|
829
|
-
for (const f of functions) {
|
|
830
|
-
if (!byModule[f.module])
|
|
831
|
-
byModule[f.module] = [];
|
|
832
|
-
byModule[f.module].push(f);
|
|
833
|
-
}
|
|
834
|
-
for (const [mod, funcs] of Object.entries(byModule)) {
|
|
835
|
-
result += `## 📁 ${mod}\n\n`;
|
|
836
|
-
for (const func of funcs) {
|
|
837
|
-
result += formatExtractedType(func, true);
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
return {
|
|
841
|
-
content: [{ type: 'text', text: result }],
|
|
842
|
-
};
|
|
843
|
-
}
|
|
844
|
-
case 'tailwind_integracoes': {
|
|
845
|
-
const { framework } = args;
|
|
846
|
-
const key = framework.toLowerCase();
|
|
847
|
-
const guides = {
|
|
848
|
-
vite: {
|
|
849
|
-
title: 'Vite (React/Vue/Svelte)',
|
|
850
|
-
v4: {
|
|
851
|
-
steps: [
|
|
852
|
-
'Instale deps: npm install tailwindcss @tailwindcss/vite',
|
|
853
|
-
'Configure o plugin no vite.config.ts',
|
|
854
|
-
'Crie o CSS com @import "tailwindcss"',
|
|
855
|
-
'Importe o CSS no entry (main.tsx/main.ts)',
|
|
856
|
-
],
|
|
857
|
-
configSnippet: `// vite.config.ts
|
|
858
|
-
import tailwindcss from '@tailwindcss/vite'
|
|
859
|
-
import { defineConfig } from 'vite'
|
|
860
|
-
|
|
861
|
-
export default defineConfig({
|
|
862
|
-
plugins: [tailwindcss()]
|
|
863
|
-
})`,
|
|
864
|
-
cssSnippet: `/* app.css */
|
|
865
|
-
@import "tailwindcss";
|
|
866
|
-
|
|
867
|
-
@theme {
|
|
868
|
-
/* Customize theme variables */
|
|
869
|
-
--color-brand: oklch(0.72 0.11 221.19);
|
|
870
|
-
}`,
|
|
871
|
-
},
|
|
872
|
-
v3: {
|
|
873
|
-
steps: [
|
|
874
|
-
'Instale deps: npm install -D tailwindcss postcss autoprefixer',
|
|
875
|
-
'Gere config: npx tailwindcss init -p',
|
|
876
|
-
'Configure content no tailwind.config.js',
|
|
877
|
-
'Crie CSS com diretivas @tailwind',
|
|
878
|
-
],
|
|
879
|
-
configSnippet: `// tailwind.config.js
|
|
880
|
-
module.exports = {
|
|
881
|
-
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx,vue,svelte}'],
|
|
882
|
-
theme: { extend: {} },
|
|
883
|
-
plugins: [],
|
|
884
|
-
}`,
|
|
885
|
-
cssSnippet: `/* src/index.css */
|
|
886
|
-
@tailwind base;
|
|
887
|
-
@tailwind components;
|
|
888
|
-
@tailwind utilities;`,
|
|
889
|
-
},
|
|
890
|
-
contentGlob: './index.html, ./src/**/*.{js,ts,jsx,tsx,vue,svelte}',
|
|
891
|
-
},
|
|
892
|
-
next: {
|
|
893
|
-
title: 'Next.js (App Router)',
|
|
894
|
-
v4: {
|
|
895
|
-
steps: [
|
|
896
|
-
'Instale deps: npm install tailwindcss @tailwindcss/postcss postcss',
|
|
897
|
-
'Configure postcss.config.mjs',
|
|
898
|
-
'Crie app/globals.css com @import "tailwindcss"',
|
|
899
|
-
'Importe em app/layout.tsx',
|
|
900
|
-
],
|
|
901
|
-
configSnippet: `// postcss.config.mjs
|
|
902
|
-
export default {
|
|
903
|
-
plugins: {
|
|
904
|
-
'@tailwindcss/postcss': {}
|
|
905
|
-
}
|
|
906
|
-
}`,
|
|
907
|
-
cssSnippet: `/* app/globals.css */
|
|
908
|
-
@import "tailwindcss";
|
|
909
|
-
|
|
910
|
-
@theme {
|
|
911
|
-
--color-primary: oklch(0.62 0.21 259.81);
|
|
912
|
-
}`,
|
|
913
|
-
},
|
|
914
|
-
v3: {
|
|
915
|
-
steps: [
|
|
916
|
-
'Instale deps: npm install -D tailwindcss postcss autoprefixer',
|
|
917
|
-
'Gere config: npx tailwindcss init -p',
|
|
918
|
-
'Configure content no tailwind.config.js',
|
|
919
|
-
'Crie globals.css com diretivas @tailwind',
|
|
920
|
-
],
|
|
921
|
-
configSnippet: `// tailwind.config.js
|
|
922
|
-
module.exports = {
|
|
923
|
-
content: [
|
|
924
|
-
'./app/**/*.{js,ts,jsx,tsx,mdx}',
|
|
925
|
-
'./pages/**/*.{js,ts,jsx,tsx}',
|
|
926
|
-
'./components/**/*.{js,ts,jsx,tsx}',
|
|
927
|
-
'./src/**/*.{js,ts,jsx,tsx,mdx}',
|
|
928
|
-
],
|
|
929
|
-
theme: { extend: {} },
|
|
930
|
-
plugins: [],
|
|
931
|
-
}`,
|
|
932
|
-
cssSnippet: `/* app/globals.css */
|
|
933
|
-
@tailwind base;
|
|
934
|
-
@tailwind components;
|
|
935
|
-
@tailwind utilities;`,
|
|
936
|
-
},
|
|
937
|
-
contentGlob: './app/**/*.{js,ts,jsx,tsx,mdx}, ./components/**/*.{js,ts,jsx,tsx}',
|
|
938
|
-
},
|
|
939
|
-
nuxt: {
|
|
940
|
-
title: 'Nuxt 3',
|
|
941
|
-
v4: {
|
|
942
|
-
steps: [
|
|
943
|
-
'Instale deps: npm install tailwindcss @tailwindcss/postcss postcss',
|
|
944
|
-
'Configure postcss no nuxt.config.ts',
|
|
945
|
-
'Crie assets/css/main.css com @import "tailwindcss"',
|
|
946
|
-
'Adicione o CSS ao nuxt.config.ts',
|
|
947
|
-
],
|
|
948
|
-
configSnippet: `// nuxt.config.ts
|
|
949
|
-
export default defineNuxtConfig({
|
|
950
|
-
css: ['~/assets/css/main.css'],
|
|
951
|
-
postcss: {
|
|
952
|
-
plugins: {
|
|
953
|
-
'@tailwindcss/postcss': {}
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
})`,
|
|
957
|
-
cssSnippet: `/* assets/css/main.css */
|
|
958
|
-
@import "tailwindcss";
|
|
959
|
-
|
|
960
|
-
@theme {
|
|
961
|
-
--color-brand: oklch(0.69 0.17 162.48);
|
|
962
|
-
}`,
|
|
963
|
-
},
|
|
964
|
-
v3: {
|
|
965
|
-
steps: [
|
|
966
|
-
'Instale deps: npm install -D tailwindcss postcss autoprefixer',
|
|
967
|
-
'Gere config: npx tailwindcss init -p',
|
|
968
|
-
'Configure content e adicione CSS ao nuxt.config.ts',
|
|
969
|
-
],
|
|
970
|
-
configSnippet: `// tailwind.config.js
|
|
971
|
-
module.exports = {
|
|
972
|
-
content: [
|
|
973
|
-
'./components/**/*.{vue,js,ts}',
|
|
974
|
-
'./layouts/**/*.vue',
|
|
975
|
-
'./pages/**/*.vue',
|
|
976
|
-
'./app.vue',
|
|
977
|
-
'./plugins/**/*.{js,ts}',
|
|
978
|
-
],
|
|
979
|
-
theme: { extend: {} },
|
|
980
|
-
plugins: [],
|
|
981
|
-
}`,
|
|
982
|
-
cssSnippet: `/* assets/css/tailwind.css */
|
|
983
|
-
@tailwind base;
|
|
984
|
-
@tailwind components;
|
|
985
|
-
@tailwind utilities;`,
|
|
986
|
-
},
|
|
987
|
-
contentGlob: './components/**/*.{vue,js,ts}, ./pages/**/*.vue, ./app.vue',
|
|
988
|
-
},
|
|
989
|
-
sveltekit: {
|
|
990
|
-
title: 'SvelteKit',
|
|
991
|
-
v4: {
|
|
992
|
-
steps: [
|
|
993
|
-
'Instale deps: npm install tailwindcss @tailwindcss/vite',
|
|
994
|
-
'Configure o plugin no vite.config.ts',
|
|
995
|
-
'Crie src/app.css com @import "tailwindcss"',
|
|
996
|
-
'Importe em src/routes/+layout.svelte',
|
|
997
|
-
],
|
|
998
|
-
configSnippet: `// vite.config.ts
|
|
999
|
-
import { sveltekit } from '@sveltejs/kit/vite'
|
|
1000
|
-
import tailwindcss from '@tailwindcss/vite'
|
|
1001
|
-
import { defineConfig } from 'vite'
|
|
1002
|
-
|
|
1003
|
-
export default defineConfig({
|
|
1004
|
-
plugins: [tailwindcss(), sveltekit()]
|
|
1005
|
-
})`,
|
|
1006
|
-
cssSnippet: `/* src/app.css */
|
|
1007
|
-
@import "tailwindcss";`,
|
|
1008
|
-
},
|
|
1009
|
-
v3: {
|
|
1010
|
-
steps: [
|
|
1011
|
-
'Instale deps: npm install -D tailwindcss postcss autoprefixer',
|
|
1012
|
-
'Gere config: npx tailwindcss init -p',
|
|
1013
|
-
'Crie src/app.css e importe em +layout.svelte',
|
|
1014
|
-
],
|
|
1015
|
-
configSnippet: `// tailwind.config.js
|
|
1016
|
-
module.exports = {
|
|
1017
|
-
content: ['./src/**/*.{html,js,svelte,ts}'],
|
|
1018
|
-
theme: { extend: {} },
|
|
1019
|
-
plugins: [],
|
|
1020
|
-
}`,
|
|
1021
|
-
cssSnippet: `/* src/app.css */
|
|
1022
|
-
@tailwind base;
|
|
1023
|
-
@tailwind components;
|
|
1024
|
-
@tailwind utilities;`,
|
|
1025
|
-
},
|
|
1026
|
-
contentGlob: './src/**/*.{html,js,svelte,ts}',
|
|
1027
|
-
},
|
|
1028
|
-
astro: {
|
|
1029
|
-
title: 'Astro',
|
|
1030
|
-
v4: {
|
|
1031
|
-
steps: [
|
|
1032
|
-
'Instale deps: npm install tailwindcss @tailwindcss/vite',
|
|
1033
|
-
'Configure o plugin no astro.config.mjs',
|
|
1034
|
-
'Crie src/styles/global.css com @import "tailwindcss"',
|
|
1035
|
-
'Importe em layouts/Layout.astro',
|
|
1036
|
-
],
|
|
1037
|
-
configSnippet: `// astro.config.mjs
|
|
1038
|
-
import { defineConfig } from 'astro/config'
|
|
1039
|
-
import tailwindcss from '@tailwindcss/vite'
|
|
1040
|
-
|
|
1041
|
-
export default defineConfig({
|
|
1042
|
-
vite: {
|
|
1043
|
-
plugins: [tailwindcss()]
|
|
1044
|
-
}
|
|
1045
|
-
})`,
|
|
1046
|
-
cssSnippet: `/* src/styles/global.css */
|
|
1047
|
-
@import "tailwindcss";`,
|
|
1048
|
-
},
|
|
1049
|
-
v3: {
|
|
1050
|
-
steps: [
|
|
1051
|
-
'Use: npx astro add tailwind (recomendado)',
|
|
1052
|
-
'Ou manual: npm install -D tailwindcss @astrojs/tailwind',
|
|
1053
|
-
],
|
|
1054
|
-
configSnippet: `// tailwind.config.js
|
|
1055
|
-
module.exports = {
|
|
1056
|
-
content: ['./src/**/*.{astro,html,js,jsx,ts,tsx,vue,svelte}'],
|
|
1057
|
-
theme: { extend: {} },
|
|
1058
|
-
plugins: [],
|
|
1059
|
-
}`,
|
|
1060
|
-
cssSnippet: `/* src/styles/global.css */
|
|
1061
|
-
@tailwind base;
|
|
1062
|
-
@tailwind components;
|
|
1063
|
-
@tailwind utilities;`,
|
|
1064
|
-
},
|
|
1065
|
-
contentGlob: './src/**/*.{astro,html,js,jsx,ts,tsx,vue,svelte}',
|
|
1066
|
-
},
|
|
1067
|
-
remix: {
|
|
1068
|
-
title: 'Remix',
|
|
1069
|
-
v4: {
|
|
1070
|
-
steps: [
|
|
1071
|
-
'Instale deps: npm install tailwindcss @tailwindcss/vite',
|
|
1072
|
-
'Configure o plugin no vite.config.ts',
|
|
1073
|
-
'Crie app/tailwind.css com @import "tailwindcss"',
|
|
1074
|
-
'Importe em app/root.tsx via links()',
|
|
1075
|
-
],
|
|
1076
|
-
configSnippet: `// vite.config.ts
|
|
1077
|
-
import { vitePlugin as remix } from '@remix-run/dev'
|
|
1078
|
-
import tailwindcss from '@tailwindcss/vite'
|
|
1079
|
-
import { defineConfig } from 'vite'
|
|
1080
|
-
|
|
1081
|
-
export default defineConfig({
|
|
1082
|
-
plugins: [tailwindcss(), remix()]
|
|
1083
|
-
})`,
|
|
1084
|
-
cssSnippet: `/* app/tailwind.css */
|
|
1085
|
-
@import "tailwindcss";`,
|
|
1086
|
-
},
|
|
1087
|
-
v3: {
|
|
1088
|
-
steps: [
|
|
1089
|
-
'Instale deps: npm install -D tailwindcss postcss autoprefixer',
|
|
1090
|
-
'Gere config: npx tailwindcss init -p',
|
|
1091
|
-
'Crie app/tailwind.css e importe em root.tsx',
|
|
1092
|
-
],
|
|
1093
|
-
configSnippet: `// tailwind.config.js
|
|
1094
|
-
module.exports = {
|
|
1095
|
-
content: ['./app/**/*.{ts,tsx,js,jsx}'],
|
|
1096
|
-
theme: { extend: {} },
|
|
1097
|
-
plugins: [],
|
|
1098
|
-
}`,
|
|
1099
|
-
cssSnippet: `/* app/tailwind.css */
|
|
1100
|
-
@tailwind base;
|
|
1101
|
-
@tailwind components;
|
|
1102
|
-
@tailwind utilities;`,
|
|
1103
|
-
},
|
|
1104
|
-
contentGlob: './app/**/*.{ts,tsx,js,jsx}',
|
|
1105
|
-
},
|
|
1106
|
-
vue: {
|
|
1107
|
-
title: 'Vue 3 (Vite)',
|
|
1108
|
-
v4: {
|
|
1109
|
-
steps: [
|
|
1110
|
-
'Instale deps: npm install tailwindcss @tailwindcss/vite',
|
|
1111
|
-
'Configure o plugin no vite.config.ts',
|
|
1112
|
-
'Crie src/assets/main.css com @import "tailwindcss"',
|
|
1113
|
-
'Importe em src/main.ts',
|
|
1114
|
-
],
|
|
1115
|
-
configSnippet: `// vite.config.ts
|
|
1116
|
-
import vue from '@vitejs/plugin-vue'
|
|
1117
|
-
import tailwindcss from '@tailwindcss/vite'
|
|
1118
|
-
import { defineConfig } from 'vite'
|
|
1119
|
-
|
|
1120
|
-
export default defineConfig({
|
|
1121
|
-
plugins: [vue(), tailwindcss()]
|
|
1122
|
-
})`,
|
|
1123
|
-
cssSnippet: `/* src/assets/main.css */
|
|
1124
|
-
@import "tailwindcss";`,
|
|
1125
|
-
},
|
|
1126
|
-
v3: {
|
|
1127
|
-
steps: [
|
|
1128
|
-
'Instale deps: npm install -D tailwindcss postcss autoprefixer',
|
|
1129
|
-
'Gere config: npx tailwindcss init -p',
|
|
1130
|
-
'Crie src/assets/tailwind.css e importe em main.ts',
|
|
1131
|
-
],
|
|
1132
|
-
configSnippet: `// tailwind.config.js
|
|
1133
|
-
module.exports = {
|
|
1134
|
-
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
|
|
1135
|
-
theme: { extend: {} },
|
|
1136
|
-
plugins: [],
|
|
1137
|
-
}`,
|
|
1138
|
-
cssSnippet: `/* src/assets/tailwind.css */
|
|
1139
|
-
@tailwind base;
|
|
1140
|
-
@tailwind components;
|
|
1141
|
-
@tailwind utilities;`,
|
|
1142
|
-
},
|
|
1143
|
-
contentGlob: './index.html, ./src/**/*.{vue,js,ts,jsx,tsx}',
|
|
1144
|
-
},
|
|
1145
|
-
react: {
|
|
1146
|
-
title: 'React (Vite)',
|
|
1147
|
-
v4: {
|
|
1148
|
-
steps: [
|
|
1149
|
-
'Instale deps: npm install tailwindcss @tailwindcss/vite',
|
|
1150
|
-
'Configure o plugin no vite.config.ts',
|
|
1151
|
-
'Crie src/index.css com @import "tailwindcss"',
|
|
1152
|
-
'Importe em src/main.tsx',
|
|
1153
|
-
],
|
|
1154
|
-
configSnippet: `// vite.config.ts
|
|
1155
|
-
import react from '@vitejs/plugin-react'
|
|
1156
|
-
import tailwindcss from '@tailwindcss/vite'
|
|
1157
|
-
import { defineConfig } from 'vite'
|
|
1158
|
-
|
|
1159
|
-
export default defineConfig({
|
|
1160
|
-
plugins: [react(), tailwindcss()]
|
|
1161
|
-
})`,
|
|
1162
|
-
cssSnippet: `/* src/index.css */
|
|
1163
|
-
@import "tailwindcss";`,
|
|
1164
|
-
},
|
|
1165
|
-
v3: {
|
|
1166
|
-
steps: [
|
|
1167
|
-
'Instale deps: npm install -D tailwindcss postcss autoprefixer',
|
|
1168
|
-
'Gere config: npx tailwindcss init -p',
|
|
1169
|
-
'Crie src/index.css e importe em main.tsx/index.tsx',
|
|
1170
|
-
],
|
|
1171
|
-
configSnippet: `// tailwind.config.js
|
|
1172
|
-
module.exports = {
|
|
1173
|
-
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
|
1174
|
-
theme: { extend: {} },
|
|
1175
|
-
plugins: [],
|
|
1176
|
-
}`,
|
|
1177
|
-
cssSnippet: `/* src/index.css */
|
|
1178
|
-
@tailwind base;
|
|
1179
|
-
@tailwind components;
|
|
1180
|
-
@tailwind utilities;`,
|
|
1181
|
-
},
|
|
1182
|
-
contentGlob: './index.html, ./src/**/*.{js,ts,jsx,tsx}',
|
|
1183
|
-
},
|
|
1184
|
-
postcss: {
|
|
1185
|
-
title: 'PostCSS (Universal)',
|
|
1186
|
-
v4: {
|
|
1187
|
-
steps: [
|
|
1188
|
-
'Instale deps: npm install tailwindcss @tailwindcss/postcss postcss',
|
|
1189
|
-
'Configure postcss.config.js',
|
|
1190
|
-
'Crie CSS com @import "tailwindcss"',
|
|
1191
|
-
],
|
|
1192
|
-
configSnippet: `// postcss.config.js
|
|
1193
|
-
export default {
|
|
1194
|
-
plugins: {
|
|
1195
|
-
'@tailwindcss/postcss': {}
|
|
1196
|
-
}
|
|
1197
|
-
}`,
|
|
1198
|
-
cssSnippet: `/* styles.css */
|
|
1199
|
-
@import "tailwindcss";`,
|
|
1200
|
-
},
|
|
1201
|
-
v3: {
|
|
1202
|
-
steps: [
|
|
1203
|
-
'Instale deps: npm install -D tailwindcss postcss autoprefixer',
|
|
1204
|
-
'Configure postcss.config.js',
|
|
1205
|
-
'Crie CSS com diretivas @tailwind',
|
|
1206
|
-
],
|
|
1207
|
-
configSnippet: `// postcss.config.js
|
|
1208
|
-
module.exports = {
|
|
1209
|
-
plugins: {
|
|
1210
|
-
tailwindcss: {},
|
|
1211
|
-
autoprefixer: {},
|
|
1212
|
-
}
|
|
1213
|
-
}`,
|
|
1214
|
-
cssSnippet: `/* styles.css */
|
|
1215
|
-
@tailwind base;
|
|
1216
|
-
@tailwind components;
|
|
1217
|
-
@tailwind utilities;`,
|
|
1218
|
-
},
|
|
1219
|
-
contentGlob: './src/**/*.{html,js,ts,jsx,tsx}',
|
|
1220
|
-
},
|
|
1221
|
-
cli: {
|
|
1222
|
-
title: 'CLI (Standalone)',
|
|
1223
|
-
v4: {
|
|
1224
|
-
steps: [
|
|
1225
|
-
'Instale: npm install tailwindcss @tailwindcss/cli',
|
|
1226
|
-
'Execute: npx @tailwindcss/cli -i input.css -o output.css --watch',
|
|
1227
|
-
],
|
|
1228
|
-
configSnippet: `# Comando para build
|
|
1229
|
-
npx @tailwindcss/cli -i input.css -o output.css
|
|
1230
|
-
|
|
1231
|
-
# Comando para watch
|
|
1232
|
-
npx @tailwindcss/cli -i input.css -o output.css --watch
|
|
1233
|
-
|
|
1234
|
-
# Minificado para produção
|
|
1235
|
-
npx @tailwindcss/cli -i input.css -o output.css --minify`,
|
|
1236
|
-
cssSnippet: `/* input.css */
|
|
1237
|
-
@import "tailwindcss";`,
|
|
1238
|
-
},
|
|
1239
|
-
v3: {
|
|
1240
|
-
steps: [
|
|
1241
|
-
'Instale: npm install -D tailwindcss',
|
|
1242
|
-
'Gere config: npx tailwindcss init',
|
|
1243
|
-
'Execute: npx tailwindcss -i input.css -o output.css --watch',
|
|
1244
|
-
],
|
|
1245
|
-
configSnippet: `# Comando para watch
|
|
1246
|
-
npx tailwindcss -i ./src/input.css -o ./dist/output.css --watch
|
|
1247
|
-
|
|
1248
|
-
# Minificado para produção
|
|
1249
|
-
npx tailwindcss -i ./src/input.css -o ./dist/output.css --minify`,
|
|
1250
|
-
cssSnippet: `/* input.css */
|
|
1251
|
-
@tailwind base;
|
|
1252
|
-
@tailwind components;
|
|
1253
|
-
@tailwind utilities;`,
|
|
1254
|
-
},
|
|
1255
|
-
contentGlob: './src/**/*.{html,js}',
|
|
1256
|
-
},
|
|
1257
|
-
};
|
|
1258
|
-
const guide = guides[key];
|
|
1259
|
-
if (!guide) {
|
|
1260
|
-
const available = Object.keys(guides).join(', ');
|
|
1261
|
-
return {
|
|
1262
|
-
content: [{ type: 'text', text: `❌ Framework não suportado: ${framework}\n\nFrameworks disponíveis: ${available}` }],
|
|
1263
|
-
isError: true,
|
|
1264
|
-
};
|
|
1265
|
-
}
|
|
1266
|
-
let result = `# 🚀 Integração Tailwind CSS + ${guide.title}\n\n`;
|
|
1267
|
-
result += '---\n\n';
|
|
1268
|
-
result += '## ⚡ Tailwind v4 (Recomendado)\n\n';
|
|
1269
|
-
result += '**Passos:**\n';
|
|
1270
|
-
for (let i = 0; i < guide.v4.steps.length; i++) {
|
|
1271
|
-
result += `${i + 1}. ${guide.v4.steps[i]}\n`;
|
|
1272
|
-
}
|
|
1273
|
-
result += '\n**Configuração:**\n```ts\n' + guide.v4.configSnippet + '\n```\n\n';
|
|
1274
|
-
result += '**CSS:**\n```css\n' + guide.v4.cssSnippet + '\n```\n\n';
|
|
1275
|
-
result += '---\n\n';
|
|
1276
|
-
result += '## 📦 Tailwind v3 (Legado)\n\n';
|
|
1277
|
-
result += '**Passos:**\n';
|
|
1278
|
-
for (let i = 0; i < guide.v3.steps.length; i++) {
|
|
1279
|
-
result += `${i + 1}. ${guide.v3.steps[i]}\n`;
|
|
1280
|
-
}
|
|
1281
|
-
result += '\n**Configuração:**\n```js\n' + guide.v3.configSnippet + '\n```\n\n';
|
|
1282
|
-
result += '**CSS:**\n```css\n' + guide.v3.cssSnippet + '\n```\n\n';
|
|
1283
|
-
result += '---\n\n';
|
|
1284
|
-
result += `**Content glob recomendado:** \`${guide.contentGlob}\`\n`;
|
|
1285
|
-
return {
|
|
1286
|
-
content: [{ type: 'text', text: result }],
|
|
1287
|
-
};
|
|
1288
|
-
}
|
|
1289
|
-
case 'tailwind_utilities': {
|
|
1290
|
-
const categoria = args?.categoria;
|
|
1291
|
-
const utilities = {
|
|
1292
|
-
layout: {
|
|
1293
|
-
desc: 'Controle de layout e posicionamento',
|
|
1294
|
-
classes: [
|
|
1295
|
-
{ class: 'block', css: 'display: block;' },
|
|
1296
|
-
{ class: 'inline-block', css: 'display: inline-block;' },
|
|
1297
|
-
{ class: 'inline', css: 'display: inline;' },
|
|
1298
|
-
{ class: 'flex', css: 'display: flex;' },
|
|
1299
|
-
{ class: 'inline-flex', css: 'display: inline-flex;' },
|
|
1300
|
-
{ class: 'grid', css: 'display: grid;' },
|
|
1301
|
-
{ class: 'inline-grid', css: 'display: inline-grid;' },
|
|
1302
|
-
{ class: 'hidden', css: 'display: none;' },
|
|
1303
|
-
{ class: 'container', css: 'width: 100%; max-width: breakpoint;' },
|
|
1304
|
-
{ class: 'static', css: 'position: static;' },
|
|
1305
|
-
{ class: 'fixed', css: 'position: fixed;' },
|
|
1306
|
-
{ class: 'absolute', css: 'position: absolute;' },
|
|
1307
|
-
{ class: 'relative', css: 'position: relative;' },
|
|
1308
|
-
{ class: 'sticky', css: 'position: sticky;' },
|
|
1309
|
-
{ class: 'inset-{n}', css: 'inset: {value};', desc: 'top, right, bottom, left' },
|
|
1310
|
-
{ class: 'top-{n}', css: 'top: {value};' },
|
|
1311
|
-
{ class: 'right-{n}', css: 'right: {value};' },
|
|
1312
|
-
{ class: 'bottom-{n}', css: 'bottom: {value};' },
|
|
1313
|
-
{ class: 'left-{n}', css: 'left: {value};' },
|
|
1314
|
-
{ class: 'z-{n}', css: 'z-index: {n};', desc: '0, 10, 20, 30, 40, 50, auto' },
|
|
1315
|
-
{ class: 'visible', css: 'visibility: visible;' },
|
|
1316
|
-
{ class: 'invisible', css: 'visibility: hidden;' },
|
|
1317
|
-
{ class: 'collapse', css: 'visibility: collapse;' },
|
|
1318
|
-
],
|
|
1319
|
-
},
|
|
1320
|
-
flexbox: {
|
|
1321
|
-
desc: 'Flexbox utilities',
|
|
1322
|
-
classes: [
|
|
1323
|
-
{ class: 'flex-row', css: 'flex-direction: row;' },
|
|
1324
|
-
{ class: 'flex-row-reverse', css: 'flex-direction: row-reverse;' },
|
|
1325
|
-
{ class: 'flex-col', css: 'flex-direction: column;' },
|
|
1326
|
-
{ class: 'flex-col-reverse', css: 'flex-direction: column-reverse;' },
|
|
1327
|
-
{ class: 'flex-wrap', css: 'flex-wrap: wrap;' },
|
|
1328
|
-
{ class: 'flex-wrap-reverse', css: 'flex-wrap: wrap-reverse;' },
|
|
1329
|
-
{ class: 'flex-nowrap', css: 'flex-wrap: nowrap;' },
|
|
1330
|
-
{ class: 'flex-1', css: 'flex: 1 1 0%;' },
|
|
1331
|
-
{ class: 'flex-auto', css: 'flex: 1 1 auto;' },
|
|
1332
|
-
{ class: 'flex-initial', css: 'flex: 0 1 auto;' },
|
|
1333
|
-
{ class: 'flex-none', css: 'flex: none;' },
|
|
1334
|
-
{ class: 'grow', css: 'flex-grow: 1;' },
|
|
1335
|
-
{ class: 'grow-0', css: 'flex-grow: 0;' },
|
|
1336
|
-
{ class: 'shrink', css: 'flex-shrink: 1;' },
|
|
1337
|
-
{ class: 'shrink-0', css: 'flex-shrink: 0;' },
|
|
1338
|
-
{ class: 'basis-{n}', css: 'flex-basis: {value};' },
|
|
1339
|
-
{ class: 'justify-start', css: 'justify-content: flex-start;' },
|
|
1340
|
-
{ class: 'justify-end', css: 'justify-content: flex-end;' },
|
|
1341
|
-
{ class: 'justify-center', css: 'justify-content: center;' },
|
|
1342
|
-
{ class: 'justify-between', css: 'justify-content: space-between;' },
|
|
1343
|
-
{ class: 'justify-around', css: 'justify-content: space-around;' },
|
|
1344
|
-
{ class: 'justify-evenly', css: 'justify-content: space-evenly;' },
|
|
1345
|
-
{ class: 'items-start', css: 'align-items: flex-start;' },
|
|
1346
|
-
{ class: 'items-end', css: 'align-items: flex-end;' },
|
|
1347
|
-
{ class: 'items-center', css: 'align-items: center;' },
|
|
1348
|
-
{ class: 'items-baseline', css: 'align-items: baseline;' },
|
|
1349
|
-
{ class: 'items-stretch', css: 'align-items: stretch;' },
|
|
1350
|
-
{ class: 'gap-{n}', css: 'gap: {value};' },
|
|
1351
|
-
{ class: 'gap-x-{n}', css: 'column-gap: {value};' },
|
|
1352
|
-
{ class: 'gap-y-{n}', css: 'row-gap: {value};' },
|
|
1353
|
-
],
|
|
1354
|
-
},
|
|
1355
|
-
grid: {
|
|
1356
|
-
desc: 'Grid utilities',
|
|
1357
|
-
classes: [
|
|
1358
|
-
{ class: 'grid-cols-{n}', css: 'grid-template-columns: repeat({n}, minmax(0, 1fr));', desc: '1-12, none' },
|
|
1359
|
-
{ class: 'grid-rows-{n}', css: 'grid-template-rows: repeat({n}, minmax(0, 1fr));', desc: '1-12, none' },
|
|
1360
|
-
{ class: 'col-span-{n}', css: 'grid-column: span {n} / span {n};', desc: '1-12, full' },
|
|
1361
|
-
{ class: 'col-start-{n}', css: 'grid-column-start: {n};' },
|
|
1362
|
-
{ class: 'col-end-{n}', css: 'grid-column-end: {n};' },
|
|
1363
|
-
{ class: 'row-span-{n}', css: 'grid-row: span {n} / span {n};' },
|
|
1364
|
-
{ class: 'row-start-{n}', css: 'grid-row-start: {n};' },
|
|
1365
|
-
{ class: 'row-end-{n}', css: 'grid-row-end: {n};' },
|
|
1366
|
-
{ class: 'grid-flow-row', css: 'grid-auto-flow: row;' },
|
|
1367
|
-
{ class: 'grid-flow-col', css: 'grid-auto-flow: column;' },
|
|
1368
|
-
{ class: 'grid-flow-dense', css: 'grid-auto-flow: dense;' },
|
|
1369
|
-
{ class: 'auto-cols-auto', css: 'grid-auto-columns: auto;' },
|
|
1370
|
-
{ class: 'auto-cols-min', css: 'grid-auto-columns: min-content;' },
|
|
1371
|
-
{ class: 'auto-cols-max', css: 'grid-auto-columns: max-content;' },
|
|
1372
|
-
{ class: 'auto-cols-fr', css: 'grid-auto-columns: minmax(0, 1fr);' },
|
|
1373
|
-
{ class: 'auto-rows-auto', css: 'grid-auto-rows: auto;' },
|
|
1374
|
-
{ class: 'auto-rows-min', css: 'grid-auto-rows: min-content;' },
|
|
1375
|
-
{ class: 'auto-rows-max', css: 'grid-auto-rows: max-content;' },
|
|
1376
|
-
{ class: 'auto-rows-fr', css: 'grid-auto-rows: minmax(0, 1fr);' },
|
|
1377
|
-
],
|
|
1378
|
-
},
|
|
1379
|
-
spacing: {
|
|
1380
|
-
desc: 'Margin e Padding',
|
|
1381
|
-
classes: [
|
|
1382
|
-
{ class: 'p-{n}', css: 'padding: {value};', desc: '0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 96, px' },
|
|
1383
|
-
{ class: 'px-{n}', css: 'padding-left: {value}; padding-right: {value};' },
|
|
1384
|
-
{ class: 'py-{n}', css: 'padding-top: {value}; padding-bottom: {value};' },
|
|
1385
|
-
{ class: 'pt-{n}', css: 'padding-top: {value};' },
|
|
1386
|
-
{ class: 'pr-{n}', css: 'padding-right: {value};' },
|
|
1387
|
-
{ class: 'pb-{n}', css: 'padding-bottom: {value};' },
|
|
1388
|
-
{ class: 'pl-{n}', css: 'padding-left: {value};' },
|
|
1389
|
-
{ class: 'm-{n}', css: 'margin: {value};' },
|
|
1390
|
-
{ class: 'mx-{n}', css: 'margin-left: {value}; margin-right: {value};' },
|
|
1391
|
-
{ class: 'my-{n}', css: 'margin-top: {value}; margin-bottom: {value};' },
|
|
1392
|
-
{ class: 'mt-{n}', css: 'margin-top: {value};' },
|
|
1393
|
-
{ class: 'mr-{n}', css: 'margin-right: {value};' },
|
|
1394
|
-
{ class: 'mb-{n}', css: 'margin-bottom: {value};' },
|
|
1395
|
-
{ class: 'ml-{n}', css: 'margin-left: {value};' },
|
|
1396
|
-
{ class: '-m-{n}', css: 'margin: -{value};', desc: 'Negative margin' },
|
|
1397
|
-
{ class: 'space-x-{n}', css: '> * + * { margin-left: {value}; }' },
|
|
1398
|
-
{ class: 'space-y-{n}', css: '> * + * { margin-top: {value}; }' },
|
|
1399
|
-
{ class: 'space-x-reverse', css: '--tw-space-x-reverse: 1;' },
|
|
1400
|
-
{ class: 'space-y-reverse', css: '--tw-space-y-reverse: 1;' },
|
|
1401
|
-
],
|
|
1402
|
-
},
|
|
1403
|
-
sizing: {
|
|
1404
|
-
desc: 'Width e Height',
|
|
1405
|
-
classes: [
|
|
1406
|
-
{ class: 'w-{n}', css: 'width: {value};', desc: '0-96, auto, full, screen, svw, lvw, dvw, min, max, fit' },
|
|
1407
|
-
{ class: 'w-1/2', css: 'width: 50%;' },
|
|
1408
|
-
{ class: 'w-1/3', css: 'width: 33.333333%;' },
|
|
1409
|
-
{ class: 'w-2/3', css: 'width: 66.666667%;' },
|
|
1410
|
-
{ class: 'w-1/4', css: 'width: 25%;' },
|
|
1411
|
-
{ class: 'w-full', css: 'width: 100%;' },
|
|
1412
|
-
{ class: 'w-screen', css: 'width: 100vw;' },
|
|
1413
|
-
{ class: 'w-auto', css: 'width: auto;' },
|
|
1414
|
-
{ class: 'min-w-{n}', css: 'min-width: {value};' },
|
|
1415
|
-
{ class: 'max-w-{n}', css: 'max-width: {value};', desc: 'xs, sm, md, lg, xl, 2xl, 3xl, 4xl, 5xl, 6xl, 7xl, full, prose, screen-sm, screen-md, screen-lg, screen-xl, screen-2xl' },
|
|
1416
|
-
{ class: 'h-{n}', css: 'height: {value};' },
|
|
1417
|
-
{ class: 'h-full', css: 'height: 100%;' },
|
|
1418
|
-
{ class: 'h-screen', css: 'height: 100vh;' },
|
|
1419
|
-
{ class: 'h-svh', css: 'height: 100svh;' },
|
|
1420
|
-
{ class: 'h-lvh', css: 'height: 100lvh;' },
|
|
1421
|
-
{ class: 'h-dvh', css: 'height: 100dvh;' },
|
|
1422
|
-
{ class: 'min-h-{n}', css: 'min-height: {value};' },
|
|
1423
|
-
{ class: 'min-h-screen', css: 'min-height: 100vh;' },
|
|
1424
|
-
{ class: 'max-h-{n}', css: 'max-height: {value};' },
|
|
1425
|
-
{ class: 'size-{n}', css: 'width: {value}; height: {value};', desc: 'v4: shorthand for w + h' },
|
|
1426
|
-
],
|
|
1427
|
-
},
|
|
1428
|
-
typography: {
|
|
1429
|
-
desc: 'Tipografia e texto',
|
|
1430
|
-
classes: [
|
|
1431
|
-
{ class: 'text-xs', css: 'font-size: 0.75rem; line-height: 1rem;' },
|
|
1432
|
-
{ class: 'text-sm', css: 'font-size: 0.875rem; line-height: 1.25rem;' },
|
|
1433
|
-
{ class: 'text-base', css: 'font-size: 1rem; line-height: 1.5rem;' },
|
|
1434
|
-
{ class: 'text-lg', css: 'font-size: 1.125rem; line-height: 1.75rem;' },
|
|
1435
|
-
{ class: 'text-xl', css: 'font-size: 1.25rem; line-height: 1.75rem;' },
|
|
1436
|
-
{ class: 'text-2xl', css: 'font-size: 1.5rem; line-height: 2rem;' },
|
|
1437
|
-
{ class: 'text-3xl', css: 'font-size: 1.875rem; line-height: 2.25rem;' },
|
|
1438
|
-
{ class: 'text-4xl', css: 'font-size: 2.25rem; line-height: 2.5rem;' },
|
|
1439
|
-
{ class: 'text-5xl', css: 'font-size: 3rem; line-height: 1;' },
|
|
1440
|
-
{ class: 'text-6xl', css: 'font-size: 3.75rem; line-height: 1;' },
|
|
1441
|
-
{ class: 'font-thin', css: 'font-weight: 100;' },
|
|
1442
|
-
{ class: 'font-light', css: 'font-weight: 300;' },
|
|
1443
|
-
{ class: 'font-normal', css: 'font-weight: 400;' },
|
|
1444
|
-
{ class: 'font-medium', css: 'font-weight: 500;' },
|
|
1445
|
-
{ class: 'font-semibold', css: 'font-weight: 600;' },
|
|
1446
|
-
{ class: 'font-bold', css: 'font-weight: 700;' },
|
|
1447
|
-
{ class: 'font-extrabold', css: 'font-weight: 800;' },
|
|
1448
|
-
{ class: 'font-black', css: 'font-weight: 900;' },
|
|
1449
|
-
{ class: 'italic', css: 'font-style: italic;' },
|
|
1450
|
-
{ class: 'not-italic', css: 'font-style: normal;' },
|
|
1451
|
-
{ class: 'text-left', css: 'text-align: left;' },
|
|
1452
|
-
{ class: 'text-center', css: 'text-align: center;' },
|
|
1453
|
-
{ class: 'text-right', css: 'text-align: right;' },
|
|
1454
|
-
{ class: 'text-justify', css: 'text-align: justify;' },
|
|
1455
|
-
{ class: 'underline', css: 'text-decoration-line: underline;' },
|
|
1456
|
-
{ class: 'overline', css: 'text-decoration-line: overline;' },
|
|
1457
|
-
{ class: 'line-through', css: 'text-decoration-line: line-through;' },
|
|
1458
|
-
{ class: 'no-underline', css: 'text-decoration-line: none;' },
|
|
1459
|
-
{ class: 'uppercase', css: 'text-transform: uppercase;' },
|
|
1460
|
-
{ class: 'lowercase', css: 'text-transform: lowercase;' },
|
|
1461
|
-
{ class: 'capitalize', css: 'text-transform: capitalize;' },
|
|
1462
|
-
{ class: 'normal-case', css: 'text-transform: none;' },
|
|
1463
|
-
{ class: 'truncate', css: 'overflow: hidden; text-overflow: ellipsis; white-space: nowrap;' },
|
|
1464
|
-
{ class: 'leading-{n}', css: 'line-height: {value};', desc: '3-10, none, tight, snug, normal, relaxed, loose' },
|
|
1465
|
-
{ class: 'tracking-{n}', css: 'letter-spacing: {value};', desc: 'tighter, tight, normal, wide, wider, widest' },
|
|
1466
|
-
],
|
|
1467
|
-
},
|
|
1468
|
-
backgrounds: {
|
|
1469
|
-
desc: 'Backgrounds e gradientes',
|
|
1470
|
-
classes: [
|
|
1471
|
-
{ class: 'bg-{color}', css: 'background-color: {color};', desc: 'Qualquer cor da paleta' },
|
|
1472
|
-
{ class: 'bg-transparent', css: 'background-color: transparent;' },
|
|
1473
|
-
{ class: 'bg-current', css: 'background-color: currentColor;' },
|
|
1474
|
-
{ class: 'bg-inherit', css: 'background-color: inherit;' },
|
|
1475
|
-
{ class: 'bg-gradient-to-{dir}', css: 'background-image: linear-gradient(to {dir}, ...);', desc: 't, tr, r, br, b, bl, l, tl' },
|
|
1476
|
-
{ class: 'from-{color}', css: '--tw-gradient-from: {color};' },
|
|
1477
|
-
{ class: 'via-{color}', css: '--tw-gradient-via: {color};' },
|
|
1478
|
-
{ class: 'to-{color}', css: '--tw-gradient-to: {color};' },
|
|
1479
|
-
{ class: 'bg-none', css: 'background-image: none;' },
|
|
1480
|
-
{ class: 'bg-cover', css: 'background-size: cover;' },
|
|
1481
|
-
{ class: 'bg-contain', css: 'background-size: contain;' },
|
|
1482
|
-
{ class: 'bg-auto', css: 'background-size: auto;' },
|
|
1483
|
-
{ class: 'bg-fixed', css: 'background-attachment: fixed;' },
|
|
1484
|
-
{ class: 'bg-local', css: 'background-attachment: local;' },
|
|
1485
|
-
{ class: 'bg-scroll', css: 'background-attachment: scroll;' },
|
|
1486
|
-
{ class: 'bg-center', css: 'background-position: center;' },
|
|
1487
|
-
{ class: 'bg-top', css: 'background-position: top;' },
|
|
1488
|
-
{ class: 'bg-bottom', css: 'background-position: bottom;' },
|
|
1489
|
-
{ class: 'bg-repeat', css: 'background-repeat: repeat;' },
|
|
1490
|
-
{ class: 'bg-no-repeat', css: 'background-repeat: no-repeat;' },
|
|
1491
|
-
{ class: 'bg-repeat-x', css: 'background-repeat: repeat-x;' },
|
|
1492
|
-
{ class: 'bg-repeat-y', css: 'background-repeat: repeat-y;' },
|
|
1493
|
-
],
|
|
1494
|
-
},
|
|
1495
|
-
borders: {
|
|
1496
|
-
desc: 'Borders e border-radius',
|
|
1497
|
-
classes: [
|
|
1498
|
-
{ class: 'border', css: 'border-width: 1px;' },
|
|
1499
|
-
{ class: 'border-0', css: 'border-width: 0px;' },
|
|
1500
|
-
{ class: 'border-2', css: 'border-width: 2px;' },
|
|
1501
|
-
{ class: 'border-4', css: 'border-width: 4px;' },
|
|
1502
|
-
{ class: 'border-8', css: 'border-width: 8px;' },
|
|
1503
|
-
{ class: 'border-t', css: 'border-top-width: 1px;' },
|
|
1504
|
-
{ class: 'border-r', css: 'border-right-width: 1px;' },
|
|
1505
|
-
{ class: 'border-b', css: 'border-bottom-width: 1px;' },
|
|
1506
|
-
{ class: 'border-l', css: 'border-left-width: 1px;' },
|
|
1507
|
-
{ class: 'border-{color}', css: 'border-color: {color};' },
|
|
1508
|
-
{ class: 'border-solid', css: 'border-style: solid;' },
|
|
1509
|
-
{ class: 'border-dashed', css: 'border-style: dashed;' },
|
|
1510
|
-
{ class: 'border-dotted', css: 'border-style: dotted;' },
|
|
1511
|
-
{ class: 'border-double', css: 'border-style: double;' },
|
|
1512
|
-
{ class: 'border-hidden', css: 'border-style: hidden;' },
|
|
1513
|
-
{ class: 'border-none', css: 'border-style: none;' },
|
|
1514
|
-
{ class: 'rounded', css: 'border-radius: 0.25rem;' },
|
|
1515
|
-
{ class: 'rounded-none', css: 'border-radius: 0px;' },
|
|
1516
|
-
{ class: 'rounded-sm', css: 'border-radius: 0.125rem;' },
|
|
1517
|
-
{ class: 'rounded-md', css: 'border-radius: 0.375rem;' },
|
|
1518
|
-
{ class: 'rounded-lg', css: 'border-radius: 0.5rem;' },
|
|
1519
|
-
{ class: 'rounded-xl', css: 'border-radius: 0.75rem;' },
|
|
1520
|
-
{ class: 'rounded-2xl', css: 'border-radius: 1rem;' },
|
|
1521
|
-
{ class: 'rounded-3xl', css: 'border-radius: 1.5rem;' },
|
|
1522
|
-
{ class: 'rounded-full', css: 'border-radius: 9999px;' },
|
|
1523
|
-
{ class: 'divide-x', css: '> * + * { border-left-width: 1px; }' },
|
|
1524
|
-
{ class: 'divide-y', css: '> * + * { border-top-width: 1px; }' },
|
|
1525
|
-
{ class: 'divide-{color}', css: '> * + * { border-color: {color}; }' },
|
|
1526
|
-
{ class: 'ring-{n}', css: 'box-shadow: 0 0 0 {n}px ...;', desc: '0, 1, 2, 4, 8, inset' },
|
|
1527
|
-
{ class: 'ring-{color}', css: '--tw-ring-color: {color};' },
|
|
1528
|
-
{ class: 'outline', css: 'outline-style: solid;' },
|
|
1529
|
-
{ class: 'outline-none', css: 'outline: 2px solid transparent; outline-offset: 2px;' },
|
|
1530
|
-
],
|
|
1531
|
-
},
|
|
1532
|
-
effects: {
|
|
1533
|
-
desc: 'Sombras e opacidade',
|
|
1534
|
-
classes: [
|
|
1535
|
-
{ class: 'shadow-sm', css: 'box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);' },
|
|
1536
|
-
{ class: 'shadow', css: 'box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);' },
|
|
1537
|
-
{ class: 'shadow-md', css: 'box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);' },
|
|
1538
|
-
{ class: 'shadow-lg', css: 'box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);' },
|
|
1539
|
-
{ class: 'shadow-xl', css: 'box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);' },
|
|
1540
|
-
{ class: 'shadow-2xl', css: 'box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);' },
|
|
1541
|
-
{ class: 'shadow-inner', css: 'box-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.05);' },
|
|
1542
|
-
{ class: 'shadow-none', css: 'box-shadow: 0 0 #0000;' },
|
|
1543
|
-
{ class: 'shadow-{color}', css: '--tw-shadow-color: {color};' },
|
|
1544
|
-
{ class: 'opacity-{n}', css: 'opacity: {n/100};', desc: '0, 5, 10, 15, 20, 25, 30, ..., 100' },
|
|
1545
|
-
{ class: 'mix-blend-{mode}', css: 'mix-blend-mode: {mode};', desc: 'normal, multiply, screen, overlay, darken, lighten, etc.' },
|
|
1546
|
-
{ class: 'bg-blend-{mode}', css: 'background-blend-mode: {mode};' },
|
|
1547
|
-
],
|
|
1548
|
-
},
|
|
1549
|
-
filters: {
|
|
1550
|
-
desc: 'Filtros CSS',
|
|
1551
|
-
classes: [
|
|
1552
|
-
{ class: 'blur', css: 'filter: blur(8px);' },
|
|
1553
|
-
{ class: 'blur-sm', css: 'filter: blur(4px);' },
|
|
1554
|
-
{ class: 'blur-md', css: 'filter: blur(12px);' },
|
|
1555
|
-
{ class: 'blur-lg', css: 'filter: blur(16px);' },
|
|
1556
|
-
{ class: 'blur-xl', css: 'filter: blur(24px);' },
|
|
1557
|
-
{ class: 'blur-2xl', css: 'filter: blur(40px);' },
|
|
1558
|
-
{ class: 'blur-3xl', css: 'filter: blur(64px);' },
|
|
1559
|
-
{ class: 'blur-none', css: 'filter: blur(0);' },
|
|
1560
|
-
{ class: 'brightness-{n}', css: 'filter: brightness({n/100});', desc: '0, 50, 75, 90, 95, 100, 105, 110, 125, 150, 200' },
|
|
1561
|
-
{ class: 'contrast-{n}', css: 'filter: contrast({n/100});' },
|
|
1562
|
-
{ class: 'grayscale', css: 'filter: grayscale(100%);' },
|
|
1563
|
-
{ class: 'grayscale-0', css: 'filter: grayscale(0);' },
|
|
1564
|
-
{ class: 'hue-rotate-{n}', css: 'filter: hue-rotate({n}deg);', desc: '0, 15, 30, 60, 90, 180' },
|
|
1565
|
-
{ class: 'invert', css: 'filter: invert(100%);' },
|
|
1566
|
-
{ class: 'invert-0', css: 'filter: invert(0);' },
|
|
1567
|
-
{ class: 'saturate-{n}', css: 'filter: saturate({n/100});' },
|
|
1568
|
-
{ class: 'sepia', css: 'filter: sepia(100%);' },
|
|
1569
|
-
{ class: 'sepia-0', css: 'filter: sepia(0);' },
|
|
1570
|
-
{ class: 'backdrop-blur-{n}', css: 'backdrop-filter: blur({value});' },
|
|
1571
|
-
{ class: 'backdrop-brightness-{n}', css: 'backdrop-filter: brightness({n/100});' },
|
|
1572
|
-
{ class: 'backdrop-contrast-{n}', css: 'backdrop-filter: contrast({n/100});' },
|
|
1573
|
-
{ class: 'backdrop-grayscale', css: 'backdrop-filter: grayscale(100%);' },
|
|
1574
|
-
{ class: 'backdrop-invert', css: 'backdrop-filter: invert(100%);' },
|
|
1575
|
-
{ class: 'backdrop-opacity-{n}', css: 'backdrop-filter: opacity({n/100});' },
|
|
1576
|
-
{ class: 'backdrop-saturate-{n}', css: 'backdrop-filter: saturate({n/100});' },
|
|
1577
|
-
{ class: 'backdrop-sepia', css: 'backdrop-filter: sepia(100%);' },
|
|
1578
|
-
],
|
|
1579
|
-
},
|
|
1580
|
-
transitions: {
|
|
1581
|
-
desc: 'Transições e animações',
|
|
1582
|
-
classes: [
|
|
1583
|
-
{ class: 'transition', css: 'transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms;' },
|
|
1584
|
-
{ class: 'transition-none', css: 'transition-property: none;' },
|
|
1585
|
-
{ class: 'transition-all', css: 'transition-property: all;' },
|
|
1586
|
-
{ class: 'transition-colors', css: 'transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;' },
|
|
1587
|
-
{ class: 'transition-opacity', css: 'transition-property: opacity;' },
|
|
1588
|
-
{ class: 'transition-shadow', css: 'transition-property: box-shadow;' },
|
|
1589
|
-
{ class: 'transition-transform', css: 'transition-property: transform;' },
|
|
1590
|
-
{ class: 'duration-{n}', css: 'transition-duration: {n}ms;', desc: '0, 75, 100, 150, 200, 300, 500, 700, 1000' },
|
|
1591
|
-
{ class: 'ease-linear', css: 'transition-timing-function: linear;' },
|
|
1592
|
-
{ class: 'ease-in', css: 'transition-timing-function: cubic-bezier(0.4, 0, 1, 1);' },
|
|
1593
|
-
{ class: 'ease-out', css: 'transition-timing-function: cubic-bezier(0, 0, 0.2, 1);' },
|
|
1594
|
-
{ class: 'ease-in-out', css: 'transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);' },
|
|
1595
|
-
{ class: 'delay-{n}', css: 'transition-delay: {n}ms;' },
|
|
1596
|
-
{ class: 'animate-none', css: 'animation: none;' },
|
|
1597
|
-
{ class: 'animate-spin', css: 'animation: spin 1s linear infinite;' },
|
|
1598
|
-
{ class: 'animate-ping', css: 'animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;' },
|
|
1599
|
-
{ class: 'animate-pulse', css: 'animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;' },
|
|
1600
|
-
{ class: 'animate-bounce', css: 'animation: bounce 1s infinite;' },
|
|
1601
|
-
],
|
|
1602
|
-
},
|
|
1603
|
-
transforms: {
|
|
1604
|
-
desc: 'Transformações CSS',
|
|
1605
|
-
classes: [
|
|
1606
|
-
{ class: 'scale-{n}', css: 'transform: scale({n/100});', desc: '0, 50, 75, 90, 95, 100, 105, 110, 125, 150' },
|
|
1607
|
-
{ class: 'scale-x-{n}', css: 'transform: scaleX({n/100});' },
|
|
1608
|
-
{ class: 'scale-y-{n}', css: 'transform: scaleY({n/100});' },
|
|
1609
|
-
{ class: 'rotate-{n}', css: 'transform: rotate({n}deg);', desc: '0, 1, 2, 3, 6, 12, 45, 90, 180' },
|
|
1610
|
-
{ class: '-rotate-{n}', css: 'transform: rotate(-{n}deg);' },
|
|
1611
|
-
{ class: 'translate-x-{n}', css: 'transform: translateX({value});' },
|
|
1612
|
-
{ class: 'translate-y-{n}', css: 'transform: translateY({value});' },
|
|
1613
|
-
{ class: '-translate-x-{n}', css: 'transform: translateX(-{value});' },
|
|
1614
|
-
{ class: '-translate-y-{n}', css: 'transform: translateY(-{value});' },
|
|
1615
|
-
{ class: 'skew-x-{n}', css: 'transform: skewX({n}deg);', desc: '0, 1, 2, 3, 6, 12' },
|
|
1616
|
-
{ class: 'skew-y-{n}', css: 'transform: skewY({n}deg);' },
|
|
1617
|
-
{ class: 'origin-center', css: 'transform-origin: center;' },
|
|
1618
|
-
{ class: 'origin-top', css: 'transform-origin: top;' },
|
|
1619
|
-
{ class: 'origin-top-right', css: 'transform-origin: top right;' },
|
|
1620
|
-
{ class: 'origin-right', css: 'transform-origin: right;' },
|
|
1621
|
-
{ class: 'origin-bottom-right', css: 'transform-origin: bottom right;' },
|
|
1622
|
-
{ class: 'origin-bottom', css: 'transform-origin: bottom;' },
|
|
1623
|
-
{ class: 'origin-bottom-left', css: 'transform-origin: bottom left;' },
|
|
1624
|
-
{ class: 'origin-left', css: 'transform-origin: left;' },
|
|
1625
|
-
{ class: 'origin-top-left', css: 'transform-origin: top left;' },
|
|
1626
|
-
],
|
|
1627
|
-
},
|
|
1628
|
-
interactivity: {
|
|
1629
|
-
desc: 'Cursor, scroll, resize',
|
|
1630
|
-
classes: [
|
|
1631
|
-
{ class: 'cursor-auto', css: 'cursor: auto;' },
|
|
1632
|
-
{ class: 'cursor-default', css: 'cursor: default;' },
|
|
1633
|
-
{ class: 'cursor-pointer', css: 'cursor: pointer;' },
|
|
1634
|
-
{ class: 'cursor-wait', css: 'cursor: wait;' },
|
|
1635
|
-
{ class: 'cursor-text', css: 'cursor: text;' },
|
|
1636
|
-
{ class: 'cursor-move', css: 'cursor: move;' },
|
|
1637
|
-
{ class: 'cursor-not-allowed', css: 'cursor: not-allowed;' },
|
|
1638
|
-
{ class: 'cursor-grab', css: 'cursor: grab;' },
|
|
1639
|
-
{ class: 'cursor-grabbing', css: 'cursor: grabbing;' },
|
|
1640
|
-
{ class: 'select-none', css: 'user-select: none;' },
|
|
1641
|
-
{ class: 'select-text', css: 'user-select: text;' },
|
|
1642
|
-
{ class: 'select-all', css: 'user-select: all;' },
|
|
1643
|
-
{ class: 'select-auto', css: 'user-select: auto;' },
|
|
1644
|
-
{ class: 'resize-none', css: 'resize: none;' },
|
|
1645
|
-
{ class: 'resize', css: 'resize: both;' },
|
|
1646
|
-
{ class: 'resize-x', css: 'resize: horizontal;' },
|
|
1647
|
-
{ class: 'resize-y', css: 'resize: vertical;' },
|
|
1648
|
-
{ class: 'scroll-auto', css: 'scroll-behavior: auto;' },
|
|
1649
|
-
{ class: 'scroll-smooth', css: 'scroll-behavior: smooth;' },
|
|
1650
|
-
{ class: 'snap-start', css: 'scroll-snap-align: start;' },
|
|
1651
|
-
{ class: 'snap-end', css: 'scroll-snap-align: end;' },
|
|
1652
|
-
{ class: 'snap-center', css: 'scroll-snap-align: center;' },
|
|
1653
|
-
{ class: 'snap-none', css: 'scroll-snap-type: none;' },
|
|
1654
|
-
{ class: 'snap-x', css: 'scroll-snap-type: x var(--tw-scroll-snap-strictness);' },
|
|
1655
|
-
{ class: 'snap-y', css: 'scroll-snap-type: y var(--tw-scroll-snap-strictness);' },
|
|
1656
|
-
{ class: 'snap-mandatory', css: '--tw-scroll-snap-strictness: mandatory;' },
|
|
1657
|
-
{ class: 'snap-proximity', css: '--tw-scroll-snap-strictness: proximity;' },
|
|
1658
|
-
{ class: 'touch-auto', css: 'touch-action: auto;' },
|
|
1659
|
-
{ class: 'touch-none', css: 'touch-action: none;' },
|
|
1660
|
-
{ class: 'touch-manipulation', css: 'touch-action: manipulation;' },
|
|
1661
|
-
{ class: 'pointer-events-none', css: 'pointer-events: none;' },
|
|
1662
|
-
{ class: 'pointer-events-auto', css: 'pointer-events: auto;' },
|
|
1663
|
-
],
|
|
1664
|
-
},
|
|
1665
|
-
svg: {
|
|
1666
|
-
desc: 'SVG fill e stroke',
|
|
1667
|
-
classes: [
|
|
1668
|
-
{ class: 'fill-none', css: 'fill: none;' },
|
|
1669
|
-
{ class: 'fill-inherit', css: 'fill: inherit;' },
|
|
1670
|
-
{ class: 'fill-current', css: 'fill: currentColor;' },
|
|
1671
|
-
{ class: 'fill-transparent', css: 'fill: transparent;' },
|
|
1672
|
-
{ class: 'fill-{color}', css: 'fill: {color};' },
|
|
1673
|
-
{ class: 'stroke-none', css: 'stroke: none;' },
|
|
1674
|
-
{ class: 'stroke-inherit', css: 'stroke: inherit;' },
|
|
1675
|
-
{ class: 'stroke-current', css: 'stroke: currentColor;' },
|
|
1676
|
-
{ class: 'stroke-transparent', css: 'stroke: transparent;' },
|
|
1677
|
-
{ class: 'stroke-{color}', css: 'stroke: {color};' },
|
|
1678
|
-
{ class: 'stroke-{n}', css: 'stroke-width: {n};', desc: '0, 1, 2' },
|
|
1679
|
-
],
|
|
1680
|
-
},
|
|
1681
|
-
tables: {
|
|
1682
|
-
desc: 'Tabelas',
|
|
1683
|
-
classes: [
|
|
1684
|
-
{ class: 'border-collapse', css: 'border-collapse: collapse;' },
|
|
1685
|
-
{ class: 'border-separate', css: 'border-collapse: separate;' },
|
|
1686
|
-
{ class: 'border-spacing-{n}', css: 'border-spacing: {value};' },
|
|
1687
|
-
{ class: 'border-spacing-x-{n}', css: 'border-spacing: {value} 0;' },
|
|
1688
|
-
{ class: 'border-spacing-y-{n}', css: 'border-spacing: 0 {value};' },
|
|
1689
|
-
{ class: 'table-auto', css: 'table-layout: auto;' },
|
|
1690
|
-
{ class: 'table-fixed', css: 'table-layout: fixed;' },
|
|
1691
|
-
{ class: 'caption-top', css: 'caption-side: top;' },
|
|
1692
|
-
{ class: 'caption-bottom', css: 'caption-side: bottom;' },
|
|
1693
|
-
],
|
|
1694
|
-
},
|
|
1695
|
-
accessibility: {
|
|
1696
|
-
desc: 'Acessibilidade',
|
|
1697
|
-
classes: [
|
|
1698
|
-
{ class: 'sr-only', css: 'position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border-width: 0;' },
|
|
1699
|
-
{ class: 'not-sr-only', css: 'position: static; width: auto; height: auto; padding: 0; margin: 0; overflow: visible; clip: auto; white-space: normal;' },
|
|
1700
|
-
{ class: 'forced-color-adjust-auto', css: 'forced-color-adjust: auto;' },
|
|
1701
|
-
{ class: 'forced-color-adjust-none', css: 'forced-color-adjust: none;' },
|
|
1702
|
-
],
|
|
1703
|
-
},
|
|
1704
|
-
};
|
|
1705
|
-
if (!categoria) {
|
|
1706
|
-
let result = '# 📚 Categorias de Utilities do Tailwind CSS\n\n';
|
|
1707
|
-
result += 'Use `tailwind_utilities` com uma categoria específica para ver as classes.\n\n';
|
|
1708
|
-
result += '| Categoria | Descrição | Classes |\n';
|
|
1709
|
-
result += '|-----------|-----------|--------|\n';
|
|
1710
|
-
for (const [key, value] of Object.entries(utilities)) {
|
|
1711
|
-
result += `| \`${key}\` | ${value.desc} | ${value.classes.length} |\n`;
|
|
1712
|
-
}
|
|
1713
|
-
result += '\n**Exemplo:** `tailwind_utilities({ categoria: "flexbox" })`\n';
|
|
1714
|
-
return { content: [{ type: 'text', text: result }] };
|
|
1715
|
-
}
|
|
1716
|
-
const cat = utilities[categoria];
|
|
1717
|
-
if (!cat) {
|
|
1718
|
-
return {
|
|
1719
|
-
content: [{ type: 'text', text: `❌ Categoria não encontrada: ${categoria}\n\nCategorias disponíveis: ${Object.keys(utilities).join(', ')}` }],
|
|
1720
|
-
isError: true,
|
|
1721
|
-
};
|
|
1722
|
-
}
|
|
1723
|
-
let result = `# 🎨 Utilities: ${categoria}\n\n`;
|
|
1724
|
-
result += `**${cat.desc}**\n\n`;
|
|
1725
|
-
result += '| Classe | CSS Gerado | Notas |\n';
|
|
1726
|
-
result += '|--------|------------|-------|\n';
|
|
1727
|
-
for (const u of cat.classes) {
|
|
1728
|
-
const notes = u.desc || '-';
|
|
1729
|
-
result += `| \`${u.class}\` | \`${u.css}\` | ${notes} |\n`;
|
|
1730
|
-
}
|
|
1731
|
-
result += `\n**Total:** ${cat.classes.length} classes\n`;
|
|
1732
|
-
return { content: [{ type: 'text', text: result }] };
|
|
1733
|
-
}
|
|
1734
|
-
case 'tailwind_variants': {
|
|
1735
|
-
const tipo = args?.tipo;
|
|
1736
|
-
const variants = {
|
|
1737
|
-
'pseudo-classes': {
|
|
1738
|
-
desc: 'Estados interativos e de formulário',
|
|
1739
|
-
items: [
|
|
1740
|
-
{ variant: 'hover', desc: 'Mouse sobre o elemento', example: 'hover:bg-blue-500' },
|
|
1741
|
-
{ variant: 'focus', desc: 'Elemento focado', example: 'focus:ring-2' },
|
|
1742
|
-
{ variant: 'focus-within', desc: 'Filho tem foco', example: 'focus-within:border-blue-500' },
|
|
1743
|
-
{ variant: 'focus-visible', desc: 'Foco visível (teclado)', example: 'focus-visible:outline-2' },
|
|
1744
|
-
{ variant: 'active', desc: 'Clique ativo', example: 'active:bg-blue-700' },
|
|
1745
|
-
{ variant: 'visited', desc: 'Link visitado', example: 'visited:text-purple-500' },
|
|
1746
|
-
{ variant: 'target', desc: 'Alvo de âncora', example: 'target:bg-yellow-200' },
|
|
1747
|
-
{ variant: 'first', desc: 'Primeiro filho', example: 'first:mt-0' },
|
|
1748
|
-
{ variant: 'last', desc: 'Último filho', example: 'last:mb-0' },
|
|
1749
|
-
{ variant: 'only', desc: 'Filho único', example: 'only:mx-auto' },
|
|
1750
|
-
{ variant: 'odd', desc: 'Filhos ímpares', example: 'odd:bg-gray-100' },
|
|
1751
|
-
{ variant: 'even', desc: 'Filhos pares', example: 'even:bg-gray-50' },
|
|
1752
|
-
{ variant: 'first-of-type', desc: 'Primeiro do tipo', example: 'first-of-type:pt-0' },
|
|
1753
|
-
{ variant: 'last-of-type', desc: 'Último do tipo', example: 'last-of-type:pb-0' },
|
|
1754
|
-
{ variant: 'only-of-type', desc: 'Único do tipo', example: 'only-of-type:mx-auto' },
|
|
1755
|
-
{ variant: 'empty', desc: 'Sem filhos', example: 'empty:hidden' },
|
|
1756
|
-
{ variant: 'enabled', desc: 'Input habilitado', example: 'enabled:cursor-pointer' },
|
|
1757
|
-
{ variant: 'disabled', desc: 'Input desabilitado', example: 'disabled:opacity-50' },
|
|
1758
|
-
{ variant: 'checked', desc: 'Checkbox/radio marcado', example: 'checked:bg-blue-500' },
|
|
1759
|
-
{ variant: 'indeterminate', desc: 'Estado indeterminado', example: 'indeterminate:bg-gray-300' },
|
|
1760
|
-
{ variant: 'default', desc: 'Opção padrão', example: 'default:ring-2' },
|
|
1761
|
-
{ variant: 'required', desc: 'Campo obrigatório', example: 'required:border-red-500' },
|
|
1762
|
-
{ variant: 'valid', desc: 'Input válido', example: 'valid:border-green-500' },
|
|
1763
|
-
{ variant: 'invalid', desc: 'Input inválido', example: 'invalid:border-red-500' },
|
|
1764
|
-
{ variant: 'in-range', desc: 'Valor no range', example: 'in-range:border-green-500' },
|
|
1765
|
-
{ variant: 'out-of-range', desc: 'Valor fora do range', example: 'out-of-range:border-red-500' },
|
|
1766
|
-
{ variant: 'placeholder-shown', desc: 'Placeholder visível', example: 'placeholder-shown:border-gray-300' },
|
|
1767
|
-
{ variant: 'autofill', desc: 'Preenchido pelo browser', example: 'autofill:bg-yellow-100' },
|
|
1768
|
-
{ variant: 'read-only', desc: 'Campo somente leitura', example: 'read-only:bg-gray-100' },
|
|
1769
|
-
],
|
|
1770
|
-
},
|
|
1771
|
-
'pseudo-elements': {
|
|
1772
|
-
desc: 'Pseudo-elementos CSS',
|
|
1773
|
-
items: [
|
|
1774
|
-
{ variant: 'before', desc: 'Pseudo-elemento ::before', example: 'before:content-[""] before:absolute' },
|
|
1775
|
-
{ variant: 'after', desc: 'Pseudo-elemento ::after', example: 'after:content-["✓"] after:ml-2' },
|
|
1776
|
-
{ variant: 'placeholder', desc: 'Texto do placeholder', example: 'placeholder:text-gray-400' },
|
|
1777
|
-
{ variant: 'file', desc: 'Botão de input file', example: 'file:bg-blue-500 file:text-white' },
|
|
1778
|
-
{ variant: 'marker', desc: 'Marcador de lista', example: 'marker:text-blue-500' },
|
|
1779
|
-
{ variant: 'selection', desc: 'Texto selecionado', example: 'selection:bg-blue-200' },
|
|
1780
|
-
{ variant: 'first-line', desc: 'Primeira linha', example: 'first-line:font-bold' },
|
|
1781
|
-
{ variant: 'first-letter', desc: 'Primeira letra', example: 'first-letter:text-4xl' },
|
|
1782
|
-
{ variant: 'backdrop', desc: 'Backdrop de dialog', example: 'backdrop:bg-black/50' },
|
|
1783
|
-
],
|
|
1784
|
-
},
|
|
1785
|
-
responsive: {
|
|
1786
|
-
desc: 'Breakpoints responsivos (mobile-first)',
|
|
1787
|
-
items: [
|
|
1788
|
-
{ variant: 'sm', desc: '≥640px', example: 'sm:flex sm:flex-row' },
|
|
1789
|
-
{ variant: 'md', desc: '≥768px', example: 'md:grid md:grid-cols-2' },
|
|
1790
|
-
{ variant: 'lg', desc: '≥1024px', example: 'lg:grid-cols-3' },
|
|
1791
|
-
{ variant: 'xl', desc: '≥1280px', example: 'xl:grid-cols-4' },
|
|
1792
|
-
{ variant: '2xl', desc: '≥1536px', example: '2xl:max-w-7xl' },
|
|
1793
|
-
{ variant: 'min-[{n}px]', desc: 'Breakpoint customizado', example: 'min-[320px]:text-sm' },
|
|
1794
|
-
{ variant: 'max-sm', desc: '<640px', example: 'max-sm:hidden' },
|
|
1795
|
-
{ variant: 'max-md', desc: '<768px', example: 'max-md:flex-col' },
|
|
1796
|
-
{ variant: 'max-lg', desc: '<1024px', example: 'max-lg:px-4' },
|
|
1797
|
-
{ variant: 'max-xl', desc: '<1280px', example: 'max-xl:grid-cols-2' },
|
|
1798
|
-
{ variant: 'max-2xl', desc: '<1536px', example: 'max-2xl:container' },
|
|
1799
|
-
{ variant: 'max-[{n}px]', desc: 'Max breakpoint custom', example: 'max-[600px]:text-xs' },
|
|
1800
|
-
{ variant: '@sm', desc: 'Container query ≥320px', example: '@sm:flex' },
|
|
1801
|
-
{ variant: '@md', desc: 'Container query ≥384px', example: '@md:grid-cols-2' },
|
|
1802
|
-
{ variant: '@lg', desc: 'Container query ≥512px', example: '@lg:p-6' },
|
|
1803
|
-
{ variant: '@xl', desc: 'Container query ≥672px', example: '@xl:text-lg' },
|
|
1804
|
-
{ variant: '@[{n}px]', desc: 'Container query custom', example: '@[400px]:flex-row' },
|
|
1805
|
-
],
|
|
1806
|
-
},
|
|
1807
|
-
'dark-mode': {
|
|
1808
|
-
desc: 'Modo escuro e preferências de mídia',
|
|
1809
|
-
items: [
|
|
1810
|
-
{ variant: 'dark', desc: 'Modo escuro', example: 'dark:bg-gray-900 dark:text-white' },
|
|
1811
|
-
{ variant: 'motion-safe', desc: 'Animações permitidas', example: 'motion-safe:animate-bounce' },
|
|
1812
|
-
{ variant: 'motion-reduce', desc: 'Animações reduzidas', example: 'motion-reduce:animate-none' },
|
|
1813
|
-
{ variant: 'contrast-more', desc: 'Alto contraste', example: 'contrast-more:border-2' },
|
|
1814
|
-
{ variant: 'contrast-less', desc: 'Baixo contraste', example: 'contrast-less:opacity-80' },
|
|
1815
|
-
{ variant: 'print', desc: 'Impressão', example: 'print:hidden print:text-black' },
|
|
1816
|
-
{ variant: 'portrait', desc: 'Orientação retrato', example: 'portrait:flex-col' },
|
|
1817
|
-
{ variant: 'landscape', desc: 'Orientação paisagem', example: 'landscape:flex-row' },
|
|
1818
|
-
],
|
|
1819
|
-
},
|
|
1820
|
-
state: {
|
|
1821
|
-
desc: 'Estados especiais',
|
|
1822
|
-
items: [
|
|
1823
|
-
{ variant: 'open', desc: 'Elemento open (details, dialog)', example: 'open:bg-white open:shadow-lg' },
|
|
1824
|
-
{ variant: 'closed', desc: 'Elemento fechado', example: 'closed:opacity-0' },
|
|
1825
|
-
{ variant: 'modal', desc: 'Dialog modal', example: 'modal:backdrop:bg-black/50' },
|
|
1826
|
-
{ variant: 'fullscreen', desc: 'Modo fullscreen', example: 'fullscreen:p-0' },
|
|
1827
|
-
{ variant: 'starting', desc: 'Estado inicial (v4)', example: 'starting:opacity-0' },
|
|
1828
|
-
{ variant: 'inert', desc: 'Elemento inert', example: 'inert:opacity-50' },
|
|
1829
|
-
],
|
|
1830
|
-
},
|
|
1831
|
-
compound: {
|
|
1832
|
-
desc: 'Variants compostos (group, peer, has)',
|
|
1833
|
-
items: [
|
|
1834
|
-
{ variant: 'group-hover', desc: 'Hover no elemento pai .group', example: 'group-hover:text-blue-500' },
|
|
1835
|
-
{ variant: 'group-focus', desc: 'Focus no elemento pai .group', example: 'group-focus:ring-2' },
|
|
1836
|
-
{ variant: 'group-active', desc: 'Active no elemento pai .group', example: 'group-active:scale-95' },
|
|
1837
|
-
{ variant: 'group-[.custom]', desc: 'Seletor custom no group', example: 'group-[.is-open]:block' },
|
|
1838
|
-
{ variant: 'peer-hover', desc: 'Hover no irmão .peer', example: 'peer-hover:visible' },
|
|
1839
|
-
{ variant: 'peer-focus', desc: 'Focus no irmão .peer', example: 'peer-focus:ring-2' },
|
|
1840
|
-
{ variant: 'peer-checked', desc: 'Peer checkbox marcado', example: 'peer-checked:bg-blue-500' },
|
|
1841
|
-
{ variant: 'peer-invalid', desc: 'Peer input inválido', example: 'peer-invalid:text-red-500' },
|
|
1842
|
-
{ variant: 'peer-[.custom]', desc: 'Seletor custom no peer', example: 'peer-[.is-active]:font-bold' },
|
|
1843
|
-
{ variant: 'has-[selector]', desc: 'Contém elemento (v4)', example: 'has-[input:focus]:ring-2' },
|
|
1844
|
-
{ variant: 'has-checked', desc: 'Contém checkbox marcado', example: 'has-checked:bg-blue-100' },
|
|
1845
|
-
{ variant: 'in-[selector]', desc: 'Está dentro de (v4)', example: 'in-[.dark]:text-white' },
|
|
1846
|
-
{ variant: 'not-[selector]', desc: 'Negação (v4)', example: 'not-[.active]:opacity-50' },
|
|
1847
|
-
],
|
|
1848
|
-
},
|
|
1849
|
-
aria: {
|
|
1850
|
-
desc: 'Atributos ARIA para acessibilidade',
|
|
1851
|
-
items: [
|
|
1852
|
-
{ variant: 'aria-checked', desc: 'aria-checked="true"', example: 'aria-checked:bg-blue-500' },
|
|
1853
|
-
{ variant: 'aria-disabled', desc: 'aria-disabled="true"', example: 'aria-disabled:opacity-50' },
|
|
1854
|
-
{ variant: 'aria-expanded', desc: 'aria-expanded="true"', example: 'aria-expanded:rotate-180' },
|
|
1855
|
-
{ variant: 'aria-hidden', desc: 'aria-hidden="true"', example: 'aria-hidden:invisible' },
|
|
1856
|
-
{ variant: 'aria-pressed', desc: 'aria-pressed="true"', example: 'aria-pressed:bg-gray-700' },
|
|
1857
|
-
{ variant: 'aria-selected', desc: 'aria-selected="true"', example: 'aria-selected:border-blue-500' },
|
|
1858
|
-
{ variant: 'aria-required', desc: 'aria-required="true"', example: 'aria-required:border-red-500' },
|
|
1859
|
-
{ variant: 'aria-invalid', desc: 'aria-invalid="true"', example: 'aria-invalid:border-red-500' },
|
|
1860
|
-
{ variant: 'aria-busy', desc: 'aria-busy="true"', example: 'aria-busy:animate-pulse' },
|
|
1861
|
-
{ variant: 'aria-[attr=value]', desc: 'ARIA customizado', example: 'aria-[current=page]:font-bold' },
|
|
1862
|
-
],
|
|
1863
|
-
},
|
|
1864
|
-
data: {
|
|
1865
|
-
desc: 'Atributos data-*',
|
|
1866
|
-
items: [
|
|
1867
|
-
{ variant: 'data-[state=open]', desc: 'data-state="open"', example: 'data-[state=open]:bg-white' },
|
|
1868
|
-
{ variant: 'data-[state=closed]', desc: 'data-state="closed"', example: 'data-[state=closed]:hidden' },
|
|
1869
|
-
{ variant: 'data-[active]', desc: 'data-active presente', example: 'data-[active]:font-bold' },
|
|
1870
|
-
{ variant: 'data-[disabled]', desc: 'data-disabled presente', example: 'data-[disabled]:opacity-50' },
|
|
1871
|
-
{ variant: 'data-[selected=true]', desc: 'data-selected="true"', example: 'data-[selected=true]:bg-blue-100' },
|
|
1872
|
-
{ variant: 'data-[orientation=vertical]', desc: 'Orientação vertical', example: 'data-[orientation=vertical]:flex-col' },
|
|
1873
|
-
{ variant: 'data-[side=left]', desc: 'Posição lado', example: 'data-[side=left]:mr-2' },
|
|
1874
|
-
],
|
|
1875
|
-
},
|
|
1876
|
-
};
|
|
1877
|
-
if (!tipo) {
|
|
1878
|
-
let result = '# 🎯 Variants do Tailwind CSS\n\n';
|
|
1879
|
-
result += 'Variants são modificadores que aplicam estilos condicionalmente.\n\n';
|
|
1880
|
-
result += '**Sintaxe:** `variant:classe` → `hover:bg-blue-500`\n\n';
|
|
1881
|
-
result += '**Empilhamento:** `variant1:variant2:classe` → `dark:hover:bg-blue-600`\n\n';
|
|
1882
|
-
result += '| Tipo | Descrição | Variants |\n';
|
|
1883
|
-
result += '|------|-----------|----------|\n';
|
|
1884
|
-
for (const [key, value] of Object.entries(variants)) {
|
|
1885
|
-
result += `| \`${key}\` | ${value.desc} | ${value.items.length} |\n`;
|
|
1886
|
-
}
|
|
1887
|
-
result += '\n**Exemplo:** `tailwind_variants({ tipo: "responsive" })`\n';
|
|
1888
|
-
return { content: [{ type: 'text', text: result }] };
|
|
1889
|
-
}
|
|
1890
|
-
const varType = variants[tipo];
|
|
1891
|
-
if (!varType) {
|
|
1892
|
-
return {
|
|
1893
|
-
content: [{ type: 'text', text: `❌ Tipo não encontrado: ${tipo}\n\nTipos disponíveis: ${Object.keys(variants).join(', ')}` }],
|
|
1894
|
-
isError: true,
|
|
1895
|
-
};
|
|
1896
|
-
}
|
|
1897
|
-
let result = `# 🎯 Variants: ${tipo}\n\n`;
|
|
1898
|
-
result += `**${varType.desc}**\n\n`;
|
|
1899
|
-
result += '| Variant | Descrição | Exemplo |\n';
|
|
1900
|
-
result += '|---------|-----------|----------|\n';
|
|
1901
|
-
for (const v of varType.items) {
|
|
1902
|
-
result += `| \`${v.variant}:\` | ${v.desc} | \`${v.example}\` |\n`;
|
|
1903
|
-
}
|
|
1904
|
-
result += `\n**Total:** ${varType.items.length} variants\n`;
|
|
1905
|
-
return { content: [{ type: 'text', text: result }] };
|
|
1906
|
-
}
|
|
1907
|
-
case 'tailwind_cores': {
|
|
1908
|
-
const corArg = args?.cor;
|
|
1909
|
-
const colors = {
|
|
1910
|
-
slate: { '50': '#f8fafc', '100': '#f1f5f9', '200': '#e2e8f0', '300': '#cbd5e1', '400': '#94a3b8', '500': '#64748b', '600': '#475569', '700': '#334155', '800': '#1e293b', '900': '#0f172a', '950': '#020617' },
|
|
1911
|
-
gray: { '50': '#f9fafb', '100': '#f3f4f6', '200': '#e5e7eb', '300': '#d1d5db', '400': '#9ca3af', '500': '#6b7280', '600': '#4b5563', '700': '#374151', '800': '#1f2937', '900': '#111827', '950': '#030712' },
|
|
1912
|
-
zinc: { '50': '#fafafa', '100': '#f4f4f5', '200': '#e4e4e7', '300': '#d4d4d8', '400': '#a1a1aa', '500': '#71717a', '600': '#52525b', '700': '#3f3f46', '800': '#27272a', '900': '#18181b', '950': '#09090b' },
|
|
1913
|
-
neutral: { '50': '#fafafa', '100': '#f5f5f5', '200': '#e5e5e5', '300': '#d4d4d4', '400': '#a3a3a3', '500': '#737373', '600': '#525252', '700': '#404040', '800': '#262626', '900': '#171717', '950': '#0a0a0a' },
|
|
1914
|
-
stone: { '50': '#fafaf9', '100': '#f5f5f4', '200': '#e7e5e4', '300': '#d6d3d1', '400': '#a8a29e', '500': '#78716c', '600': '#57534e', '700': '#44403c', '800': '#292524', '900': '#1c1917', '950': '#0c0a09' },
|
|
1915
|
-
red: { '50': '#fef2f2', '100': '#fee2e2', '200': '#fecaca', '300': '#fca5a5', '400': '#f87171', '500': '#ef4444', '600': '#dc2626', '700': '#b91c1c', '800': '#991b1b', '900': '#7f1d1d', '950': '#450a0a' },
|
|
1916
|
-
orange: { '50': '#fff7ed', '100': '#ffedd5', '200': '#fed7aa', '300': '#fdba74', '400': '#fb923c', '500': '#f97316', '600': '#ea580c', '700': '#c2410c', '800': '#9a3412', '900': '#7c2d12', '950': '#431407' },
|
|
1917
|
-
amber: { '50': '#fffbeb', '100': '#fef3c7', '200': '#fde68a', '300': '#fcd34d', '400': '#fbbf24', '500': '#f59e0b', '600': '#d97706', '700': '#b45309', '800': '#92400e', '900': '#78350f', '950': '#451a03' },
|
|
1918
|
-
yellow: { '50': '#fefce8', '100': '#fef9c3', '200': '#fef08a', '300': '#fde047', '400': '#facc15', '500': '#eab308', '600': '#ca8a04', '700': '#a16207', '800': '#854d0e', '900': '#713f12', '950': '#422006' },
|
|
1919
|
-
lime: { '50': '#f7fee7', '100': '#ecfccb', '200': '#d9f99d', '300': '#bef264', '400': '#a3e635', '500': '#84cc16', '600': '#65a30d', '700': '#4d7c0f', '800': '#3f6212', '900': '#365314', '950': '#1a2e05' },
|
|
1920
|
-
green: { '50': '#f0fdf4', '100': '#dcfce7', '200': '#bbf7d0', '300': '#86efac', '400': '#4ade80', '500': '#22c55e', '600': '#16a34a', '700': '#15803d', '800': '#166534', '900': '#14532d', '950': '#052e16' },
|
|
1921
|
-
emerald: { '50': '#ecfdf5', '100': '#d1fae5', '200': '#a7f3d0', '300': '#6ee7b7', '400': '#34d399', '500': '#10b981', '600': '#059669', '700': '#047857', '800': '#065f46', '900': '#064e3b', '950': '#022c22' },
|
|
1922
|
-
teal: { '50': '#f0fdfa', '100': '#ccfbf1', '200': '#99f6e4', '300': '#5eead4', '400': '#2dd4bf', '500': '#14b8a6', '600': '#0d9488', '700': '#0f766e', '800': '#115e59', '900': '#134e4a', '950': '#042f2e' },
|
|
1923
|
-
cyan: { '50': '#ecfeff', '100': '#cffafe', '200': '#a5f3fc', '300': '#67e8f9', '400': '#22d3ee', '500': '#06b6d4', '600': '#0891b2', '700': '#0e7490', '800': '#155e75', '900': '#164e63', '950': '#083344' },
|
|
1924
|
-
sky: { '50': '#f0f9ff', '100': '#e0f2fe', '200': '#bae6fd', '300': '#7dd3fc', '400': '#38bdf8', '500': '#0ea5e9', '600': '#0284c7', '700': '#0369a1', '800': '#075985', '900': '#0c4a6e', '950': '#082f49' },
|
|
1925
|
-
blue: { '50': '#eff6ff', '100': '#dbeafe', '200': '#bfdbfe', '300': '#93c5fd', '400': '#60a5fa', '500': '#3b82f6', '600': '#2563eb', '700': '#1d4ed8', '800': '#1e40af', '900': '#1e3a8a', '950': '#172554' },
|
|
1926
|
-
indigo: { '50': '#eef2ff', '100': '#e0e7ff', '200': '#c7d2fe', '300': '#a5b4fc', '400': '#818cf8', '500': '#6366f1', '600': '#4f46e5', '700': '#4338ca', '800': '#3730a3', '900': '#312e81', '950': '#1e1b4b' },
|
|
1927
|
-
violet: { '50': '#f5f3ff', '100': '#ede9fe', '200': '#ddd6fe', '300': '#c4b5fd', '400': '#a78bfa', '500': '#8b5cf6', '600': '#7c3aed', '700': '#6d28d9', '800': '#5b21b6', '900': '#4c1d95', '950': '#2e1065' },
|
|
1928
|
-
purple: { '50': '#faf5ff', '100': '#f3e8ff', '200': '#e9d5ff', '300': '#d8b4fe', '400': '#c084fc', '500': '#a855f7', '600': '#9333ea', '700': '#7e22ce', '800': '#6b21a8', '900': '#581c87', '950': '#3b0764' },
|
|
1929
|
-
fuchsia: { '50': '#fdf4ff', '100': '#fae8ff', '200': '#f5d0fe', '300': '#f0abfc', '400': '#e879f9', '500': '#d946ef', '600': '#c026d3', '700': '#a21caf', '800': '#86198f', '900': '#701a75', '950': '#4a044e' },
|
|
1930
|
-
pink: { '50': '#fdf2f8', '100': '#fce7f3', '200': '#fbcfe8', '300': '#f9a8d4', '400': '#f472b6', '500': '#ec4899', '600': '#db2777', '700': '#be185d', '800': '#9d174d', '900': '#831843', '950': '#500724' },
|
|
1931
|
-
rose: { '50': '#fff1f2', '100': '#ffe4e6', '200': '#fecdd3', '300': '#fda4af', '400': '#fb7185', '500': '#f43f5e', '600': '#e11d48', '700': '#be123c', '800': '#9f1239', '900': '#881337', '950': '#4c0519' },
|
|
1932
|
-
};
|
|
1933
|
-
const specialColors = {
|
|
1934
|
-
inherit: 'Herda do pai',
|
|
1935
|
-
current: 'currentColor',
|
|
1936
|
-
transparent: 'transparent',
|
|
1937
|
-
black: '#000000',
|
|
1938
|
-
white: '#ffffff',
|
|
1939
|
-
};
|
|
1940
|
-
if (!corArg) {
|
|
1941
|
-
let result = '# 🎨 Paleta de Cores do Tailwind CSS\n\n';
|
|
1942
|
-
result += '## Cores Especiais\n\n';
|
|
1943
|
-
result += '| Classe | Valor |\n';
|
|
1944
|
-
result += '|--------|-------|\n';
|
|
1945
|
-
for (const [name, value] of Object.entries(specialColors)) {
|
|
1946
|
-
result += `| \`{type}-${name}\` | ${value} |\n`;
|
|
1947
|
-
}
|
|
1948
|
-
result += '\n## Paleta Completa\n\n';
|
|
1949
|
-
result += 'Use `tailwind_cores({ cor: "blue" })` para ver uma cor específica.\n\n';
|
|
1950
|
-
result += '| Cor | Preview (500) | Escalas |\n';
|
|
1951
|
-
result += '|-----|---------------|--------|\n';
|
|
1952
|
-
for (const [name, shades] of Object.entries(colors)) {
|
|
1953
|
-
result += `| \`${name}\` | ${shades['500']} | 50-950 |\n`;
|
|
1954
|
-
}
|
|
1955
|
-
result += '\n**Uso:** `text-{cor}-{escala}`, `bg-{cor}-{escala}`, `border-{cor}-{escala}`\n';
|
|
1956
|
-
result += '\n**Exemplo:** `bg-blue-500`, `text-gray-900`, `border-red-300`\n';
|
|
1957
|
-
return { content: [{ type: 'text', text: result }] };
|
|
1958
|
-
}
|
|
1959
|
-
const colorShades = colors[corArg];
|
|
1960
|
-
if (!colorShades) {
|
|
1961
|
-
return {
|
|
1962
|
-
content: [{ type: 'text', text: `❌ Cor não encontrada: ${corArg}\n\nCores disponíveis: ${Object.keys(colors).join(', ')}` }],
|
|
1963
|
-
isError: true,
|
|
1964
|
-
};
|
|
1965
|
-
}
|
|
1966
|
-
let result = `# 🎨 Cor: ${corArg}\n\n`;
|
|
1967
|
-
result += '| Escala | Hex | Classes |\n';
|
|
1968
|
-
result += '|--------|-----|--------|\n';
|
|
1969
|
-
for (const [shade, hex] of Object.entries(colorShades)) {
|
|
1970
|
-
result += `| ${shade} | ${hex} | \`text-${corArg}-${shade}\` \`bg-${corArg}-${shade}\` \`border-${corArg}-${shade}\` |\n`;
|
|
1971
|
-
}
|
|
1972
|
-
result += `\n**Exemplos de uso:**\n`;
|
|
1973
|
-
result += '```html\n';
|
|
1974
|
-
result += `<div class="bg-${corArg}-500 text-white">Background</div>\n`;
|
|
1975
|
-
result += `<p class="text-${corArg}-700">Texto</p>\n`;
|
|
1976
|
-
result += `<div class="border border-${corArg}-300">Border</div>\n`;
|
|
1977
|
-
result += `<div class="ring-2 ring-${corArg}-500">Ring</div>\n`;
|
|
1978
|
-
result += '```\n';
|
|
1979
|
-
return { content: [{ type: 'text', text: result }] };
|
|
1980
|
-
}
|
|
1981
|
-
case 'tailwind_spacing': {
|
|
1982
|
-
const spacing = [
|
|
1983
|
-
{ key: '0', rem: '0', px: '0px' },
|
|
1984
|
-
{ key: 'px', rem: '1px', px: '1px' },
|
|
1985
|
-
{ key: '0.5', rem: '0.125rem', px: '2px' },
|
|
1986
|
-
{ key: '1', rem: '0.25rem', px: '4px' },
|
|
1987
|
-
{ key: '1.5', rem: '0.375rem', px: '6px' },
|
|
1988
|
-
{ key: '2', rem: '0.5rem', px: '8px' },
|
|
1989
|
-
{ key: '2.5', rem: '0.625rem', px: '10px' },
|
|
1990
|
-
{ key: '3', rem: '0.75rem', px: '12px' },
|
|
1991
|
-
{ key: '3.5', rem: '0.875rem', px: '14px' },
|
|
1992
|
-
{ key: '4', rem: '1rem', px: '16px' },
|
|
1993
|
-
{ key: '5', rem: '1.25rem', px: '20px' },
|
|
1994
|
-
{ key: '6', rem: '1.5rem', px: '24px' },
|
|
1995
|
-
{ key: '7', rem: '1.75rem', px: '28px' },
|
|
1996
|
-
{ key: '8', rem: '2rem', px: '32px' },
|
|
1997
|
-
{ key: '9', rem: '2.25rem', px: '36px' },
|
|
1998
|
-
{ key: '10', rem: '2.5rem', px: '40px' },
|
|
1999
|
-
{ key: '11', rem: '2.75rem', px: '44px' },
|
|
2000
|
-
{ key: '12', rem: '3rem', px: '48px' },
|
|
2001
|
-
{ key: '14', rem: '3.5rem', px: '56px' },
|
|
2002
|
-
{ key: '16', rem: '4rem', px: '64px' },
|
|
2003
|
-
{ key: '20', rem: '5rem', px: '80px' },
|
|
2004
|
-
{ key: '24', rem: '6rem', px: '96px' },
|
|
2005
|
-
{ key: '28', rem: '7rem', px: '112px' },
|
|
2006
|
-
{ key: '32', rem: '8rem', px: '128px' },
|
|
2007
|
-
{ key: '36', rem: '9rem', px: '144px' },
|
|
2008
|
-
{ key: '40', rem: '10rem', px: '160px' },
|
|
2009
|
-
{ key: '44', rem: '11rem', px: '176px' },
|
|
2010
|
-
{ key: '48', rem: '12rem', px: '192px' },
|
|
2011
|
-
{ key: '52', rem: '13rem', px: '208px' },
|
|
2012
|
-
{ key: '56', rem: '14rem', px: '224px' },
|
|
2013
|
-
{ key: '60', rem: '15rem', px: '240px' },
|
|
2014
|
-
{ key: '64', rem: '16rem', px: '256px' },
|
|
2015
|
-
{ key: '72', rem: '18rem', px: '288px' },
|
|
2016
|
-
{ key: '80', rem: '20rem', px: '320px' },
|
|
2017
|
-
{ key: '96', rem: '24rem', px: '384px' },
|
|
2018
|
-
];
|
|
2019
|
-
let result = '# 📏 Escala de Espaçamento do Tailwind CSS\n\n';
|
|
2020
|
-
result += 'A escala de spacing é usada para margin, padding, gap, width, height, e outras propriedades.\n\n';
|
|
2021
|
-
result += '| Valor | Rem | Pixels | Exemplo Classes |\n';
|
|
2022
|
-
result += '|-------|-----|--------|----------------|\n';
|
|
2023
|
-
for (const s of spacing) {
|
|
2024
|
-
result += `| \`${s.key}\` | ${s.rem} | ${s.px} | \`p-${s.key}\` \`m-${s.key}\` \`gap-${s.key}\` \`w-${s.key}\` |\n`;
|
|
2025
|
-
}
|
|
2026
|
-
result += '\n## Valores Especiais\n\n';
|
|
2027
|
-
result += '| Valor | Descrição | Exemplo |\n';
|
|
2028
|
-
result += '|-------|-----------|--------|\n';
|
|
2029
|
-
result += '| `auto` | auto | `m-auto`, `ml-auto` |\n';
|
|
2030
|
-
result += '| `full` | 100% | `w-full`, `h-full` |\n';
|
|
2031
|
-
result += '| `screen` | 100vw/100vh | `w-screen`, `h-screen` |\n';
|
|
2032
|
-
result += '| `svh/lvh/dvh` | viewport units | `h-svh`, `h-lvh`, `h-dvh` |\n';
|
|
2033
|
-
result += '| `min` | min-content | `w-min`, `h-min` |\n';
|
|
2034
|
-
result += '| `max` | max-content | `w-max`, `h-max` |\n';
|
|
2035
|
-
result += '| `fit` | fit-content | `w-fit`, `h-fit` |\n';
|
|
2036
|
-
result += '\n## Frações (Width/Basis)\n\n';
|
|
2037
|
-
result += '| Valor | CSS | Exemplo |\n';
|
|
2038
|
-
result += '|-------|-----|--------|\n';
|
|
2039
|
-
result += '| `1/2` | 50% | `w-1/2`, `basis-1/2` |\n';
|
|
2040
|
-
result += '| `1/3` | 33.333% | `w-1/3`, `basis-1/3` |\n';
|
|
2041
|
-
result += '| `2/3` | 66.666% | `w-2/3`, `basis-2/3` |\n';
|
|
2042
|
-
result += '| `1/4` | 25% | `w-1/4`, `basis-1/4` |\n';
|
|
2043
|
-
result += '| `3/4` | 75% | `w-3/4`, `basis-3/4` |\n';
|
|
2044
|
-
result += '| `1/5` | 20% | `w-1/5`, `basis-1/5` |\n';
|
|
2045
|
-
result += '| `2/5` | 40% | `w-2/5`, `basis-2/5` |\n';
|
|
2046
|
-
result += '| `3/5` | 60% | `w-3/5`, `basis-3/5` |\n';
|
|
2047
|
-
result += '| `4/5` | 80% | `w-4/5`, `basis-4/5` |\n';
|
|
2048
|
-
result += '| `1/6` | 16.666% | `w-1/6`, `basis-1/6` |\n';
|
|
2049
|
-
result += '| `5/6` | 83.333% | `w-5/6`, `basis-5/6` |\n';
|
|
2050
|
-
result += '| `1/12` | 8.333% | `w-1/12`, `basis-1/12` |\n';
|
|
2051
|
-
return { content: [{ type: 'text', text: result }] };
|
|
2052
|
-
}
|
|
2053
|
-
case 'tailwind_breakpoints': {
|
|
2054
|
-
let result = '# 📱 Breakpoints Responsivos do Tailwind CSS\n\n';
|
|
2055
|
-
result += '## Breakpoints Padrão (Mobile-First)\n\n';
|
|
2056
|
-
result += '| Prefixo | Min-Width | CSS Media Query |\n';
|
|
2057
|
-
result += '|---------|-----------|----------------|\n';
|
|
2058
|
-
result += '| `sm:` | 640px | `@media (min-width: 640px)` |\n';
|
|
2059
|
-
result += '| `md:` | 768px | `@media (min-width: 768px)` |\n';
|
|
2060
|
-
result += '| `lg:` | 1024px | `@media (min-width: 1024px)` |\n';
|
|
2061
|
-
result += '| `xl:` | 1280px | `@media (min-width: 1280px)` |\n';
|
|
2062
|
-
result += '| `2xl:` | 1536px | `@media (min-width: 1536px)` |\n';
|
|
2063
|
-
result += '\n## Max-Width Variants\n\n';
|
|
2064
|
-
result += '| Prefixo | Max-Width | CSS Media Query |\n';
|
|
2065
|
-
result += '|---------|-----------|----------------|\n';
|
|
2066
|
-
result += '| `max-sm:` | <640px | `@media (max-width: 639px)` |\n';
|
|
2067
|
-
result += '| `max-md:` | <768px | `@media (max-width: 767px)` |\n';
|
|
2068
|
-
result += '| `max-lg:` | <1024px | `@media (max-width: 1023px)` |\n';
|
|
2069
|
-
result += '| `max-xl:` | <1280px | `@media (max-width: 1279px)` |\n';
|
|
2070
|
-
result += '| `max-2xl:` | <1536px | `@media (max-width: 1535px)` |\n';
|
|
2071
|
-
result += '\n## Breakpoints Arbitrários\n\n';
|
|
2072
|
-
result += '```html\n';
|
|
2073
|
-
result += '<!-- Min-width customizado -->\n';
|
|
2074
|
-
result += '<div class="min-[320px]:text-sm min-[480px]:text-base">\n\n';
|
|
2075
|
-
result += '<!-- Max-width customizado -->\n';
|
|
2076
|
-
result += '<div class="max-[600px]:hidden">\n';
|
|
2077
|
-
result += '```\n';
|
|
2078
|
-
result += '\n## Container Queries (v4)\n\n';
|
|
2079
|
-
result += '| Prefixo | Container Width | Uso |\n';
|
|
2080
|
-
result += '|---------|----------------|-----|\n';
|
|
2081
|
-
result += '| `@xs:` | ≥320px | `@xs:flex-row` |\n';
|
|
2082
|
-
result += '| `@sm:` | ≥384px | `@sm:grid-cols-2` |\n';
|
|
2083
|
-
result += '| `@md:` | ≥448px | `@md:p-6` |\n';
|
|
2084
|
-
result += '| `@lg:` | ≥512px | `@lg:text-lg` |\n';
|
|
2085
|
-
result += '| `@xl:` | ≥576px | `@xl:gap-8` |\n';
|
|
2086
|
-
result += '| `@2xl:` | ≥672px | `@2xl:grid-cols-4` |\n';
|
|
2087
|
-
result += '\n```html\n';
|
|
2088
|
-
result += '<!-- Uso de container queries -->\n';
|
|
2089
|
-
result += '<div class="@container">\n';
|
|
2090
|
-
result += ' <div class="@sm:flex @lg:grid @lg:grid-cols-2">\n';
|
|
2091
|
-
result += ' <!-- Responde ao tamanho do container pai -->\n';
|
|
2092
|
-
result += ' </div>\n';
|
|
2093
|
-
result += '</div>\n\n';
|
|
2094
|
-
result += '<!-- Container query arbitrário -->\n';
|
|
2095
|
-
result += '<div class="@[400px]:flex-row">\n';
|
|
2096
|
-
result += '```\n';
|
|
2097
|
-
result += '\n## Exemplo Responsivo Completo\n\n';
|
|
2098
|
-
result += '```html\n';
|
|
2099
|
-
result += '<div class="\n';
|
|
2100
|
-
result += ' flex flex-col /* Mobile: coluna */\n';
|
|
2101
|
-
result += ' sm:flex-row /* ≥640px: linha */\n';
|
|
2102
|
-
result += ' gap-2 sm:gap-4 /* Gap responsivo */\n';
|
|
2103
|
-
result += ' p-4 md:p-6 lg:p-8 /* Padding responsivo */\n';
|
|
2104
|
-
result += '">\n';
|
|
2105
|
-
result += ' <div class="w-full sm:w-1/2 lg:w-1/3">Item 1</div>\n';
|
|
2106
|
-
result += ' <div class="w-full sm:w-1/2 lg:w-1/3">Item 2</div>\n';
|
|
2107
|
-
result += ' <div class="hidden lg:block lg:w-1/3">Item 3</div>\n';
|
|
2108
|
-
result += '</div>\n';
|
|
2109
|
-
result += '```\n';
|
|
2110
|
-
return { content: [{ type: 'text', text: result }] };
|
|
2111
|
-
}
|
|
2112
|
-
case 'tailwind_receitas': {
|
|
2113
|
-
const componente = args?.componente;
|
|
2114
|
-
const receitas = {
|
|
2115
|
-
button: {
|
|
2116
|
-
desc: 'Botões com variantes',
|
|
2117
|
-
html: `<!-- Botão Primário -->
|
|
2118
|
-
<button class="px-4 py-2 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors">
|
|
2119
|
-
Botão Primário
|
|
2120
|
-
</button>
|
|
2121
|
-
|
|
2122
|
-
<!-- Botão Secundário -->
|
|
2123
|
-
<button class="px-4 py-2 bg-gray-200 text-gray-800 font-medium rounded-lg hover:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 transition-colors">
|
|
2124
|
-
Botão Secundário
|
|
2125
|
-
</button>
|
|
2126
|
-
|
|
2127
|
-
<!-- Botão Outline -->
|
|
2128
|
-
<button class="px-4 py-2 border-2 border-blue-600 text-blue-600 font-medium rounded-lg hover:bg-blue-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors">
|
|
2129
|
-
Botão Outline
|
|
2130
|
-
</button>
|
|
2131
|
-
|
|
2132
|
-
<!-- Botão com Ícone -->
|
|
2133
|
-
<button class="inline-flex items-center gap-2 px-4 py-2 bg-green-600 text-white font-medium rounded-lg hover:bg-green-700">
|
|
2134
|
-
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
2135
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
|
|
2136
|
-
</svg>
|
|
2137
|
-
Confirmar
|
|
2138
|
-
</button>
|
|
2139
|
-
|
|
2140
|
-
<!-- Botão Disabled -->
|
|
2141
|
-
<button disabled class="px-4 py-2 bg-gray-400 text-gray-200 font-medium rounded-lg cursor-not-allowed opacity-50">
|
|
2142
|
-
Desabilitado
|
|
2143
|
-
</button>
|
|
2144
|
-
|
|
2145
|
-
<!-- Botão Loading -->
|
|
2146
|
-
<button class="inline-flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg" disabled>
|
|
2147
|
-
<svg class="animate-spin h-5 w-5" viewBox="0 0 24 24">
|
|
2148
|
-
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none"/>
|
|
2149
|
-
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/>
|
|
2150
|
-
</svg>
|
|
2151
|
-
Carregando...
|
|
2152
|
-
</button>`,
|
|
2153
|
-
},
|
|
2154
|
-
card: {
|
|
2155
|
-
desc: 'Cards com imagem, conteúdo e ações',
|
|
2156
|
-
html: `<!-- Card Básico -->
|
|
2157
|
-
<div class="max-w-sm bg-white rounded-xl shadow-md overflow-hidden">
|
|
2158
|
-
<img class="w-full h-48 object-cover" src="image.jpg" alt="Card image">
|
|
2159
|
-
<div class="p-6">
|
|
2160
|
-
<h3 class="text-xl font-bold text-gray-900 mb-2">Título do Card</h3>
|
|
2161
|
-
<p class="text-gray-600 mb-4">Descrição breve do conteúdo do card.</p>
|
|
2162
|
-
<a href="#" class="text-blue-600 hover:text-blue-800 font-medium">Saiba mais →</a>
|
|
2163
|
-
</div>
|
|
2164
|
-
</div>
|
|
2165
|
-
|
|
2166
|
-
<!-- Card Horizontal -->
|
|
2167
|
-
<div class="flex max-w-2xl bg-white rounded-xl shadow-md overflow-hidden">
|
|
2168
|
-
<img class="w-48 object-cover" src="image.jpg" alt="">
|
|
2169
|
-
<div class="p-6 flex flex-col justify-between">
|
|
2170
|
-
<div>
|
|
2171
|
-
<span class="text-sm text-blue-600 font-semibold">Categoria</span>
|
|
2172
|
-
<h3 class="text-xl font-bold text-gray-900 mt-1">Título do Card</h3>
|
|
2173
|
-
<p class="text-gray-600 mt-2">Descrição do conteúdo.</p>
|
|
2174
|
-
</div>
|
|
2175
|
-
<div class="flex items-center gap-4 mt-4">
|
|
2176
|
-
<button class="px-4 py-2 bg-blue-600 text-white rounded-lg">Ação</button>
|
|
2177
|
-
</div>
|
|
2178
|
-
</div>
|
|
2179
|
-
</div>
|
|
2180
|
-
|
|
2181
|
-
<!-- Card com Footer -->
|
|
2182
|
-
<div class="max-w-sm bg-white rounded-xl shadow-md overflow-hidden">
|
|
2183
|
-
<div class="p-6">
|
|
2184
|
-
<h3 class="text-xl font-bold text-gray-900">Título</h3>
|
|
2185
|
-
<p class="text-gray-600 mt-2">Conteúdo do card.</p>
|
|
2186
|
-
</div>
|
|
2187
|
-
<div class="px-6 py-4 bg-gray-50 border-t flex justify-end gap-2">
|
|
2188
|
-
<button class="px-4 py-2 text-gray-600 hover:text-gray-800">Cancelar</button>
|
|
2189
|
-
<button class="px-4 py-2 bg-blue-600 text-white rounded-lg">Salvar</button>
|
|
2190
|
-
</div>
|
|
2191
|
-
</div>`,
|
|
2192
|
-
},
|
|
2193
|
-
form: {
|
|
2194
|
-
desc: 'Formulário completo com validação visual',
|
|
2195
|
-
html: `<form class="max-w-md mx-auto space-y-6">
|
|
2196
|
-
<!-- Input com Label -->
|
|
2197
|
-
<div>
|
|
2198
|
-
<label class="block text-sm font-medium text-gray-700 mb-1">Email</label>
|
|
2199
|
-
<input type="email" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-colors" placeholder="seu@email.com">
|
|
2200
|
-
</div>
|
|
2201
|
-
|
|
2202
|
-
<!-- Input com Erro -->
|
|
2203
|
-
<div>
|
|
2204
|
-
<label class="block text-sm font-medium text-gray-700 mb-1">Senha</label>
|
|
2205
|
-
<input type="password" class="w-full px-4 py-2 border border-red-500 rounded-lg focus:ring-2 focus:ring-red-500 focus:border-red-500 outline-none">
|
|
2206
|
-
<p class="mt-1 text-sm text-red-500">Senha deve ter no mínimo 8 caracteres</p>
|
|
2207
|
-
</div>
|
|
2208
|
-
|
|
2209
|
-
<!-- Select -->
|
|
2210
|
-
<div>
|
|
2211
|
-
<label class="block text-sm font-medium text-gray-700 mb-1">País</label>
|
|
2212
|
-
<select class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none bg-white">
|
|
2213
|
-
<option>Brasil</option>
|
|
2214
|
-
<option>Portugal</option>
|
|
2215
|
-
<option>EUA</option>
|
|
2216
|
-
</select>
|
|
2217
|
-
</div>
|
|
2218
|
-
|
|
2219
|
-
<!-- Checkbox -->
|
|
2220
|
-
<div class="flex items-center gap-2">
|
|
2221
|
-
<input type="checkbox" id="terms" class="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500">
|
|
2222
|
-
<label for="terms" class="text-sm text-gray-700">Aceito os termos de uso</label>
|
|
2223
|
-
</div>
|
|
2224
|
-
|
|
2225
|
-
<!-- Submit -->
|
|
2226
|
-
<button type="submit" class="w-full px-4 py-2 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 transition-colors">
|
|
2227
|
-
Enviar
|
|
2228
|
-
</button>
|
|
2229
|
-
</form>`,
|
|
2230
|
-
},
|
|
2231
|
-
input: {
|
|
2232
|
-
desc: 'Campos de input com variantes',
|
|
2233
|
-
html: `<!-- Input Padrão -->
|
|
2234
|
-
<input type="text" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none" placeholder="Digite aqui...">
|
|
2235
|
-
|
|
2236
|
-
<!-- Input com Ícone à Esquerda -->
|
|
2237
|
-
<div class="relative">
|
|
2238
|
-
<div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
|
|
2239
|
-
<svg class="w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
2240
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
|
|
2241
|
-
</svg>
|
|
2242
|
-
</div>
|
|
2243
|
-
<input type="search" class="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500" placeholder="Buscar...">
|
|
2244
|
-
</div>
|
|
2245
|
-
|
|
2246
|
-
<!-- Input com Botão -->
|
|
2247
|
-
<div class="flex">
|
|
2248
|
-
<input type="email" class="flex-1 px-4 py-2 border border-r-0 border-gray-300 rounded-l-lg focus:ring-2 focus:ring-blue-500" placeholder="seu@email.com">
|
|
2249
|
-
<button class="px-4 py-2 bg-blue-600 text-white rounded-r-lg hover:bg-blue-700">Inscrever</button>
|
|
2250
|
-
</div>
|
|
2251
|
-
|
|
2252
|
-
<!-- Textarea -->
|
|
2253
|
-
<textarea rows="4" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 resize-none" placeholder="Sua mensagem..."></textarea>`,
|
|
2254
|
-
},
|
|
2255
|
-
modal: {
|
|
2256
|
-
desc: 'Modal/Dialog com backdrop',
|
|
2257
|
-
html: `<!-- Modal Container -->
|
|
2258
|
-
<div class="fixed inset-0 z-50 flex items-center justify-center">
|
|
2259
|
-
<!-- Backdrop -->
|
|
2260
|
-
<div class="fixed inset-0 bg-black/50 backdrop-blur-sm"></div>
|
|
2261
|
-
|
|
2262
|
-
<!-- Modal -->
|
|
2263
|
-
<div class="relative bg-white rounded-xl shadow-2xl w-full max-w-md mx-4 overflow-hidden">
|
|
2264
|
-
<!-- Header -->
|
|
2265
|
-
<div class="flex items-center justify-between px-6 py-4 border-b">
|
|
2266
|
-
<h3 class="text-lg font-semibold text-gray-900">Título do Modal</h3>
|
|
2267
|
-
<button class="p-1 hover:bg-gray-100 rounded-lg">
|
|
2268
|
-
<svg class="w-5 h-5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
2269
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
|
|
2270
|
-
</svg>
|
|
2271
|
-
</button>
|
|
2272
|
-
</div>
|
|
2273
|
-
|
|
2274
|
-
<!-- Body -->
|
|
2275
|
-
<div class="px-6 py-4">
|
|
2276
|
-
<p class="text-gray-600">Conteúdo do modal aqui...</p>
|
|
2277
|
-
</div>
|
|
2278
|
-
|
|
2279
|
-
<!-- Footer -->
|
|
2280
|
-
<div class="flex justify-end gap-2 px-6 py-4 bg-gray-50 border-t">
|
|
2281
|
-
<button class="px-4 py-2 text-gray-600 hover:bg-gray-100 rounded-lg">Cancelar</button>
|
|
2282
|
-
<button class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">Confirmar</button>
|
|
2283
|
-
</div>
|
|
2284
|
-
</div>
|
|
2285
|
-
</div>`,
|
|
2286
|
-
},
|
|
2287
|
-
navbar: {
|
|
2288
|
-
desc: 'Navbar responsiva',
|
|
2289
|
-
html: `<nav class="bg-white shadow-md">
|
|
2290
|
-
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
2291
|
-
<div class="flex justify-between h-16">
|
|
2292
|
-
<!-- Logo -->
|
|
2293
|
-
<div class="flex items-center">
|
|
2294
|
-
<a href="#" class="text-xl font-bold text-blue-600">Logo</a>
|
|
2295
|
-
</div>
|
|
2296
|
-
|
|
2297
|
-
<!-- Desktop Menu -->
|
|
2298
|
-
<div class="hidden md:flex items-center gap-8">
|
|
2299
|
-
<a href="#" class="text-gray-600 hover:text-blue-600">Home</a>
|
|
2300
|
-
<a href="#" class="text-gray-600 hover:text-blue-600">Sobre</a>
|
|
2301
|
-
<a href="#" class="text-gray-600 hover:text-blue-600">Serviços</a>
|
|
2302
|
-
<a href="#" class="text-gray-600 hover:text-blue-600">Contato</a>
|
|
2303
|
-
<button class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">Login</button>
|
|
2304
|
-
</div>
|
|
2305
|
-
|
|
2306
|
-
<!-- Mobile Menu Button -->
|
|
2307
|
-
<div class="md:hidden flex items-center">
|
|
2308
|
-
<button class="p-2 rounded-lg hover:bg-gray-100">
|
|
2309
|
-
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
2310
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
|
|
2311
|
-
</svg>
|
|
2312
|
-
</button>
|
|
2313
|
-
</div>
|
|
2314
|
-
</div>
|
|
2315
|
-
</div>
|
|
2316
|
-
|
|
2317
|
-
<!-- Mobile Menu (toggle com JS) -->
|
|
2318
|
-
<div class="md:hidden border-t">
|
|
2319
|
-
<div class="px-4 py-2 space-y-1">
|
|
2320
|
-
<a href="#" class="block py-2 text-gray-600">Home</a>
|
|
2321
|
-
<a href="#" class="block py-2 text-gray-600">Sobre</a>
|
|
2322
|
-
<a href="#" class="block py-2 text-gray-600">Serviços</a>
|
|
2323
|
-
<a href="#" class="block py-2 text-gray-600">Contato</a>
|
|
2324
|
-
</div>
|
|
2325
|
-
</div>
|
|
2326
|
-
</nav>`,
|
|
2327
|
-
},
|
|
2328
|
-
footer: {
|
|
2329
|
-
desc: 'Footer com múltiplas colunas',
|
|
2330
|
-
html: `<footer class="bg-gray-900 text-gray-300">
|
|
2331
|
-
<div class="max-w-7xl mx-auto px-4 py-12 sm:px-6 lg:px-8">
|
|
2332
|
-
<div class="grid grid-cols-1 md:grid-cols-4 gap-8">
|
|
2333
|
-
<!-- Brand -->
|
|
2334
|
-
<div>
|
|
2335
|
-
<h3 class="text-white text-lg font-bold mb-4">Empresa</h3>
|
|
2336
|
-
<p class="text-sm">Descrição breve da empresa ou produto.</p>
|
|
2337
|
-
</div>
|
|
2338
|
-
|
|
2339
|
-
<!-- Links -->
|
|
2340
|
-
<div>
|
|
2341
|
-
<h4 class="text-white font-semibold mb-4">Produto</h4>
|
|
2342
|
-
<ul class="space-y-2 text-sm">
|
|
2343
|
-
<li><a href="#" class="hover:text-white">Features</a></li>
|
|
2344
|
-
<li><a href="#" class="hover:text-white">Preços</a></li>
|
|
2345
|
-
<li><a href="#" class="hover:text-white">FAQ</a></li>
|
|
2346
|
-
</ul>
|
|
2347
|
-
</div>
|
|
2348
|
-
|
|
2349
|
-
<div>
|
|
2350
|
-
<h4 class="text-white font-semibold mb-4">Empresa</h4>
|
|
2351
|
-
<ul class="space-y-2 text-sm">
|
|
2352
|
-
<li><a href="#" class="hover:text-white">Sobre</a></li>
|
|
2353
|
-
<li><a href="#" class="hover:text-white">Blog</a></li>
|
|
2354
|
-
<li><a href="#" class="hover:text-white">Carreiras</a></li>
|
|
2355
|
-
</ul>
|
|
2356
|
-
</div>
|
|
2357
|
-
|
|
2358
|
-
<div>
|
|
2359
|
-
<h4 class="text-white font-semibold mb-4">Legal</h4>
|
|
2360
|
-
<ul class="space-y-2 text-sm">
|
|
2361
|
-
<li><a href="#" class="hover:text-white">Privacidade</a></li>
|
|
2362
|
-
<li><a href="#" class="hover:text-white">Termos</a></li>
|
|
2363
|
-
</ul>
|
|
2364
|
-
</div>
|
|
2365
|
-
</div>
|
|
2366
|
-
|
|
2367
|
-
<div class="border-t border-gray-800 mt-8 pt-8 flex flex-col md:flex-row justify-between items-center">
|
|
2368
|
-
<p class="text-sm">© 2024 Empresa. Todos os direitos reservados.</p>
|
|
2369
|
-
<div class="flex gap-4 mt-4 md:mt-0">
|
|
2370
|
-
<a href="#" class="hover:text-white">Twitter</a>
|
|
2371
|
-
<a href="#" class="hover:text-white">GitHub</a>
|
|
2372
|
-
<a href="#" class="hover:text-white">LinkedIn</a>
|
|
2373
|
-
</div>
|
|
2374
|
-
</div>
|
|
2375
|
-
</div>
|
|
2376
|
-
</footer>`,
|
|
2377
|
-
},
|
|
2378
|
-
hero: {
|
|
2379
|
-
desc: 'Hero section para landing pages',
|
|
2380
|
-
html: `<!-- Hero com Background -->
|
|
2381
|
-
<section class="relative bg-gradient-to-br from-blue-600 to-purple-700 text-white">
|
|
2382
|
-
<div class="max-w-7xl mx-auto px-4 py-24 sm:px-6 lg:px-8">
|
|
2383
|
-
<div class="text-center">
|
|
2384
|
-
<h1 class="text-4xl md:text-6xl font-bold mb-6">
|
|
2385
|
-
Título Impactante
|
|
2386
|
-
</h1>
|
|
2387
|
-
<p class="text-xl md:text-2xl text-blue-100 mb-8 max-w-2xl mx-auto">
|
|
2388
|
-
Subtítulo explicando o valor do seu produto ou serviço.
|
|
2389
|
-
</p>
|
|
2390
|
-
<div class="flex flex-col sm:flex-row gap-4 justify-center">
|
|
2391
|
-
<button class="px-8 py-3 bg-white text-blue-600 font-semibold rounded-lg hover:bg-blue-50">
|
|
2392
|
-
Começar Agora
|
|
2393
|
-
</button>
|
|
2394
|
-
<button class="px-8 py-3 border-2 border-white text-white font-semibold rounded-lg hover:bg-white/10">
|
|
2395
|
-
Saiba Mais
|
|
2396
|
-
</button>
|
|
2397
|
-
</div>
|
|
2398
|
-
</div>
|
|
2399
|
-
</div>
|
|
2400
|
-
</section>
|
|
2401
|
-
|
|
2402
|
-
<!-- Hero com Imagem -->
|
|
2403
|
-
<section class="bg-white">
|
|
2404
|
-
<div class="max-w-7xl mx-auto px-4 py-16 sm:px-6 lg:px-8">
|
|
2405
|
-
<div class="grid md:grid-cols-2 gap-12 items-center">
|
|
2406
|
-
<div>
|
|
2407
|
-
<h1 class="text-4xl md:text-5xl font-bold text-gray-900 mb-6">
|
|
2408
|
-
Título Principal
|
|
2409
|
-
</h1>
|
|
2410
|
-
<p class="text-xl text-gray-600 mb-8">
|
|
2411
|
-
Descrição do produto com benefícios claros para o usuário.
|
|
2412
|
-
</p>
|
|
2413
|
-
<button class="px-8 py-3 bg-blue-600 text-white font-semibold rounded-lg hover:bg-blue-700">
|
|
2414
|
-
Call to Action
|
|
2415
|
-
</button>
|
|
2416
|
-
</div>
|
|
2417
|
-
<div>
|
|
2418
|
-
<img src="hero-image.png" alt="Hero" class="rounded-xl shadow-2xl">
|
|
2419
|
-
</div>
|
|
2420
|
-
</div>
|
|
2421
|
-
</div>
|
|
2422
|
-
</section>`,
|
|
2423
|
-
},
|
|
2424
|
-
grid: {
|
|
2425
|
-
desc: 'Grid responsivo para layouts',
|
|
2426
|
-
html: `<!-- Grid de 3 colunas responsivo -->
|
|
2427
|
-
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
2428
|
-
<div class="p-6 bg-white rounded-lg shadow">Item 1</div>
|
|
2429
|
-
<div class="p-6 bg-white rounded-lg shadow">Item 2</div>
|
|
2430
|
-
<div class="p-6 bg-white rounded-lg shadow">Item 3</div>
|
|
2431
|
-
</div>
|
|
2432
|
-
|
|
2433
|
-
<!-- Grid de 4 colunas com span -->
|
|
2434
|
-
<div class="grid grid-cols-4 gap-4">
|
|
2435
|
-
<div class="col-span-4 md:col-span-2 lg:col-span-1 p-4 bg-blue-100 rounded">1</div>
|
|
2436
|
-
<div class="col-span-4 md:col-span-2 lg:col-span-1 p-4 bg-blue-200 rounded">2</div>
|
|
2437
|
-
<div class="col-span-4 md:col-span-2 lg:col-span-1 p-4 bg-blue-300 rounded">3</div>
|
|
2438
|
-
<div class="col-span-4 md:col-span-2 lg:col-span-1 p-4 bg-blue-400 rounded">4</div>
|
|
2439
|
-
</div>
|
|
2440
|
-
|
|
2441
|
-
<!-- Grid de 12 colunas (dashboard) -->
|
|
2442
|
-
<div class="grid grid-cols-12 gap-4">
|
|
2443
|
-
<div class="col-span-12 lg:col-span-8 p-6 bg-white rounded-lg shadow">Conteúdo Principal</div>
|
|
2444
|
-
<div class="col-span-12 lg:col-span-4 p-6 bg-white rounded-lg shadow">Sidebar</div>
|
|
2445
|
-
<div class="col-span-12 md:col-span-6 lg:col-span-4 p-6 bg-white rounded-lg shadow">Card 1</div>
|
|
2446
|
-
<div class="col-span-12 md:col-span-6 lg:col-span-4 p-6 bg-white rounded-lg shadow">Card 2</div>
|
|
2447
|
-
<div class="col-span-12 md:col-span-12 lg:col-span-4 p-6 bg-white rounded-lg shadow">Card 3</div>
|
|
2448
|
-
</div>
|
|
2449
|
-
|
|
2450
|
-
<!-- Auto-fit Grid -->
|
|
2451
|
-
<div class="grid grid-cols-[repeat(auto-fit,minmax(250px,1fr))] gap-4">
|
|
2452
|
-
<div class="p-6 bg-white rounded-lg shadow">Auto 1</div>
|
|
2453
|
-
<div class="p-6 bg-white rounded-lg shadow">Auto 2</div>
|
|
2454
|
-
<div class="p-6 bg-white rounded-lg shadow">Auto 3</div>
|
|
2455
|
-
<div class="p-6 bg-white rounded-lg shadow">Auto 4</div>
|
|
2456
|
-
</div>`,
|
|
2457
|
-
},
|
|
2458
|
-
alert: {
|
|
2459
|
-
desc: 'Alertas e notificações',
|
|
2460
|
-
html: `<!-- Alert Info -->
|
|
2461
|
-
<div class="flex items-center gap-3 p-4 bg-blue-50 border border-blue-200 text-blue-800 rounded-lg">
|
|
2462
|
-
<svg class="w-5 h-5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
|
2463
|
-
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"/>
|
|
2464
|
-
</svg>
|
|
2465
|
-
<p>Informação importante para o usuário.</p>
|
|
2466
|
-
</div>
|
|
2467
|
-
|
|
2468
|
-
<!-- Alert Success -->
|
|
2469
|
-
<div class="flex items-center gap-3 p-4 bg-green-50 border border-green-200 text-green-800 rounded-lg">
|
|
2470
|
-
<svg class="w-5 h-5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
|
2471
|
-
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
|
|
2472
|
-
</svg>
|
|
2473
|
-
<p>Operação realizada com sucesso!</p>
|
|
2474
|
-
</div>
|
|
2475
|
-
|
|
2476
|
-
<!-- Alert Warning -->
|
|
2477
|
-
<div class="flex items-center gap-3 p-4 bg-yellow-50 border border-yellow-200 text-yellow-800 rounded-lg">
|
|
2478
|
-
<svg class="w-5 h-5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
|
2479
|
-
<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd"/>
|
|
2480
|
-
</svg>
|
|
2481
|
-
<p>Atenção! Verifique os dados antes de continuar.</p>
|
|
2482
|
-
</div>
|
|
2483
|
-
|
|
2484
|
-
<!-- Alert Error -->
|
|
2485
|
-
<div class="flex items-center gap-3 p-4 bg-red-50 border border-red-200 text-red-800 rounded-lg">
|
|
2486
|
-
<svg class="w-5 h-5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
|
2487
|
-
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/>
|
|
2488
|
-
</svg>
|
|
2489
|
-
<p>Erro! Algo deu errado. Tente novamente.</p>
|
|
2490
|
-
</div>
|
|
2491
|
-
|
|
2492
|
-
<!-- Alert Dismissible -->
|
|
2493
|
-
<div class="flex items-center justify-between gap-3 p-4 bg-blue-50 border border-blue-200 text-blue-800 rounded-lg">
|
|
2494
|
-
<p>Notificação que pode ser fechada.</p>
|
|
2495
|
-
<button class="p-1 hover:bg-blue-100 rounded">
|
|
2496
|
-
<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
|
|
2497
|
-
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"/>
|
|
2498
|
-
</svg>
|
|
2499
|
-
</button>
|
|
2500
|
-
</div>`,
|
|
2501
|
-
},
|
|
2502
|
-
badge: {
|
|
2503
|
-
desc: 'Badges e tags',
|
|
2504
|
-
html: `<!-- Badges Coloridos -->
|
|
2505
|
-
<span class="px-2 py-1 text-xs font-medium bg-blue-100 text-blue-800 rounded-full">Novo</span>
|
|
2506
|
-
<span class="px-2 py-1 text-xs font-medium bg-green-100 text-green-800 rounded-full">Ativo</span>
|
|
2507
|
-
<span class="px-2 py-1 text-xs font-medium bg-yellow-100 text-yellow-800 rounded-full">Pendente</span>
|
|
2508
|
-
<span class="px-2 py-1 text-xs font-medium bg-red-100 text-red-800 rounded-full">Urgente</span>
|
|
2509
|
-
<span class="px-2 py-1 text-xs font-medium bg-gray-100 text-gray-800 rounded-full">Default</span>
|
|
2510
|
-
|
|
2511
|
-
<!-- Badge com Dot -->
|
|
2512
|
-
<span class="inline-flex items-center gap-1 px-2 py-1 text-xs font-medium bg-green-100 text-green-800 rounded-full">
|
|
2513
|
-
<span class="w-2 h-2 bg-green-500 rounded-full"></span>
|
|
2514
|
-
Online
|
|
2515
|
-
</span>
|
|
2516
|
-
|
|
2517
|
-
<!-- Badge Pill -->
|
|
2518
|
-
<span class="px-3 py-1 text-sm font-semibold bg-purple-600 text-white rounded-full">PRO</span>
|
|
2519
|
-
|
|
2520
|
-
<!-- Badge com Ícone -->
|
|
2521
|
-
<span class="inline-flex items-center gap-1 px-2 py-1 text-xs font-medium bg-blue-100 text-blue-800 rounded">
|
|
2522
|
-
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20">
|
|
2523
|
-
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
|
|
2524
|
-
</svg>
|
|
2525
|
-
Verificado
|
|
2526
|
-
</span>`,
|
|
2527
|
-
},
|
|
2528
|
-
avatar: {
|
|
2529
|
-
desc: 'Avatares e fotos de perfil',
|
|
2530
|
-
html: `<!-- Avatar Circular -->
|
|
2531
|
-
<img class="w-12 h-12 rounded-full object-cover" src="avatar.jpg" alt="Avatar">
|
|
2532
|
-
|
|
2533
|
-
<!-- Avatar com Iniciais -->
|
|
2534
|
-
<div class="w-12 h-12 rounded-full bg-blue-500 flex items-center justify-center text-white font-semibold">
|
|
2535
|
-
JD
|
|
2536
|
-
</div>
|
|
2537
|
-
|
|
2538
|
-
<!-- Avatar com Status -->
|
|
2539
|
-
<div class="relative">
|
|
2540
|
-
<img class="w-12 h-12 rounded-full object-cover" src="avatar.jpg" alt="">
|
|
2541
|
-
<span class="absolute bottom-0 right-0 w-3 h-3 bg-green-500 border-2 border-white rounded-full"></span>
|
|
2542
|
-
</div>
|
|
2543
|
-
|
|
2544
|
-
<!-- Avatar Group -->
|
|
2545
|
-
<div class="flex -space-x-2">
|
|
2546
|
-
<img class="w-10 h-10 rounded-full border-2 border-white" src="avatar1.jpg" alt="">
|
|
2547
|
-
<img class="w-10 h-10 rounded-full border-2 border-white" src="avatar2.jpg" alt="">
|
|
2548
|
-
<img class="w-10 h-10 rounded-full border-2 border-white" src="avatar3.jpg" alt="">
|
|
2549
|
-
<div class="w-10 h-10 rounded-full border-2 border-white bg-gray-200 flex items-center justify-center text-sm text-gray-600">+5</div>
|
|
2550
|
-
</div>
|
|
2551
|
-
|
|
2552
|
-
<!-- Avatar Tamanhos -->
|
|
2553
|
-
<img class="w-8 h-8 rounded-full" src="avatar.jpg" alt="XS">
|
|
2554
|
-
<img class="w-10 h-10 rounded-full" src="avatar.jpg" alt="SM">
|
|
2555
|
-
<img class="w-12 h-12 rounded-full" src="avatar.jpg" alt="MD">
|
|
2556
|
-
<img class="w-16 h-16 rounded-full" src="avatar.jpg" alt="LG">
|
|
2557
|
-
<img class="w-20 h-20 rounded-full" src="avatar.jpg" alt="XL">`,
|
|
2558
|
-
},
|
|
2559
|
-
dropdown: {
|
|
2560
|
-
desc: 'Dropdown menu',
|
|
2561
|
-
html: `<!-- Dropdown Container -->
|
|
2562
|
-
<div class="relative inline-block">
|
|
2563
|
-
<!-- Trigger Button -->
|
|
2564
|
-
<button class="inline-flex items-center gap-2 px-4 py-2 bg-white border border-gray-300 rounded-lg hover:bg-gray-50">
|
|
2565
|
-
Opções
|
|
2566
|
-
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
2567
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
|
2568
|
-
</svg>
|
|
2569
|
-
</button>
|
|
2570
|
-
|
|
2571
|
-
<!-- Dropdown Menu -->
|
|
2572
|
-
<div class="absolute right-0 mt-2 w-48 bg-white rounded-lg shadow-lg border border-gray-200 py-1 z-10">
|
|
2573
|
-
<a href="#" class="block px-4 py-2 text-gray-700 hover:bg-gray-100">Editar</a>
|
|
2574
|
-
<a href="#" class="block px-4 py-2 text-gray-700 hover:bg-gray-100">Duplicar</a>
|
|
2575
|
-
<a href="#" class="block px-4 py-2 text-gray-700 hover:bg-gray-100">Arquivar</a>
|
|
2576
|
-
<hr class="my-1 border-gray-200">
|
|
2577
|
-
<a href="#" class="block px-4 py-2 text-red-600 hover:bg-red-50">Excluir</a>
|
|
2578
|
-
</div>
|
|
2579
|
-
</div>
|
|
2580
|
-
|
|
2581
|
-
<!-- Dropdown com Ícones -->
|
|
2582
|
-
<div class="w-48 bg-white rounded-lg shadow-lg border border-gray-200 py-1">
|
|
2583
|
-
<a href="#" class="flex items-center gap-3 px-4 py-2 text-gray-700 hover:bg-gray-100">
|
|
2584
|
-
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
2585
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"/>
|
|
2586
|
-
</svg>
|
|
2587
|
-
Editar
|
|
2588
|
-
</a>
|
|
2589
|
-
<a href="#" class="flex items-center gap-3 px-4 py-2 text-gray-700 hover:bg-gray-100">
|
|
2590
|
-
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
2591
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/>
|
|
2592
|
-
</svg>
|
|
2593
|
-
Duplicar
|
|
2594
|
-
</a>
|
|
2595
|
-
</div>`,
|
|
2596
|
-
},
|
|
2597
|
-
tabs: {
|
|
2598
|
-
desc: 'Abas de navegação',
|
|
2599
|
-
html: `<!-- Tabs Underline -->
|
|
2600
|
-
<div class="border-b border-gray-200">
|
|
2601
|
-
<nav class="flex gap-8">
|
|
2602
|
-
<a href="#" class="py-4 px-1 border-b-2 border-blue-500 text-blue-600 font-medium">Tab Ativa</a>
|
|
2603
|
-
<a href="#" class="py-4 px-1 border-b-2 border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300">Tab 2</a>
|
|
2604
|
-
<a href="#" class="py-4 px-1 border-b-2 border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300">Tab 3</a>
|
|
2605
|
-
</nav>
|
|
2606
|
-
</div>
|
|
2607
|
-
|
|
2608
|
-
<!-- Tabs Pills -->
|
|
2609
|
-
<div class="flex gap-2 bg-gray-100 p-1 rounded-lg">
|
|
2610
|
-
<button class="px-4 py-2 bg-white text-gray-900 rounded-md shadow-sm font-medium">Tab Ativa</button>
|
|
2611
|
-
<button class="px-4 py-2 text-gray-600 hover:text-gray-900 rounded-md font-medium">Tab 2</button>
|
|
2612
|
-
<button class="px-4 py-2 text-gray-600 hover:text-gray-900 rounded-md font-medium">Tab 3</button>
|
|
2613
|
-
</div>
|
|
2614
|
-
|
|
2615
|
-
<!-- Tabs com Ícones -->
|
|
2616
|
-
<div class="flex border-b border-gray-200">
|
|
2617
|
-
<a href="#" class="flex items-center gap-2 py-4 px-4 border-b-2 border-blue-500 text-blue-600">
|
|
2618
|
-
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
2619
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/>
|
|
2620
|
-
</svg>
|
|
2621
|
-
Home
|
|
2622
|
-
</a>
|
|
2623
|
-
<a href="#" class="flex items-center gap-2 py-4 px-4 text-gray-500 hover:text-gray-700">
|
|
2624
|
-
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
2625
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/>
|
|
2626
|
-
</svg>
|
|
2627
|
-
Perfil
|
|
2628
|
-
</a>
|
|
2629
|
-
</div>`,
|
|
2630
|
-
},
|
|
2631
|
-
breadcrumb: {
|
|
2632
|
-
desc: 'Breadcrumb de navegação',
|
|
2633
|
-
html: `<!-- Breadcrumb Simples -->
|
|
2634
|
-
<nav class="flex" aria-label="Breadcrumb">
|
|
2635
|
-
<ol class="flex items-center gap-2">
|
|
2636
|
-
<li>
|
|
2637
|
-
<a href="#" class="text-gray-500 hover:text-gray-700">Home</a>
|
|
2638
|
-
</li>
|
|
2639
|
-
<li class="text-gray-400">/</li>
|
|
2640
|
-
<li>
|
|
2641
|
-
<a href="#" class="text-gray-500 hover:text-gray-700">Produtos</a>
|
|
2642
|
-
</li>
|
|
2643
|
-
<li class="text-gray-400">/</li>
|
|
2644
|
-
<li>
|
|
2645
|
-
<span class="text-gray-900 font-medium">Detalhes</span>
|
|
2646
|
-
</li>
|
|
2647
|
-
</ol>
|
|
2648
|
-
</nav>
|
|
2649
|
-
|
|
2650
|
-
<!-- Breadcrumb com Chevron -->
|
|
2651
|
-
<nav class="flex" aria-label="Breadcrumb">
|
|
2652
|
-
<ol class="flex items-center">
|
|
2653
|
-
<li>
|
|
2654
|
-
<a href="#" class="text-gray-500 hover:text-gray-700">
|
|
2655
|
-
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
|
2656
|
-
<path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"/>
|
|
2657
|
-
</svg>
|
|
2658
|
-
</a>
|
|
2659
|
-
</li>
|
|
2660
|
-
<li class="flex items-center">
|
|
2661
|
-
<svg class="w-5 h-5 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
|
|
2662
|
-
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/>
|
|
2663
|
-
</svg>
|
|
2664
|
-
<a href="#" class="ml-2 text-gray-500 hover:text-gray-700">Categoria</a>
|
|
2665
|
-
</li>
|
|
2666
|
-
<li class="flex items-center">
|
|
2667
|
-
<svg class="w-5 h-5 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
|
|
2668
|
-
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/>
|
|
2669
|
-
</svg>
|
|
2670
|
-
<span class="ml-2 text-gray-900 font-medium">Página Atual</span>
|
|
2671
|
-
</li>
|
|
2672
|
-
</ol>
|
|
2673
|
-
</nav>`,
|
|
2674
|
-
},
|
|
2675
|
-
pagination: {
|
|
2676
|
-
desc: 'Paginação',
|
|
2677
|
-
html: `<!-- Paginação Simples -->
|
|
2678
|
-
<nav class="flex items-center gap-1">
|
|
2679
|
-
<button class="px-3 py-2 text-gray-500 hover:bg-gray-100 rounded-lg disabled:opacity-50" disabled>
|
|
2680
|
-
Anterior
|
|
2681
|
-
</button>
|
|
2682
|
-
<button class="px-3 py-2 bg-blue-600 text-white rounded-lg">1</button>
|
|
2683
|
-
<button class="px-3 py-2 text-gray-700 hover:bg-gray-100 rounded-lg">2</button>
|
|
2684
|
-
<button class="px-3 py-2 text-gray-700 hover:bg-gray-100 rounded-lg">3</button>
|
|
2685
|
-
<span class="px-3 py-2 text-gray-500">...</span>
|
|
2686
|
-
<button class="px-3 py-2 text-gray-700 hover:bg-gray-100 rounded-lg">10</button>
|
|
2687
|
-
<button class="px-3 py-2 text-gray-700 hover:bg-gray-100 rounded-lg">
|
|
2688
|
-
Próximo
|
|
2689
|
-
</button>
|
|
2690
|
-
</nav>
|
|
2691
|
-
|
|
2692
|
-
<!-- Paginação com Ícones -->
|
|
2693
|
-
<nav class="flex items-center gap-1">
|
|
2694
|
-
<button class="p-2 text-gray-500 hover:bg-gray-100 rounded-lg">
|
|
2695
|
-
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
2696
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
|
|
2697
|
-
</svg>
|
|
2698
|
-
</button>
|
|
2699
|
-
<button class="w-10 h-10 bg-blue-600 text-white rounded-lg">1</button>
|
|
2700
|
-
<button class="w-10 h-10 text-gray-700 hover:bg-gray-100 rounded-lg">2</button>
|
|
2701
|
-
<button class="w-10 h-10 text-gray-700 hover:bg-gray-100 rounded-lg">3</button>
|
|
2702
|
-
<button class="p-2 text-gray-500 hover:bg-gray-100 rounded-lg">
|
|
2703
|
-
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
2704
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
|
|
2705
|
-
</svg>
|
|
2706
|
-
</button>
|
|
2707
|
-
</nav>`,
|
|
2708
|
-
},
|
|
2709
|
-
skeleton: {
|
|
2710
|
-
desc: 'Skeleton loaders',
|
|
2711
|
-
html: `<!-- Skeleton de Texto -->
|
|
2712
|
-
<div class="animate-pulse space-y-3">
|
|
2713
|
-
<div class="h-4 bg-gray-200 rounded w-3/4"></div>
|
|
2714
|
-
<div class="h-4 bg-gray-200 rounded"></div>
|
|
2715
|
-
<div class="h-4 bg-gray-200 rounded w-5/6"></div>
|
|
2716
|
-
</div>
|
|
2717
|
-
|
|
2718
|
-
<!-- Skeleton de Card -->
|
|
2719
|
-
<div class="animate-pulse">
|
|
2720
|
-
<div class="bg-gray-200 h-48 rounded-t-lg"></div>
|
|
2721
|
-
<div class="p-4 space-y-3">
|
|
2722
|
-
<div class="h-4 bg-gray-200 rounded w-3/4"></div>
|
|
2723
|
-
<div class="h-4 bg-gray-200 rounded"></div>
|
|
2724
|
-
<div class="h-4 bg-gray-200 rounded w-1/2"></div>
|
|
2725
|
-
</div>
|
|
2726
|
-
</div>
|
|
2727
|
-
|
|
2728
|
-
<!-- Skeleton de Avatar + Texto -->
|
|
2729
|
-
<div class="animate-pulse flex items-center gap-4">
|
|
2730
|
-
<div class="w-12 h-12 bg-gray-200 rounded-full"></div>
|
|
2731
|
-
<div class="flex-1 space-y-2">
|
|
2732
|
-
<div class="h-4 bg-gray-200 rounded w-1/4"></div>
|
|
2733
|
-
<div class="h-3 bg-gray-200 rounded w-1/2"></div>
|
|
2734
|
-
</div>
|
|
2735
|
-
</div>
|
|
2736
|
-
|
|
2737
|
-
<!-- Skeleton de Lista -->
|
|
2738
|
-
<div class="animate-pulse space-y-4">
|
|
2739
|
-
<div class="flex items-center gap-4">
|
|
2740
|
-
<div class="w-10 h-10 bg-gray-200 rounded"></div>
|
|
2741
|
-
<div class="flex-1 space-y-2">
|
|
2742
|
-
<div class="h-4 bg-gray-200 rounded w-3/4"></div>
|
|
2743
|
-
<div class="h-3 bg-gray-200 rounded w-1/2"></div>
|
|
2744
|
-
</div>
|
|
2745
|
-
</div>
|
|
2746
|
-
<div class="flex items-center gap-4">
|
|
2747
|
-
<div class="w-10 h-10 bg-gray-200 rounded"></div>
|
|
2748
|
-
<div class="flex-1 space-y-2">
|
|
2749
|
-
<div class="h-4 bg-gray-200 rounded w-2/3"></div>
|
|
2750
|
-
<div class="h-3 bg-gray-200 rounded w-1/3"></div>
|
|
2751
|
-
</div>
|
|
2752
|
-
</div>
|
|
2753
|
-
</div>`,
|
|
2754
|
-
},
|
|
2755
|
-
};
|
|
2756
|
-
if (!componente) {
|
|
2757
|
-
return {
|
|
2758
|
-
content: [{ type: 'text', text: `❌ Parâmetro 'componente' é obrigatório.\n\nComponentes disponíveis: ${Object.keys(receitas).join(', ')}` }],
|
|
2759
|
-
isError: true,
|
|
2760
|
-
};
|
|
2761
|
-
}
|
|
2762
|
-
const receita = receitas[componente];
|
|
2763
|
-
if (!receita) {
|
|
2764
|
-
return {
|
|
2765
|
-
content: [{ type: 'text', text: `❌ Componente não encontrado: ${componente}\n\nComponentes disponíveis: ${Object.keys(receitas).join(', ')}` }],
|
|
2766
|
-
isError: true,
|
|
2767
|
-
};
|
|
2768
|
-
}
|
|
2769
|
-
let result = `# 🍳 Receita: ${componente}\n\n`;
|
|
2770
|
-
result += `**${receita.desc}**\n\n`;
|
|
2771
|
-
result += '```html\n';
|
|
2772
|
-
result += receita.html;
|
|
2773
|
-
result += '\n```\n';
|
|
2774
|
-
return { content: [{ type: 'text', text: result }] };
|
|
2775
|
-
}
|
|
2776
|
-
case 'tailwind_migracao_v4': {
|
|
2777
|
-
const topico = args?.topico;
|
|
2778
|
-
const migracaoContent = {
|
|
2779
|
-
overview: `# 🚀 Migração Tailwind CSS v3 → v4
|
|
2780
|
-
|
|
2781
|
-
## Principais Mudanças
|
|
2782
|
-
|
|
2783
|
-
### 1. CSS-First Configuration
|
|
2784
|
-
O Tailwind v4 usa configuração via CSS ao invés de JavaScript:
|
|
2785
|
-
|
|
2786
|
-
\`\`\`css
|
|
2787
|
-
/* v4: Configuração em CSS */
|
|
2788
|
-
@import "tailwindcss";
|
|
2789
|
-
|
|
2790
|
-
@theme {
|
|
2791
|
-
--color-primary: oklch(0.6 0.2 250);
|
|
2792
|
-
--font-display: "Inter", sans-serif;
|
|
2793
|
-
}
|
|
2794
|
-
\`\`\`
|
|
2795
|
-
|
|
2796
|
-
### 2. Nova Sintaxe de Import
|
|
2797
|
-
\`\`\`css
|
|
2798
|
-
/* v3 */
|
|
2799
|
-
@tailwind base;
|
|
2800
|
-
@tailwind components;
|
|
2801
|
-
@tailwind utilities;
|
|
2802
|
-
|
|
2803
|
-
/* v4 */
|
|
2804
|
-
@import "tailwindcss";
|
|
2805
|
-
\`\`\`
|
|
2806
|
-
|
|
2807
|
-
### 3. Plugins via CSS
|
|
2808
|
-
\`\`\`css
|
|
2809
|
-
/* v4 */
|
|
2810
|
-
@import "tailwindcss";
|
|
2811
|
-
@plugin "@tailwindcss/typography";
|
|
2812
|
-
@plugin "@tailwindcss/forms";
|
|
2813
|
-
\`\`\`
|
|
2814
|
-
|
|
2815
|
-
### 4. Novas Features
|
|
2816
|
-
- Container Queries nativas
|
|
2817
|
-
- \`@starting-style\` para animações
|
|
2818
|
-
- Variantes \`in-*\`, \`has-*\`, \`not-*\`
|
|
2819
|
-
- Cores em OKLCH
|
|
2820
|
-
- Performance 10x mais rápida
|
|
2821
|
-
|
|
2822
|
-
### 5. Breaking Changes Importantes
|
|
2823
|
-
- \`text-opacity-*\` → usar modificador de cor \`/opacity\`
|
|
2824
|
-
- \`bg-opacity-*\` → usar modificador de cor \`/opacity\`
|
|
2825
|
-
- Algumas classes renomeadas`,
|
|
2826
|
-
'css-first': `# 📝 CSS-First Configuration (v4)
|
|
2827
|
-
|
|
2828
|
-
## Configuração no CSS
|
|
2829
|
-
|
|
2830
|
-
O v4 elimina o \`tailwind.config.js\` para a maioria dos casos:
|
|
2831
|
-
|
|
2832
|
-
\`\`\`css
|
|
2833
|
-
@import "tailwindcss";
|
|
2834
|
-
|
|
2835
|
-
/* Customização de tema */
|
|
2836
|
-
@theme {
|
|
2837
|
-
/* Cores customizadas */
|
|
2838
|
-
--color-brand: oklch(0.6 0.2 250);
|
|
2839
|
-
--color-accent: oklch(0.7 0.15 150);
|
|
2840
|
-
|
|
2841
|
-
/* Fontes */
|
|
2842
|
-
--font-display: "Cal Sans", sans-serif;
|
|
2843
|
-
--font-body: "Inter", sans-serif;
|
|
2844
|
-
|
|
2845
|
-
/* Spacing customizado */
|
|
2846
|
-
--spacing-18: 4.5rem;
|
|
2847
|
-
--spacing-88: 22rem;
|
|
2848
|
-
|
|
2849
|
-
/* Breakpoints customizados */
|
|
2850
|
-
--breakpoint-3xl: 1920px;
|
|
2851
|
-
|
|
2852
|
-
/* Border radius */
|
|
2853
|
-
--radius-4xl: 2rem;
|
|
2854
|
-
|
|
2855
|
-
/* Shadows */
|
|
2856
|
-
--shadow-glow: 0 0 20px oklch(0.6 0.2 250 / 0.5);
|
|
2857
|
-
}
|
|
2858
|
-
\`\`\`
|
|
2859
|
-
|
|
2860
|
-
## Vantagens
|
|
2861
|
-
- Tipagem automática das variáveis CSS
|
|
2862
|
-
- Intellisense melhorado
|
|
2863
|
-
- Menor bundle size
|
|
2864
|
-
- Mais rápido para compilar`,
|
|
2865
|
-
'theme-config': `# 🎨 Configuração de Tema (v4)
|
|
2866
|
-
|
|
2867
|
-
## Variáveis de Tema
|
|
2868
|
-
|
|
2869
|
-
\`\`\`css
|
|
2870
|
-
@theme {
|
|
2871
|
-
/* === CORES === */
|
|
2872
|
-
/* Substitui colors no config JS */
|
|
2873
|
-
--color-*: valor;
|
|
2874
|
-
|
|
2875
|
-
/* Exemplo */
|
|
2876
|
-
--color-primary-50: oklch(0.97 0.01 250);
|
|
2877
|
-
--color-primary-500: oklch(0.6 0.2 250);
|
|
2878
|
-
--color-primary-900: oklch(0.3 0.1 250);
|
|
2879
|
-
|
|
2880
|
-
/* === TIPOGRAFIA === */
|
|
2881
|
-
--font-sans: "Inter", system-ui, sans-serif;
|
|
2882
|
-
--font-mono: "Fira Code", monospace;
|
|
2883
|
-
|
|
2884
|
-
--text-xs: 0.75rem;
|
|
2885
|
-
--text-xs--line-height: 1rem;
|
|
2886
|
-
|
|
2887
|
-
/* === SPACING === */
|
|
2888
|
-
--spacing-*: valor;
|
|
2889
|
-
--spacing-13: 3.25rem;
|
|
2890
|
-
|
|
2891
|
-
/* === BREAKPOINTS === */
|
|
2892
|
-
--breakpoint-sm: 640px;
|
|
2893
|
-
--breakpoint-md: 768px;
|
|
2894
|
-
--breakpoint-3xl: 1920px;
|
|
2895
|
-
|
|
2896
|
-
/* === RADIUS === */
|
|
2897
|
-
--radius-sm: 0.25rem;
|
|
2898
|
-
--radius-xl: 1rem;
|
|
2899
|
-
|
|
2900
|
-
/* === SHADOWS === */
|
|
2901
|
-
--shadow-sm: 0 1px 2px rgb(0 0 0 / 0.05);
|
|
2902
|
-
--shadow-xl: 0 20px 25px rgb(0 0 0 / 0.1);
|
|
2903
|
-
|
|
2904
|
-
/* === ANIMAÇÕES === */
|
|
2905
|
-
--animate-spin: spin 1s linear infinite;
|
|
2906
|
-
--animate-custom: myAnimation 2s ease-in-out;
|
|
2907
|
-
}
|
|
2908
|
-
|
|
2909
|
-
@keyframes myAnimation {
|
|
2910
|
-
from { opacity: 0; }
|
|
2911
|
-
to { opacity: 1; }
|
|
2912
|
-
}
|
|
2913
|
-
\`\`\``,
|
|
2914
|
-
utilities: `# 🔧 Mudanças em Utilities (v4)
|
|
2915
|
-
|
|
2916
|
-
## Classes Renomeadas
|
|
2917
|
-
|
|
2918
|
-
| v3 | v4 | Motivo |
|
|
2919
|
-
|----|----|--------|
|
|
2920
|
-
| \`shadow-sm\` | \`shadow-xs\` | Mais consistente |
|
|
2921
|
-
| \`shadow\` | \`shadow-sm\` | Escala ajustada |
|
|
2922
|
-
| \`drop-shadow-sm\` | \`drop-shadow-xs\` | Consistência |
|
|
2923
|
-
| \`blur-sm\` | \`blur-xs\` | Consistência |
|
|
2924
|
-
| \`rounded-sm\` | \`rounded-xs\` | Consistência |
|
|
2925
|
-
|
|
2926
|
-
## Opacidade Inline
|
|
2927
|
-
|
|
2928
|
-
\`\`\`html
|
|
2929
|
-
<!-- v3 (deprecated) -->
|
|
2930
|
-
<div class="bg-blue-500 bg-opacity-50">
|
|
2931
|
-
|
|
2932
|
-
<!-- v4 (novo) -->
|
|
2933
|
-
<div class="bg-blue-500/50">
|
|
2934
|
-
\`\`\`
|
|
2935
|
-
|
|
2936
|
-
## Novas Utilities
|
|
2937
|
-
|
|
2938
|
-
\`\`\`html
|
|
2939
|
-
<!-- Size (width + height) -->
|
|
2940
|
-
<div class="size-10"> <!-- w-10 h-10 -->
|
|
2941
|
-
|
|
2942
|
-
<!-- Inset shortcuts -->
|
|
2943
|
-
<div class="inset-x-4"> <!-- left-4 right-4 -->
|
|
2944
|
-
<div class="inset-y-4"> <!-- top-4 bottom-4 -->
|
|
2945
|
-
|
|
2946
|
-
<!-- Logical properties -->
|
|
2947
|
-
<div class="ps-4"> <!-- padding-inline-start -->
|
|
2948
|
-
<div class="pe-4"> <!-- padding-inline-end -->
|
|
2949
|
-
<div class="ms-4"> <!-- margin-inline-start -->
|
|
2950
|
-
<div class="me-4"> <!-- margin-inline-end -->
|
|
2951
|
-
\`\`\``,
|
|
2952
|
-
variants: `# 🎯 Novos Variants (v4)
|
|
2953
|
-
|
|
2954
|
-
## Container Queries
|
|
2955
|
-
|
|
2956
|
-
\`\`\`html
|
|
2957
|
-
<div class="@container">
|
|
2958
|
-
<div class="@sm:flex @lg:grid @lg:grid-cols-2">
|
|
2959
|
-
<!-- Responde ao tamanho do container -->
|
|
2960
|
-
</div>
|
|
2961
|
-
</div>
|
|
2962
|
-
|
|
2963
|
-
<!-- Named containers -->
|
|
2964
|
-
<div class="@container/sidebar">
|
|
2965
|
-
<div class="@lg/sidebar:block">
|
|
2966
|
-
\`\`\`
|
|
2967
|
-
|
|
2968
|
-
## Variants Compostos
|
|
2969
|
-
|
|
2970
|
-
\`\`\`html
|
|
2971
|
-
<!-- has-* (parent has child) -->
|
|
2972
|
-
<div class="has-[input:focus]:ring-2">
|
|
2973
|
-
<input type="text">
|
|
2974
|
-
</div>
|
|
2975
|
-
|
|
2976
|
-
<!-- in-* (is inside) -->
|
|
2977
|
-
<div class="in-[.dark]:text-white">
|
|
2978
|
-
|
|
2979
|
-
<!-- not-* (negation) -->
|
|
2980
|
-
<div class="not-[.active]:opacity-50">
|
|
2981
|
-
\`\`\`
|
|
2982
|
-
|
|
2983
|
-
## Starting Style
|
|
2984
|
-
|
|
2985
|
-
\`\`\`html
|
|
2986
|
-
<!-- Animação de entrada -->
|
|
2987
|
-
<div class="
|
|
2988
|
-
opacity-100 transition-opacity
|
|
2989
|
-
starting:opacity-0
|
|
2990
|
-
">
|
|
2991
|
-
\`\`\`
|
|
2992
|
-
|
|
2993
|
-
## Novos State Variants
|
|
2994
|
-
|
|
2995
|
-
\`\`\`html
|
|
2996
|
-
<!-- Inert state -->
|
|
2997
|
-
<div class="inert:opacity-50" inert>
|
|
2998
|
-
|
|
2999
|
-
<!-- Open/closed (details, dialog) -->
|
|
3000
|
-
<details class="open:bg-white">
|
|
3001
|
-
<summary>Click me</summary>
|
|
3002
|
-
</details>
|
|
3003
|
-
\`\`\``,
|
|
3004
|
-
plugins: `# 🔌 Plugins no v4
|
|
3005
|
-
|
|
3006
|
-
## Import via CSS
|
|
3007
|
-
|
|
3008
|
-
\`\`\`css
|
|
3009
|
-
@import "tailwindcss";
|
|
3010
|
-
|
|
3011
|
-
/* Plugins oficiais */
|
|
3012
|
-
@plugin "@tailwindcss/typography";
|
|
3013
|
-
@plugin "@tailwindcss/forms";
|
|
3014
|
-
@plugin "@tailwindcss/aspect-ratio";
|
|
3015
|
-
@plugin "@tailwindcss/container-queries";
|
|
3016
|
-
|
|
3017
|
-
/* Plugin customizado local */
|
|
3018
|
-
@plugin "./my-plugin.js";
|
|
3019
|
-
\`\`\`
|
|
3020
|
-
|
|
3021
|
-
## Criando Plugin (v4)
|
|
3022
|
-
|
|
3023
|
-
\`\`\`js
|
|
3024
|
-
// my-plugin.js
|
|
3025
|
-
export default function({ addUtilities, theme }) {
|
|
3026
|
-
addUtilities({
|
|
3027
|
-
'.text-shadow': {
|
|
3028
|
-
'text-shadow': '2px 2px 4px rgb(0 0 0 / 0.1)',
|
|
3029
|
-
},
|
|
3030
|
-
'.text-shadow-lg': {
|
|
3031
|
-
'text-shadow': '4px 4px 8px rgb(0 0 0 / 0.2)',
|
|
3032
|
-
},
|
|
3033
|
-
})
|
|
3034
|
-
}
|
|
3035
|
-
\`\`\`
|
|
3036
|
-
|
|
3037
|
-
## Diferenças do v3
|
|
3038
|
-
|
|
3039
|
-
| v3 | v4 |
|
|
3040
|
-
|----|----|
|
|
3041
|
-
| \`plugins: [require(...)]\` | \`@plugin "..."\` |
|
|
3042
|
-
| CommonJS | ES Modules |
|
|
3043
|
-
| \`tailwind.config.js\` | CSS direto |`,
|
|
3044
|
-
'breaking-changes': `# ⚠️ Breaking Changes (v3 → v4)
|
|
3045
|
-
|
|
3046
|
-
## Classes Removidas/Alteradas
|
|
3047
|
-
|
|
3048
|
-
### Opacidade Separada (REMOVIDO)
|
|
3049
|
-
\`\`\`html
|
|
3050
|
-
<!-- ❌ NÃO funciona no v4 -->
|
|
3051
|
-
<div class="bg-blue-500 bg-opacity-50">
|
|
3052
|
-
<div class="text-red-500 text-opacity-75">
|
|
3053
|
-
|
|
3054
|
-
<!-- ✅ Use modificador inline -->
|
|
3055
|
-
<div class="bg-blue-500/50">
|
|
3056
|
-
<div class="text-red-500/75">
|
|
3057
|
-
\`\`\`
|
|
3058
|
-
|
|
3059
|
-
### Transform Utilities
|
|
3060
|
-
\`\`\`html
|
|
3061
|
-
<!-- ❌ v3 (removido) -->
|
|
3062
|
-
<div class="transform scale-50">
|
|
3063
|
-
|
|
3064
|
-
<!-- ✅ v4 (automático) -->
|
|
3065
|
-
<div class="scale-50">
|
|
3066
|
-
\`\`\`
|
|
3067
|
-
|
|
3068
|
-
### Filter Utilities
|
|
3069
|
-
\`\`\`html
|
|
3070
|
-
<!-- ❌ v3 (removido) -->
|
|
3071
|
-
<div class="filter blur-sm">
|
|
3072
|
-
|
|
3073
|
-
<!-- ✅ v4 (automático) -->
|
|
3074
|
-
<div class="blur-sm">
|
|
3075
|
-
\`\`\`
|
|
3076
|
-
|
|
3077
|
-
### Ring Width Default
|
|
3078
|
-
\`\`\`html
|
|
3079
|
-
<!-- v3: ring = 3px -->
|
|
3080
|
-
<!-- v4: ring = 1px -->
|
|
3081
|
-
|
|
3082
|
-
<!-- Para manter 3px no v4 -->
|
|
3083
|
-
<div class="ring-3">
|
|
3084
|
-
\`\`\`
|
|
3085
|
-
|
|
3086
|
-
## Configuração
|
|
3087
|
-
|
|
3088
|
-
\`\`\`js
|
|
3089
|
-
// ❌ v3 tailwind.config.js (não necessário no v4)
|
|
3090
|
-
module.exports = {
|
|
3091
|
-
content: ['./src/**/*.{html,js}'],
|
|
3092
|
-
theme: { extend: {} },
|
|
3093
|
-
plugins: [],
|
|
3094
|
-
}
|
|
3095
|
-
\`\`\`
|
|
3096
|
-
|
|
3097
|
-
\`\`\`css
|
|
3098
|
-
/* ✅ v4 - tudo no CSS */
|
|
3099
|
-
@import "tailwindcss";
|
|
3100
|
-
@source "./src/**/*.{html,js}";
|
|
3101
|
-
\`\`\``,
|
|
3102
|
-
'postcss-vite': `# 🛠️ Setup PostCSS e Vite (v4)
|
|
3103
|
-
|
|
3104
|
-
## Vite (Recomendado)
|
|
3105
|
-
|
|
3106
|
-
\`\`\`bash
|
|
3107
|
-
npm install tailwindcss @tailwindcss/vite
|
|
3108
|
-
\`\`\`
|
|
3109
|
-
|
|
3110
|
-
\`\`\`js
|
|
3111
|
-
// vite.config.js
|
|
3112
|
-
import tailwindcss from '@tailwindcss/vite'
|
|
3113
|
-
|
|
3114
|
-
export default {
|
|
3115
|
-
plugins: [tailwindcss()],
|
|
3116
|
-
}
|
|
3117
|
-
\`\`\`
|
|
3118
|
-
|
|
3119
|
-
\`\`\`css
|
|
3120
|
-
/* main.css */
|
|
3121
|
-
@import "tailwindcss";
|
|
3122
|
-
\`\`\`
|
|
3123
|
-
|
|
3124
|
-
## PostCSS
|
|
3125
|
-
|
|
3126
|
-
\`\`\`bash
|
|
3127
|
-
npm install tailwindcss @tailwindcss/postcss
|
|
3128
|
-
\`\`\`
|
|
3129
|
-
|
|
3130
|
-
\`\`\`js
|
|
3131
|
-
// postcss.config.js
|
|
3132
|
-
export default {
|
|
3133
|
-
plugins: {
|
|
3134
|
-
'@tailwindcss/postcss': {},
|
|
3135
|
-
},
|
|
3136
|
-
}
|
|
3137
|
-
\`\`\`
|
|
3138
|
-
|
|
3139
|
-
## CLI Standalone
|
|
3140
|
-
|
|
3141
|
-
\`\`\`bash
|
|
3142
|
-
npm install tailwindcss @tailwindcss/cli
|
|
3143
|
-
npx @tailwindcss/cli -i input.css -o output.css --watch
|
|
3144
|
-
\`\`\`
|
|
3145
|
-
|
|
3146
|
-
## Content Sources
|
|
3147
|
-
|
|
3148
|
-
\`\`\`css
|
|
3149
|
-
/* Detecta automaticamente, mas pode especificar */
|
|
3150
|
-
@import "tailwindcss";
|
|
3151
|
-
|
|
3152
|
-
/* Adicionar sources explícitos */
|
|
3153
|
-
@source "./src/**/*.{html,js,jsx,ts,tsx}";
|
|
3154
|
-
@source "./components/**/*.vue";
|
|
3155
|
-
|
|
3156
|
-
/* Ignorar paths */
|
|
3157
|
-
@source not "./src/legacy/**";
|
|
3158
|
-
\`\`\``,
|
|
3159
|
-
};
|
|
3160
|
-
if (!topico) {
|
|
3161
|
-
let result = '# 📚 Guia de Migração Tailwind CSS v3 → v4\n\n';
|
|
3162
|
-
result += 'Escolha um tópico para ver detalhes:\n\n';
|
|
3163
|
-
result += '| Tópico | Descrição |\n';
|
|
3164
|
-
result += '|--------|----------|\n';
|
|
3165
|
-
result += '| `overview` | Visão geral das mudanças |\n';
|
|
3166
|
-
result += '| `css-first` | Nova configuração via CSS |\n';
|
|
3167
|
-
result += '| `theme-config` | Customização de tema |\n';
|
|
3168
|
-
result += '| `utilities` | Mudanças em classes |\n';
|
|
3169
|
-
result += '| `variants` | Novos variants |\n';
|
|
3170
|
-
result += '| `plugins` | Plugins no v4 |\n';
|
|
3171
|
-
result += '| `breaking-changes` | O que quebra |\n';
|
|
3172
|
-
result += '| `postcss-vite` | Setup do build |\n';
|
|
3173
|
-
result += '\n**Exemplo:** `tailwind_migracao_v4({ topico: "breaking-changes" })`\n';
|
|
3174
|
-
return { content: [{ type: 'text', text: result }] };
|
|
3175
|
-
}
|
|
3176
|
-
const content = migracaoContent[topico];
|
|
3177
|
-
if (!content) {
|
|
3178
|
-
return {
|
|
3179
|
-
content: [{ type: 'text', text: `❌ Tópico não encontrado: ${topico}\n\nTópicos disponíveis: ${Object.keys(migracaoContent).join(', ')}` }],
|
|
3180
|
-
isError: true,
|
|
3181
|
-
};
|
|
3182
|
-
}
|
|
3183
|
-
return { content: [{ type: 'text', text: content }] };
|
|
3184
|
-
}
|
|
3185
|
-
case 'tailwind_boas_praticas': {
|
|
3186
|
-
const topico = args?.topico;
|
|
3187
|
-
const boasPraticas = {
|
|
3188
|
-
organizacao: `# 📋 Organização de Classes
|
|
3189
|
-
|
|
3190
|
-
## Ordem Recomendada
|
|
3191
|
-
|
|
3192
|
-
Organize classes nesta ordem para consistência:
|
|
3193
|
-
|
|
3194
|
-
1. **Layout** (display, position, flexbox/grid)
|
|
3195
|
-
2. **Sizing** (width, height)
|
|
3196
|
-
3. **Spacing** (margin, padding)
|
|
3197
|
-
4. **Typography** (font, text)
|
|
3198
|
-
5. **Visual** (background, border, shadow)
|
|
3199
|
-
6. **Effects** (opacity, filters)
|
|
3200
|
-
7. **Transitions/Animations**
|
|
3201
|
-
8. **Variants** (hover, focus, responsive)
|
|
3202
|
-
|
|
3203
|
-
\`\`\`html
|
|
3204
|
-
<button class="
|
|
3205
|
-
flex items-center justify-center /* Layout */
|
|
3206
|
-
w-full h-12 /* Sizing */
|
|
3207
|
-
px-4 py-2 /* Spacing */
|
|
3208
|
-
text-sm font-medium text-white /* Typography */
|
|
3209
|
-
bg-blue-600 rounded-lg shadow /* Visual */
|
|
3210
|
-
transition-colors /* Transitions */
|
|
3211
|
-
hover:bg-blue-700 focus:ring-2 /* Variants */
|
|
3212
|
-
">
|
|
3213
|
-
Botão
|
|
3214
|
-
</button>
|
|
3215
|
-
\`\`\`
|
|
3216
|
-
|
|
3217
|
-
## Multi-line para Legibilidade
|
|
3218
|
-
|
|
3219
|
-
\`\`\`html
|
|
3220
|
-
<!-- ❌ Difícil de ler -->
|
|
3221
|
-
<div class="flex items-center justify-between p-4 bg-white rounded-lg shadow-md hover:shadow-lg transition-shadow">
|
|
3222
|
-
|
|
3223
|
-
<!-- ✅ Mais legível -->
|
|
3224
|
-
<div class="
|
|
3225
|
-
flex items-center justify-between
|
|
3226
|
-
p-4
|
|
3227
|
-
bg-white rounded-lg
|
|
3228
|
-
shadow-md hover:shadow-lg
|
|
3229
|
-
transition-shadow
|
|
3230
|
-
">
|
|
3231
|
-
\`\`\``,
|
|
3232
|
-
componentes: `# 🧩 Extração de Componentes
|
|
3233
|
-
|
|
3234
|
-
## Quando Extrair
|
|
3235
|
-
|
|
3236
|
-
Extraia quando:
|
|
3237
|
-
- Mesmo conjunto de classes usado 3+ vezes
|
|
3238
|
-
- Componente tem lógica complexa
|
|
3239
|
-
- Precisa de variantes (primary, secondary)
|
|
3240
|
-
|
|
3241
|
-
## React/Vue Components
|
|
3242
|
-
|
|
3243
|
-
\`\`\`jsx
|
|
3244
|
-
// ✅ Componente React
|
|
3245
|
-
function Button({ variant = 'primary', children }) {
|
|
3246
|
-
const variants = {
|
|
3247
|
-
primary: 'bg-blue-600 text-white hover:bg-blue-700',
|
|
3248
|
-
secondary: 'bg-gray-200 text-gray-800 hover:bg-gray-300',
|
|
3249
|
-
outline: 'border-2 border-blue-600 text-blue-600 hover:bg-blue-50',
|
|
3250
|
-
}
|
|
3251
|
-
|
|
3252
|
-
return (
|
|
3253
|
-
<button className={\`
|
|
3254
|
-
px-4 py-2 font-medium rounded-lg
|
|
3255
|
-
transition-colors focus:outline-none focus:ring-2
|
|
3256
|
-
\${variants[variant]}
|
|
3257
|
-
\`}>
|
|
3258
|
-
{children}
|
|
3259
|
-
</button>
|
|
3260
|
-
)
|
|
3261
|
-
}
|
|
3262
|
-
\`\`\`
|
|
3263
|
-
|
|
3264
|
-
## @apply (Usar com Moderação)
|
|
3265
|
-
|
|
3266
|
-
\`\`\`css
|
|
3267
|
-
/* ⚠️ Use apenas quando necessário */
|
|
3268
|
-
@layer components {
|
|
3269
|
-
.btn {
|
|
3270
|
-
@apply px-4 py-2 font-medium rounded-lg transition-colors;
|
|
3271
|
-
}
|
|
3272
|
-
|
|
3273
|
-
.btn-primary {
|
|
3274
|
-
@apply bg-blue-600 text-white hover:bg-blue-700;
|
|
3275
|
-
}
|
|
3276
|
-
}
|
|
3277
|
-
\`\`\`
|
|
3278
|
-
|
|
3279
|
-
## Tailwind Merge (recomendado)
|
|
3280
|
-
|
|
3281
|
-
\`\`\`jsx
|
|
3282
|
-
import { twMerge } from 'tailwind-merge'
|
|
3283
|
-
|
|
3284
|
-
// Resolve conflitos de classes
|
|
3285
|
-
<div className={twMerge('px-4 py-2', className)}>
|
|
3286
|
-
\`\`\``,
|
|
3287
|
-
performance: `# ⚡ Performance
|
|
3288
|
-
|
|
3289
|
-
## Content Configuration
|
|
3290
|
-
|
|
3291
|
-
\`\`\`css
|
|
3292
|
-
/* v4: Seja específico nos sources */
|
|
3293
|
-
@import "tailwindcss";
|
|
3294
|
-
@source "./src/**/*.{js,jsx,ts,tsx}";
|
|
3295
|
-
@source "./components/**/*.vue";
|
|
3296
|
-
@source not "./node_modules/**";
|
|
3297
|
-
\`\`\`
|
|
3298
|
-
|
|
3299
|
-
## Evite Classes Dinâmicas
|
|
3300
|
-
|
|
3301
|
-
\`\`\`jsx
|
|
3302
|
-
// ❌ Tailwind não detecta
|
|
3303
|
-
<div className={\`bg-\${color}-500\`}>
|
|
3304
|
-
|
|
3305
|
-
// ✅ Use objeto de mapeamento
|
|
3306
|
-
const colors = {
|
|
3307
|
-
blue: 'bg-blue-500',
|
|
3308
|
-
red: 'bg-red-500',
|
|
3309
|
-
green: 'bg-green-500',
|
|
3310
|
-
}
|
|
3311
|
-
<div className={colors[color]}>
|
|
3312
|
-
\`\`\`
|
|
3313
|
-
|
|
3314
|
-
## Safelist (quando necessário)
|
|
3315
|
-
|
|
3316
|
-
\`\`\`css
|
|
3317
|
-
/* v4: Forçar inclusão de classes */
|
|
3318
|
-
@import "tailwindcss";
|
|
3319
|
-
@utility bg-brand-* {
|
|
3320
|
-
/* Garante que bg-brand-{any} seja incluído */
|
|
3321
|
-
}
|
|
3322
|
-
\`\`\`
|
|
3323
|
-
|
|
3324
|
-
## Minificação
|
|
3325
|
-
|
|
3326
|
-
\`\`\`bash
|
|
3327
|
-
# CLI com minificação
|
|
3328
|
-
npx @tailwindcss/cli -i input.css -o output.css --minify
|
|
3329
|
-
|
|
3330
|
-
# Vite faz automaticamente em build
|
|
3331
|
-
\`\`\`
|
|
3332
|
-
|
|
3333
|
-
## Cache
|
|
3334
|
-
|
|
3335
|
-
- Use cache do bundler (Vite/Webpack)
|
|
3336
|
-
- Tailwind v4 é 10x mais rápido que v3`,
|
|
3337
|
-
acessibilidade: `# ♿ Acessibilidade
|
|
3338
|
-
|
|
3339
|
-
## Focus Visible
|
|
3340
|
-
|
|
3341
|
-
\`\`\`html
|
|
3342
|
-
<!-- Foco apenas para navegação por teclado -->
|
|
3343
|
-
<button class="
|
|
3344
|
-
focus:outline-none
|
|
3345
|
-
focus-visible:ring-2 focus-visible:ring-blue-500
|
|
3346
|
-
">
|
|
3347
|
-
Botão Acessível
|
|
3348
|
-
</button>
|
|
3349
|
-
\`\`\`
|
|
3350
|
-
|
|
3351
|
-
## Screen Reader Only
|
|
3352
|
-
|
|
3353
|
-
\`\`\`html
|
|
3354
|
-
<!-- Texto só para leitores de tela -->
|
|
3355
|
-
<span class="sr-only">Fechar menu</span>
|
|
3356
|
-
|
|
3357
|
-
<!-- Ícone com label acessível -->
|
|
3358
|
-
<button aria-label="Fechar">
|
|
3359
|
-
<svg class="w-5 h-5" aria-hidden="true">...</svg>
|
|
3360
|
-
</button>
|
|
3361
|
-
\`\`\`
|
|
3362
|
-
|
|
3363
|
-
## Motion Reduce
|
|
3364
|
-
|
|
3365
|
-
\`\`\`html
|
|
3366
|
-
<!-- Respeitar preferências do usuário -->
|
|
3367
|
-
<div class="
|
|
3368
|
-
animate-bounce
|
|
3369
|
-
motion-reduce:animate-none
|
|
3370
|
-
">
|
|
3371
|
-
\`\`\`
|
|
3372
|
-
|
|
3373
|
-
## Contraste
|
|
3374
|
-
|
|
3375
|
-
\`\`\`html
|
|
3376
|
-
<!-- Alto contraste quando necessário -->
|
|
3377
|
-
<div class="
|
|
3378
|
-
text-gray-600
|
|
3379
|
-
contrast-more:text-gray-900
|
|
3380
|
-
contrast-more:border-2
|
|
3381
|
-
">
|
|
3382
|
-
\`\`\`
|
|
3383
|
-
|
|
3384
|
-
## ARIA Variants
|
|
3385
|
-
|
|
3386
|
-
\`\`\`html
|
|
3387
|
-
<!-- Estilos baseados em ARIA -->
|
|
3388
|
-
<button
|
|
3389
|
-
aria-expanded="true"
|
|
3390
|
-
class="aria-expanded:rotate-180"
|
|
3391
|
-
>
|
|
3392
|
-
<svg>...</svg>
|
|
3393
|
-
</button>
|
|
3394
|
-
\`\`\``,
|
|
3395
|
-
responsivo: `# 📱 Design Responsivo
|
|
3396
|
-
|
|
3397
|
-
## Mobile-First
|
|
3398
|
-
|
|
3399
|
-
\`\`\`html
|
|
3400
|
-
<!-- Base = mobile, depois aumenta -->
|
|
3401
|
-
<div class="
|
|
3402
|
-
flex flex-col /* Mobile: coluna */
|
|
3403
|
-
md:flex-row /* Tablet+: linha */
|
|
3404
|
-
">
|
|
3405
|
-
\`\`\`
|
|
3406
|
-
|
|
3407
|
-
## Container Queries (v4)
|
|
3408
|
-
|
|
3409
|
-
\`\`\`html
|
|
3410
|
-
<!-- Responde ao container, não à viewport -->
|
|
3411
|
-
<div class="@container">
|
|
3412
|
-
<div class="
|
|
3413
|
-
@sm:flex
|
|
3414
|
-
@lg:grid @lg:grid-cols-2
|
|
3415
|
-
">
|
|
3416
|
-
\`\`\`
|
|
3417
|
-
|
|
3418
|
-
## Breakpoints Úteis
|
|
3419
|
-
|
|
3420
|
-
\`\`\`html
|
|
3421
|
-
<div class="
|
|
3422
|
-
grid grid-cols-1 /* < 640px */
|
|
3423
|
-
sm:grid-cols-2 /* ≥ 640px */
|
|
3424
|
-
md:grid-cols-3 /* ≥ 768px */
|
|
3425
|
-
lg:grid-cols-4 /* ≥ 1024px */
|
|
3426
|
-
xl:grid-cols-5 /* ≥ 1280px */
|
|
3427
|
-
">
|
|
3428
|
-
\`\`\`
|
|
3429
|
-
|
|
3430
|
-
## Max-Width Variants
|
|
3431
|
-
|
|
3432
|
-
\`\`\`html
|
|
3433
|
-
<!-- Esconder apenas em mobile -->
|
|
3434
|
-
<div class="hidden sm:block">Desktop only</div>
|
|
3435
|
-
|
|
3436
|
-
<!-- Mostrar apenas em mobile -->
|
|
3437
|
-
<div class="sm:hidden">Mobile only</div>
|
|
3438
|
-
\`\`\`
|
|
3439
|
-
|
|
3440
|
-
## Layout Responsivo Completo
|
|
3441
|
-
|
|
3442
|
-
\`\`\`html
|
|
3443
|
-
<div class="min-h-screen flex flex-col">
|
|
3444
|
-
<header class="h-16 px-4 md:px-6 lg:px-8">
|
|
3445
|
-
Nav
|
|
3446
|
-
</header>
|
|
3447
|
-
|
|
3448
|
-
<main class="flex-1 container mx-auto px-4 py-6">
|
|
3449
|
-
<div class="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
|
3450
|
-
<!-- Cards -->
|
|
3451
|
-
</div>
|
|
3452
|
-
</main>
|
|
3453
|
-
|
|
3454
|
-
<footer class="h-20">
|
|
3455
|
-
Footer
|
|
3456
|
-
</footer>
|
|
3457
|
-
</div>
|
|
3458
|
-
\`\`\``,
|
|
3459
|
-
'dark-mode': `# 🌙 Dark Mode
|
|
3460
|
-
|
|
3461
|
-
## Setup Básico
|
|
3462
|
-
|
|
3463
|
-
\`\`\`html
|
|
3464
|
-
<!-- Classe no html ou body -->
|
|
3465
|
-
<html class="dark">
|
|
3466
|
-
<body class="bg-white dark:bg-gray-900">
|
|
3467
|
-
\`\`\`
|
|
3468
|
-
|
|
3469
|
-
## Padrões Comuns
|
|
3470
|
-
|
|
3471
|
-
\`\`\`html
|
|
3472
|
-
<!-- Texto -->
|
|
3473
|
-
<p class="text-gray-900 dark:text-white">
|
|
3474
|
-
<p class="text-gray-600 dark:text-gray-400">
|
|
3475
|
-
|
|
3476
|
-
<!-- Backgrounds -->
|
|
3477
|
-
<div class="bg-white dark:bg-gray-800">
|
|
3478
|
-
<div class="bg-gray-50 dark:bg-gray-900">
|
|
3479
|
-
|
|
3480
|
-
<!-- Borders -->
|
|
3481
|
-
<div class="border-gray-200 dark:border-gray-700">
|
|
3482
|
-
|
|
3483
|
-
<!-- Shadows -->
|
|
3484
|
-
<div class="shadow-lg dark:shadow-gray-900/20">
|
|
3485
|
-
\`\`\`
|
|
3486
|
-
|
|
3487
|
-
## Toggle com JavaScript
|
|
3488
|
-
|
|
3489
|
-
\`\`\`js
|
|
3490
|
-
// Alternar dark mode
|
|
3491
|
-
document.documentElement.classList.toggle('dark')
|
|
3492
|
-
|
|
3493
|
-
// Persistir preferência
|
|
3494
|
-
localStorage.setItem('theme', 'dark')
|
|
3495
|
-
|
|
3496
|
-
// Detectar preferência do sistema
|
|
3497
|
-
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
3498
|
-
document.documentElement.classList.add('dark')
|
|
3499
|
-
}
|
|
3500
|
-
\`\`\`
|
|
3501
|
-
|
|
3502
|
-
## Componente Dark Mode Aware
|
|
3503
|
-
|
|
3504
|
-
\`\`\`html
|
|
3505
|
-
<div class="
|
|
3506
|
-
bg-white dark:bg-gray-800
|
|
3507
|
-
text-gray-900 dark:text-white
|
|
3508
|
-
border border-gray-200 dark:border-gray-700
|
|
3509
|
-
shadow-lg dark:shadow-none
|
|
3510
|
-
rounded-lg p-6
|
|
3511
|
-
">
|
|
3512
|
-
<h2 class="text-xl font-bold">Título</h2>
|
|
3513
|
-
<p class="text-gray-600 dark:text-gray-400">
|
|
3514
|
-
Conteúdo que funciona nos dois modos.
|
|
3515
|
-
</p>
|
|
3516
|
-
</div>
|
|
3517
|
-
\`\`\``,
|
|
3518
|
-
animacoes: `# 🎬 Animações e Transições
|
|
3519
|
-
|
|
3520
|
-
## Transições Básicas
|
|
3521
|
-
|
|
3522
|
-
\`\`\`html
|
|
3523
|
-
<!-- Transição suave -->
|
|
3524
|
-
<button class="
|
|
3525
|
-
bg-blue-500
|
|
3526
|
-
transition-colors duration-200
|
|
3527
|
-
hover:bg-blue-600
|
|
3528
|
-
">
|
|
3529
|
-
|
|
3530
|
-
<!-- Transição completa -->
|
|
3531
|
-
<div class="
|
|
3532
|
-
transform transition-all duration-300 ease-out
|
|
3533
|
-
hover:scale-105 hover:shadow-lg
|
|
3534
|
-
">
|
|
3535
|
-
\`\`\`
|
|
3536
|
-
|
|
3537
|
-
## Animações Built-in
|
|
3538
|
-
|
|
3539
|
-
\`\`\`html
|
|
3540
|
-
<!-- Spin (loading) -->
|
|
3541
|
-
<svg class="animate-spin h-5 w-5">
|
|
3542
|
-
|
|
3543
|
-
<!-- Pulse -->
|
|
3544
|
-
<div class="animate-pulse">
|
|
3545
|
-
|
|
3546
|
-
<!-- Bounce -->
|
|
3547
|
-
<div class="animate-bounce">
|
|
3548
|
-
|
|
3549
|
-
<!-- Ping (notification) -->
|
|
3550
|
-
<span class="animate-ping">
|
|
3551
|
-
\`\`\`
|
|
3552
|
-
|
|
3553
|
-
## Animação Customizada
|
|
3554
|
-
|
|
3555
|
-
\`\`\`css
|
|
3556
|
-
@theme {
|
|
3557
|
-
--animate-fade-in: fadeIn 0.3s ease-out;
|
|
3558
|
-
--animate-slide-up: slideUp 0.4s ease-out;
|
|
3559
|
-
}
|
|
3560
|
-
|
|
3561
|
-
@keyframes fadeIn {
|
|
3562
|
-
from { opacity: 0; }
|
|
3563
|
-
to { opacity: 1; }
|
|
3564
|
-
}
|
|
3565
|
-
|
|
3566
|
-
@keyframes slideUp {
|
|
3567
|
-
from {
|
|
3568
|
-
opacity: 0;
|
|
3569
|
-
transform: translateY(10px);
|
|
3570
|
-
}
|
|
3571
|
-
to {
|
|
3572
|
-
opacity: 1;
|
|
3573
|
-
transform: translateY(0);
|
|
3574
|
-
}
|
|
3575
|
-
}
|
|
3576
|
-
\`\`\`
|
|
3577
|
-
|
|
3578
|
-
## Starting Style (v4)
|
|
3579
|
-
|
|
3580
|
-
\`\`\`html
|
|
3581
|
-
<!-- Animação de entrada automática -->
|
|
3582
|
-
<div class="
|
|
3583
|
-
opacity-100 transition-opacity duration-300
|
|
3584
|
-
starting:opacity-0
|
|
3585
|
-
">
|
|
3586
|
-
Aparece com fade
|
|
3587
|
-
</div>
|
|
3588
|
-
\`\`\`
|
|
3589
|
-
|
|
3590
|
-
## Motion Safe/Reduce
|
|
3591
|
-
|
|
3592
|
-
\`\`\`html
|
|
3593
|
-
<div class="
|
|
3594
|
-
animate-bounce
|
|
3595
|
-
motion-reduce:animate-none
|
|
3596
|
-
motion-safe:transition-transform
|
|
3597
|
-
">
|
|
3598
|
-
\`\`\``,
|
|
3599
|
-
forms: `# 📝 Formulários
|
|
3600
|
-
|
|
3601
|
-
## Input Estilizado
|
|
3602
|
-
|
|
3603
|
-
\`\`\`html
|
|
3604
|
-
<input
|
|
3605
|
-
type="text"
|
|
3606
|
-
class="
|
|
3607
|
-
w-full px-4 py-2
|
|
3608
|
-
border border-gray-300 rounded-lg
|
|
3609
|
-
focus:ring-2 focus:ring-blue-500 focus:border-blue-500
|
|
3610
|
-
placeholder:text-gray-400
|
|
3611
|
-
disabled:bg-gray-100 disabled:cursor-not-allowed
|
|
3612
|
-
"
|
|
3613
|
-
placeholder="Digite aqui..."
|
|
3614
|
-
>
|
|
3615
|
-
\`\`\`
|
|
3616
|
-
|
|
3617
|
-
## Estados de Validação
|
|
3618
|
-
|
|
3619
|
-
\`\`\`html
|
|
3620
|
-
<!-- Input válido -->
|
|
3621
|
-
<input class="
|
|
3622
|
-
border-green-500
|
|
3623
|
-
focus:ring-green-500
|
|
3624
|
-
valid:border-green-500
|
|
3625
|
-
">
|
|
3626
|
-
|
|
3627
|
-
<!-- Input inválido -->
|
|
3628
|
-
<input class="
|
|
3629
|
-
border-red-500
|
|
3630
|
-
focus:ring-red-500
|
|
3631
|
-
invalid:border-red-500
|
|
3632
|
-
">
|
|
3633
|
-
\`\`\`
|
|
3634
|
-
|
|
3635
|
-
## Checkbox Customizado
|
|
3636
|
-
|
|
3637
|
-
\`\`\`html
|
|
3638
|
-
<label class="flex items-center gap-2 cursor-pointer">
|
|
3639
|
-
<input
|
|
3640
|
-
type="checkbox"
|
|
3641
|
-
class="
|
|
3642
|
-
w-5 h-5 rounded
|
|
3643
|
-
text-blue-600
|
|
3644
|
-
border-gray-300
|
|
3645
|
-
focus:ring-blue-500
|
|
3646
|
-
"
|
|
3647
|
-
>
|
|
3648
|
-
<span class="text-gray-700">Aceito os termos</span>
|
|
3649
|
-
</label>
|
|
3650
|
-
\`\`\`
|
|
3651
|
-
|
|
3652
|
-
## Select Estilizado
|
|
3653
|
-
|
|
3654
|
-
\`\`\`html
|
|
3655
|
-
<select class="
|
|
3656
|
-
w-full px-4 py-2
|
|
3657
|
-
border border-gray-300 rounded-lg
|
|
3658
|
-
bg-white
|
|
3659
|
-
focus:ring-2 focus:ring-blue-500
|
|
3660
|
-
">
|
|
3661
|
-
<option>Opção 1</option>
|
|
3662
|
-
<option>Opção 2</option>
|
|
3663
|
-
</select>
|
|
3664
|
-
\`\`\`
|
|
3665
|
-
|
|
3666
|
-
## Plugin Forms (Recomendado)
|
|
3667
|
-
|
|
3668
|
-
\`\`\`css
|
|
3669
|
-
@import "tailwindcss";
|
|
3670
|
-
@plugin "@tailwindcss/forms";
|
|
3671
|
-
\`\`\`
|
|
3672
|
-
|
|
3673
|
-
Aplica estilos base automaticamente a todos os inputs.`,
|
|
3674
|
-
};
|
|
3675
|
-
if (!topico) {
|
|
3676
|
-
let result = '# 💡 Boas Práticas Tailwind CSS\n\n';
|
|
3677
|
-
result += 'Escolha um tópico:\n\n';
|
|
3678
|
-
result += '| Tópico | Descrição |\n';
|
|
3679
|
-
result += '|--------|----------|\n';
|
|
3680
|
-
result += '| `organizacao` | Ordem e organização de classes |\n';
|
|
3681
|
-
result += '| `componentes` | Extração e reutilização |\n';
|
|
3682
|
-
result += '| `performance` | Otimização de bundle |\n';
|
|
3683
|
-
result += '| `acessibilidade` | A11y com Tailwind |\n';
|
|
3684
|
-
result += '| `responsivo` | Design responsivo |\n';
|
|
3685
|
-
result += '| `dark-mode` | Implementação de dark mode |\n';
|
|
3686
|
-
result += '| `animacoes` | Transições e animações |\n';
|
|
3687
|
-
result += '| `forms` | Estilização de formulários |\n';
|
|
3688
|
-
result += '\n**Exemplo:** `tailwind_boas_praticas({ topico: "responsivo" })`\n';
|
|
3689
|
-
return { content: [{ type: 'text', text: result }] };
|
|
3690
|
-
}
|
|
3691
|
-
const content = boasPraticas[topico];
|
|
3692
|
-
if (!content) {
|
|
3693
|
-
return {
|
|
3694
|
-
content: [{ type: 'text', text: `❌ Tópico não encontrado: ${topico}\n\nTópicos disponíveis: ${Object.keys(boasPraticas).join(', ')}` }],
|
|
3695
|
-
isError: true,
|
|
3696
|
-
};
|
|
3697
|
-
}
|
|
3698
|
-
return { content: [{ type: 'text', text: content }] };
|
|
3699
|
-
}
|
|
3700
|
-
case 'tailwind_check_updates': {
|
|
3701
|
-
const updateInfo = await checkForUpdates();
|
|
3702
|
-
let result = '# 🔍 Verificação de Atualizações\n\n';
|
|
3703
|
-
if (updateInfo.hasUpdate) {
|
|
3704
|
-
result += '⚠️ **Atualização disponível!**\n\n';
|
|
3705
|
-
result += `**Commit local:** \`${updateInfo.currentSha?.substring(0, 7) || 'N/A'}\`\n`;
|
|
3706
|
-
result += `**Commit remoto:** \`${updateInfo.latestSha?.substring(0, 7) || 'N/A'}\`\n\n`;
|
|
3707
|
-
if (updateInfo.latestCommit) {
|
|
3708
|
-
result += `**Último commit:**\n`;
|
|
3709
|
-
result += `- Mensagem: ${updateInfo.latestCommit.message}\n`;
|
|
3710
|
-
result += `- Autor: ${updateInfo.latestCommit.author}\n`;
|
|
3711
|
-
result += `- Data: ${updateInfo.latestCommit.date}\n\n`;
|
|
3712
|
-
}
|
|
3713
|
-
result += '> Use `tailwind_update` para atualizar o repositório.\n';
|
|
3714
|
-
}
|
|
3715
|
-
else {
|
|
3716
|
-
result += '✅ **Repositório está atualizado!**\n\n';
|
|
3717
|
-
result += `**Commit atual:** \`${updateInfo.currentSha?.substring(0, 7) || 'N/A'}\`\n`;
|
|
3718
|
-
}
|
|
3719
|
-
return {
|
|
3720
|
-
content: [{ type: 'text', text: result }],
|
|
3721
|
-
};
|
|
3722
|
-
}
|
|
3723
|
-
case 'tailwind_update': {
|
|
3724
|
-
const updateResult = await checkAndUpdate();
|
|
3725
|
-
let result = '# 🔄 Atualização do Repositório\n\n';
|
|
3726
|
-
if (updateResult.updated) {
|
|
3727
|
-
result += '✅ **Repositório atualizado com sucesso!**\n\n';
|
|
3728
|
-
if (updateResult.previousSha) {
|
|
3729
|
-
result += `**De:** \`${updateResult.previousSha.substring(0, 7)}\`\n`;
|
|
3730
|
-
}
|
|
3731
|
-
result += `**Para:** \`${updateResult.currentSha?.substring(0, 7) || 'N/A'}\`\n\n`;
|
|
3732
|
-
if (updateResult.commitMessage) {
|
|
3733
|
-
result += `**Commit:** ${updateResult.commitMessage}\n`;
|
|
3734
|
-
}
|
|
3735
|
-
if (updateResult.commitDate) {
|
|
3736
|
-
result += `**Data:** ${updateResult.commitDate}\n`;
|
|
3737
|
-
}
|
|
3738
|
-
result += '\n> ⚡ O contexto da biblioteca foi atualizado automaticamente.\n';
|
|
3739
|
-
}
|
|
3740
|
-
else if (updateResult.error) {
|
|
3741
|
-
result += '❌ **Erro ao atualizar:**\n\n';
|
|
3742
|
-
result += `\`\`\`\n${updateResult.error}\n\`\`\`\n`;
|
|
3743
|
-
}
|
|
3744
|
-
else {
|
|
3745
|
-
result += '✅ **Já está na versão mais recente!**\n\n';
|
|
3746
|
-
result += `**Commit atual:** \`${updateResult.currentSha?.substring(0, 7) || 'N/A'}\`\n`;
|
|
3747
|
-
}
|
|
3748
|
-
return {
|
|
3749
|
-
content: [{ type: 'text', text: result }],
|
|
3750
|
-
};
|
|
3751
|
-
}
|
|
3752
|
-
case 'tailwind_status': {
|
|
3753
|
-
const status = await getRepositoryStatus();
|
|
3754
|
-
let result = '# 📊 Status do Repositório Tailwind CSS\n\n';
|
|
3755
|
-
result += `**Repositório válido:** ${status.isValid ? '✅ Sim' : '❌ Não'}\n`;
|
|
3756
|
-
result += `**Caminho:** \`${status.repoPath}\`\n\n`;
|
|
3757
|
-
result += `**Commit local:** \`${status.localSha?.substring(0, 7) || 'N/A'}\`\n`;
|
|
3758
|
-
result += `**Commit remoto:** \`${status.remoteSha?.substring(0, 7) || 'N/A'}\`\n\n`;
|
|
3759
|
-
if (status.hasUpdates) {
|
|
3760
|
-
result += '⚠️ **Há atualizações disponíveis!**\n\n';
|
|
3761
|
-
result += '> Use `tailwind_update` para atualizar.\n';
|
|
3762
|
-
}
|
|
3763
|
-
else {
|
|
3764
|
-
result += '✅ **Repositório está sincronizado com o GitHub.**\n';
|
|
3765
|
-
}
|
|
3766
|
-
result += `\n**Última verificação:** ${status.lastCheck}\n`;
|
|
3767
|
-
return {
|
|
3768
|
-
content: [{ type: 'text', text: result }],
|
|
3769
|
-
};
|
|
3770
|
-
}
|
|
3771
|
-
default:
|
|
3772
|
-
return {
|
|
3773
|
-
content: [{ type: 'text', text: `❌ Ferramenta desconhecida: ${name}` }],
|
|
3774
|
-
isError: true,
|
|
3775
|
-
};
|
|
3776
|
-
}
|
|
3777
|
-
}
|
|
3778
|
-
catch (error) {
|
|
3779
|
-
return {
|
|
3780
|
-
content: [
|
|
3781
|
-
{
|
|
3782
|
-
type: 'text',
|
|
3783
|
-
text: `❌ Erro: ${error instanceof Error ? error.message : String(error)}`,
|
|
3784
|
-
},
|
|
3785
|
-
],
|
|
3786
|
-
isError: true,
|
|
3787
|
-
};
|
|
3788
|
-
}
|
|
3789
|
-
});
|
|
3790
|
-
mcpServer.server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
3791
|
-
return {
|
|
3792
|
-
resources: [
|
|
3793
|
-
{
|
|
3794
|
-
uri: 'tailwind://readme',
|
|
3795
|
-
name: 'Tailwind CSS README',
|
|
3796
|
-
description: 'Documentação principal da biblioteca Tailwind CSS',
|
|
3797
|
-
mimeType: 'text/markdown',
|
|
3798
|
-
},
|
|
3799
|
-
{
|
|
3800
|
-
uri: 'tailwind://types',
|
|
3801
|
-
name: 'Types Index',
|
|
3802
|
-
description: 'Tipos principais expostos pelo Tailwind',
|
|
3803
|
-
mimeType: 'text/markdown',
|
|
3804
|
-
},
|
|
3805
|
-
{
|
|
3806
|
-
uri: 'tailwind://statistics',
|
|
3807
|
-
name: 'Library Statistics',
|
|
3808
|
-
description: 'Estatísticas completas da biblioteca',
|
|
3809
|
-
mimeType: 'text/markdown',
|
|
3810
|
-
},
|
|
3811
|
-
],
|
|
3812
|
-
};
|
|
3813
|
-
});
|
|
3814
|
-
mcpServer.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
3815
|
-
const uri = request.params.uri;
|
|
3816
|
-
if (uri === 'tailwind://readme') {
|
|
3817
|
-
const readmePath = path.join(TAILWIND_SRC_PATH, '..', 'README.md');
|
|
3818
|
-
if (fs.existsSync(readmePath)) {
|
|
3819
|
-
const content = fs.readFileSync(readmePath, 'utf-8');
|
|
3820
|
-
return { contents: [{ uri, mimeType: 'text/markdown', text: content }] };
|
|
3821
|
-
}
|
|
3822
|
-
}
|
|
3823
|
-
if (uri === 'tailwind://types') {
|
|
3824
|
-
const indexPath = path.join(TAILWIND_SRC_PATH, 'types.ts');
|
|
3825
|
-
if (fs.existsSync(indexPath)) {
|
|
3826
|
-
const content = fs.readFileSync(indexPath, 'utf-8');
|
|
3827
|
-
return {
|
|
3828
|
-
contents: [
|
|
3829
|
-
{
|
|
3830
|
-
uri,
|
|
3831
|
-
mimeType: 'text/markdown',
|
|
3832
|
-
text: `# Types Index\n\n\`\`\`typescript\n${content}\n\`\`\``,
|
|
3833
|
-
},
|
|
3834
|
-
],
|
|
3835
|
-
};
|
|
3836
|
-
}
|
|
3837
|
-
}
|
|
3838
|
-
if (uri === 'tailwind://statistics') {
|
|
3839
|
-
const parser = new AstParser(TAILWIND_SRC_PATH);
|
|
3840
|
-
const stats = parser.getStatistics();
|
|
3841
|
-
return {
|
|
3842
|
-
contents: [
|
|
3843
|
-
{
|
|
3844
|
-
uri,
|
|
3845
|
-
mimeType: 'text/markdown',
|
|
3846
|
-
text: formatStatistics(stats),
|
|
3847
|
-
},
|
|
3848
|
-
],
|
|
3849
|
-
};
|
|
3850
|
-
}
|
|
3851
|
-
return { contents: [{ uri, mimeType: 'text/plain', text: 'Resource not found' }] };
|
|
3852
|
-
});
|
|
3853
|
-
const AUTO_UPDATE_INTERVAL = parseInt(process.env.AUTO_UPDATE_INTERVAL || '3600000', 10);
|
|
3854
|
-
const AUTO_UPDATE_ENABLED = process.env.AUTO_UPDATE_ENABLED !== 'false';
|
|
3855
22
|
async function main() {
|
|
3856
23
|
const repoResult = await ensureRepository();
|
|
3857
24
|
if (!repoResult.success) {
|
|
3858
25
|
console.error(`❌ ${repoResult.error}`);
|
|
3859
26
|
process.exit(1);
|
|
3860
27
|
}
|
|
3861
|
-
|
|
3862
|
-
console.error(`📁 Usando Tailwind CSS: ${
|
|
28
|
+
const srcPath = repoResult.path;
|
|
29
|
+
console.error(`📁 Usando Tailwind CSS: ${srcPath}`);
|
|
30
|
+
// Register all tools and resources
|
|
31
|
+
registerAstTools(mcpServer, srcPath);
|
|
32
|
+
registerRepoTools(mcpServer, srcPath, APP_VERSION);
|
|
33
|
+
registerContentTools(mcpServer, srcPath);
|
|
34
|
+
registerResources(mcpServer, srcPath);
|
|
35
|
+
// Connect transport
|
|
3863
36
|
const transport = new StdioServerTransport();
|
|
3864
37
|
await mcpServer.connect(transport);
|
|
3865
38
|
console.error(`MCP Tailwind CSS server v${APP_VERSION} running on stdio`);
|
|
39
|
+
// Auto-update check (repositório Tailwind)
|
|
3866
40
|
if (AUTO_UPDATE_ENABLED) {
|
|
3867
41
|
const initialCheck = await checkForUpdates();
|
|
3868
42
|
if (initialCheck.hasUpdate) {
|
|
3869
|
-
console.error(`⚠️ Atualização disponível: ${initialCheck.latestCommit?.message}`);
|
|
43
|
+
console.error(`⚠️ Atualização do repositório disponível: ${initialCheck.latestCommit?.message}`);
|
|
3870
44
|
}
|
|
3871
45
|
scheduleUpdateCheck(AUTO_UPDATE_INTERVAL);
|
|
3872
46
|
}
|
|
47
|
+
// Self-update check (pacote mcp-tailwindcss no npm)
|
|
48
|
+
const packageCheck = await checkPackageUpdate(APP_VERSION);
|
|
49
|
+
if (packageCheck.hasUpdate) {
|
|
50
|
+
console.error(`\n⚠️ Nova versão do mcp-tailwindcss: v${packageCheck.latestVersion} (atual: v${APP_VERSION})`);
|
|
51
|
+
console.error(` Atualize: npm install -g mcp-tailwindcss@latest\n`);
|
|
52
|
+
}
|
|
53
|
+
schedulePackageUpdateCheck(APP_VERSION);
|
|
3873
54
|
}
|
|
3874
55
|
main().catch((error) => {
|
|
3875
56
|
console.error('Fatal error:', error);
|