jasmincss 1.0.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.
Files changed (76) hide show
  1. package/README.md +524 -0
  2. package/bin/jasmin.js +45 -0
  3. package/dist/index.d.ts +62 -0
  4. package/dist/index.js +14568 -0
  5. package/dist/index.mjs +14524 -0
  6. package/dist/jasmin.css +63308 -0
  7. package/dist/jasmin.min.css +1 -0
  8. package/dist/plugins/nextjs.js +14777 -0
  9. package/dist/plugins/nextjs.mjs +14747 -0
  10. package/dist/plugins/vite.js +14889 -0
  11. package/dist/plugins/vite.mjs +14860 -0
  12. package/package.json +101 -0
  13. package/src/cli/add.js +83 -0
  14. package/src/cli/init.js +210 -0
  15. package/src/cli/run.js +142 -0
  16. package/src/components/accordion.js +309 -0
  17. package/src/components/alerts.js +357 -0
  18. package/src/components/avatars.js +331 -0
  19. package/src/components/badges.js +353 -0
  20. package/src/components/buttons.js +412 -0
  21. package/src/components/cards.js +342 -0
  22. package/src/components/carousel.js +495 -0
  23. package/src/components/chips.js +440 -0
  24. package/src/components/command-palette.js +434 -0
  25. package/src/components/datepicker.js +517 -0
  26. package/src/components/dropdown.js +411 -0
  27. package/src/components/forms.js +516 -0
  28. package/src/components/index.js +81 -0
  29. package/src/components/modals.js +349 -0
  30. package/src/components/navigation.js +463 -0
  31. package/src/components/offcanvas.js +390 -0
  32. package/src/components/popover.js +427 -0
  33. package/src/components/progress.js +396 -0
  34. package/src/components/rating.js +394 -0
  35. package/src/components/skeleton.js +408 -0
  36. package/src/components/spinner.js +453 -0
  37. package/src/components/stepper.js +389 -0
  38. package/src/components/tables.js +304 -0
  39. package/src/components/timeline.js +452 -0
  40. package/src/components/timepicker.js +529 -0
  41. package/src/components/tooltips.js +345 -0
  42. package/src/components/upload.js +490 -0
  43. package/src/config/defaults.js +263 -0
  44. package/src/config/loader.js +109 -0
  45. package/src/core/base.js +241 -0
  46. package/src/core/compiler.js +135 -0
  47. package/src/core/utilities/accessibility.js +290 -0
  48. package/src/core/utilities/animations.js +205 -0
  49. package/src/core/utilities/background.js +109 -0
  50. package/src/core/utilities/colors.js +234 -0
  51. package/src/core/utilities/columns.js +161 -0
  52. package/src/core/utilities/effects.js +261 -0
  53. package/src/core/utilities/filters.js +135 -0
  54. package/src/core/utilities/icons.js +806 -0
  55. package/src/core/utilities/index.js +239 -0
  56. package/src/core/utilities/layout.js +321 -0
  57. package/src/core/utilities/scroll.js +205 -0
  58. package/src/core/utilities/spacing.js +120 -0
  59. package/src/core/utilities/svg.js +191 -0
  60. package/src/core/utilities/transforms.js +116 -0
  61. package/src/core/utilities/typography.js +188 -0
  62. package/src/index.js +7 -0
  63. package/src/js/components/accordion.js +154 -0
  64. package/src/js/components/alert.js +198 -0
  65. package/src/js/components/carousel.js +226 -0
  66. package/src/js/components/dropdown.js +166 -0
  67. package/src/js/components/modal.js +169 -0
  68. package/src/js/components/offcanvas.js +175 -0
  69. package/src/js/components/popover.js +221 -0
  70. package/src/js/components/tabs.js +163 -0
  71. package/src/js/components/tooltip.js +200 -0
  72. package/src/js/index.js +79 -0
  73. package/src/js/types/config.d.ts +228 -0
  74. package/src/js/types/index.d.ts +439 -0
  75. package/src/plugins/nextjs.js +100 -0
  76. package/src/plugins/vite.js +133 -0
@@ -0,0 +1,135 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import fg from 'fast-glob';
4
+ import postcss from 'postcss';
5
+ import cssnano from 'cssnano';
6
+ import { resolveConfig } from '../config/loader.js';
7
+ import { generateUtilities } from './utilities/index.js';
8
+ import { generateComponents } from '../components/index.js';
9
+ import { generateBase } from './base.js';
10
+
11
+ export async function compileCSS(config, options = {}) {
12
+ const { usedClasses, minify = false, includeAll = false } = options;
13
+
14
+ // Resolve configuration
15
+ const resolvedConfig = resolveConfig(config);
16
+
17
+ // Generate CSS parts
18
+ const parts = [];
19
+
20
+ // 1. Base styles and CSS variables
21
+ parts.push(generateBase(resolvedConfig));
22
+
23
+ // 2. Utility classes
24
+ const utilities = generateUtilities(resolvedConfig, {
25
+ usedClasses,
26
+ includeAll
27
+ });
28
+ parts.push(utilities.css);
29
+
30
+ // 3. Component styles
31
+ const components = generateComponents(resolvedConfig, {
32
+ selected: config.components,
33
+ usedClasses,
34
+ includeAll
35
+ });
36
+ parts.push(components.css);
37
+
38
+ // Combine all CSS
39
+ let css = parts.join('\n\n');
40
+
41
+ // Process with PostCSS
42
+ let minified = null;
43
+ if (minify) {
44
+ const result = await postcss([
45
+ cssnano({
46
+ preset: ['default', {
47
+ discardComments: { removeAll: true },
48
+ normalizeWhitespace: true
49
+ }]
50
+ })
51
+ ]).process(css, { from: undefined });
52
+
53
+ minified = result.css;
54
+ }
55
+
56
+ return {
57
+ css,
58
+ minified,
59
+ stats: {
60
+ utilities: utilities.count,
61
+ components: components.count
62
+ }
63
+ };
64
+ }
65
+
66
+ export async function scanForUsedClasses(cwd, patterns) {
67
+ const usedClasses = new Set();
68
+
69
+ // Find all matching files
70
+ const files = await fg(patterns, {
71
+ cwd,
72
+ absolute: true,
73
+ ignore: ['**/node_modules/**', '**/dist/**', '**/.git/**']
74
+ });
75
+
76
+ // Regex to match class-like patterns
77
+ // Matches: class="...", className="...", :class="...", class:..., etc.
78
+ const classPatterns = [
79
+ /class(?:Name)?=["'`]([^"'`]+)["'`]/g,
80
+ /class(?:Name)?=\{["'`]([^"'`]+)["'`]\}/g,
81
+ /class:([a-zA-Z0-9_-]+)/g,
82
+ /:class=["'`]\{([^}]+)\}["'`]/g,
83
+ /classList\.(?:add|toggle)\(["'`]([^"'`]+)["'`]\)/g,
84
+ /clsx\(([^)]+)\)/g,
85
+ /cn\(([^)]+)\)/g,
86
+ /classnames\(([^)]+)\)/g
87
+ ];
88
+
89
+ for (const file of files) {
90
+ try {
91
+ const content = fs.readFileSync(file, 'utf-8');
92
+
93
+ for (const pattern of classPatterns) {
94
+ let match;
95
+ while ((match = pattern.exec(content)) !== null) {
96
+ // Extract individual classes
97
+ const classes = match[1]
98
+ .split(/\s+/)
99
+ .map(c => c.trim())
100
+ .filter(c => c && !c.includes('{') && !c.includes('$'));
101
+
102
+ classes.forEach(cls => usedClasses.add(cls));
103
+ }
104
+ // Reset regex lastIndex
105
+ pattern.lastIndex = 0;
106
+ }
107
+ } catch (err) {
108
+ // Skip files that can't be read
109
+ }
110
+ }
111
+
112
+ return usedClasses;
113
+ }
114
+
115
+ export function shouldIncludeClass(className, usedClasses, includeAll) {
116
+ if (includeAll) return true;
117
+ if (!usedClasses) return true;
118
+
119
+ // Check exact match
120
+ if (usedClasses.has(className)) return true;
121
+
122
+ // Check responsive variants
123
+ const breakpoints = ['sm', 'md', 'lg', 'xl', '2xl'];
124
+ for (const bp of breakpoints) {
125
+ if (usedClasses.has(`${bp}:${className}`)) return true;
126
+ }
127
+
128
+ // Check state variants
129
+ const states = ['hover', 'focus', 'active', 'disabled', 'dark'];
130
+ for (const state of states) {
131
+ if (usedClasses.has(`${state}:${className}`)) return true;
132
+ }
133
+
134
+ return false;
135
+ }
@@ -0,0 +1,290 @@
1
+ // Accessibility utilities for JasminCSS
2
+
3
+ export function generateAccessibilityUtilities(config) {
4
+ const classes = [];
5
+
6
+ // Screen Reader Only - visually hidden but accessible
7
+ classes.push({
8
+ name: 'sr-only',
9
+ css: `.sr-only {
10
+ position: absolute;
11
+ width: 1px;
12
+ height: 1px;
13
+ padding: 0;
14
+ margin: -1px;
15
+ overflow: hidden;
16
+ clip: rect(0, 0, 0, 0);
17
+ white-space: nowrap;
18
+ border-width: 0;
19
+ }`
20
+ });
21
+
22
+ // Not Screen Reader Only - reverses sr-only
23
+ classes.push({
24
+ name: 'not-sr-only',
25
+ css: `.not-sr-only {
26
+ position: static;
27
+ width: auto;
28
+ height: auto;
29
+ padding: 0;
30
+ margin: 0;
31
+ overflow: visible;
32
+ clip: auto;
33
+ white-space: normal;
34
+ }`
35
+ });
36
+
37
+ // Focus variants for sr-only (show on focus)
38
+ classes.push({
39
+ name: 'sr-only-focusable',
40
+ css: `.sr-only-focusable:not(:focus):not(:focus-within) {
41
+ position: absolute;
42
+ width: 1px;
43
+ height: 1px;
44
+ padding: 0;
45
+ margin: -1px;
46
+ overflow: hidden;
47
+ clip: rect(0, 0, 0, 0);
48
+ white-space: nowrap;
49
+ border-width: 0;
50
+ }`
51
+ });
52
+
53
+ // Focus Visible - only show focus ring on keyboard navigation
54
+ classes.push({
55
+ name: 'focus-visible-ring',
56
+ css: `.focus-visible-ring:focus {
57
+ outline: none;
58
+ }
59
+ .focus-visible-ring:focus-visible {
60
+ outline: 2px solid var(--j-primary);
61
+ outline-offset: 2px;
62
+ }`
63
+ });
64
+
65
+ // Focus Within
66
+ classes.push({
67
+ name: 'focus-within-ring',
68
+ css: `.focus-within-ring:focus-within {
69
+ outline: 2px solid var(--j-primary);
70
+ outline-offset: 2px;
71
+ }`
72
+ });
73
+
74
+ // Skip Link - for skip to main content
75
+ classes.push({
76
+ name: 'skip-link',
77
+ css: `.skip-link {
78
+ position: absolute;
79
+ top: -100%;
80
+ left: 0;
81
+ z-index: 9999;
82
+ padding: 1rem 1.5rem;
83
+ background-color: var(--j-primary);
84
+ color: white;
85
+ font-weight: 600;
86
+ text-decoration: none;
87
+ transition: top 150ms ease-in-out;
88
+ }
89
+ .skip-link:focus {
90
+ top: 0;
91
+ }`
92
+ });
93
+
94
+ // Reduced Motion - respect user preference
95
+ classes.push({
96
+ name: 'motion-safe',
97
+ css: `@media (prefers-reduced-motion: no-preference) {
98
+ .motion-safe\\:animate { animation-play-state: running; }
99
+ .motion-safe\\:transition { transition-property: all; }
100
+ }`
101
+ });
102
+
103
+ classes.push({
104
+ name: 'motion-reduce',
105
+ css: `@media (prefers-reduced-motion: reduce) {
106
+ .motion-reduce\\:animate-none { animation: none; }
107
+ .motion-reduce\\:transition-none { transition: none; }
108
+ }`
109
+ });
110
+
111
+ // Global reduced motion
112
+ classes.push({
113
+ name: 'reduce-motion',
114
+ css: `@media (prefers-reduced-motion: reduce) {
115
+ .reduce-motion,
116
+ .reduce-motion * {
117
+ animation-duration: 0.01ms !important;
118
+ animation-iteration-count: 1 !important;
119
+ transition-duration: 0.01ms !important;
120
+ scroll-behavior: auto !important;
121
+ }
122
+ }`
123
+ });
124
+
125
+ // High Contrast Mode
126
+ classes.push({
127
+ name: 'forced-colors',
128
+ css: `@media (forced-colors: active) {
129
+ .forced-colors\\:visible { visibility: visible; }
130
+ .forced-colors\\:border { border: 1px solid CanvasText; }
131
+ }`
132
+ });
133
+
134
+ // Focus trap container (visual indicator)
135
+ classes.push({
136
+ name: 'focus-trap',
137
+ css: `.focus-trap { position: relative; }`
138
+ });
139
+
140
+ // Keyboard focus indicator enhancement
141
+ classes.push({
142
+ name: 'focus-ring',
143
+ css: `.focus-ring:focus {
144
+ outline: 2px solid var(--j-primary);
145
+ outline-offset: 2px;
146
+ }`
147
+ });
148
+
149
+ classes.push({
150
+ name: 'focus-ring-inset',
151
+ css: `.focus-ring-inset:focus {
152
+ outline: 2px solid var(--j-primary);
153
+ outline-offset: -2px;
154
+ }`
155
+ });
156
+
157
+ // Focus ring colors
158
+ const colors = ['primary', 'secondary', 'success', 'warning', 'error', 'info'];
159
+ colors.forEach(color => {
160
+ classes.push({
161
+ name: `focus-ring-${color}`,
162
+ css: `.focus-ring-${color}:focus {
163
+ outline: 2px solid var(--j-${color});
164
+ outline-offset: 2px;
165
+ }`
166
+ });
167
+ });
168
+
169
+ // No focus outline (use sparingly, only with alternative indication)
170
+ classes.push({
171
+ name: 'focus-none',
172
+ css: `.focus-none:focus { outline: none; }`
173
+ });
174
+
175
+ // Touch target sizing (minimum 44x44px for accessibility)
176
+ classes.push({
177
+ name: 'touch-target',
178
+ css: `.touch-target {
179
+ min-width: 44px;
180
+ min-height: 44px;
181
+ }`
182
+ });
183
+
184
+ classes.push({
185
+ name: 'touch-target-sm',
186
+ css: `.touch-target-sm {
187
+ min-width: 36px;
188
+ min-height: 36px;
189
+ }`
190
+ });
191
+
192
+ // Aria hidden visual
193
+ classes.push({
194
+ name: 'aria-hidden',
195
+ css: `.aria-hidden[aria-hidden="true"] { display: none; }`
196
+ });
197
+
198
+ // Disabled state styling
199
+ classes.push({
200
+ name: 'disabled',
201
+ css: `.disabled, [disabled], [aria-disabled="true"] {
202
+ opacity: 0.6;
203
+ cursor: not-allowed;
204
+ pointer-events: none;
205
+ }`
206
+ });
207
+
208
+ // Live region announcement (for dynamic content)
209
+ classes.push({
210
+ name: 'live-polite',
211
+ css: `.live-polite { /* Use with aria-live="polite" */ }`
212
+ });
213
+
214
+ classes.push({
215
+ name: 'live-assertive',
216
+ css: `.live-assertive { /* Use with aria-live="assertive" */ }`
217
+ });
218
+
219
+ // Selection customization
220
+ classes.push({
221
+ name: 'selection-primary',
222
+ css: `.selection-primary::selection {
223
+ background-color: var(--j-primary);
224
+ color: white;
225
+ }`
226
+ });
227
+
228
+ // Caret/cursor color
229
+ classes.push({
230
+ name: 'caret-primary',
231
+ css: `.caret-primary { caret-color: var(--j-primary); }`
232
+ });
233
+
234
+ classes.push({
235
+ name: 'caret-transparent',
236
+ css: `.caret-transparent { caret-color: transparent; }`
237
+ });
238
+
239
+ colors.forEach(color => {
240
+ classes.push({
241
+ name: `caret-${color}`,
242
+ css: `.caret-${color} { caret-color: var(--j-${color}); }`
243
+ });
244
+ });
245
+
246
+ // Accent color (for form elements)
247
+ classes.push({
248
+ name: 'accent-primary',
249
+ css: `.accent-primary { accent-color: var(--j-primary); }`
250
+ });
251
+
252
+ colors.forEach(color => {
253
+ classes.push({
254
+ name: `accent-${color}`,
255
+ css: `.accent-${color} { accent-color: var(--j-${color}); }`
256
+ });
257
+ });
258
+
259
+ // Print utilities
260
+ classes.push({
261
+ name: 'print-hidden',
262
+ css: `@media print { .print-hidden { display: none !important; } }`
263
+ });
264
+
265
+ classes.push({
266
+ name: 'print-only',
267
+ css: `.print-only { display: none; }
268
+ @media print { .print-only { display: block; } }`
269
+ });
270
+
271
+ classes.push({
272
+ name: 'print-break-before',
273
+ css: `@media print { .print-break-before { break-before: page; } }`
274
+ });
275
+
276
+ classes.push({
277
+ name: 'print-break-after',
278
+ css: `@media print { .print-break-after { break-after: page; } }`
279
+ });
280
+
281
+ classes.push({
282
+ name: 'print-break-inside-avoid',
283
+ css: `@media print { .print-break-inside-avoid { break-inside: avoid; } }`
284
+ });
285
+
286
+ return {
287
+ css: classes.map(c => c.css).join('\n'),
288
+ classes
289
+ };
290
+ }
@@ -0,0 +1,205 @@
1
+ export function generateAnimationUtilities(config) {
2
+ const classes = [];
3
+
4
+ // Transition Property
5
+ classes.push({ name: 'transition-none', css: '.transition-none { transition-property: none; }' });
6
+ classes.push({ name: 'transition-all', css: '.transition-all { transition-property: all; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms; }' });
7
+ classes.push({ name: 'transition', css: '.transition { 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; }' });
8
+ classes.push({ name: 'transition-colors', css: '.transition-colors { transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms; }' });
9
+ classes.push({ name: 'transition-opacity', css: '.transition-opacity { transition-property: opacity; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms; }' });
10
+ classes.push({ name: 'transition-shadow', css: '.transition-shadow { transition-property: box-shadow; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms; }' });
11
+ classes.push({ name: 'transition-transform', css: '.transition-transform { transition-property: transform; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms; }' });
12
+
13
+ // Transition Duration
14
+ const durations = [0, 75, 100, 150, 200, 300, 500, 700, 1000];
15
+ durations.forEach(d => {
16
+ classes.push({ name: `duration-${d}`, css: `.duration-${d} { transition-duration: ${d}ms; }` });
17
+ });
18
+
19
+ // Transition Timing Function
20
+ classes.push({ name: 'ease-linear', css: '.ease-linear { transition-timing-function: linear; }' });
21
+ classes.push({ name: 'ease-in', css: '.ease-in { transition-timing-function: cubic-bezier(0.4, 0, 1, 1); }' });
22
+ classes.push({ name: 'ease-out', css: '.ease-out { transition-timing-function: cubic-bezier(0, 0, 0.2, 1); }' });
23
+ classes.push({ name: 'ease-in-out', css: '.ease-in-out { transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); }' });
24
+ classes.push({ name: 'ease-spring', css: '.ease-spring { transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275); }' });
25
+ classes.push({ name: 'ease-bounce', css: '.ease-bounce { transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55); }' });
26
+
27
+ // Transition Delay
28
+ durations.forEach(d => {
29
+ classes.push({ name: `delay-${d}`, css: `.delay-${d} { transition-delay: ${d}ms; }` });
30
+ });
31
+
32
+ // Keyframe Animations
33
+ const keyframes = `
34
+ @keyframes j-spin {
35
+ to { transform: rotate(360deg); }
36
+ }
37
+
38
+ @keyframes j-ping {
39
+ 75%, 100% { transform: scale(2); opacity: 0; }
40
+ }
41
+
42
+ @keyframes j-pulse {
43
+ 50% { opacity: .5; }
44
+ }
45
+
46
+ @keyframes j-bounce {
47
+ 0%, 100% { transform: translateY(-25%); animation-timing-function: cubic-bezier(0.8, 0, 1, 1); }
48
+ 50% { transform: none; animation-timing-function: cubic-bezier(0, 0, 0.2, 1); }
49
+ }
50
+
51
+ @keyframes j-shake {
52
+ 0%, 100% { transform: translateX(0); }
53
+ 10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
54
+ 20%, 40%, 60%, 80% { transform: translateX(5px); }
55
+ }
56
+
57
+ @keyframes j-wiggle {
58
+ 0%, 100% { transform: rotate(-3deg); }
59
+ 50% { transform: rotate(3deg); }
60
+ }
61
+
62
+ @keyframes j-fade-in {
63
+ from { opacity: 0; }
64
+ to { opacity: 1; }
65
+ }
66
+
67
+ @keyframes j-fade-out {
68
+ from { opacity: 1; }
69
+ to { opacity: 0; }
70
+ }
71
+
72
+ @keyframes j-slide-in-up {
73
+ from { transform: translateY(100%); opacity: 0; }
74
+ to { transform: translateY(0); opacity: 1; }
75
+ }
76
+
77
+ @keyframes j-slide-in-down {
78
+ from { transform: translateY(-100%); opacity: 0; }
79
+ to { transform: translateY(0); opacity: 1; }
80
+ }
81
+
82
+ @keyframes j-slide-in-left {
83
+ from { transform: translateX(-100%); opacity: 0; }
84
+ to { transform: translateX(0); opacity: 1; }
85
+ }
86
+
87
+ @keyframes j-slide-in-right {
88
+ from { transform: translateX(100%); opacity: 0; }
89
+ to { transform: translateX(0); opacity: 1; }
90
+ }
91
+
92
+ @keyframes j-zoom-in {
93
+ from { transform: scale(0.95); opacity: 0; }
94
+ to { transform: scale(1); opacity: 1; }
95
+ }
96
+
97
+ @keyframes j-zoom-out {
98
+ from { transform: scale(1); opacity: 1; }
99
+ to { transform: scale(0.95); opacity: 0; }
100
+ }
101
+
102
+ @keyframes j-float {
103
+ 0%, 100% { transform: translateY(0); }
104
+ 50% { transform: translateY(-10px); }
105
+ }
106
+
107
+ @keyframes j-glow {
108
+ 0%, 100% { box-shadow: 0 0 5px var(--j-primary), 0 0 10px var(--j-primary); }
109
+ 50% { box-shadow: 0 0 20px var(--j-primary), 0 0 30px var(--j-primary); }
110
+ }
111
+
112
+ @keyframes j-shimmer {
113
+ 0% { background-position: -200% 0; }
114
+ 100% { background-position: 200% 0; }
115
+ }
116
+
117
+ @keyframes j-heartbeat {
118
+ 0%, 100% { transform: scale(1); }
119
+ 14% { transform: scale(1.3); }
120
+ 28% { transform: scale(1); }
121
+ 42% { transform: scale(1.3); }
122
+ 70% { transform: scale(1); }
123
+ }
124
+
125
+ @keyframes j-flip {
126
+ 0% { transform: perspective(400px) rotateY(0); }
127
+ 100% { transform: perspective(400px) rotateY(360deg); }
128
+ }
129
+ `;
130
+
131
+ classes.push({ name: 'keyframes', css: keyframes });
132
+
133
+ // Animation Classes
134
+ classes.push({ name: 'animate-none', css: '.animate-none { animation: none; }' });
135
+ classes.push({ name: 'animate-spin', css: '.animate-spin { animation: j-spin 1s linear infinite; }' });
136
+ classes.push({ name: 'animate-ping', css: '.animate-ping { animation: j-ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; }' });
137
+ classes.push({ name: 'animate-pulse', css: '.animate-pulse { animation: j-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; }' });
138
+ classes.push({ name: 'animate-bounce', css: '.animate-bounce { animation: j-bounce 1s infinite; }' });
139
+ classes.push({ name: 'animate-shake', css: '.animate-shake { animation: j-shake 0.5s ease-in-out; }' });
140
+ classes.push({ name: 'animate-wiggle', css: '.animate-wiggle { animation: j-wiggle 0.5s ease-in-out infinite; }' });
141
+
142
+ // Fade animations
143
+ classes.push({ name: 'animate-fade-in', css: '.animate-fade-in { animation: j-fade-in 0.3s ease-out forwards; }' });
144
+ classes.push({ name: 'animate-fade-out', css: '.animate-fade-out { animation: j-fade-out 0.3s ease-out forwards; }' });
145
+
146
+ // Slide animations
147
+ classes.push({ name: 'animate-slide-in-up', css: '.animate-slide-in-up { animation: j-slide-in-up 0.3s ease-out forwards; }' });
148
+ classes.push({ name: 'animate-slide-in-down', css: '.animate-slide-in-down { animation: j-slide-in-down 0.3s ease-out forwards; }' });
149
+ classes.push({ name: 'animate-slide-in-left', css: '.animate-slide-in-left { animation: j-slide-in-left 0.3s ease-out forwards; }' });
150
+ classes.push({ name: 'animate-slide-in-right', css: '.animate-slide-in-right { animation: j-slide-in-right 0.3s ease-out forwards; }' });
151
+
152
+ // Zoom animations
153
+ classes.push({ name: 'animate-zoom-in', css: '.animate-zoom-in { animation: j-zoom-in 0.3s ease-out forwards; }' });
154
+ classes.push({ name: 'animate-zoom-out', css: '.animate-zoom-out { animation: j-zoom-out 0.3s ease-out forwards; }' });
155
+
156
+ // Futuristic animations
157
+ classes.push({ name: 'animate-float', css: '.animate-float { animation: j-float 3s ease-in-out infinite; }' });
158
+ classes.push({ name: 'animate-glow', css: '.animate-glow { animation: j-glow 2s ease-in-out infinite; }' });
159
+ classes.push({ name: 'animate-shimmer', css: `.animate-shimmer { background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent); background-size: 200% 100%; animation: j-shimmer 1.5s infinite; }` });
160
+ classes.push({ name: 'animate-heartbeat', css: '.animate-heartbeat { animation: j-heartbeat 1.5s ease-in-out infinite; }' });
161
+ classes.push({ name: 'animate-flip', css: '.animate-flip { animation: j-flip 1s ease-in-out; }' });
162
+
163
+ // Animation Duration
164
+ const animDurations = ['75', '100', '150', '200', '300', '500', '700', '1000', '2000', '3000'];
165
+ animDurations.forEach(d => {
166
+ classes.push({
167
+ name: `animate-duration-${d}`,
168
+ css: `.animate-duration-${d} { animation-duration: ${d}ms; }`
169
+ });
170
+ });
171
+
172
+ // Animation Delay
173
+ animDurations.forEach(d => {
174
+ classes.push({
175
+ name: `animate-delay-${d}`,
176
+ css: `.animate-delay-${d} { animation-delay: ${d}ms; }`
177
+ });
178
+ });
179
+
180
+ // Animation Iteration Count
181
+ classes.push({ name: 'animate-infinite', css: '.animate-infinite { animation-iteration-count: infinite; }' });
182
+ classes.push({ name: 'animate-once', css: '.animate-once { animation-iteration-count: 1; }' });
183
+ classes.push({ name: 'animate-twice', css: '.animate-twice { animation-iteration-count: 2; }' });
184
+
185
+ // Animation Direction
186
+ classes.push({ name: 'animate-normal', css: '.animate-normal { animation-direction: normal; }' });
187
+ classes.push({ name: 'animate-reverse', css: '.animate-reverse { animation-direction: reverse; }' });
188
+ classes.push({ name: 'animate-alternate', css: '.animate-alternate { animation-direction: alternate; }' });
189
+ classes.push({ name: 'animate-alternate-reverse', css: '.animate-alternate-reverse { animation-direction: alternate-reverse; }' });
190
+
191
+ // Animation Fill Mode
192
+ classes.push({ name: 'animate-fill-none', css: '.animate-fill-none { animation-fill-mode: none; }' });
193
+ classes.push({ name: 'animate-fill-forwards', css: '.animate-fill-forwards { animation-fill-mode: forwards; }' });
194
+ classes.push({ name: 'animate-fill-backwards', css: '.animate-fill-backwards { animation-fill-mode: backwards; }' });
195
+ classes.push({ name: 'animate-fill-both', css: '.animate-fill-both { animation-fill-mode: both; }' });
196
+
197
+ // Animation Play State
198
+ classes.push({ name: 'animate-running', css: '.animate-running { animation-play-state: running; }' });
199
+ classes.push({ name: 'animate-paused', css: '.animate-paused { animation-play-state: paused; }' });
200
+
201
+ return {
202
+ css: classes.map(c => c.css).join('\n'),
203
+ classes
204
+ };
205
+ }