@mgcrea/react-native-tailwind 0.7.0 → 0.8.1
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/README.md +2 -1
- package/dist/babel/index.cjs +334 -196
- package/dist/babel/index.d.ts +4 -40
- package/dist/babel/index.test.ts +214 -1
- package/dist/babel/index.ts +4 -1169
- package/dist/babel/plugin.d.ts +42 -0
- package/{src/babel/index.test.ts → dist/babel/plugin.test.ts} +216 -2
- package/dist/babel/plugin.ts +491 -0
- package/dist/babel/utils/attributeMatchers.d.ts +23 -0
- package/dist/babel/utils/attributeMatchers.test.ts +294 -0
- package/dist/babel/utils/attributeMatchers.ts +71 -0
- package/dist/babel/utils/componentSupport.d.ts +18 -0
- package/dist/babel/utils/componentSupport.test.ts +426 -0
- package/dist/babel/utils/componentSupport.ts +68 -0
- package/dist/babel/utils/dynamicProcessing.d.ts +32 -0
- package/dist/babel/utils/dynamicProcessing.ts +223 -0
- package/dist/babel/utils/modifierProcessing.d.ts +26 -0
- package/dist/babel/utils/modifierProcessing.ts +118 -0
- package/dist/babel/utils/styleInjection.d.ts +15 -0
- package/dist/babel/utils/styleInjection.ts +80 -0
- package/dist/babel/utils/styleTransforms.d.ts +39 -0
- package/dist/babel/utils/styleTransforms.test.ts +349 -0
- package/dist/babel/utils/styleTransforms.ts +258 -0
- package/dist/babel/utils/twProcessing.d.ts +28 -0
- package/dist/babel/utils/twProcessing.ts +124 -0
- package/dist/components/TextInput.d.ts +171 -14
- package/dist/config/tailwind.d.ts +302 -0
- package/dist/config/tailwind.js +1 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +1 -1
- package/dist/parser/colors.js +1 -1
- package/dist/parser/colors.test.js +1 -1
- package/dist/parser/index.d.ts +1 -0
- package/dist/parser/index.js +1 -1
- package/dist/parser/modifiers.d.ts +2 -2
- package/dist/parser/modifiers.js +1 -1
- package/dist/parser/placeholder.d.ts +36 -0
- package/dist/parser/placeholder.js +1 -0
- package/dist/parser/placeholder.test.js +1 -0
- package/dist/parser/typography.d.ts +1 -0
- package/dist/parser/typography.js +1 -1
- package/dist/parser/typography.test.js +1 -1
- package/dist/runtime.cjs +1 -1
- package/dist/runtime.cjs.map +4 -4
- package/dist/runtime.d.ts +1 -14
- package/dist/runtime.js +1 -1
- package/dist/runtime.js.map +4 -4
- package/dist/stubs/tw.d.ts +1 -14
- package/dist/types/core.d.ts +40 -0
- package/dist/types/core.js +0 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +1 -0
- package/dist/types/runtime.d.ts +15 -0
- package/dist/types/runtime.js +1 -0
- package/dist/types/util.d.ts +3 -0
- package/dist/types/util.js +0 -0
- package/dist/utils/flattenColors.d.ts +1 -0
- package/dist/utils/flattenColors.js +1 -1
- package/dist/utils/flattenColors.test.js +1 -1
- package/package.json +1 -1
- package/src/babel/index.ts +4 -1169
- package/src/babel/plugin.test.ts +482 -0
- package/src/babel/plugin.ts +491 -0
- package/src/babel/utils/attributeMatchers.test.ts +294 -0
- package/src/babel/utils/attributeMatchers.ts +71 -0
- package/src/babel/utils/componentSupport.test.ts +426 -0
- package/src/babel/utils/componentSupport.ts +68 -0
- package/src/babel/utils/dynamicProcessing.ts +223 -0
- package/src/babel/utils/modifierProcessing.ts +118 -0
- package/src/babel/utils/styleInjection.ts +80 -0
- package/src/babel/utils/styleTransforms.test.ts +349 -0
- package/src/babel/utils/styleTransforms.ts +258 -0
- package/src/babel/utils/twProcessing.ts +124 -0
- package/src/components/TextInput.tsx +17 -14
- package/src/config/{palettes.ts → tailwind.ts} +2 -2
- package/src/index.ts +6 -3
- package/src/parser/colors.test.ts +32 -0
- package/src/parser/colors.ts +2 -2
- package/src/parser/index.ts +2 -1
- package/src/parser/modifiers.ts +10 -4
- package/src/parser/placeholder.test.ts +105 -0
- package/src/parser/placeholder.ts +78 -0
- package/src/parser/typography.test.ts +11 -0
- package/src/parser/typography.ts +20 -2
- package/src/runtime.ts +1 -16
- package/src/stubs/tw.ts +1 -16
- package/src/{types.ts → types/core.ts} +0 -4
- package/src/types/index.ts +2 -0
- package/src/types/runtime.ts +17 -0
- package/src/types/util.ts +1 -0
- package/src/utils/flattenColors.test.ts +100 -0
- package/src/utils/flattenColors.ts +3 -1
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_CLASS_ATTRIBUTES,
|
|
4
|
+
buildAttributeMatchers,
|
|
5
|
+
getTargetStyleProp,
|
|
6
|
+
isAttributeSupported,
|
|
7
|
+
} from "./attributeMatchers";
|
|
8
|
+
|
|
9
|
+
describe("DEFAULT_CLASS_ATTRIBUTES", () => {
|
|
10
|
+
it("should contain standard className attributes", () => {
|
|
11
|
+
expect(DEFAULT_CLASS_ATTRIBUTES).toEqual([
|
|
12
|
+
"className",
|
|
13
|
+
"contentContainerClassName",
|
|
14
|
+
"columnWrapperClassName",
|
|
15
|
+
"ListHeaderComponentClassName",
|
|
16
|
+
"ListFooterComponentClassName",
|
|
17
|
+
]);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("should be a readonly array", () => {
|
|
21
|
+
// TypeScript compile-time check - if this compiles, the const assertion works
|
|
22
|
+
const _typeCheck: readonly string[] = DEFAULT_CLASS_ATTRIBUTES;
|
|
23
|
+
expect(_typeCheck).toBeDefined();
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe("buildAttributeMatchers", () => {
|
|
28
|
+
it("should separate exact matches from patterns", () => {
|
|
29
|
+
const attributes = ["className", "containerClassName", "*Style", "custom*"];
|
|
30
|
+
const result = buildAttributeMatchers(attributes);
|
|
31
|
+
|
|
32
|
+
// Exact matches should be in a Set
|
|
33
|
+
expect(result.exactMatches).toBeInstanceOf(Set);
|
|
34
|
+
expect(result.exactMatches.has("className")).toBe(true);
|
|
35
|
+
expect(result.exactMatches.has("containerClassName")).toBe(true);
|
|
36
|
+
expect(result.exactMatches.size).toBe(2);
|
|
37
|
+
|
|
38
|
+
// Patterns should be RegExp objects
|
|
39
|
+
expect(result.patterns).toHaveLength(2);
|
|
40
|
+
expect(result.patterns[0]).toBeInstanceOf(RegExp);
|
|
41
|
+
expect(result.patterns[1]).toBeInstanceOf(RegExp);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("should handle only exact matches", () => {
|
|
45
|
+
const attributes = ["className", "customClass", "anotherClass"];
|
|
46
|
+
const result = buildAttributeMatchers(attributes);
|
|
47
|
+
|
|
48
|
+
expect(result.exactMatches.size).toBe(3);
|
|
49
|
+
expect(result.patterns).toHaveLength(0);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("should handle only patterns", () => {
|
|
53
|
+
const attributes = ["*ClassName", "container*", "*Style*"];
|
|
54
|
+
const result = buildAttributeMatchers(attributes);
|
|
55
|
+
|
|
56
|
+
expect(result.exactMatches.size).toBe(0);
|
|
57
|
+
expect(result.patterns).toHaveLength(3);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("should handle empty array", () => {
|
|
61
|
+
const result = buildAttributeMatchers([]);
|
|
62
|
+
|
|
63
|
+
expect(result.exactMatches.size).toBe(0);
|
|
64
|
+
expect(result.patterns).toHaveLength(0);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("should convert glob patterns to regex correctly", () => {
|
|
68
|
+
const attributes = ["*ClassName", "container*", "*custom*"];
|
|
69
|
+
const result = buildAttributeMatchers(attributes);
|
|
70
|
+
|
|
71
|
+
// Test that patterns match expected strings
|
|
72
|
+
expect(result.patterns[0]?.test("myClassName")).toBe(true);
|
|
73
|
+
expect(result.patterns[0]?.test("fooClassName")).toBe(true);
|
|
74
|
+
expect(result.patterns[0]?.test("className")).toBe(false); // Doesn't start with anything
|
|
75
|
+
|
|
76
|
+
expect(result.patterns[1]?.test("containerStyle")).toBe(true);
|
|
77
|
+
expect(result.patterns[1]?.test("containerFoo")).toBe(true);
|
|
78
|
+
expect(result.patterns[1]?.test("myContainer")).toBe(false);
|
|
79
|
+
|
|
80
|
+
expect(result.patterns[2]?.test("mycustomattr")).toBe(true);
|
|
81
|
+
expect(result.patterns[2]?.test("customattr")).toBe(true);
|
|
82
|
+
expect(result.patterns[2]?.test("attrcustom")).toBe(true);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("should handle multiple wildcards in same pattern", () => {
|
|
86
|
+
const attributes = ["*custom*Class*"];
|
|
87
|
+
const result = buildAttributeMatchers(attributes);
|
|
88
|
+
|
|
89
|
+
expect(result.patterns[0]?.test("mycustomFooClassName")).toBe(true);
|
|
90
|
+
expect(result.patterns[0]?.test("customClassName")).toBe(true);
|
|
91
|
+
expect(result.patterns[0]?.test("foocustombarClassbaz")).toBe(true);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
describe("isAttributeSupported", () => {
|
|
96
|
+
it("should match exact attributes", () => {
|
|
97
|
+
const { exactMatches, patterns } = buildAttributeMatchers(["className", "customClass"]);
|
|
98
|
+
|
|
99
|
+
expect(isAttributeSupported("className", exactMatches, patterns)).toBe(true);
|
|
100
|
+
expect(isAttributeSupported("customClass", exactMatches, patterns)).toBe(true);
|
|
101
|
+
expect(isAttributeSupported("otherClass", exactMatches, patterns)).toBe(false);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("should match pattern-based attributes", () => {
|
|
105
|
+
const { exactMatches, patterns } = buildAttributeMatchers(["*ClassName", "container*"]);
|
|
106
|
+
|
|
107
|
+
expect(isAttributeSupported("myClassName", exactMatches, patterns)).toBe(true);
|
|
108
|
+
expect(isAttributeSupported("fooClassName", exactMatches, patterns)).toBe(true);
|
|
109
|
+
expect(isAttributeSupported("containerStyle", exactMatches, patterns)).toBe(true);
|
|
110
|
+
expect(isAttributeSupported("containerFoo", exactMatches, patterns)).toBe(true);
|
|
111
|
+
expect(isAttributeSupported("randomAttr", exactMatches, patterns)).toBe(false);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("should match both exact and pattern attributes", () => {
|
|
115
|
+
const { exactMatches, patterns } = buildAttributeMatchers(["className", "*Style"]);
|
|
116
|
+
|
|
117
|
+
// Exact match
|
|
118
|
+
expect(isAttributeSupported("className", exactMatches, patterns)).toBe(true);
|
|
119
|
+
|
|
120
|
+
// Pattern match
|
|
121
|
+
expect(isAttributeSupported("containerStyle", exactMatches, patterns)).toBe(true);
|
|
122
|
+
expect(isAttributeSupported("customStyle", exactMatches, patterns)).toBe(true);
|
|
123
|
+
|
|
124
|
+
// No match
|
|
125
|
+
expect(isAttributeSupported("otherAttr", exactMatches, patterns)).toBe(false);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("should prioritize exact matches (performance)", () => {
|
|
129
|
+
// Even if a pattern would match, exact match should work
|
|
130
|
+
const { exactMatches, patterns } = buildAttributeMatchers(["className", "*Name"]);
|
|
131
|
+
|
|
132
|
+
expect(isAttributeSupported("className", exactMatches, patterns)).toBe(true);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("should handle empty matchers", () => {
|
|
136
|
+
const { exactMatches, patterns } = buildAttributeMatchers([]);
|
|
137
|
+
|
|
138
|
+
expect(isAttributeSupported("className", exactMatches, patterns)).toBe(false);
|
|
139
|
+
expect(isAttributeSupported("anyAttr", exactMatches, patterns)).toBe(false);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("should be case-sensitive", () => {
|
|
143
|
+
const { exactMatches, patterns } = buildAttributeMatchers(["className"]);
|
|
144
|
+
|
|
145
|
+
expect(isAttributeSupported("className", exactMatches, patterns)).toBe(true);
|
|
146
|
+
expect(isAttributeSupported("ClassName", exactMatches, patterns)).toBe(false);
|
|
147
|
+
expect(isAttributeSupported("classname", exactMatches, patterns)).toBe(false);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("should match default React Native FlatList attributes", () => {
|
|
151
|
+
const { exactMatches, patterns } = buildAttributeMatchers([...DEFAULT_CLASS_ATTRIBUTES]);
|
|
152
|
+
|
|
153
|
+
expect(isAttributeSupported("className", exactMatches, patterns)).toBe(true);
|
|
154
|
+
expect(isAttributeSupported("contentContainerClassName", exactMatches, patterns)).toBe(true);
|
|
155
|
+
expect(isAttributeSupported("columnWrapperClassName", exactMatches, patterns)).toBe(true);
|
|
156
|
+
expect(isAttributeSupported("ListHeaderComponentClassName", exactMatches, patterns)).toBe(true);
|
|
157
|
+
expect(isAttributeSupported("ListFooterComponentClassName", exactMatches, patterns)).toBe(true);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it("should work with complex glob patterns", () => {
|
|
161
|
+
const { exactMatches, patterns } = buildAttributeMatchers(["*Container*Class*"]);
|
|
162
|
+
|
|
163
|
+
expect(isAttributeSupported("myContainerFooClassName", exactMatches, patterns)).toBe(true);
|
|
164
|
+
expect(isAttributeSupported("ContainerClassName", exactMatches, patterns)).toBe(true);
|
|
165
|
+
expect(isAttributeSupported("fooContainerBarClassBaz", exactMatches, patterns)).toBe(true);
|
|
166
|
+
expect(isAttributeSupported("ContainerStyle", exactMatches, patterns)).toBe(false);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
describe("getTargetStyleProp", () => {
|
|
171
|
+
it("should convert className to style", () => {
|
|
172
|
+
expect(getTargetStyleProp("className")).toBe("style");
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it("should convert *ClassName to *Style", () => {
|
|
176
|
+
expect(getTargetStyleProp("contentContainerClassName")).toBe("contentContainerStyle");
|
|
177
|
+
expect(getTargetStyleProp("columnWrapperClassName")).toBe("columnWrapperStyle");
|
|
178
|
+
expect(getTargetStyleProp("ListHeaderComponentClassName")).toBe("ListHeaderComponentStyle");
|
|
179
|
+
expect(getTargetStyleProp("ListFooterComponentClassName")).toBe("ListFooterComponentStyle");
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it("should handle custom className attributes", () => {
|
|
183
|
+
expect(getTargetStyleProp("customClassName")).toBe("customStyle");
|
|
184
|
+
expect(getTargetStyleProp("myCustomClassName")).toBe("myCustomStyle");
|
|
185
|
+
expect(getTargetStyleProp("fooBarClassName")).toBe("fooBarStyle");
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it("should return style for attributes not ending in ClassName", () => {
|
|
189
|
+
expect(getTargetStyleProp("customClass")).toBe("style");
|
|
190
|
+
expect(getTargetStyleProp("class")).toBe("style");
|
|
191
|
+
expect(getTargetStyleProp("myAttr")).toBe("style");
|
|
192
|
+
expect(getTargetStyleProp("")).toBe("style");
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it("should handle edge cases", () => {
|
|
196
|
+
// Attribute IS exactly "ClassName"
|
|
197
|
+
expect(getTargetStyleProp("ClassName")).toBe("Style");
|
|
198
|
+
|
|
199
|
+
// Multiple "ClassName" occurrences (only last one replaced)
|
|
200
|
+
expect(getTargetStyleProp("classNameClassName")).toBe("classNameStyle");
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it("should be case-sensitive", () => {
|
|
204
|
+
expect(getTargetStyleProp("classname")).toBe("style");
|
|
205
|
+
expect(getTargetStyleProp("CLASSNAME")).toBe("style");
|
|
206
|
+
expect(getTargetStyleProp("classNamee")).toBe("style");
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it("should handle all default attributes correctly", () => {
|
|
210
|
+
const expectedMappings = [
|
|
211
|
+
["className", "style"],
|
|
212
|
+
["contentContainerClassName", "contentContainerStyle"],
|
|
213
|
+
["columnWrapperClassName", "columnWrapperStyle"],
|
|
214
|
+
["ListHeaderComponentClassName", "ListHeaderComponentStyle"],
|
|
215
|
+
["ListFooterComponentClassName", "ListFooterComponentStyle"],
|
|
216
|
+
] as const;
|
|
217
|
+
|
|
218
|
+
for (const [input, expected] of expectedMappings) {
|
|
219
|
+
expect(getTargetStyleProp(input)).toBe(expected);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
describe("Integration - Real-world scenarios", () => {
|
|
225
|
+
it("should handle FlatList with multiple className attributes", () => {
|
|
226
|
+
const { exactMatches, patterns } = buildAttributeMatchers([...DEFAULT_CLASS_ATTRIBUTES]);
|
|
227
|
+
|
|
228
|
+
// All FlatList className props should be supported
|
|
229
|
+
const flatListAttrs = [
|
|
230
|
+
["className", "style"],
|
|
231
|
+
["contentContainerClassName", "contentContainerStyle"],
|
|
232
|
+
["columnWrapperClassName", "columnWrapperStyle"],
|
|
233
|
+
["ListHeaderComponentClassName", "ListHeaderComponentStyle"],
|
|
234
|
+
["ListFooterComponentClassName", "ListFooterComponentStyle"],
|
|
235
|
+
] as const;
|
|
236
|
+
|
|
237
|
+
for (const [attr, expectedStyle] of flatListAttrs) {
|
|
238
|
+
expect(isAttributeSupported(attr, exactMatches, patterns)).toBe(true);
|
|
239
|
+
expect(getTargetStyleProp(attr)).toBe(expectedStyle);
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it("should support custom wildcard pattern for all *ClassName attributes", () => {
|
|
244
|
+
const { exactMatches, patterns } = buildAttributeMatchers(["*ClassName"]);
|
|
245
|
+
|
|
246
|
+
// Should match any attribute ending in ClassName (with at least one char before)
|
|
247
|
+
// Note: The regex ^.*ClassName$ requires at least one character due to .*
|
|
248
|
+
expect(isAttributeSupported("myCustomClassName", exactMatches, patterns)).toBe(true);
|
|
249
|
+
expect(isAttributeSupported("fooBarBazClassName", exactMatches, patterns)).toBe(true);
|
|
250
|
+
expect(isAttributeSupported("xClassName", exactMatches, patterns)).toBe(true);
|
|
251
|
+
|
|
252
|
+
// Edge case: bare "className" needs at least one char before it for .* to match
|
|
253
|
+
// If you want to include "className", add it explicitly or use a different pattern
|
|
254
|
+
expect(isAttributeSupported("className", exactMatches, patterns)).toBe(false);
|
|
255
|
+
|
|
256
|
+
// Should convert to corresponding style prop
|
|
257
|
+
expect(getTargetStyleProp("myCustomClassName")).toBe("myCustomStyle");
|
|
258
|
+
|
|
259
|
+
// Should not match non-className attributes
|
|
260
|
+
expect(isAttributeSupported("myCustomClass", exactMatches, patterns)).toBe(false);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it("should support combining exact matches with patterns", () => {
|
|
264
|
+
const { exactMatches, patterns } = buildAttributeMatchers([
|
|
265
|
+
"className",
|
|
266
|
+
"customClass",
|
|
267
|
+
"*ClassName",
|
|
268
|
+
"container*",
|
|
269
|
+
]);
|
|
270
|
+
|
|
271
|
+
// Exact matches
|
|
272
|
+
expect(isAttributeSupported("className", exactMatches, patterns)).toBe(true);
|
|
273
|
+
expect(isAttributeSupported("customClass", exactMatches, patterns)).toBe(true);
|
|
274
|
+
|
|
275
|
+
// Pattern matches
|
|
276
|
+
expect(isAttributeSupported("myClassName", exactMatches, patterns)).toBe(true);
|
|
277
|
+
expect(isAttributeSupported("containerStyle", exactMatches, patterns)).toBe(true);
|
|
278
|
+
|
|
279
|
+
// No matches
|
|
280
|
+
expect(isAttributeSupported("randomAttr", exactMatches, patterns)).toBe(false);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it("should handle empty configuration gracefully", () => {
|
|
284
|
+
const { exactMatches, patterns } = buildAttributeMatchers([]);
|
|
285
|
+
|
|
286
|
+
// Nothing should be supported
|
|
287
|
+
expect(isAttributeSupported("className", exactMatches, patterns)).toBe(false);
|
|
288
|
+
expect(isAttributeSupported("anything", exactMatches, patterns)).toBe(false);
|
|
289
|
+
|
|
290
|
+
// getTargetStyleProp should still work
|
|
291
|
+
expect(getTargetStyleProp("className")).toBe("style");
|
|
292
|
+
expect(getTargetStyleProp("customClassName")).toBe("customStyle");
|
|
293
|
+
});
|
|
294
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for matching and handling JSX attribute names
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Default className-like attributes (used when no custom attributes are provided)
|
|
7
|
+
*/
|
|
8
|
+
export const DEFAULT_CLASS_ATTRIBUTES = [
|
|
9
|
+
"className",
|
|
10
|
+
"contentContainerClassName",
|
|
11
|
+
"columnWrapperClassName",
|
|
12
|
+
"ListHeaderComponentClassName",
|
|
13
|
+
"ListFooterComponentClassName",
|
|
14
|
+
] as const;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Build attribute matching structures from plugin options
|
|
18
|
+
* Separates exact matches from pattern-based matches
|
|
19
|
+
*/
|
|
20
|
+
export function buildAttributeMatchers(attributes: string[]): {
|
|
21
|
+
exactMatches: Set<string>;
|
|
22
|
+
patterns: RegExp[];
|
|
23
|
+
} {
|
|
24
|
+
const exactMatches = new Set<string>();
|
|
25
|
+
const patterns: RegExp[] = [];
|
|
26
|
+
|
|
27
|
+
for (const attr of attributes) {
|
|
28
|
+
if (attr.includes("*")) {
|
|
29
|
+
// Convert glob pattern to regex
|
|
30
|
+
// *ClassName -> /^.*ClassName$/
|
|
31
|
+
// container* -> /^container.*$/
|
|
32
|
+
const regexPattern = "^" + attr.replace(/\*/g, ".*") + "$";
|
|
33
|
+
patterns.push(new RegExp(regexPattern));
|
|
34
|
+
} else {
|
|
35
|
+
// Exact match
|
|
36
|
+
exactMatches.add(attr);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return { exactMatches, patterns };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Check if an attribute name matches the configured attributes
|
|
45
|
+
*/
|
|
46
|
+
export function isAttributeSupported(
|
|
47
|
+
attributeName: string,
|
|
48
|
+
exactMatches: Set<string>,
|
|
49
|
+
patterns: RegExp[],
|
|
50
|
+
): boolean {
|
|
51
|
+
// Check exact matches first (faster)
|
|
52
|
+
if (exactMatches.has(attributeName)) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Check pattern matches
|
|
57
|
+
for (const pattern of patterns) {
|
|
58
|
+
if (pattern.test(attributeName)) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Get the target style prop name based on the className attribute
|
|
68
|
+
*/
|
|
69
|
+
export function getTargetStyleProp(attributeName: string): string {
|
|
70
|
+
return attributeName.endsWith("ClassName") ? attributeName.replace("ClassName", "Style") : "style";
|
|
71
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for determining component modifier support
|
|
3
|
+
*/
|
|
4
|
+
import type * as BabelTypes from "@babel/types";
|
|
5
|
+
import type { ModifierType } from "../../parser/index.js";
|
|
6
|
+
/**
|
|
7
|
+
* Check if a JSX element supports modifiers and determine which modifiers are supported
|
|
8
|
+
* Returns an object with component info and supported modifiers
|
|
9
|
+
*/
|
|
10
|
+
export declare function getComponentModifierSupport(jsxElement: BabelTypes.Node, t: typeof BabelTypes): {
|
|
11
|
+
component: string;
|
|
12
|
+
supportedModifiers: ModifierType[];
|
|
13
|
+
} | null;
|
|
14
|
+
/**
|
|
15
|
+
* Get the state property name for a modifier type
|
|
16
|
+
* Maps modifier types to component state parameter properties
|
|
17
|
+
*/
|
|
18
|
+
export declare function getStatePropertyForModifier(modifier: ModifierType): string;
|