@cwcss/crosswind 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +390 -0
  3. package/dist/build.d.ts +24 -0
  4. package/dist/config.d.ts +5 -0
  5. package/dist/generator.d.ts +31 -0
  6. package/dist/index.d.ts +10 -0
  7. package/dist/index.js +12798 -0
  8. package/dist/parser.d.ts +42 -0
  9. package/dist/plugin.d.ts +22 -0
  10. package/dist/preflight-forms.d.ts +5 -0
  11. package/dist/preflight.d.ts +2 -0
  12. package/dist/rules-advanced.d.ts +27 -0
  13. package/dist/rules-effects.d.ts +25 -0
  14. package/dist/rules-forms.d.ts +7 -0
  15. package/dist/rules-grid.d.ts +13 -0
  16. package/dist/rules-interactivity.d.ts +41 -0
  17. package/dist/rules-layout.d.ts +26 -0
  18. package/dist/rules-transforms.d.ts +33 -0
  19. package/dist/rules-typography.d.ts +41 -0
  20. package/dist/rules.d.ts +39 -0
  21. package/dist/scanner.d.ts +18 -0
  22. package/dist/transformer-compile-class.d.ts +37 -0
  23. package/{src/types.ts → dist/types.d.ts} +17 -86
  24. package/package.json +1 -1
  25. package/PLUGIN.md +0 -235
  26. package/benchmark/framework-comparison.bench.ts +0 -850
  27. package/bin/cli.ts +0 -365
  28. package/bin/crosswind +0 -0
  29. package/bin/headwind +0 -0
  30. package/build.ts +0 -8
  31. package/crosswind.config.ts +0 -9
  32. package/example/comprehensive.html +0 -70
  33. package/example/index.html +0 -21
  34. package/example/output.css +0 -236
  35. package/examples/plugin/README.md +0 -112
  36. package/examples/plugin/build.ts +0 -32
  37. package/examples/plugin/src/index.html +0 -34
  38. package/examples/plugin/src/index.ts +0 -7
  39. package/headwind +0 -2
  40. package/src/build.ts +0 -101
  41. package/src/config.ts +0 -529
  42. package/src/generator.ts +0 -2173
  43. package/src/index.ts +0 -10
  44. package/src/parser.ts +0 -1471
  45. package/src/plugin.ts +0 -118
  46. package/src/preflight-forms.ts +0 -229
  47. package/src/preflight.ts +0 -388
  48. package/src/rules-advanced.ts +0 -477
  49. package/src/rules-effects.ts +0 -461
  50. package/src/rules-forms.ts +0 -103
  51. package/src/rules-grid.ts +0 -241
  52. package/src/rules-interactivity.ts +0 -525
  53. package/src/rules-layout.ts +0 -385
  54. package/src/rules-transforms.ts +0 -412
  55. package/src/rules-typography.ts +0 -486
  56. package/src/rules.ts +0 -809
  57. package/src/scanner.ts +0 -84
  58. package/src/transformer-compile-class.ts +0 -275
  59. package/test/advanced-features.test.ts +0 -911
  60. package/test/arbitrary.test.ts +0 -396
  61. package/test/attributify.test.ts +0 -592
  62. package/test/bracket-syntax.test.ts +0 -1133
  63. package/test/build.test.ts +0 -99
  64. package/test/colors.test.ts +0 -934
  65. package/test/flexbox.test.ts +0 -669
  66. package/test/generator.test.ts +0 -597
  67. package/test/grid.test.ts +0 -584
  68. package/test/layout.test.ts +0 -404
  69. package/test/modifiers.test.ts +0 -417
  70. package/test/parser.test.ts +0 -564
  71. package/test/performance-regression.test.ts +0 -376
  72. package/test/performance.test.ts +0 -568
  73. package/test/plugin.test.ts +0 -160
  74. package/test/scanner.test.ts +0 -94
  75. package/test/sizing.test.ts +0 -481
  76. package/test/spacing.test.ts +0 -394
  77. package/test/transformer-compile-class.test.ts +0 -287
  78. package/test/transforms.test.ts +0 -448
  79. package/test/typography.test.ts +0 -632
  80. package/test/variants-form-states.test.ts +0 -225
  81. package/test/variants-group-peer.test.ts +0 -66
  82. package/test/variants-media.test.ts +0 -213
  83. package/test/variants-positional.test.ts +0 -58
  84. package/test/variants-pseudo-elements.test.ts +0 -47
  85. package/test/variants-state.test.ts +0 -62
  86. package/tsconfig.json +0 -18
package/bin/cli.ts DELETED
@@ -1,365 +0,0 @@
1
- #!/usr/bin/env bun
2
- import type { CrosswindConfig } from '../src/types'
3
- import { existsSync, watch } from 'node:fs'
4
- import { unlink } from 'node:fs/promises'
5
- import process from 'node:process'
6
- import { CLI } from '@stacksjs/clapp'
7
- import { version } from '../package.json'
8
- import { build, buildAndWrite } from '../src/build'
9
- import { config } from '../src/config'
10
- import { tailwindPreflight } from '../src/preflight'
11
-
12
- const cli = new CLI('crosswind')
13
-
14
- interface GlobalOptions {
15
- verbose?: boolean
16
- config?: string
17
- }
18
-
19
- interface BuildOptions extends GlobalOptions {
20
- output?: string
21
- minify?: boolean
22
- watch?: boolean
23
- content?: string
24
- noPreflight?: boolean
25
- }
26
-
27
- interface InitOptions {
28
- force?: boolean
29
- }
30
-
31
- interface AnalyzeOptions extends GlobalOptions {
32
- json?: boolean
33
- top?: number
34
- }
35
-
36
- /**
37
- * Load custom config if specified
38
- */
39
- async function loadCustomConfig(configPath?: string): Promise<CrosswindConfig> {
40
- if (configPath) {
41
- if (!existsSync(configPath)) {
42
- console.error(`❌ Config file not found: ${configPath}`)
43
- process.exit(1)
44
- }
45
- try {
46
- const customConfig = await import(configPath)
47
- return { ...config, ...(customConfig.default || customConfig) }
48
- }
49
- catch (error) {
50
- console.error(`❌ Failed to load config file: ${configPath}`)
51
- console.error(error)
52
- process.exit(1)
53
- }
54
- }
55
- return config
56
- }
57
-
58
- /**
59
- * Merge CLI options with config
60
- */
61
- function mergeConfig(baseConfig: CrosswindConfig, options: BuildOptions): CrosswindConfig {
62
- return {
63
- ...baseConfig,
64
- output: options.output || baseConfig.output,
65
- minify: options.minify ?? baseConfig.minify,
66
- content: options.content ? [options.content] : baseConfig.content,
67
- verbose: options.verbose ?? baseConfig.verbose,
68
- }
69
- }
70
-
71
- /**
72
- * Run the build process
73
- */
74
- async function runBuild(buildConfig: CrosswindConfig, options: BuildOptions): Promise<void> {
75
- try {
76
- const startMsg = options.verbose ? '🚀 Building CSS (verbose mode)...' : '🚀 Building CSS...'
77
- console.log(startMsg)
78
-
79
- if (options.verbose) {
80
- console.log(`📂 Content patterns: ${buildConfig.content.join(', ')}`)
81
- console.log(`📝 Output: ${buildConfig.output}`)
82
- console.log(`🗜️ Minify: ${buildConfig.minify ? 'Yes' : 'No'}`)
83
- }
84
-
85
- const result = await buildAndWrite(buildConfig)
86
-
87
- console.log(`✅ Built ${result.classes.size} classes in ${result.duration.toFixed(2)}ms`)
88
- console.log(`📝 Output: ${buildConfig.output}`)
89
-
90
- // Show compile class stats if enabled
91
- if (result.compiledClasses && result.compiledClasses.size > 0) {
92
- console.log(`🔨 Compiled ${result.compiledClasses.size} class groups`)
93
- if (result.transformedFiles) {
94
- console.log(`📝 Transformed ${result.transformedFiles.size} files`)
95
- }
96
-
97
- if (options.verbose) {
98
- console.log(`\n📦 Compiled classes:`)
99
- for (const [, { className, utilities }] of result.compiledClasses) {
100
- console.log(` ${className} ← ${utilities.join(' ')}`)
101
- }
102
- }
103
- }
104
-
105
- if (options.verbose && result.classes.size > 0) {
106
- const classesArray = Array.from(result.classes).sort()
107
- console.log(`\n📋 Classes found (${result.classes.size}):`)
108
- classesArray.forEach(cls => console.log(` - ${cls}`))
109
- }
110
-
111
- // Show size info
112
- if (existsSync(buildConfig.output)) {
113
- const file = Bun.file(buildConfig.output)
114
- const sizeKB = (file.size / 1024).toFixed(2)
115
- console.log(`📦 File size: ${sizeKB} KB`)
116
- }
117
- }
118
- catch (error) {
119
- console.error('❌ Build failed:', error)
120
- if (options.verbose && error instanceof Error) {
121
- console.error(error.stack)
122
- }
123
- process.exit(1)
124
- }
125
- }
126
-
127
- /**
128
- * Setup file watching
129
- */
130
- function setupWatch(buildConfig: CrosswindConfig, options: BuildOptions): void {
131
- console.log('👀 Watching for changes...')
132
-
133
- // Watch content directories
134
- const watchDirs = new Set<string>()
135
- for (const pattern of buildConfig.content) {
136
- const dir = pattern.split('**')[0] || '.'
137
- watchDirs.add(dir)
138
- }
139
-
140
- for (const dir of watchDirs) {
141
- watch(dir, { recursive: true }, async (eventType, filename) => {
142
- if (filename && /\.(?:html|js|ts|jsx|tsx|stx)$/.test(filename)) {
143
- console.log(`\n📝 ${filename} changed, rebuilding...`)
144
- await runBuild(buildConfig, options)
145
- }
146
- })
147
- }
148
-
149
- console.log(`\n👀 Watching: ${Array.from(watchDirs).join(', ')}`)
150
- }
151
-
152
- // Build command
153
- cli
154
- .command('build', 'Build CSS from content files')
155
- .option('--output <path>', 'Output CSS file path')
156
- .option('--minify', 'Minify CSS output')
157
- .option('--watch', 'Watch for file changes')
158
- .option('--content <pattern>', 'Content file pattern (can override config)')
159
- .option('--config <path>', 'Path to config file')
160
- .option('--verbose', 'Show detailed output')
161
- .option('--no-preflight', 'Skip preflight CSS')
162
- .example('crosswind build')
163
- .example('crosswind build --output ./dist/styles.css')
164
- .example('crosswind build --minify --watch')
165
- .example('crosswind build --verbose')
166
- .example('crosswind build --config ./custom.config.ts')
167
- .action(async (options: BuildOptions) => {
168
- const baseConfig = await loadCustomConfig(options.config)
169
- const buildConfig = mergeConfig(baseConfig, options)
170
-
171
- await runBuild(buildConfig, options)
172
-
173
- if (options.watch) {
174
- setupWatch(buildConfig, options)
175
- }
176
- })
177
-
178
- // Watch command (alias for build --watch)
179
- cli
180
- .command('watch', 'Build and watch for changes')
181
- .option('--output <path>', 'Output CSS file path')
182
- .option('--minify', 'Minify CSS output')
183
- .option('--content <pattern>', 'Content file pattern')
184
- .option('--config <path>', 'Path to config file')
185
- .option('--verbose', 'Show detailed output')
186
- .example('crosswind watch')
187
- .example('crosswind watch --output ./dist/styles.css')
188
- .example('crosswind watch --verbose')
189
- .action(async (options: BuildOptions) => {
190
- const baseConfig = await loadCustomConfig(options.config)
191
- const buildConfig = mergeConfig(baseConfig, options)
192
-
193
- await runBuild(buildConfig, options)
194
- setupWatch(buildConfig, options)
195
- })
196
-
197
- // Init command - Create a config file
198
- cli
199
- .command('init', 'Create a crosswind.config.ts file')
200
- .option('--force', 'Overwrite existing config file')
201
- .example('crosswind init')
202
- .example('crosswind init --force')
203
- .action(async (options: InitOptions) => {
204
- const configPath = './crosswind.config.ts'
205
-
206
- if (existsSync(configPath) && !options.force) {
207
- console.error('❌ Config file already exists. Use --force to overwrite.')
208
- process.exit(1)
209
- }
210
-
211
- const defaultConfig = `import type { CrosswindOptions } from '@cwcss/crosswind'
212
-
213
- const config = {
214
- content: ['./src/**/*.{html,js,ts,jsx,tsx}'],
215
- output: './dist/crosswind.css',
216
- minify: false,
217
- watch: false,
218
- } satisfies CrosswindOptions
219
-
220
- export default config
221
- `
222
-
223
- try {
224
- await Bun.write(configPath, defaultConfig)
225
- console.log('✅ Created crosswind.config.ts')
226
- console.log('\nNext steps:')
227
- console.log(' 1. Update the content paths in crosswind.config.ts')
228
- console.log(' 2. Run: crosswind build')
229
- }
230
- catch (error) {
231
- console.error('❌ Failed to create config file:', error)
232
- process.exit(1)
233
- }
234
- })
235
-
236
- // Analyze command - Show statistics
237
- cli
238
- .command('analyze', 'Analyze utility class usage')
239
- .option('--config <path>', 'Path to config file')
240
- .option('--verbose', 'Show detailed output')
241
- .option('--json', 'Output as JSON')
242
- .option('--top <n>', 'Show top N most used classes', { default: 10 })
243
- .example('crosswind analyze')
244
- .example('crosswind analyze --top 20')
245
- .example('crosswind analyze --json')
246
- .action(async (options: AnalyzeOptions) => {
247
- try {
248
- const baseConfig = await loadCustomConfig(options.config)
249
-
250
- if (!options.json) {
251
- console.log('🔍 Analyzing utility classes...\n')
252
- }
253
-
254
- const result = await build(baseConfig)
255
-
256
- // Group classes by utility type
257
- const utilityGroups = new Map<string, string[]>()
258
- for (const cls of result.classes) {
259
- const utility = cls.split('-')[0].split(':').pop() || 'other'
260
- if (!utilityGroups.has(utility)) {
261
- utilityGroups.set(utility, [])
262
- }
263
- utilityGroups.get(utility)!.push(cls)
264
- }
265
-
266
- const stats = {
267
- totalClasses: result.classes.size,
268
- buildTime: result.duration,
269
- outputSize: existsSync(baseConfig.output) ? Bun.file(baseConfig.output).size : 0,
270
- utilityGroups: Object.fromEntries(
271
- Array.from(utilityGroups.entries())
272
- .map(([key, value]) => [key, value.length] as [string, number])
273
- .sort((a, b) => (b[1] as number) - (a[1] as number)),
274
- ),
275
- topClasses: Array.from(result.classes).slice(0, options.top || 10),
276
- }
277
-
278
- if (options.json) {
279
- console.log(JSON.stringify(stats, null, 2))
280
- }
281
- else {
282
- console.log(`📊 Total classes: ${stats.totalClasses}`)
283
- console.log(`⏱️ Build time: ${stats.buildTime.toFixed(2)}ms`)
284
- console.log(`📦 Output size: ${(stats.outputSize / 1024).toFixed(2)} KB\n`)
285
-
286
- console.log(`🏷️ Utility groups (top ${options.top}):`)
287
- const topGroups = Object.entries(stats.utilityGroups).slice(0, options.top || 10)
288
- for (const [utility, count] of topGroups) {
289
- console.log(` ${utility.padEnd(20)} ${count} classes`)
290
- }
291
-
292
- if (options.verbose) {
293
- console.log(`\n📋 All classes:`)
294
- for (const cls of Array.from(result.classes).sort()) {
295
- console.log(` - ${cls}`)
296
- }
297
- }
298
- }
299
- }
300
- catch (error) {
301
- console.error('❌ Analysis failed:', error)
302
- process.exit(1)
303
- }
304
- })
305
-
306
- // Clean command - Remove output file
307
- cli
308
- .command('clean', 'Remove the output CSS file')
309
- .option('--config <path>', 'Path to config file')
310
- .example('crosswind clean')
311
- .action(async (options: GlobalOptions) => {
312
- try {
313
- const baseConfig = await loadCustomConfig(options.config)
314
-
315
- if (!existsSync(baseConfig.output)) {
316
- console.log('ℹ️ Output file does not exist')
317
- return
318
- }
319
-
320
- await unlink(baseConfig.output)
321
- console.log(`✅ Removed ${baseConfig.output}`)
322
- }
323
- catch (error) {
324
- console.error('❌ Failed to remove output file:', error)
325
- process.exit(1)
326
- }
327
- })
328
-
329
- // Preflight command - Generate just the preflight CSS
330
- cli
331
- .command('preflight', 'Generate preflight CSS only')
332
- .option('--output <path>', 'Output CSS file path', { default: './preflight.css' })
333
- .example('crosswind preflight')
334
- .example('crosswind preflight --output ./reset.css')
335
- .action(async (options: { output?: string }) => {
336
- try {
337
- const outputPath = options.output || './preflight.css'
338
- const preflightCSS = tailwindPreflight.getCSS()
339
-
340
- await Bun.write(outputPath, preflightCSS)
341
- console.log(`✅ Generated preflight CSS`)
342
- console.log(`📝 Output: ${outputPath}`)
343
-
344
- const file = Bun.file(outputPath)
345
- const sizeKB = (file.size / 1024).toFixed(2)
346
- console.log(`📦 File size: ${sizeKB} KB`)
347
- }
348
- catch (error) {
349
- console.error('❌ Failed to generate preflight CSS:', error)
350
- process.exit(1)
351
- }
352
- })
353
-
354
- // Version command
355
- cli
356
- .command('version', 'Show the version of Crosswind')
357
- .action(() => {
358
- console.log(version)
359
- })
360
-
361
- cli.version(version)
362
- cli.help()
363
-
364
- // Parse arguments
365
- cli.parse()
package/bin/crosswind DELETED
Binary file
package/bin/headwind DELETED
Binary file
package/build.ts DELETED
@@ -1,8 +0,0 @@
1
- import { dts } from 'bun-plugin-dtsx'
2
-
3
- await Bun.build({
4
- entrypoints: ['src/index.ts'],
5
- outdir: './dist',
6
- target: 'bun',
7
- plugins: [dts()],
8
- })
@@ -1,9 +0,0 @@
1
- import type { CrosswindOptions } from './src/types'
2
-
3
- const config: CrosswindOptions = {
4
- content: ['./example/**/*.html'],
5
- output: './example/output.css',
6
- minify: false,
7
- }
8
-
9
- export default config
@@ -1,70 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Crosswind - Comprehensive Example</title>
7
- </head>
8
- <body>
9
- <!-- Layout Utilities -->
10
- <div class="relative top-4 z-10 aspect-square">
11
- <div class="absolute inset-0 overflow-hidden">Content</div>
12
- </div>
13
-
14
- <!-- Grid Utilities -->
15
- <div class="grid grid-cols-3 gap-4">
16
- <div class="col-span-2">Span 2</div>
17
- <div>Cell</div>
18
- </div>
19
-
20
- <!-- Typography -->
21
- <div class="uppercase italic underline whitespace-nowrap truncate">
22
- Styled Text
23
- </div>
24
-
25
- <!-- Transforms -->
26
- <div class="scale-150 rotate-45 translate-x-4 skew-x-12">
27
- Transformed
28
- </div>
29
-
30
- <!-- Transitions -->
31
- <button class="transition-all duration-300 ease-in-out hover:opacity-50">
32
- Animated Button
33
- </button>
34
-
35
- <!-- Filters -->
36
- <div class="blur-sm grayscale-100 brightness-150">
37
- Filtered Content
38
- </div>
39
-
40
- <!-- Interactivity -->
41
- <div class="cursor-pointer select-none pointer-events-auto resize-both">
42
- Interactive
43
- </div>
44
-
45
- <!-- Arbitrary Values -->
46
- <div class="w-[250px] p-[2.5rem] bg-[#ff6b6b]">
47
- Custom Values
48
- </div>
49
-
50
- <!-- Important Modifier -->
51
- <div class="!text-white !bg-black !p-8">
52
- Important Styles
53
- </div>
54
-
55
- <!-- SVG -->
56
- <svg class="fill-current stroke-current">
57
- <circle cx="50" cy="50" r="40" />
58
- </svg>
59
-
60
- <!-- Table -->
61
- <table class="border-collapse table-fixed">
62
- <tr><td>Cell</td></tr>
63
- </table>
64
-
65
- <!-- Scroll -->
66
- <div class="scroll-smooth scroll-p-4 snap-y">
67
- Scrollable
68
- </div>
69
- </body>
70
- </html>
@@ -1,21 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Crosswind Example</title>
7
- </head>
8
- <body>
9
- <div class="flex flex-col items-center justify-center h-screen bg-gray-100">
10
- <h1 class="text-4xl font-bold text-gray-900 mb-4">
11
- Welcome to Crosswind
12
- </h1>
13
- <p class="text-lg text-gray-600 mb-8">
14
- A Bun-powered CSS utility framework
15
- </p>
16
- <button class="px-6 py-3 bg-blue-500 text-white rounded-lg hover:bg-blue-600 focus:outline-none">
17
- Get Started
18
- </button>
19
- </div>
20
- </body>
21
- </html>
@@ -1,236 +0,0 @@
1
- .flex {
2
- display: flex;
3
- }
4
-
5
- .flex-col {
6
- flex-direction: column;
7
- }
8
-
9
- .items-center {
10
- align-items: center;
11
- }
12
-
13
- .justify-center {
14
- justify-content: center;
15
- }
16
-
17
- .h-screen {
18
- height: 100vh;
19
- }
20
-
21
- .bg-gray-100 {
22
- background-color: #f3f4f6;
23
- }
24
-
25
- .text-4xl {
26
- font-size: 2.25rem;
27
- line-height: 2.5rem;
28
- }
29
-
30
- .font-bold {
31
- font-weight: 700;
32
- }
33
-
34
- .text-gray-900 {
35
- color: #111827;
36
- }
37
-
38
- .mb-4 {
39
- margin-bottom: 1rem;
40
- }
41
-
42
- .text-lg {
43
- font-size: 1.125rem;
44
- line-height: 1.75rem;
45
- }
46
-
47
- .text-gray-600 {
48
- color: #4b5563;
49
- }
50
-
51
- .mb-8 {
52
- margin-bottom: 2rem;
53
- }
54
-
55
- .px-6 {
56
- padding-left: 1.5rem;
57
- padding-right: 1.5rem;
58
- }
59
-
60
- .py-3 {
61
- padding-top: 0.75rem;
62
- padding-bottom: 0.75rem;
63
- }
64
-
65
- .bg-blue-500 {
66
- background-color: blue-500;
67
- }
68
-
69
- .text-white {
70
- color: #fff;
71
- }
72
-
73
- .rounded-lg {
74
- border-radius: 0.5rem;
75
- }
76
-
77
- .hover\:bg-blue-600:hover {
78
- background-color: blue-600;
79
- }
80
-
81
- .focus\:outline-none:focus {
82
- outline-width: none;
83
- }
84
-
85
- .relative {
86
- position: relative;
87
- }
88
-
89
- .top-4 {
90
- top: 1rem;
91
- }
92
-
93
- .z-10 {
94
- z-index: 10;
95
- }
96
-
97
- .aspect-square {
98
- aspect-ratio: 1 / 1;
99
- }
100
-
101
- .absolute {
102
- position: absolute;
103
- }
104
-
105
- .inset-0 {
106
- top: 0;
107
- right: 0;
108
- bottom: 0;
109
- left: 0;
110
- }
111
-
112
- .overflow-hidden {
113
- overflow: hidden;
114
- }
115
-
116
- .grid {
117
- display: grid;
118
- }
119
-
120
- .grid-cols-3 {
121
- grid-template-columns: repeat(3, minmax(0, 1fr));
122
- }
123
-
124
- .gap-4 {
125
- gap: 1rem;
126
- }
127
-
128
- .col-span-2 {
129
- grid-column: span 2 / span 2;
130
- }
131
-
132
- .uppercase {
133
- text-transform: uppercase;
134
- }
135
-
136
- .italic {
137
- font-style: italic;
138
- }
139
-
140
- .underline {
141
- text-decoration-line: underline;
142
- }
143
-
144
- .whitespace-nowrap {
145
- white-space: nowrap;
146
- }
147
-
148
- .truncate {
149
- overflow: hidden;
150
- text-overflow: ellipsis;
151
- white-space: nowrap;
152
- }
153
-
154
- .scale-150 {
155
- transform: scale(1.5);
156
- }
157
-
158
- .rotate-45 {
159
- transform: rotate(45deg);
160
- }
161
-
162
- .translate-x-4 {
163
- transform: translateX(1rem);
164
- }
165
-
166
- .skew-x-12 {
167
- transform: skewX(12deg);
168
- }
169
-
170
- .transition-all {
171
- transition-property: all;
172
- }
173
-
174
- .duration-300 {
175
- transition-duration: 300ms;
176
- }
177
-
178
- .ease-in-out {
179
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
180
- }
181
-
182
- .hover\:opacity-50:hover {
183
- opacity: 0.5;
184
- }
185
-
186
- .blur-sm {
187
- filter: blur(4px);
188
- }
189
-
190
- .grayscale-100 {
191
- filter: grayscale(1);
192
- }
193
-
194
- .brightness-150 {
195
- filter: brightness(1.5);
196
- }
197
-
198
- .cursor-pointer {
199
- cursor: pointer;
200
- }
201
-
202
- .select-none {
203
- user-select: none;
204
- }
205
-
206
- .pointer-events-auto {
207
- pointer-events: auto;
208
- }
209
-
210
- .fill-current {
211
- fill: currentColor;
212
- }
213
-
214
- .stroke-current {
215
- stroke: currentColor;
216
- }
217
-
218
- .border-collapse {
219
- border-collapse: collapse;
220
- }
221
-
222
- .table-fixed {
223
- table-layout: fixed;
224
- }
225
-
226
- .scroll-smooth {
227
- scroll-behavior: smooth;
228
- }
229
-
230
- .scroll-p-4 {
231
- scroll-padding: 1rem;
232
- }
233
-
234
- .snap-y {
235
- scroll-snap-type: y mandatory;
236
- }