Skip to content

Commit ced2305

Browse files
committed
feat: integrate directional modifiers into className visitor
Wire up directional modifier support in JSX className attributes: - Detect ltr:/rtl: modifiers in className visitor - Process directional modifiers using I18nManager.isRTL conditionals - Inject I18nManager import and variable in Program.exit - Set needsI18nManagerImport flag when directional modifiers found
1 parent 3513edd commit ced2305

File tree

2 files changed

+55
-10
lines changed

2 files changed

+55
-10
lines changed

src/babel/plugin/visitors/className.ts

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type { ParsedModifier, StateModifierType } from "../../../parser/index.js
88
import {
99
expandSchemeModifier,
1010
isColorSchemeModifier,
11+
isDirectionalModifier,
1112
isPlatformModifier,
1213
isSchemeModifier,
1314
isStateModifier,
@@ -19,6 +20,7 @@ import { generateStyleKey } from "../../../utils/styleKey.js";
1920
import { getTargetStyleProp, isAttributeSupported } from "../../utils/attributeMatchers.js";
2021
import { processColorSchemeModifiers } from "../../utils/colorSchemeModifierProcessing.js";
2122
import { getComponentModifierSupport, getStatePropertyForModifier } from "../../utils/componentSupport.js";
23+
import { processDirectionalModifiers } from "../../utils/directionalModifierProcessing.js";
2224
import { processDynamicExpression } from "../../utils/dynamicProcessing.js";
2325
import { createStyleFunction, processStaticClassNameWithModifiers } from "../../utils/modifierProcessing.js";
2426
import { processPlatformModifiers } from "../../utils/platformModifierProcessing.js";
@@ -107,6 +109,7 @@ export function jsxAttributeVisitor(
107109
const placeholderModifiers = modifierClasses.filter((m) => m.modifier === "placeholder");
108110
const platformModifiers = modifierClasses.filter((m) => isPlatformModifier(m.modifier));
109111
const colorSchemeModifiers = modifierClasses.filter((m) => isColorSchemeModifier(m.modifier));
112+
const directionalModifiers = modifierClasses.filter((m) => isDirectionalModifier(m.modifier));
110113
const stateModifiers = modifierClasses.filter(
111114
(m) => isStateModifier(m.modifier) && m.modifier !== "placeholder",
112115
);
@@ -138,6 +141,7 @@ export function jsxAttributeVisitor(
138141
// Handle combination of modifiers
139142
const hasPlatformModifiers = platformModifiers.length > 0;
140143
const hasColorSchemeModifiers = colorSchemeModifiers.length > 0;
144+
const hasDirectionalModifiers = directionalModifiers.length > 0;
141145
const hasStateModifiers = stateModifiers.length > 0;
142146
const hasBaseClasses = baseClasses.length > 0;
143147

@@ -160,14 +164,14 @@ export function jsxAttributeVisitor(
160164
}
161165

162166
// If we have multiple modifier types, combine them in an array expression
163-
// For state modifiers, wrap in arrow function; for color scheme, they're just conditionals
164-
if (hasStateModifiers && (hasPlatformModifiers || hasColorSchemeModifiers)) {
167+
// For state modifiers, wrap in arrow function; for color scheme and directional, they're just conditionals
168+
if (hasStateModifiers && (hasPlatformModifiers || hasColorSchemeModifiers || hasDirectionalModifiers)) {
165169
// Get the JSX opening element for component support checking
166170
const jsxOpeningElement = path.parent;
167171
const componentSupport = getComponentModifierSupport(jsxOpeningElement, t);
168172

169173
if (componentSupport) {
170-
// Build style array: [baseStyle, Platform.select(...), colorSchemeConditionals, stateConditionals]
174+
// Build style array: [baseStyle, Platform.select(...), colorSchemeConditionals, directionalConditionals, stateConditionals]
171175
const styleArrayElements: BabelTypes.Expression[] = [];
172176

173177
// Add base classes
@@ -179,7 +183,7 @@ export function jsxAttributeVisitor(
179183
if (hasRuntimeDimensions(baseStyleObject)) {
180184
throw path.buildCodeFrameError(
181185
`w-screen and h-screen cannot be combined with modifiers. ` +
182-
`Found: "${baseClassName}" with state, platform, or color scheme modifiers. ` +
186+
`Found: "${baseClassName}" with state, platform, color scheme, or directional modifiers. ` +
183187
`Use w-screen/h-screen without modifiers instead.`,
184188
);
185189
}
@@ -215,6 +219,18 @@ export function jsxAttributeVisitor(
215219
styleArrayElements.push(...colorSchemeConditionals);
216220
}
217221

222+
// Add directional modifiers as conditionals
223+
if (hasDirectionalModifiers) {
224+
const directionalConditionals = processDirectionalModifiers(
225+
directionalModifiers,
226+
state,
227+
parseClassName,
228+
generateStyleKey,
229+
t,
230+
);
231+
styleArrayElements.push(...directionalConditionals);
232+
}
233+
218234
// Add state modifiers as conditionals
219235
// Group by modifier type
220236
const modifiersByType = new Map<StateModifierType, ParsedModifier[]>();
@@ -267,9 +283,9 @@ export function jsxAttributeVisitor(
267283
}
268284
}
269285

270-
// Handle platform and/or color scheme modifiers (no state modifiers)
271-
if ((hasPlatformModifiers || hasColorSchemeModifiers) && !hasStateModifiers) {
272-
// Build style array/expression: [baseStyle, Platform.select(...), colorSchemeConditionals]
286+
// Handle platform, color scheme, and/or directional modifiers (no state modifiers)
287+
if ((hasPlatformModifiers || hasColorSchemeModifiers || hasDirectionalModifiers) && !hasStateModifiers) {
288+
// Build style array/expression: [baseStyle, Platform.select(...), colorSchemeConditionals, directionalConditionals]
273289
const styleExpressions: BabelTypes.Expression[] = [];
274290

275291
// Add base classes
@@ -281,7 +297,7 @@ export function jsxAttributeVisitor(
281297
if (hasRuntimeDimensions(baseStyleObject)) {
282298
throw path.buildCodeFrameError(
283299
`w-screen and h-screen cannot be combined with modifiers. ` +
284-
`Found: "${baseClassName}" with platform or color scheme modifiers. ` +
300+
`Found: "${baseClassName}" with platform, color scheme, or directional modifiers. ` +
285301
`Use w-screen/h-screen without modifiers instead.`,
286302
);
287303
}
@@ -317,6 +333,18 @@ export function jsxAttributeVisitor(
317333
styleExpressions.push(...colorSchemeConditionals);
318334
}
319335

336+
// Add directional modifiers as conditionals
337+
if (hasDirectionalModifiers) {
338+
const directionalConditionals = processDirectionalModifiers(
339+
directionalModifiers,
340+
state,
341+
parseClassName,
342+
generateStyleKey,
343+
t,
344+
);
345+
styleExpressions.push(...directionalConditionals);
346+
}
347+
320348
// Generate style attribute
321349
const styleExpression =
322350
styleExpressions.length === 1 ? styleExpressions[0] : t.arrayExpression(styleExpressions);

src/babel/plugin/visitors/program.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import type { NodePath } from "@babel/core";
66
import type * as BabelTypes from "@babel/types";
77
import {
88
addColorSchemeImport,
9+
addI18nManagerImport,
910
addPlatformImport,
1011
addStyleSheetImport,
1112
addWindowDimensionsImport,
1213
injectColorSchemeHook,
14+
injectI18nManagerVariable,
1315
injectStylesAtTop,
1416
injectWindowDimensionsHook,
1517
} from "../../utils/styleInjection.js";
@@ -39,8 +41,13 @@ export function programExit(
3941
removeTwImports(path, t);
4042
}
4143

42-
// If no classNames were found and no hooks needed, skip processing
43-
if (!state.hasClassNames && !state.needsWindowDimensionsImport && !state.needsColorSchemeImport) {
44+
// If no classNames were found and no hooks/imports needed, skip processing
45+
if (
46+
!state.hasClassNames &&
47+
!state.needsWindowDimensionsImport &&
48+
!state.needsColorSchemeImport &&
49+
!state.needsI18nManagerImport
50+
) {
4451
return;
4552
}
4653

@@ -54,6 +61,16 @@ export function programExit(
5461
addPlatformImport(path, t);
5562
}
5663

64+
// Add I18nManager import if directional modifiers were used and not already present
65+
if (state.needsI18nManagerImport && !state.hasI18nManagerImport) {
66+
addI18nManagerImport(path, t);
67+
}
68+
69+
// Inject I18nManager.isRTL variable at module level (not a hook, so no component scope needed)
70+
if (state.needsI18nManagerImport) {
71+
injectI18nManagerVariable(path, state.i18nManagerVariableName, state.i18nManagerLocalIdentifier, t);
72+
}
73+
5774
// Add color scheme hook import if color scheme modifiers were used and not already present
5875
if (state.needsColorSchemeImport && !state.hasColorSchemeImport) {
5976
addColorSchemeImport(path, state.colorSchemeImportSource, state.colorSchemeHookName, t);

0 commit comments

Comments
 (0)