tailwind-typescript-plugin 1.3.1-beta.5 → 1.4.0-beta.10

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 (69) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/README.md +372 -33
  3. package/lib/core/interfaces.d.ts +2 -2
  4. package/lib/core/interfaces.d.ts.map +1 -1
  5. package/lib/core/types.d.ts +27 -1
  6. package/lib/core/types.d.ts.map +1 -1
  7. package/lib/extractors/BaseExtractor.d.ts +49 -2
  8. package/lib/extractors/BaseExtractor.d.ts.map +1 -1
  9. package/lib/extractors/BaseExtractor.js +184 -5
  10. package/lib/extractors/BaseExtractor.js.map +1 -1
  11. package/lib/extractors/CvaExtractor.d.ts.map +1 -1
  12. package/lib/extractors/CvaExtractor.js +7 -3
  13. package/lib/extractors/CvaExtractor.js.map +1 -1
  14. package/lib/extractors/ExpressionExtractor.d.ts.map +1 -1
  15. package/lib/extractors/ExpressionExtractor.js +35 -5
  16. package/lib/extractors/ExpressionExtractor.js.map +1 -1
  17. package/lib/extractors/JsxAttributeExtractor.js +1 -1
  18. package/lib/extractors/JsxAttributeExtractor.js.map +1 -1
  19. package/lib/extractors/TailwindVariantsExtractor.d.ts +2 -0
  20. package/lib/extractors/TailwindVariantsExtractor.d.ts.map +1 -1
  21. package/lib/extractors/TailwindVariantsExtractor.js +12 -8
  22. package/lib/extractors/TailwindVariantsExtractor.js.map +1 -1
  23. package/lib/extractors/VariableReferenceExtractor.d.ts.map +1 -1
  24. package/lib/extractors/VariableReferenceExtractor.js +21 -0
  25. package/lib/extractors/VariableReferenceExtractor.js.map +1 -1
  26. package/lib/infrastructure/TailwindConflictDetector.d.ts +83 -0
  27. package/lib/infrastructure/TailwindConflictDetector.d.ts.map +1 -0
  28. package/lib/infrastructure/TailwindConflictDetector.js +342 -0
  29. package/lib/infrastructure/TailwindConflictDetector.js.map +1 -0
  30. package/lib/infrastructure/TailwindValidator.d.ts +15 -0
  31. package/lib/infrastructure/TailwindValidator.d.ts.map +1 -1
  32. package/lib/infrastructure/TailwindValidator.js +84 -5
  33. package/lib/infrastructure/TailwindValidator.js.map +1 -1
  34. package/lib/infrastructure/TailwindValidator.spec.js +194 -0
  35. package/lib/infrastructure/TailwindValidator.spec.js.map +1 -1
  36. package/lib/plugin/TailwindTypescriptPlugin.d.ts +17 -0
  37. package/lib/plugin/TailwindTypescriptPlugin.d.ts.map +1 -1
  38. package/lib/plugin/TailwindTypescriptPlugin.js +117 -1
  39. package/lib/plugin/TailwindTypescriptPlugin.js.map +1 -1
  40. package/lib/services/ClassNameExtractionService.d.ts +2 -2
  41. package/lib/services/ClassNameExtractionService.d.ts.map +1 -1
  42. package/lib/services/ClassNameExtractionService.js.map +1 -1
  43. package/lib/services/ConflictClassDetection.spec.d.ts +2 -0
  44. package/lib/services/ConflictClassDetection.spec.d.ts.map +1 -0
  45. package/lib/services/ConflictClassDetection.spec.js +477 -0
  46. package/lib/services/ConflictClassDetection.spec.js.map +1 -0
  47. package/lib/services/DiagnosticService.d.ts +14 -0
  48. package/lib/services/DiagnosticService.d.ts.map +1 -1
  49. package/lib/services/DiagnosticService.js +32 -1
  50. package/lib/services/DiagnosticService.js.map +1 -1
  51. package/lib/services/DuplicateClassDetection.spec.js +41 -60
  52. package/lib/services/DuplicateClassDetection.spec.js.map +1 -1
  53. package/lib/services/PluginConfigService.d.ts +2 -1
  54. package/lib/services/PluginConfigService.d.ts.map +1 -1
  55. package/lib/services/PluginConfigService.js +19 -12
  56. package/lib/services/PluginConfigService.js.map +1 -1
  57. package/lib/services/ValidationService.d.ts +5 -2
  58. package/lib/services/ValidationService.d.ts.map +1 -1
  59. package/lib/services/ValidationService.js +22 -9
  60. package/lib/services/ValidationService.js.map +1 -1
  61. package/package.json +4 -2
  62. package/lib/extractors/StringLiteralExtractor.d.ts +0 -12
  63. package/lib/extractors/StringLiteralExtractor.d.ts.map +0 -1
  64. package/lib/extractors/StringLiteralExtractor.js +0 -21
  65. package/lib/extractors/StringLiteralExtractor.js.map +0 -1
  66. package/lib/services/ClassNameExtractionService.original.d.ts +0 -20
  67. package/lib/services/ClassNameExtractionService.original.d.ts.map +0 -1
  68. package/lib/services/ClassNameExtractionService.original.js +0 -48
  69. package/lib/services/ClassNameExtractionService.original.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,85 @@
1
+ ## [1.4.0-beta.10](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/compare/v1.4.0-beta.9...v1.4.0-beta.10) (2025-11-29)
2
+
3
+ ### ⚡ Performance
4
+
5
+ * optimize test execution with sharding and separated test commands ([0a89bdd](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/0a89bddcd77ec96eba6a2c0ff579b1c8b4d46f2d))
6
+
7
+ ## [1.4.0-beta.9](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/compare/v1.4.0-beta.8...v1.4.0-beta.9) (2025-11-29)
8
+
9
+ ### ♻️ Code Refactoring
10
+
11
+ * restructure test cases into folder-based organization with JSDoc comments ([13cc790](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/13cc7900545d35b215e12618c8e7b003cfc67d02))
12
+
13
+ ## [1.4.0-beta.8](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/compare/v1.4.0-beta.7...v1.4.0-beta.8) (2025-11-28)
14
+
15
+ ### ✨ Features
16
+
17
+ * add import verification for utility functions ([9d34a12](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/9d34a129cdb05d5e74cba1510d89b9b6c6afeab6))
18
+ * add namespace import verification for member expressions ([eaacf9a](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/eaacf9a808c7f63e1d2fa5a284c24e1426821aa6))
19
+
20
+ ### ♻️ Code Refactoring
21
+
22
+ * add imports to test files and update default utility functions ([698fdc2](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/698fdc2afcfbb59dcd1cf6b17c754ef4a0b9a542))
23
+
24
+ ## [1.4.0-beta.7](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/compare/v1.4.0-beta.6...v1.4.0-beta.7) (2025-11-28)
25
+
26
+ ### ✨ Features
27
+
28
+ * add wildcard pattern support for allowedClasses ([a490b68](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/a490b68800b54bfde6eadef42ab97aaee51550fc))
29
+
30
+ ## [1.4.0-beta.6](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/compare/v1.4.0-beta.5...v1.4.0-beta.6) (2025-11-28)
31
+
32
+ ### ✨ Features
33
+
34
+ * add spread operator support for class name validation ([a4c4ad1](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/a4c4ad1fc2ef42e7d4d87351af4fe464384c44b3))
35
+
36
+ ### 🔧 Chores
37
+
38
+ * add utility libraries and cn helper ([2ac664d](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/2ac664dc33ba4a5c52e3059ee5ec5c9257da1c78))
39
+
40
+ ## [1.4.0-beta.5](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/compare/v1.4.0-beta.4...v1.4.0-beta.5) (2025-11-27)
41
+
42
+ ### ♻️ Code Refactoring
43
+
44
+ * split test cases into folder structure for better organization ([fbe6774](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/fbe67742147857fb7c01e6e925142ba26d9fe7bf))
45
+
46
+ ## [1.4.0-beta.4](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/compare/v1.4.0-beta.3...v1.4.0-beta.4) (2025-11-27)
47
+
48
+ ### ✨ Features
49
+
50
+ * warn on all duplicate class occurrences ([d01d878](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/d01d87844da17e15d5608ddddb1e3fdc033c8d38))
51
+
52
+ ### 🐛 Bug Fixes
53
+
54
+ * dispose plugin in benchmark to close file watchers ([9efdc6a](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/9efdc6a8e24de4dd3000c44fc075bb765ddba1bb))
55
+
56
+ ## [1.4.0-beta.3](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/compare/v1.4.0-beta.2...v1.4.0-beta.3) (2025-11-26)
57
+
58
+ ### ✨ Features
59
+
60
+ * add hot reloading for global.css changes ([c215ae6](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/c215ae68b71741b1909460df0d22606dbfd5c0f1)), closes [#ff0000](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/issues/ff0000)
61
+
62
+ ## [1.4.0-beta.2](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/compare/v1.4.0-beta.1...v1.4.0-beta.2) (2025-11-26)
63
+
64
+ ### ✨ Features
65
+
66
+ * add conflicting class detection ([a31c01a](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/a31c01aa6e747e2949109273f7eec3f1b7ac4876))
67
+
68
+ ## [1.4.0-beta.1](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/compare/v1.3.0...v1.4.0-beta.1) (2025-11-26)
69
+
70
+ ### ✨ Features
71
+
72
+ * add duplicate class detection ([8ffcee9](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/8ffcee91120c4a8c69cb92e223253ead4a296101))
73
+
74
+ ### 📚 Documentation
75
+
76
+ * add variable resolution feature documentation ([9461272](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/94612728d635aeb1319fd98a614f32119a0dd3f5))
77
+
78
+ ### 🔧 Chores
79
+
80
+ * add release branch for semantic-release ([097e25a](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/097e25ab400aa7fbd8c5ddfadd32a21941175b6f))
81
+ * configure semantic-release for beta prereleases ([b3f1513](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/b3f1513e788af1abd1e4c240c71f495ebe62a58f))
82
+
1
83
  ## [1.3.0](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/compare/v1.2.0...v1.3.0) (2025-11-25)
2
84
 
3
85
  ### ✨ Features
package/README.md CHANGED
@@ -33,6 +33,7 @@ Ever written `className="flex itms-center"` instead of `"flex items-center"`? Th
33
33
 
34
34
  - **Real-time validation**: Get instant feedback on invalid Tailwind classes while you code
35
35
  - **Duplicate class detection**: Warns when the same class appears multiple times in the same `className` attribute
36
+ - **Conflicting class detection**: Warns when Tailwind utilities that affect the same CSS property are used together (e.g., `text-left text-center`)
36
37
  - **Editor integration**: Works with any editor that supports TypeScript Language Service (VS Code, WebStorm, etc.)
37
38
  - **Supports Tailwind variants**: Validates responsive (`md:`, `lg:`), state (`hover:`, `focus:`), and other variants
38
39
  - **Arbitrary values**: Correctly handles Tailwind arbitrary values like `h-[50vh]` or `bg-[#ff0000]`
@@ -81,15 +82,27 @@ Add the plugin to the `compilerOptions.plugins` array in your `tsconfig.json`:
81
82
 
82
83
  - `globalCss` (required): Path to your global CSS file that imports Tailwind CSS. This can be relative to your project root.
83
84
 
84
- - `allowedClasses` (optional): Array of custom class names that should be treated as valid alongside Tailwind classes. Useful for project-specific or third-party utility classes that aren't part of Tailwind.
85
+ - `allowedClasses` (optional): Array of custom class names or wildcard patterns that should be treated as valid alongside Tailwind classes. Useful for project-specific or third-party utility classes that aren't part of Tailwind.
85
86
  - **Default**: `[]` (no custom classes allowed)
87
+ - **Supports wildcard patterns**:
88
+ | Pattern | Description | Example | Matches |
89
+ |---------|-------------|---------|---------|
90
+ | `prefix-*` | Matches classes starting with prefix | `custom-*` | `custom-button`, `custom-card` |
91
+ | `*-suffix` | Matches classes ending with suffix | `*-icon` | `arrow-icon`, `close-icon` |
92
+ | `*-contains-*` | Matches classes containing the string | `*-component-*` | `app-component-header` |
93
+ | `exact` | Exact match (no wildcards) | `my-class` | Only `my-class` |
86
94
  - **Example**:
87
95
  ```json
88
96
  {
89
- "allowedClasses": ["custom-button", "app-header", "project-card"]
97
+ "allowedClasses": [
98
+ "custom-*",
99
+ "*-icon",
100
+ "*-component-*",
101
+ "exact-class"
102
+ ]
90
103
  }
91
104
  ```
92
- - Classes in this list will be considered valid and won't trigger validation errors
105
+ - Classes matching any pattern will be considered valid and won't trigger validation errors
93
106
  - Works with all extraction patterns (literals, expressions, functions, arrays, etc.)
94
107
  - Combines with Tailwind classes - both are validated independently
95
108
 
@@ -127,34 +140,99 @@ Add the plugin to the `compilerOptions.plugins` array in your `tsconfig.json`:
127
140
  ```
128
141
  - **Performance impact**: Disabling unused extractors skips TypeChecker operations and symbol resolution for that library, providing faster validation
129
142
 
130
- - `utilityFunctions` (optional): Array of additional function names to validate. These will be **merged with the defaults**, so you don't lose the common ones.
131
- - **Defaults (always included)**: `['clsx', 'cn', 'classnames', 'classNames', 'cx', 'cva', 'twMerge', 'tv']`
132
- - **Add your own**: Provide custom function names that will be added to the defaults
133
- - **Example config**:
134
- ```json
135
- {
136
- "utilityFunctions": ["myCustomFn", "buildClasses"]
137
- }
138
- ```
139
- This will validate: `clsx`, `cn`, `classnames`, `classNames`, `cx`, `cva`, `twMerge`, `tv`, **`myCustomFn`**, **`buildClasses`**
143
+ - `utilityFunctions` (optional): Array of utility functions to validate. These will be **merged with the defaults**, so you don't lose the common ones. Supports two formats:
140
144
 
141
- - **Supported patterns**:
142
- ```typescript
143
- // Simple calls (validated by default):
144
- className={clsx('flex', 'items-center')}
145
- className={cn('flex', 'items-center')}
145
+ **Simple string format** (matches by function name only):
146
+ ```json
147
+ {
148
+ "utilityFunctions": ["myCustomFn", "buildClasses"]
149
+ }
150
+ ```
151
+
152
+ **Object format with import verification** (matches by name AND verifies import source):
153
+ ```json
154
+ {
155
+ "utilityFunctions": [
156
+ { "name": "merge", "from": "@/lib/utils" },
157
+ { "name": "cx", "from": "my-styling-package" }
158
+ ]
159
+ }
160
+ ```
161
+
162
+ **Mixed format** (combine both):
163
+ ```json
164
+ {
165
+ "utilityFunctions": [
166
+ "anyFunctionNamedThis",
167
+ { "name": "merge", "from": "@/lib/utils" }
168
+ ]
169
+ }
170
+ ```
146
171
 
147
- // Member expressions (nested property access):
148
- className={utils.cn('flex', 'items-center')}
149
- className={lib.clsx('flex', 'items-center')}
172
+ - **Defaults (always included)**: `clsx` (from 'clsx'), `cn` (name-only), `classnames`/`classNames`/`cx` (from 'classnames'), `twMerge` (from 'tailwind-merge'). Note: `cva` and `tv` are variant functions handled by dedicated extractors.
173
+ - **Import verification**: When using the object format with `from`, the plugin verifies the function is actually imported from that package before validating. This prevents false positives when a function with the same name exists but isn't a className utility.
174
+ - **Subpath matching**: `{ "name": "fn", "from": "my-pkg" }` also matches `import { fn } from 'my-pkg/utils'`
150
175
 
151
- // Custom functions (add via config):
152
- className={myCustomFn('flex', 'items-center')}
153
- className={buildClasses('flex', 'items-center')}
176
+ **Example configurations**:
177
+ ```json
178
+ // Simple: just add function names
179
+ {
180
+ "utilityFunctions": ["myCustomFn", "buildClasses"]
181
+ }
154
182
 
155
- // Dynamic calls (ignored, won't throw errors):
156
- className={functions['cn']('flex', 'items-center')}
157
- ```
183
+ // Precise: verify import sources
184
+ {
185
+ "utilityFunctions": [
186
+ { "name": "cn", "from": "@/lib/utils" },
187
+ { "name": "merge", "from": "tailwind-merge" }
188
+ ]
189
+ }
190
+
191
+ // Mixed: some with import verification, some without
192
+ {
193
+ "utilityFunctions": [
194
+ "anyFn",
195
+ { "name": "preciseFn", "from": "@/utils" }
196
+ ]
197
+ }
198
+ ```
199
+
200
+ **Supported import patterns**:
201
+ ```typescript
202
+ // Named import
203
+ import { merge } from '@/lib/utils';
204
+ className={merge('flex', 'items-center')} // ✅ Validated
205
+
206
+ // Default import
207
+ import merge from '@/lib/utils';
208
+ className={merge('flex', 'items-center')} // ✅ Validated
209
+
210
+ // Aliased import
211
+ import { something as merge } from '@/lib/utils';
212
+ className={merge('flex', 'items-center')} // ✅ Validated
213
+
214
+ // Wrong import source (not validated when using object format)
215
+ import { merge } from 'different-package';
216
+ className={merge('flex', 'invalid-class')} // ⏭️ Skipped (wrong import)
217
+ ```
218
+
219
+ **Supported call patterns**:
220
+ ```typescript
221
+ // Simple calls (validated by default):
222
+ className={clsx('flex', 'items-center')}
223
+ className={cn('flex', 'items-center')}
224
+
225
+ // Member expressions (nested property access):
226
+ className={utils.cn('flex', 'items-center')}
227
+ className={lib.clsx('flex', 'items-center')}
228
+
229
+ // Custom functions (add via config):
230
+ className={myCustomFn('flex', 'items-center')}
231
+ className={buildClasses('flex', 'items-center')}
232
+
233
+ // Dynamic calls (ignored, won't throw errors):
234
+ className={functions['cn']('flex', 'items-center')}
235
+ ```
158
236
 
159
237
  ### 2. Ensure your CSS file imports Tailwind
160
238
 
@@ -244,6 +322,18 @@ const validClass = 'flex items-center';
244
322
  const baseClass = 'flex';
245
323
  <div className={[baseClass, 'items-center']}>Array with variable</div>
246
324
 
325
+ // ✅ Spread operator in arrays
326
+ const baseClasses = ['flex', 'items-center'];
327
+ <div className={[...baseClasses, 'p-4']}>Spread in array</div>
328
+
329
+ // ✅ Spread operator in function calls
330
+ <div className={cn(...baseClasses, 'p-4')}>Spread in function</div>
331
+
332
+ // ✅ Multiple spreads
333
+ const layoutClasses = ['flex', 'items-center'];
334
+ const spacingClasses = ['p-4', 'm-2'];
335
+ <div className={cn(...layoutClasses, ...spacingClasses)}>Multiple spreads</div>
336
+
247
337
  // ✅ Variables in tv() and cva()
248
338
  const buttonBase = 'font-semibold text-white';
249
339
  const button = tv({ base: buttonBase });
@@ -274,6 +364,14 @@ const badClass = 'invalid-array-class';
274
364
  // Error: The class "invalid-array-class" is not a valid Tailwind class.
275
365
  // This value is used as className via variable "badClass" on line 8
276
366
  <div className={['flex', badClass]}>Array with invalid variable</div>
367
+
368
+ // ❌ Invalid class in spread operator
369
+ const invalidClasses = ['flex', 'invalid-spread-class'];
370
+ // Error: The class "invalid-spread-class" is not a valid Tailwind class.
371
+ <div className={[...invalidClasses, 'items-center']}>Spread with invalid</div>
372
+
373
+ // ❌ Invalid class in spread within function call
374
+ <div className={cn(...invalidClasses, 'p-4')}>Function spread with invalid</div>
277
375
  ```
278
376
 
279
377
  **Custom allowed classes**:
@@ -325,6 +423,18 @@ The plugin detects duplicate classes within the same `className` attribute and s
325
423
  <div className={cn(['flex', 'flex', 'items-center'])}>In array</div>
326
424
  // Warning: Duplicate class "flex"
327
425
 
426
+ // ⚠️ Warning: Duplicates with spread operators
427
+ const baseClasses = ['flex', 'items-center'];
428
+ <div className={cn(...baseClasses, 'flex', 'items-center', 'p-4')}>Spread duplicates</div>
429
+ // Warning: Duplicate class "flex"
430
+ // Warning: Duplicate class "items-center"
431
+
432
+ // ⚠️ Warning: Duplicates between multiple spreads
433
+ const layoutClasses = ['flex', 'items-center'];
434
+ const containerClasses = ['flex', 'justify-center'];
435
+ <div className={cn(...layoutClasses, ...containerClasses)}>Multiple spread duplicates</div>
436
+ // Warning: Duplicate class "flex"
437
+
328
438
  // ✅ Valid: Same class in DIFFERENT elements (not duplicates)
329
439
  <div className="flex items-center">
330
440
  <span className="flex justify-center">Different elements</span>
@@ -387,6 +497,179 @@ const conditionalOneBranch = isActive ? 'flex bg-blue-500' : 'bg-gray-500';
387
497
  // No warning - 'flex' only appears in the true branch of the variable
388
498
  ```
389
499
 
500
+ **Conflicting class detection**:
501
+
502
+ The plugin detects when you use multiple Tailwind utilities that affect the same CSS property. This catches common mistakes where conflicting styles cancel each other out.
503
+
504
+ ```tsx
505
+ // ⚠️ Warning: Text alignment conflict (both affect text-align)
506
+ <div className="text-left text-center">Conflicting alignment</div>
507
+ // Warning: Class "text-left" conflicts with "text-center". Both affect the text-align property.
508
+ // Warning: Class "text-center" conflicts with "text-left". Both affect the text-align property.
509
+
510
+ // ⚠️ Warning: Display conflict (both affect display)
511
+ <div className="flex block">Conflicting display</div>
512
+ // Warning: Class "flex" conflicts with "block". Both affect the display property.
513
+ // Warning: Class "block" conflicts with "flex". Both affect the display property.
514
+
515
+ // ⚠️ Warning: Position conflict
516
+ <div className="absolute relative">Conflicting position</div>
517
+ // Warning: Class "absolute" conflicts with "relative". Both affect the position property.
518
+
519
+ // ⚠️ Warning: Flex direction conflict
520
+ <div className="flex-row flex-col">Conflicting direction</div>
521
+ // Warning: Class "flex-row" conflicts with "flex-col". Both affect the flex-direction property.
522
+
523
+ // ⚠️ Warning: Justify content conflict
524
+ <div className="justify-start justify-center">Conflicting justify</div>
525
+ // Warning: Class "justify-start" conflicts with "justify-center". Both affect the justify-content property.
526
+
527
+ // ⚠️ Warning: Align items conflict
528
+ <div className="items-start items-center">Conflicting alignment</div>
529
+ // Warning: Class "items-start" conflicts with "items-center". Both affect the align-items property.
530
+
531
+ // ✅ Valid: Different utilities (no conflict)
532
+ <div className="flex items-center justify-between">No conflict</div>
533
+
534
+ // ✅ Valid: Same class in different elements
535
+ <div className="text-left">
536
+ <span className="text-center">Different elements</span>
537
+ </div>
538
+ ```
539
+
540
+ **Responsive and state variants**:
541
+
542
+ The plugin correctly handles responsive and state variants - conflicts are only flagged when the same variant prefix is used:
543
+
544
+ ```tsx
545
+ // ⚠️ Warning: Same variant prefix = conflict
546
+ <div className="md:text-left md:text-center">Conflict at md breakpoint</div>
547
+ // Warning: Both classes affect text-align at the md: breakpoint
548
+
549
+ // ✅ Valid: Different breakpoints = no conflict
550
+ <div className="sm:text-left md:text-center lg:text-right">No conflict</div>
551
+ // Each breakpoint has its own text-align value
552
+
553
+ // ⚠️ Warning: Same state variant = conflict
554
+ <div className="hover:flex hover:block">Conflict on hover</div>
555
+ // Warning: Both classes affect display on hover
556
+
557
+ // ✅ Valid: Different state variants = no conflict
558
+ <div className="hover:flex focus:block">No conflict</div>
559
+ // Different states trigger different display values
560
+ ```
561
+
562
+ **Ternary conditional expressions**:
563
+
564
+ The plugin intelligently handles ternary expressions - conflicts are NOT flagged between mutually exclusive branches:
565
+
566
+ ```tsx
567
+ // ✅ Valid: Different ternary branches = no conflict
568
+ <div className={clsx(isActive ? 'text-left' : 'text-center')}>No conflict</div>
569
+ // Only one branch executes at runtime
570
+
571
+ // ⚠️ Warning: Root conflicts with branch
572
+ <div className={clsx('text-left', isActive ? 'text-center' : 'bg-gray-500')}>Conflict</div>
573
+ // Warning: 'text-left' at root conflicts with 'text-center' in true branch
574
+
575
+ // ⚠️ Warning: Conflict within same branch
576
+ <div className={clsx(isActive ? 'text-left text-center' : 'bg-gray-500')}>Conflict</div>
577
+ // Warning: Conflict within the true branch
578
+ ```
579
+
580
+ **Conflicts in utility functions**:
581
+
582
+ ```tsx
583
+ // ⚠️ Warning: Conflicts detected in clsx/cn arguments
584
+ <div className={clsx('flex', 'block', 'items-center')}>Conflict</div>
585
+ // Warning: Class "flex" conflicts with "block". Both affect the display property.
586
+
587
+ <div className={cn('text-left', 'text-right')}>Conflict</div>
588
+ // Warning: Both classes affect text-align
589
+ ```
590
+
591
+ **Conflicts with spread operators**:
592
+
593
+ ```tsx
594
+ // ⚠️ Warning: Conflicts with spread operator
595
+ const baseClasses = ['flex', 'p-4'];
596
+ <div className={cn(...baseClasses, 'p-2', 'items-center')}>Spread conflict</div>
597
+ // Warning: Class "p-4" conflicts with "p-2". Both affect the padding property.
598
+
599
+ // ⚠️ Warning: Conflicts between multiple spreads
600
+ const smallText = ['text-sm', 'font-medium'];
601
+ const largeText = ['text-lg', 'font-bold'];
602
+ <div className={cn(...smallText, ...largeText)}>Multiple spread conflicts</div>
603
+ // Warning: Class "text-sm" conflicts with "text-lg". Both affect the font-size property.
604
+ // Warning: Class "font-medium" conflicts with "font-bold". Both affect the font-weight property.
605
+ ```
606
+
607
+ **Conflicts in tv() and cva()**:
608
+
609
+ The plugin detects conflicts within `tv()` and `cva()` base properties, but intelligently skips conflicts between base and variants since variants are designed to override base styles:
610
+
611
+ ```tsx
612
+ import { tv } from 'tailwind-variants';
613
+ import { cva } from 'class-variance-authority';
614
+
615
+ // ⚠️ Warning: Conflict in tv() base
616
+ const button = tv({
617
+ base: 'flex block items-center'
618
+ // Warning: "flex" conflicts with "block"
619
+ });
620
+
621
+ // ✅ Valid: Base vs variant = NO conflict (intentional override)
622
+ const button2 = tv({
623
+ base: 'text-left items-center',
624
+ variants: {
625
+ align: {
626
+ center: 'text-center' // This is designed to override base
627
+ }
628
+ }
629
+ });
630
+ // No warning - variants intentionally override base styles
631
+
632
+ // ⚠️ Warning: Conflict in cva() base
633
+ const card = cva(['flex', 'grid', 'items-center']);
634
+ // Warning: "flex" conflicts with "grid"
635
+
636
+ // ✅ Valid: Base vs variant = NO conflict
637
+ const card2 = cva(['justify-start'], {
638
+ variants: {
639
+ centered: {
640
+ true: ['justify-center'] // Designed to override
641
+ }
642
+ }
643
+ });
644
+ // No warning - variant overrides base
645
+
646
+ // ✅ Valid: Different tv()/cva() calls = no conflict
647
+ const buttonA = tv({ base: 'text-left' });
648
+ const buttonB = tv({ base: 'text-center' });
649
+ // No warning - each call has its own scope
650
+ ```
651
+
652
+ **Detected conflict groups**:
653
+
654
+ The plugin detects conflicts in these CSS property groups:
655
+
656
+ | CSS Property | Conflicting Classes |
657
+ |--------------|---------------------|
658
+ | `text-align` | `text-left`, `text-center`, `text-right`, `text-justify`, `text-start`, `text-end` |
659
+ | `display` | `block`, `inline-block`, `inline`, `flex`, `inline-flex`, `grid`, `inline-grid`, `hidden`, `table`, `contents`, `flow-root`, `list-item` |
660
+ | `position` | `static`, `relative`, `absolute`, `fixed`, `sticky` |
661
+ | `flex-direction` | `flex-row`, `flex-row-reverse`, `flex-col`, `flex-col-reverse` |
662
+ | `justify-content` | `justify-start`, `justify-end`, `justify-center`, `justify-between`, `justify-around`, `justify-evenly`, `justify-stretch`, `justify-normal` |
663
+ | `align-items` | `items-start`, `items-end`, `items-center`, `items-baseline`, `items-stretch` |
664
+ | `visibility` | `visible`, `invisible`, `collapse` |
665
+ | `overflow` | `overflow-auto`, `overflow-hidden`, `overflow-clip`, `overflow-visible`, `overflow-scroll` |
666
+ | `font-style` | `italic`, `not-italic` |
667
+ | `text-transform` | `uppercase`, `lowercase`, `capitalize`, `normal-case` |
668
+ | `whitespace` | `whitespace-normal`, `whitespace-nowrap`, `whitespace-pre`, `whitespace-pre-line`, `whitespace-pre-wrap`, `whitespace-break-spaces` |
669
+ | `text-wrap` | `text-wrap`, `text-nowrap`, `text-balance`, `text-pretty` |
670
+ | `cursor` | `cursor-auto`, `cursor-default`, `cursor-pointer`, `cursor-wait`, `cursor-text`, `cursor-move`, `cursor-help`, `cursor-not-allowed`, `cursor-none`, `cursor-context-menu`, `cursor-progress`, `cursor-cell`, `cursor-crosshair`, `cursor-vertical-text`, `cursor-alias`, `cursor-copy`, `cursor-no-drop`, `cursor-grab`, `cursor-grabbing`, `cursor-all-scroll`, `cursor-col-resize`, `cursor-row-resize`, `cursor-n-resize`, `cursor-e-resize`, `cursor-s-resize`, `cursor-w-resize`, `cursor-ne-resize`, `cursor-nw-resize`, `cursor-se-resize`, `cursor-sw-resize`, `cursor-ew-resize`, `cursor-ns-resize`, `cursor-nesw-resize`, `cursor-nwse-resize`, `cursor-zoom-in`, `cursor-zoom-out` |
671
+ | And more... | `flex-wrap`, `align-content`, `align-self`, `justify-items`, `justify-self`, `float`, `clear`, `box-sizing`, `isolation`, `object-fit`, `pointer-events`, `resize`, `user-select`, `table-layout`, `border-collapse`, `caption-side` |
672
+
390
673
  **tailwind-variants validation**:
391
674
  ```tsx
392
675
  import { tv } from 'tailwind-variants';
@@ -676,6 +959,15 @@ const card2 = tv({ base: 'flex justify-center' });
676
959
  Validates variables used in computed object property keys
677
960
  Example: `const myClass = 'invalid-class'; <div className={{ [myClass]: true }}>Object</div>`
678
961
 
962
+ - [X] **Spread Operator** → [`test-spread-operator/`](./example/src/test-spread-operator/)
963
+ Validates spread operators in arrays and function calls
964
+ Example: `const base = ['flex', 'invalid']; <div className={[...base, 'p-4']}>Spread</div>`
965
+ - Spread in arrays: `className={[...baseClasses, 'p-4']}`
966
+ - Spread in function calls: `className={cn(...baseClasses, 'p-4')}`
967
+ - Multiple spreads: `className={cn(...layoutClasses, ...spacingClasses)}`
968
+ - Nested spreads: Variables containing arrays with spreads are resolved
969
+ - Detects invalid classes, duplicates, and conflicts within spread expressions
970
+
679
971
  - [X] **TV Variable** → [`tv-variable.tsx`](./example/src/tv-variable.tsx)
680
972
  Validates variables in tailwind-variants tv() definitions
681
973
  Example: `const baseClasses = 'invalid-class'; const button = tv({ base: baseClasses })`
@@ -684,19 +976,19 @@ const card2 = tv({ base: 'flex justify-center' });
684
976
  Validates variables in class-variance-authority cva() definitions
685
977
  Example: `const baseClasses = 'invalid-class'; const button = cva(baseClasses)`
686
978
 
687
- - [X] **Duplicate Classes** → [`duplicate-classes.tsx`](./example/src/duplicate-classes.tsx)
979
+ - [X] **Duplicate Classes** → [`duplicate-classes/`](./example/src/duplicate-classes/)
688
980
  Detects duplicate classes within the same className attribute
689
- Example: `className="flex flex items-center"` shows warning on second `flex`
981
+ Example: `className="flex flex items-center"` shows warning on both `flex` occurrences
690
982
 
691
- - [X] **Duplicate Classes in Ternary** → [`duplicate-classes.tsx`](./example/src/duplicate-classes.tsx)
983
+ - [X] **Duplicate Classes in Ternary** → [`duplicate-classes/`](./example/src/duplicate-classes/)
692
984
  Smart detection of duplicates in ternary expressions:
693
- - Root + branch duplicate: `clsx('flex', isActive ? 'flex' : 'flex')` → Warning (true duplicate)
985
+ - Root + branch duplicate: `clsx('flex', isActive ? 'flex' : 'flex')` → Warning on all occurrences
694
986
  - Both branches same class: `clsx('mt-4', isActive ? 'flex' : 'flex')` → Warning (consider extracting)
695
987
  - Single branch only: `clsx('mt-4', isActive ? 'flex' : '')` → No warning (valid pattern)
696
988
 
697
- - [X] **Duplicate Classes in Variables with Conditionals** → [`duplicate-classes.tsx`](./example/src/duplicate-classes.tsx)
989
+ - [X] **Duplicate Classes in Variables with Conditionals** → [`duplicate-classes/`](./example/src/duplicate-classes/)
698
990
  Resolves variables containing ternary expressions and detects duplicates:
699
- - `const x = isActive ? 'flex' : 'flex'; clsx('flex', x)` → Warning (root + variable duplicate)
991
+ - `const x = isActive ? 'flex' : 'flex'; clsx('flex', x)` → Warning on all occurrences
700
992
  - `const x = isActive ? 'flex' : 'flex'; clsx('mt-4', x)` → Warning (consider extracting from variable)
701
993
  - `const x = isActive ? 'flex' : ''; clsx('mt-4', x)` → No warning (single branch)
702
994
 
@@ -712,6 +1004,25 @@ const card2 = tv({ base: 'flex justify-center' });
712
1004
  - Duplicates detected across base array/string, variants, and compoundVariants
713
1005
  - Same class in different cva() calls is NOT a duplicate (scoped per call)
714
1006
 
1007
+ - [X] **Conflicting Classes** → [`conflicting-classes.tsx`](./example/src/conflicting-classes.tsx)
1008
+ Detects conflicting Tailwind utilities that affect the same CSS property
1009
+ Example: `className="text-left text-center"` → Warning on both classes
1010
+ - Detects conflicts in 50+ CSS property groups (display, position, text-align, flex-direction, etc.)
1011
+ - Handles responsive/state variants: `md:text-left md:text-center` = conflict, `sm:text-left md:text-center` = no conflict
1012
+ - Smart ternary handling: mutually exclusive branches don't conflict
1013
+ - Works with clsx, cn, tv(), cva() and other utility functions
1014
+ - tv()/cva() base vs variant: NO conflict (variants are designed to override base)
1015
+
1016
+ - [X] **Utility Function Import Verification** → [`utility-function-imports/`](./example/src/utility-function-imports/)
1017
+ Validates custom utility functions with optional import source verification
1018
+ Example: `{ "name": "merge", "from": "@/lib/utils" }` only validates `merge()` if imported from `@/lib/utils`
1019
+ - Supports simple string format (name-only matching) and object format (with import verification)
1020
+ - Named imports: `import { merge } from '@/lib/utils'`
1021
+ - Default imports: `import merge from '@/lib/utils'`
1022
+ - Aliased imports: `import { something as merge } from '@/lib/utils'`
1023
+ - Subpath matching: `{ "from": "my-pkg" }` matches `import from 'my-pkg/utils'`
1024
+ - Functions from wrong import sources are skipped (prevents false positives)
1025
+
715
1026
  ## How It Works
716
1027
 
717
1028
  The plugin hooks into the TypeScript Language Service and:
@@ -735,6 +1046,34 @@ The plugin is designed for minimal performance impact:
735
1046
 
736
1047
  **Typical overhead**: <1ms per file for most files, ~2-3ms for files with many tv()/cva() calls
737
1048
 
1049
+ ## Hot Reloading
1050
+
1051
+ The plugin automatically watches your global CSS file for changes. When you modify your Tailwind configuration or add custom classes in your CSS file, the plugin will:
1052
+
1053
+ 1. **Detect changes** - Watches the `globalCss` file specified in your `tsconfig.json`
1054
+ 2. **Reload the design system** - Automatically re-parses your Tailwind configuration
1055
+ 3. **Clear caches** - Invalidates all diagnostic caches
1056
+ 4. **Refresh diagnostics** - Requests TypeScript to revalidate all open files
1057
+
1058
+ This means you can add new custom classes or modify your Tailwind theme, and the plugin will immediately recognize them without restarting your editor or TypeScript server.
1059
+
1060
+ ```css
1061
+ /* global.css */
1062
+ @import "tailwindcss";
1063
+
1064
+ /* Add a custom utility - plugin will recognize it after save */
1065
+ @utility custom-gradient {
1066
+ background: linear-gradient(to right, #ff7e5f, #feb47b);
1067
+ }
1068
+ ```
1069
+
1070
+ ```tsx
1071
+ // This will be valid immediately after saving global.css
1072
+ <div className="custom-gradient">Hot reloaded!</div>
1073
+ ```
1074
+
1075
+ **Note**: The file watcher uses debouncing (300ms) to avoid excessive reloads when making rapid changes.
1076
+
738
1077
  ## Development
739
1078
 
740
1079
  This is a monorepo using Yarn workspaces:
@@ -1,5 +1,5 @@
1
1
  import * as ts from 'typescript/lib/tsserverlibrary';
2
- import { ClassNameInfo, ExtractionContext } from './types';
2
+ import { ClassNameInfo, ExtractionContext, UtilityFunction } from './types';
3
3
  /**
4
4
  * Base interface for class name extractors
5
5
  * Follows the Strategy pattern for extensibility
@@ -34,7 +34,7 @@ export interface IVariantsConfig {
34
34
  */
35
35
  export interface IPluginConfig {
36
36
  globalCss?: string;
37
- utilityFunctions?: string[];
37
+ utilityFunctions?: UtilityFunction[];
38
38
  variants?: IVariantsConfig;
39
39
  allowedClasses?: string[];
40
40
  enableLogging?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/core/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gCAAgC,CAAC;AAErD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE3D;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IACnC;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC;IAE9D;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,aAAa,EAAE,CAAC;CACpE;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IACzC,aAAa,IAAI,OAAO,CAAC;IACzB,iBAAiB,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CAClD;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,sBAAsB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,gBAAgB,CAAC,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,EAAE,CAAC,UAAU,CAAC;CACrF"}
1
+ {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/core/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gCAAgC,CAAC;AAErD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE5E;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IACnC;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC;IAE9D;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,aAAa,EAAE,CAAC;CACpE;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IACzC,aAAa,IAAI,OAAO,CAAC;IACzB,iBAAiB,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CAClD;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,sBAAsB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,gBAAgB,CAAC,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,EAAE,CAAC,UAAU,CAAC;CACrF"}
@@ -1,4 +1,22 @@
1
1
  import * as ts from 'typescript/lib/tsserverlibrary';
2
+ /**
3
+ * Represents a utility function configuration with optional import source
4
+ * When 'from' is specified, the import will be verified before matching
5
+ *
6
+ * Examples:
7
+ * - { name: 'clsx', from: 'clsx' } - matches `import { clsx } from 'clsx'` or `import clsx from 'clsx'`
8
+ * - { name: 'cn', from: '@/lib/utils' } - matches `import { cn } from '@/lib/utils'`
9
+ */
10
+ export interface UtilityFunctionConfig {
11
+ name: string;
12
+ from: string;
13
+ }
14
+ /**
15
+ * A utility function can be either:
16
+ * - A simple string (matches by function name only, backwards compatible)
17
+ * - A UtilityFunctionConfig object (matches by name AND verifies import source)
18
+ */
19
+ export type UtilityFunction = string | UtilityFunctionConfig;
2
20
  /**
3
21
  * Represents information about a class name found in source code
4
22
  */
@@ -30,6 +48,14 @@ export interface ClassNameInfo {
30
48
  * Used to distinguish true duplicates from classes repeated in mutually exclusive branches.
31
49
  */
32
50
  conditionalBranchId?: string;
51
+ /**
52
+ * Indicates if this class comes from a variant context in tv() or cva().
53
+ * - undefined or false: Class is from base/root (always applied)
54
+ * - true: Class is from a variant (only applied when variant is selected)
55
+ * Used to avoid flagging conflicts between base and variant classes,
56
+ * since variants are intentionally designed to override base styles.
57
+ */
58
+ isVariant?: boolean;
33
59
  }
34
60
  /**
35
61
  * Context provided to extractors for class name extraction
@@ -37,7 +63,7 @@ export interface ClassNameInfo {
37
63
  export interface ExtractionContext {
38
64
  readonly typescript: typeof ts;
39
65
  readonly sourceFile: ts.SourceFile;
40
- readonly utilityFunctions: string[];
66
+ readonly utilityFunctions: UtilityFunction[];
41
67
  readonly typeChecker?: ts.TypeChecker;
42
68
  }
43
69
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gCAAgC,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,aAAa,CAAC,EAAE;QACf,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;KAClB,CAAC;IACF;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC;IACnC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,UAAU,EAAE,aAAa,EAAE,CAAC;CAC5B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gCAAgC,CAAC;AAErD;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACb;AAED;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,qBAAqB,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,aAAa,CAAC,EAAE;QACf,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;KAClB,CAAC;IACF;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC;IACnC,QAAQ,CAAC,gBAAgB,EAAE,eAAe,EAAE,CAAC;IAC7C,QAAQ,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,UAAU,EAAE,aAAa,EAAE,CAAC;CAC5B"}