@stylexjs/babel-plugin 0.17.5 → 0.18.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.
@@ -1484,6 +1484,12 @@ const checkRuntimeInjection = unionOf3(boolean(), string(), object({
1484
1484
  from: string(),
1485
1485
  as: string()
1486
1486
  }));
1487
+ const checkEnvOption = (value, name = 'options.env') => {
1488
+ if (typeof value !== 'object' || value == null || Array.isArray(value)) {
1489
+ return new Error(`Expected (${name}) to be an object, but got \`${String(JSON.stringify(value))}\`.`);
1490
+ }
1491
+ return value;
1492
+ };
1487
1493
  const DEFAULT_INJECT_PATH = '@stylexjs/stylex/lib/stylex-inject';
1488
1494
  class StateManager {
1489
1495
  importPaths = new Set();
@@ -1503,6 +1509,7 @@ class StateManager {
1503
1509
  stylexViewTransitionClassImport = new Set();
1504
1510
  stylexDefaultMarkerImport = new Set();
1505
1511
  stylexWhenImport = new Set();
1512
+ stylexEnvImport = new Set();
1506
1513
  injectImportInserted = null;
1507
1514
  styleMap = new Map();
1508
1515
  styleVars = new Map();
@@ -1536,6 +1543,10 @@ class StateManager {
1536
1543
  const propertyValidationMode = logAndDefault(unionOf3(literal('throw'), literal('warn'), literal('silent')), options.propertyValidationMode ?? defaultOptions.propertyValidationMode, 'silent', 'options.propertyValidationMode');
1537
1544
  const unstable_moduleResolution = logAndDefault(unionOf(nullish(), CheckModuleResolution), options.unstable_moduleResolution, null, 'options.unstable_moduleResolution');
1538
1545
  const treeshakeCompensation = logAndDefault(boolean(), options.treeshakeCompensation ?? defaultOptions.treeshakeCompensation, false, 'options.treeshakeCompensation');
1546
+ const envInput = logAndDefault(checkEnvOption, options.env ?? {}, {}, 'options.env');
1547
+ const env = Object.freeze({
1548
+ ...envInput
1549
+ });
1539
1550
  const aliasesOption = logAndDefault(unionOf(nullish(), objectOf(unionOf(string(), array(string())))), options.aliases, null, 'options.aliases');
1540
1551
  const aliases = aliasesOption == null ? aliasesOption : Object.fromEntries(Object.entries(aliasesOption).map(([key, value]) => {
1541
1552
  if (typeof value === 'string') {
@@ -1551,6 +1562,7 @@ class StateManager {
1551
1562
  definedStylexCSSVariables: {},
1552
1563
  dev,
1553
1564
  propertyValidationMode,
1565
+ env,
1554
1566
  enableDebugClassNames,
1555
1567
  enableDebugDataProp,
1556
1568
  enableDevClassNames,
@@ -1592,6 +1604,31 @@ class StateManager {
1592
1604
  }
1593
1605
  return null;
1594
1606
  }
1607
+ applyStylexEnv(identifiers) {
1608
+ const env = this.options.env;
1609
+ this.stylexImport.forEach(importName => {
1610
+ const current = identifiers[importName];
1611
+ if (current != null && typeof current === 'object' && !Array.isArray(current)) {
1612
+ if ('fn' in current) {
1613
+ identifiers[importName] = {
1614
+ env
1615
+ };
1616
+ } else {
1617
+ identifiers[importName] = {
1618
+ ...current,
1619
+ env
1620
+ };
1621
+ }
1622
+ return;
1623
+ }
1624
+ identifiers[importName] = {
1625
+ env
1626
+ };
1627
+ });
1628
+ this.stylexEnvImport.forEach(importName => {
1629
+ identifiers[importName] = env;
1630
+ });
1631
+ }
1595
1632
  get canReferenceTheme() {
1596
1633
  return !!this.inStyleXCreate;
1597
1634
  }
@@ -1910,6 +1947,9 @@ function readImportDeclarations(path, state) {
1910
1947
  if (importedName === 'defaultMarker') {
1911
1948
  state.stylexDefaultMarkerImport.add(localName);
1912
1949
  }
1950
+ if (importedName === 'env') {
1951
+ state.stylexEnvImport.add(localName);
1952
+ }
1913
1953
  }
1914
1954
  }
1915
1955
  }
@@ -1976,6 +2016,9 @@ function readRequires(path, state) {
1976
2016
  if (prop.key.name === 'defaultMarker') {
1977
2017
  state.stylexDefaultMarkerImport.add(value.name);
1978
2018
  }
2019
+ if (prop.key.name === 'env') {
2020
+ state.stylexEnvImport.add(value.name);
2021
+ }
1979
2022
  }
1980
2023
  }
1981
2024
  }
@@ -4574,7 +4617,6 @@ const ILLEGAL_NESTED_PSEUDO = "Pseudo objects can't be nested more than one leve
4574
4617
  const ILLEGAL_PROP_VALUE = 'A style value can only contain an array, string or number.';
4575
4618
  const ILLEGAL_PROP_ARRAY_VALUE = 'A style array value can only contain strings or numbers.';
4576
4619
  const ILLEGAL_NAMESPACE_VALUE = 'A StyleX namespace must be an object.';
4577
- const INVALID_CONST_KEY = 'Keys in defineConsts() cannot start with "--".';
4578
4620
  const INVALID_PSEUDO = 'Invalid pseudo selector, not on the whitelist.';
4579
4621
  const INVALID_PSEUDO_OR_AT_RULE = 'Invalid pseudo or at-rule.';
4580
4622
  const INVALID_MEDIA_QUERY_SYNTAX = 'Invalid media query syntax.';
@@ -4597,7 +4639,6 @@ var m = /*#__PURE__*/Object.freeze({
4597
4639
  ILLEGAL_NESTED_PSEUDO: ILLEGAL_NESTED_PSEUDO,
4598
4640
  ILLEGAL_PROP_ARRAY_VALUE: ILLEGAL_PROP_ARRAY_VALUE,
4599
4641
  ILLEGAL_PROP_VALUE: ILLEGAL_PROP_VALUE,
4600
- INVALID_CONST_KEY: INVALID_CONST_KEY,
4601
4642
  INVALID_MEDIA_QUERY_SYNTAX: INVALID_MEDIA_QUERY_SYNTAX,
4602
4643
  INVALID_PSEUDO: INVALID_PSEUDO,
4603
4644
  INVALID_PSEUDO_OR_AT_RULE: INVALID_PSEUDO_OR_AT_RULE,
@@ -5598,6 +5639,16 @@ function requirePropertyPriorities () {
5598
5639
  SIBLING_AFTER: /^:where\(:has\(~\s\.[0-9a-zA-Z_-]+(:[a-zA-Z-]+)\)\)$/,
5599
5640
  ANY_SIBLING: /^:where\(\.[0-9a-zA-Z_-]+(:[a-zA-Z-]+)\s+~\s+\*,\s+:has\(~\s\.[0-9a-zA-Z_-]+(:[a-zA-Z-]+)\)\)$/
5600
5641
  };
5642
+ const PSEUDO_PART_REGEX = /::[a-zA-Z-]+|:[a-zA-Z-]+(?:\([^)]*\))?/g;
5643
+ function getCompoundPseudoPriority(key) {
5644
+ const parts = key.match(PSEUDO_PART_REGEX);
5645
+ if (!parts || parts.length <= 1 || parts.some(p => p.includes('('))) return;
5646
+ let total = 0;
5647
+ for (const part of parts) {
5648
+ total += part.startsWith('::') ? PSEUDO_ELEMENT_PRIORITY : PSEUDO_CLASS_PRIORITIES[part] ?? 40;
5649
+ }
5650
+ return total;
5651
+ }
5601
5652
  function getAtRulePriority(key) {
5602
5653
  if (key.startsWith('--')) {
5603
5654
  return 1;
@@ -5638,7 +5689,7 @@ function requirePropertyPriorities () {
5638
5689
  return 40 + pseudoBase(siblingAfterMatch[1]);
5639
5690
  }
5640
5691
  if (key.startsWith(':')) {
5641
- const prop = key.startsWith(':') && key.includes('(') ? key.slice(0, key.indexOf('(')) : key;
5692
+ const prop = key.split('(')[0];
5642
5693
  return PSEUDO_CLASS_PRIORITIES[prop] ?? 40;
5643
5694
  }
5644
5695
  }
@@ -5659,6 +5710,8 @@ function requirePropertyPriorities () {
5659
5710
  function getPriority(key) {
5660
5711
  const atRulePriority = getAtRulePriority(key);
5661
5712
  if (atRulePriority) return atRulePriority;
5713
+ const compoundPriority = getCompoundPseudoPriority(key);
5714
+ if (compoundPriority != null) return compoundPriority;
5662
5715
  const pseudoElementPriority = getPseudoElementPriority(key);
5663
5716
  if (pseudoElementPriority) return pseudoElementPriority;
5664
5717
  const pseudoClassPriority = getPseudoClassPriority(key);
@@ -5869,7 +5922,7 @@ class PreRule {
5869
5922
  this.value = value;
5870
5923
  }
5871
5924
  get pseudos() {
5872
- const unsortedPseudos = this.keyPath.filter(key => key.startsWith(':'));
5925
+ const unsortedPseudos = this.keyPath.filter(key => key.startsWith(':') || key.startsWith('['));
5873
5926
  return sortPseudos(unsortedPseudos);
5874
5927
  }
5875
5928
  get atRules() {
@@ -5974,7 +6027,7 @@ function _flattenRawStyleObject(style, keyPath, options) {
5974
6027
  });
5975
6028
  continue;
5976
6029
  }
5977
- if (typeof value === 'object' && !key.startsWith(':') && !key.startsWith('@')) {
6030
+ if (typeof value === 'object' && !key.startsWith(':') && !key.startsWith('@') && !key.startsWith('[')) {
5978
6031
  const equivalentPairs = {};
5979
6032
  for (const condition in value) {
5980
6033
  const innerValue = value[condition];
@@ -6000,7 +6053,7 @@ function _flattenRawStyleObject(style, keyPath, options) {
6000
6053
  flattened.push([property, PreRuleSet.create(rules)]);
6001
6054
  }
6002
6055
  }
6003
- if (typeof value === 'object' && (key.startsWith(':') || key.startsWith('@'))) {
6056
+ if (typeof value === 'object' && (key.startsWith(':') || key.startsWith('@') || key.startsWith('['))) {
6004
6057
  const pairs = _flattenRawStyleObject(value, [...keyPath, _key], options);
6005
6058
  for (const [property, preRule] of pairs) {
6006
6059
  flattened.push([key + '_' + property, preRule]);
@@ -6030,7 +6083,7 @@ function validateNamespace(namespace, conditions = []) {
6030
6083
  continue;
6031
6084
  }
6032
6085
  if (isPlainObject(val)) {
6033
- if (key.startsWith('@') || key.startsWith(':')) {
6086
+ if (key.startsWith('@') || key.startsWith(':') || key.startsWith('[')) {
6034
6087
  if (conditions.includes(key)) {
6035
6088
  throw new Error(DUPLICATE_CONDITIONAL);
6036
6089
  }
@@ -6046,7 +6099,7 @@ function validateNamespace(namespace, conditions = []) {
6046
6099
  function validateConditionalStyles(val, conditions = []) {
6047
6100
  for (const key in val) {
6048
6101
  const v = val[key];
6049
- if (!(key.startsWith('@') || key.startsWith(':') || key.startsWith('var(--') || key === 'default')) {
6102
+ if (!(key.startsWith('@') || key.startsWith(':') || key.startsWith('[') || key.startsWith('var(--') || key === 'default')) {
6050
6103
  throw new Error(INVALID_PSEUDO_OR_AT_RULE);
6051
6104
  }
6052
6105
  if (conditions.includes(key)) {
@@ -6432,11 +6485,8 @@ function styleXDefineConsts(constants, options) {
6432
6485
  const jsOutput = {};
6433
6486
  const injectableStyles = {};
6434
6487
  for (const [key, value] of Object.entries(constants)) {
6435
- if (key.startsWith('--')) {
6436
- throw new Error(INVALID_CONST_KEY);
6437
- }
6438
6488
  const varSafeKey = (key[0] >= '0' && key[0] <= '9' ? `_${key}` : key).replace(/[^a-zA-Z0-9]/g, '_');
6439
- const constKey = debug && enableDebugClassNames ? `${varSafeKey}-${classNamePrefix}${hash(`${exportId}.${key}`)}` : `${classNamePrefix}${hash(`${exportId}.${key}`)}`;
6489
+ const constKey = key.startsWith('--') ? key.slice(2) : debug && enableDebugClassNames ? `${varSafeKey}-${classNamePrefix}${hash(`${exportId}.${key}`)}` : `${classNamePrefix}${hash(`${exportId}.${key}`)}`;
6440
6490
  jsOutput[key] = value;
6441
6491
  injectableStyles[constKey] = {
6442
6492
  constKey,
@@ -6608,12 +6658,15 @@ function getDefaultMarkerClassName(options = defaultOptions) {
6608
6658
  return `${prefix}default-marker`;
6609
6659
  }
6610
6660
  function validatePseudoSelector(pseudo) {
6611
- if (!pseudo.startsWith(':')) {
6612
- throw new Error('Pseudo selector must start with ":"');
6661
+ if (!(pseudo.startsWith(':') || pseudo.startsWith('['))) {
6662
+ throw new Error('Pseudo selector must start with ":" or "["');
6613
6663
  }
6614
6664
  if (pseudo.startsWith('::')) {
6615
6665
  throw new Error('Pseudo selector cannot start with "::" (pseudo-elements are not supported)');
6616
6666
  }
6667
+ if (pseudo.startsWith('[') && !pseudo.endsWith(']')) {
6668
+ throw new Error('Attribute selector must end with "]"');
6669
+ }
6617
6670
  }
6618
6671
  function ancestor(pseudo, options = defaultOptions) {
6619
6672
  validatePseudoSelector(pseudo);
@@ -7651,6 +7704,18 @@ function isSafeToSkipNullCheck(expr) {
7651
7704
  }
7652
7705
  return false;
7653
7706
  }
7707
+ function hasExplicitNullishFallback(expr) {
7708
+ if (isNullLiteral(expr)) return true;
7709
+ if (isIdentifier(expr) && expr.name === 'undefined') return true;
7710
+ if (isUnaryExpression(expr) && expr.operator === 'void') return true;
7711
+ if (isConditionalExpression(expr)) {
7712
+ return hasExplicitNullishFallback(expr.consequent) || hasExplicitNullishFallback(expr.alternate);
7713
+ }
7714
+ if (isLogicalExpression(expr)) {
7715
+ return hasExplicitNullishFallback(expr.left) || hasExplicitNullishFallback(expr.right);
7716
+ }
7717
+ return false;
7718
+ }
7654
7719
  function transformStyleXCreate(path, state) {
7655
7720
  const {
7656
7721
  node
@@ -7719,6 +7784,7 @@ function transformStyleXCreate(path, state) {
7719
7784
  when: stylexWhen
7720
7785
  };
7721
7786
  });
7787
+ state.applyStylexEnv(identifiers);
7722
7788
  const {
7723
7789
  confident,
7724
7790
  value,
@@ -7746,7 +7812,7 @@ function transformStyleXCreate(path, state) {
7746
7812
  const isPseudoElement = path.some(p => p.startsWith('::'));
7747
7813
  injectedInheritStyles[variableName] = {
7748
7814
  priority: 0,
7749
- ltr: `@property ${variableName} { syntax: "*";${isPseudoElement ? '' : ' inherits: false;'}}`,
7815
+ ltr: `@property ${variableName} { syntax: "*"; inherits: ${isPseudoElement ? 'true' : 'false'};}`,
7750
7816
  rtl: null
7751
7817
  };
7752
7818
  });
@@ -7795,14 +7861,21 @@ function transformStyleXCreate(path, state) {
7795
7861
  for (const [className, classPaths] of Object.entries(classPathsPerNamespace[key])) {
7796
7862
  origClassPaths[className] = classPaths.join('_');
7797
7863
  }
7798
- let dynamicStyles = Object.entries(inlineStyles).map(([_key, v]) => ({
7864
+ let dynamicStyles = Object.entries(inlineStyles).map(([varName, v]) => ({
7799
7865
  expression: v.originalExpression,
7800
7866
  key: v.path.slice(0, v.path.findIndex(p => !p.startsWith(':') && !p.startsWith('@')) + 1).join('_'),
7867
+ varName,
7801
7868
  path: v.path.join('_')
7802
7869
  }));
7803
7870
  if (state.options.styleResolution === 'legacy-expand-shorthands') {
7804
7871
  dynamicStyles = legacyExpandShorthands(dynamicStyles);
7805
7872
  }
7873
+ const nullishVarExpressions = new Map();
7874
+ dynamicStyles.forEach(style => {
7875
+ if (hasExplicitNullishFallback(style.expression)) {
7876
+ nullishVarExpressions.set(style.varName, style.expression);
7877
+ }
7878
+ });
7806
7879
  if (isObjectExpression(prop.value)) {
7807
7880
  const value = prop.value;
7808
7881
  let cssTagValue = booleanLiteral(true);
@@ -7826,9 +7899,23 @@ function transformStyleXCreate(path, state) {
7826
7899
  let isStatic = true;
7827
7900
  const exprList = [];
7828
7901
  classList.forEach((cls, index) => {
7829
- const expr = dynamicStyles.find(({
7902
+ let expr = dynamicStyles.find(({
7830
7903
  path
7831
7904
  }) => origClassPaths[cls] === path)?.expression;
7905
+ if (expr == null && nullishVarExpressions.size > 0) {
7906
+ const injectedStyle = injectedStyles[cls];
7907
+ const rule = injectedStyle != null ? typeof injectedStyle.ltr === 'string' ? injectedStyle.ltr : typeof injectedStyle.rtl === 'string' ? injectedStyle.rtl : null : null;
7908
+ if (rule != null) {
7909
+ const matches = rule.matchAll(/var\((--x-[^,)]+)[^)]*\)/g);
7910
+ for (const match of matches) {
7911
+ const varExpr = nullishVarExpressions.get(match[1]);
7912
+ if (varExpr != null) {
7913
+ expr = varExpr;
7914
+ break;
7915
+ }
7916
+ }
7917
+ }
7918
+ }
7832
7919
  const isLast = index === classList.length - 1;
7833
7920
  const clsWithSpace = isLast ? cls : cls + ' ';
7834
7921
  if (expr && !isSafeToSkipNullCheck(expr)) {
@@ -7989,6 +8076,7 @@ function transformStyleXCreateTheme(callExpressionPath, state) {
7989
8076
  types: stylexTypes
7990
8077
  };
7991
8078
  });
8079
+ state.applyStylexEnv(identifiers);
7992
8080
  const {
7993
8081
  confident: confident2,
7994
8082
  value: overrides
@@ -8103,6 +8191,7 @@ function transformStyleXDefineVars(callExpressionPath, state) {
8103
8191
  types: stylexTypes
8104
8192
  };
8105
8193
  });
8194
+ state.applyStylexEnv(identifiers);
8106
8195
  const {
8107
8196
  confident,
8108
8197
  value
@@ -8165,10 +8254,16 @@ function transformStyleXDefineConsts(callExpressionPath, state) {
8165
8254
  const varId = variableDeclaratorNode.id;
8166
8255
  const args = callExpressionPath.get('arguments');
8167
8256
  const firstArg = args[0];
8257
+ const evaluatePathFnConfig = {
8258
+ identifiers: {},
8259
+ memberExpressions: {},
8260
+ disableImports: true
8261
+ };
8262
+ state.applyStylexEnv(evaluatePathFnConfig.identifiers);
8168
8263
  const {
8169
8264
  confident,
8170
8265
  value
8171
- } = evaluate(firstArg, state);
8266
+ } = evaluate(firstArg, state, evaluatePathFnConfig);
8172
8267
  if (!confident) {
8173
8268
  throw callExpressionPath.buildCodeFrameError(messages.nonStaticValue('defineConsts'), SyntaxError);
8174
8269
  }
@@ -8250,6 +8345,7 @@ function transformStyleXKeyframes(path, state) {
8250
8345
  fn: firstThatWorks
8251
8346
  };
8252
8347
  });
8348
+ state.applyStylexEnv(identifiers);
8253
8349
  const {
8254
8350
  confident,
8255
8351
  value
@@ -8321,6 +8417,7 @@ function transformStyleXPositionTry(path, state) {
8321
8417
  fn: firstThatWorks
8322
8418
  };
8323
8419
  });
8420
+ state.applyStylexEnv(identifiers);
8324
8421
  const {
8325
8422
  confident,
8326
8423
  value
@@ -8375,6 +8472,12 @@ function transformStyleXMerge(path, state) {
8375
8472
  if (node == null || node.callee.type !== 'Identifier' || !state.stylexImport.has(node.callee.name)) {
8376
8473
  return;
8377
8474
  }
8475
+ const evaluatePathFnConfig = {
8476
+ identifiers: {},
8477
+ memberExpressions: {},
8478
+ disableImports: true
8479
+ };
8480
+ state.applyStylexEnv(evaluatePathFnConfig.identifiers);
8378
8481
  let bailOut = false;
8379
8482
  let conditional = 0;
8380
8483
  let currentIndex = -1;
@@ -8481,7 +8584,7 @@ function transformStyleXMerge(path, state) {
8481
8584
  const {
8482
8585
  confident,
8483
8586
  value: styleValue
8484
- } = evaluate(path, state);
8587
+ } = evaluate(path, state, evaluatePathFnConfig);
8485
8588
  if (!confident || styleValue == null) {
8486
8589
  nonNullProps = true;
8487
8590
  styleNonNullProps = true;
@@ -8617,6 +8720,7 @@ function transformStylexProps(path, state) {
8617
8720
  }
8618
8721
  };
8619
8722
  });
8723
+ state.applyStylexEnv(identifiers);
8620
8724
  const evaluatePathFnConfig = {
8621
8725
  identifiers,
8622
8726
  memberExpressions,
@@ -8942,6 +9046,7 @@ function transformStyleXViewTransitionClass(path, state) {
8942
9046
  fn: keyframes$1
8943
9047
  };
8944
9048
  });
9049
+ state.applyStylexEnv(identifiers);
8945
9050
  const {
8946
9051
  confident,
8947
9052
  value
package/lib/index.js CHANGED
@@ -370,6 +370,12 @@ const checkRuntimeInjection = unionOf3(boolean(), string(), object({
370
370
  from: string(),
371
371
  as: string()
372
372
  }));
373
+ const checkEnvOption = (value, name = 'options.env') => {
374
+ if (typeof value !== 'object' || value == null || Array.isArray(value)) {
375
+ return new Error(`Expected (${name}) to be an object, but got \`${String(JSON.stringify(value))}\`.`);
376
+ }
377
+ return value;
378
+ };
373
379
  const DEFAULT_INJECT_PATH = '@stylexjs/stylex/lib/stylex-inject';
374
380
  class StateManager {
375
381
  importPaths = new Set();
@@ -389,6 +395,7 @@ class StateManager {
389
395
  stylexViewTransitionClassImport = new Set();
390
396
  stylexDefaultMarkerImport = new Set();
391
397
  stylexWhenImport = new Set();
398
+ stylexEnvImport = new Set();
392
399
  injectImportInserted = null;
393
400
  styleMap = new Map();
394
401
  styleVars = new Map();
@@ -422,6 +429,10 @@ class StateManager {
422
429
  const propertyValidationMode = logAndDefault(unionOf3(literal('throw'), literal('warn'), literal('silent')), options.propertyValidationMode ?? defaultOptions.propertyValidationMode, 'silent', 'options.propertyValidationMode');
423
430
  const unstable_moduleResolution = logAndDefault(unionOf(nullish(), CheckModuleResolution), options.unstable_moduleResolution, null, 'options.unstable_moduleResolution');
424
431
  const treeshakeCompensation = logAndDefault(boolean(), options.treeshakeCompensation ?? defaultOptions.treeshakeCompensation, false, 'options.treeshakeCompensation');
432
+ const envInput = logAndDefault(checkEnvOption, options.env ?? {}, {}, 'options.env');
433
+ const env = Object.freeze({
434
+ ...envInput
435
+ });
425
436
  const aliasesOption = logAndDefault(unionOf(nullish(), objectOf(unionOf(string(), array(string())))), options.aliases, null, 'options.aliases');
426
437
  const aliases = aliasesOption == null ? aliasesOption : Object.fromEntries(Object.entries(aliasesOption).map(([key, value]) => {
427
438
  if (typeof value === 'string') {
@@ -437,6 +448,7 @@ class StateManager {
437
448
  definedStylexCSSVariables: {},
438
449
  dev,
439
450
  propertyValidationMode,
451
+ env,
440
452
  enableDebugClassNames,
441
453
  enableDebugDataProp,
442
454
  enableDevClassNames,
@@ -478,6 +490,31 @@ class StateManager {
478
490
  }
479
491
  return null;
480
492
  }
493
+ applyStylexEnv(identifiers) {
494
+ const env = this.options.env;
495
+ this.stylexImport.forEach(importName => {
496
+ const current = identifiers[importName];
497
+ if (current != null && typeof current === 'object' && !Array.isArray(current)) {
498
+ if ('fn' in current) {
499
+ identifiers[importName] = {
500
+ env
501
+ };
502
+ } else {
503
+ identifiers[importName] = {
504
+ ...current,
505
+ env
506
+ };
507
+ }
508
+ return;
509
+ }
510
+ identifiers[importName] = {
511
+ env
512
+ };
513
+ });
514
+ this.stylexEnvImport.forEach(importName => {
515
+ identifiers[importName] = env;
516
+ });
517
+ }
481
518
  get canReferenceTheme() {
482
519
  return !!this.inStyleXCreate;
483
520
  }
@@ -796,6 +833,9 @@ function readImportDeclarations(path, state) {
796
833
  if (importedName === 'defaultMarker') {
797
834
  state.stylexDefaultMarkerImport.add(localName);
798
835
  }
836
+ if (importedName === 'env') {
837
+ state.stylexEnvImport.add(localName);
838
+ }
799
839
  }
800
840
  }
801
841
  }
@@ -862,6 +902,9 @@ function readRequires(path, state) {
862
902
  if (prop.key.name === 'defaultMarker') {
863
903
  state.stylexDefaultMarkerImport.add(value.name);
864
904
  }
905
+ if (prop.key.name === 'env') {
906
+ state.stylexEnvImport.add(value.name);
907
+ }
865
908
  }
866
909
  }
867
910
  }
@@ -3460,7 +3503,6 @@ const ILLEGAL_NESTED_PSEUDO = "Pseudo objects can't be nested more than one leve
3460
3503
  const ILLEGAL_PROP_VALUE = 'A style value can only contain an array, string or number.';
3461
3504
  const ILLEGAL_PROP_ARRAY_VALUE = 'A style array value can only contain strings or numbers.';
3462
3505
  const ILLEGAL_NAMESPACE_VALUE = 'A StyleX namespace must be an object.';
3463
- const INVALID_CONST_KEY = 'Keys in defineConsts() cannot start with "--".';
3464
3506
  const INVALID_PSEUDO = 'Invalid pseudo selector, not on the whitelist.';
3465
3507
  const INVALID_PSEUDO_OR_AT_RULE = 'Invalid pseudo or at-rule.';
3466
3508
  const INVALID_MEDIA_QUERY_SYNTAX = 'Invalid media query syntax.';
@@ -3483,7 +3525,6 @@ var m = /*#__PURE__*/Object.freeze({
3483
3525
  ILLEGAL_NESTED_PSEUDO: ILLEGAL_NESTED_PSEUDO,
3484
3526
  ILLEGAL_PROP_ARRAY_VALUE: ILLEGAL_PROP_ARRAY_VALUE,
3485
3527
  ILLEGAL_PROP_VALUE: ILLEGAL_PROP_VALUE,
3486
- INVALID_CONST_KEY: INVALID_CONST_KEY,
3487
3528
  INVALID_MEDIA_QUERY_SYNTAX: INVALID_MEDIA_QUERY_SYNTAX,
3488
3529
  INVALID_PSEUDO: INVALID_PSEUDO,
3489
3530
  INVALID_PSEUDO_OR_AT_RULE: INVALID_PSEUDO_OR_AT_RULE,
@@ -4484,6 +4525,16 @@ function requirePropertyPriorities () {
4484
4525
  SIBLING_AFTER: /^:where\(:has\(~\s\.[0-9a-zA-Z_-]+(:[a-zA-Z-]+)\)\)$/,
4485
4526
  ANY_SIBLING: /^:where\(\.[0-9a-zA-Z_-]+(:[a-zA-Z-]+)\s+~\s+\*,\s+:has\(~\s\.[0-9a-zA-Z_-]+(:[a-zA-Z-]+)\)\)$/
4486
4527
  };
4528
+ const PSEUDO_PART_REGEX = /::[a-zA-Z-]+|:[a-zA-Z-]+(?:\([^)]*\))?/g;
4529
+ function getCompoundPseudoPriority(key) {
4530
+ const parts = key.match(PSEUDO_PART_REGEX);
4531
+ if (!parts || parts.length <= 1 || parts.some(p => p.includes('('))) return;
4532
+ let total = 0;
4533
+ for (const part of parts) {
4534
+ total += part.startsWith('::') ? PSEUDO_ELEMENT_PRIORITY : PSEUDO_CLASS_PRIORITIES[part] ?? 40;
4535
+ }
4536
+ return total;
4537
+ }
4487
4538
  function getAtRulePriority(key) {
4488
4539
  if (key.startsWith('--')) {
4489
4540
  return 1;
@@ -4524,7 +4575,7 @@ function requirePropertyPriorities () {
4524
4575
  return 40 + pseudoBase(siblingAfterMatch[1]);
4525
4576
  }
4526
4577
  if (key.startsWith(':')) {
4527
- const prop = key.startsWith(':') && key.includes('(') ? key.slice(0, key.indexOf('(')) : key;
4578
+ const prop = key.split('(')[0];
4528
4579
  return PSEUDO_CLASS_PRIORITIES[prop] ?? 40;
4529
4580
  }
4530
4581
  }
@@ -4545,6 +4596,8 @@ function requirePropertyPriorities () {
4545
4596
  function getPriority(key) {
4546
4597
  const atRulePriority = getAtRulePriority(key);
4547
4598
  if (atRulePriority) return atRulePriority;
4599
+ const compoundPriority = getCompoundPseudoPriority(key);
4600
+ if (compoundPriority != null) return compoundPriority;
4548
4601
  const pseudoElementPriority = getPseudoElementPriority(key);
4549
4602
  if (pseudoElementPriority) return pseudoElementPriority;
4550
4603
  const pseudoClassPriority = getPseudoClassPriority(key);
@@ -4755,7 +4808,7 @@ class PreRule {
4755
4808
  this.value = value;
4756
4809
  }
4757
4810
  get pseudos() {
4758
- const unsortedPseudos = this.keyPath.filter(key => key.startsWith(':'));
4811
+ const unsortedPseudos = this.keyPath.filter(key => key.startsWith(':') || key.startsWith('['));
4759
4812
  return sortPseudos(unsortedPseudos);
4760
4813
  }
4761
4814
  get atRules() {
@@ -4860,7 +4913,7 @@ function _flattenRawStyleObject(style, keyPath, options) {
4860
4913
  });
4861
4914
  continue;
4862
4915
  }
4863
- if (typeof value === 'object' && !key.startsWith(':') && !key.startsWith('@')) {
4916
+ if (typeof value === 'object' && !key.startsWith(':') && !key.startsWith('@') && !key.startsWith('[')) {
4864
4917
  const equivalentPairs = {};
4865
4918
  for (const condition in value) {
4866
4919
  const innerValue = value[condition];
@@ -4886,7 +4939,7 @@ function _flattenRawStyleObject(style, keyPath, options) {
4886
4939
  flattened.push([property, PreRuleSet.create(rules)]);
4887
4940
  }
4888
4941
  }
4889
- if (typeof value === 'object' && (key.startsWith(':') || key.startsWith('@'))) {
4942
+ if (typeof value === 'object' && (key.startsWith(':') || key.startsWith('@') || key.startsWith('['))) {
4890
4943
  const pairs = _flattenRawStyleObject(value, [...keyPath, _key], options);
4891
4944
  for (const [property, preRule] of pairs) {
4892
4945
  flattened.push([key + '_' + property, preRule]);
@@ -4916,7 +4969,7 @@ function validateNamespace(namespace, conditions = []) {
4916
4969
  continue;
4917
4970
  }
4918
4971
  if (isPlainObject(val)) {
4919
- if (key.startsWith('@') || key.startsWith(':')) {
4972
+ if (key.startsWith('@') || key.startsWith(':') || key.startsWith('[')) {
4920
4973
  if (conditions.includes(key)) {
4921
4974
  throw new Error(DUPLICATE_CONDITIONAL);
4922
4975
  }
@@ -4932,7 +4985,7 @@ function validateNamespace(namespace, conditions = []) {
4932
4985
  function validateConditionalStyles(val, conditions = []) {
4933
4986
  for (const key in val) {
4934
4987
  const v = val[key];
4935
- if (!(key.startsWith('@') || key.startsWith(':') || key.startsWith('var(--') || key === 'default')) {
4988
+ if (!(key.startsWith('@') || key.startsWith(':') || key.startsWith('[') || key.startsWith('var(--') || key === 'default')) {
4936
4989
  throw new Error(INVALID_PSEUDO_OR_AT_RULE);
4937
4990
  }
4938
4991
  if (conditions.includes(key)) {
@@ -5318,11 +5371,8 @@ function styleXDefineConsts(constants, options) {
5318
5371
  const jsOutput = {};
5319
5372
  const injectableStyles = {};
5320
5373
  for (const [key, value] of Object.entries(constants)) {
5321
- if (key.startsWith('--')) {
5322
- throw new Error(INVALID_CONST_KEY);
5323
- }
5324
5374
  const varSafeKey = (key[0] >= '0' && key[0] <= '9' ? `_${key}` : key).replace(/[^a-zA-Z0-9]/g, '_');
5325
- const constKey = debug && enableDebugClassNames ? `${varSafeKey}-${classNamePrefix}${hash(`${exportId}.${key}`)}` : `${classNamePrefix}${hash(`${exportId}.${key}`)}`;
5375
+ const constKey = key.startsWith('--') ? key.slice(2) : debug && enableDebugClassNames ? `${varSafeKey}-${classNamePrefix}${hash(`${exportId}.${key}`)}` : `${classNamePrefix}${hash(`${exportId}.${key}`)}`;
5326
5376
  jsOutput[key] = value;
5327
5377
  injectableStyles[constKey] = {
5328
5378
  constKey,
@@ -5494,12 +5544,15 @@ function getDefaultMarkerClassName(options = defaultOptions) {
5494
5544
  return `${prefix}default-marker`;
5495
5545
  }
5496
5546
  function validatePseudoSelector(pseudo) {
5497
- if (!pseudo.startsWith(':')) {
5498
- throw new Error('Pseudo selector must start with ":"');
5547
+ if (!(pseudo.startsWith(':') || pseudo.startsWith('['))) {
5548
+ throw new Error('Pseudo selector must start with ":" or "["');
5499
5549
  }
5500
5550
  if (pseudo.startsWith('::')) {
5501
5551
  throw new Error('Pseudo selector cannot start with "::" (pseudo-elements are not supported)');
5502
5552
  }
5553
+ if (pseudo.startsWith('[') && !pseudo.endsWith(']')) {
5554
+ throw new Error('Attribute selector must end with "]"');
5555
+ }
5503
5556
  }
5504
5557
  function ancestor(pseudo, options = defaultOptions) {
5505
5558
  validatePseudoSelector(pseudo);
@@ -6533,6 +6586,18 @@ function isSafeToSkipNullCheck(expr) {
6533
6586
  }
6534
6587
  return false;
6535
6588
  }
6589
+ function hasExplicitNullishFallback(expr) {
6590
+ if (t__namespace.isNullLiteral(expr)) return true;
6591
+ if (t__namespace.isIdentifier(expr) && expr.name === 'undefined') return true;
6592
+ if (t__namespace.isUnaryExpression(expr) && expr.operator === 'void') return true;
6593
+ if (t__namespace.isConditionalExpression(expr)) {
6594
+ return hasExplicitNullishFallback(expr.consequent) || hasExplicitNullishFallback(expr.alternate);
6595
+ }
6596
+ if (t__namespace.isLogicalExpression(expr)) {
6597
+ return hasExplicitNullishFallback(expr.left) || hasExplicitNullishFallback(expr.right);
6598
+ }
6599
+ return false;
6600
+ }
6536
6601
  function transformStyleXCreate(path, state) {
6537
6602
  const {
6538
6603
  node
@@ -6601,6 +6666,7 @@ function transformStyleXCreate(path, state) {
6601
6666
  when: stylexWhen
6602
6667
  };
6603
6668
  });
6669
+ state.applyStylexEnv(identifiers);
6604
6670
  const {
6605
6671
  confident,
6606
6672
  value,
@@ -6628,7 +6694,7 @@ function transformStyleXCreate(path, state) {
6628
6694
  const isPseudoElement = path.some(p => p.startsWith('::'));
6629
6695
  injectedInheritStyles[variableName] = {
6630
6696
  priority: 0,
6631
- ltr: `@property ${variableName} { syntax: "*";${isPseudoElement ? '' : ' inherits: false;'}}`,
6697
+ ltr: `@property ${variableName} { syntax: "*"; inherits: ${isPseudoElement ? 'true' : 'false'};}`,
6632
6698
  rtl: null
6633
6699
  };
6634
6700
  });
@@ -6677,14 +6743,21 @@ function transformStyleXCreate(path, state) {
6677
6743
  for (const [className, classPaths] of Object.entries(classPathsPerNamespace[key])) {
6678
6744
  origClassPaths[className] = classPaths.join('_');
6679
6745
  }
6680
- let dynamicStyles = Object.entries(inlineStyles).map(([_key, v]) => ({
6746
+ let dynamicStyles = Object.entries(inlineStyles).map(([varName, v]) => ({
6681
6747
  expression: v.originalExpression,
6682
6748
  key: v.path.slice(0, v.path.findIndex(p => !p.startsWith(':') && !p.startsWith('@')) + 1).join('_'),
6749
+ varName,
6683
6750
  path: v.path.join('_')
6684
6751
  }));
6685
6752
  if (state.options.styleResolution === 'legacy-expand-shorthands') {
6686
6753
  dynamicStyles = legacyExpandShorthands(dynamicStyles);
6687
6754
  }
6755
+ const nullishVarExpressions = new Map();
6756
+ dynamicStyles.forEach(style => {
6757
+ if (hasExplicitNullishFallback(style.expression)) {
6758
+ nullishVarExpressions.set(style.varName, style.expression);
6759
+ }
6760
+ });
6688
6761
  if (t__namespace.isObjectExpression(prop.value)) {
6689
6762
  const value = prop.value;
6690
6763
  let cssTagValue = t__namespace.booleanLiteral(true);
@@ -6708,9 +6781,23 @@ function transformStyleXCreate(path, state) {
6708
6781
  let isStatic = true;
6709
6782
  const exprList = [];
6710
6783
  classList.forEach((cls, index) => {
6711
- const expr = dynamicStyles.find(({
6784
+ let expr = dynamicStyles.find(({
6712
6785
  path
6713
6786
  }) => origClassPaths[cls] === path)?.expression;
6787
+ if (expr == null && nullishVarExpressions.size > 0) {
6788
+ const injectedStyle = injectedStyles[cls];
6789
+ const rule = injectedStyle != null ? typeof injectedStyle.ltr === 'string' ? injectedStyle.ltr : typeof injectedStyle.rtl === 'string' ? injectedStyle.rtl : null : null;
6790
+ if (rule != null) {
6791
+ const matches = rule.matchAll(/var\((--x-[^,)]+)[^)]*\)/g);
6792
+ for (const match of matches) {
6793
+ const varExpr = nullishVarExpressions.get(match[1]);
6794
+ if (varExpr != null) {
6795
+ expr = varExpr;
6796
+ break;
6797
+ }
6798
+ }
6799
+ }
6800
+ }
6714
6801
  const isLast = index === classList.length - 1;
6715
6802
  const clsWithSpace = isLast ? cls : cls + ' ';
6716
6803
  if (expr && !isSafeToSkipNullCheck(expr)) {
@@ -6871,6 +6958,7 @@ function transformStyleXCreateTheme(callExpressionPath, state) {
6871
6958
  types: stylexTypes
6872
6959
  };
6873
6960
  });
6961
+ state.applyStylexEnv(identifiers);
6874
6962
  const {
6875
6963
  confident: confident2,
6876
6964
  value: overrides
@@ -6985,6 +7073,7 @@ function transformStyleXDefineVars(callExpressionPath, state) {
6985
7073
  types: stylexTypes
6986
7074
  };
6987
7075
  });
7076
+ state.applyStylexEnv(identifiers);
6988
7077
  const {
6989
7078
  confident,
6990
7079
  value
@@ -7047,10 +7136,16 @@ function transformStyleXDefineConsts(callExpressionPath, state) {
7047
7136
  const varId = variableDeclaratorNode.id;
7048
7137
  const args = callExpressionPath.get('arguments');
7049
7138
  const firstArg = args[0];
7139
+ const evaluatePathFnConfig = {
7140
+ identifiers: {},
7141
+ memberExpressions: {},
7142
+ disableImports: true
7143
+ };
7144
+ state.applyStylexEnv(evaluatePathFnConfig.identifiers);
7050
7145
  const {
7051
7146
  confident,
7052
7147
  value
7053
- } = evaluate(firstArg, state);
7148
+ } = evaluate(firstArg, state, evaluatePathFnConfig);
7054
7149
  if (!confident) {
7055
7150
  throw callExpressionPath.buildCodeFrameError(messages.nonStaticValue('defineConsts'), SyntaxError);
7056
7151
  }
@@ -7132,6 +7227,7 @@ function transformStyleXKeyframes(path, state) {
7132
7227
  fn: firstThatWorks
7133
7228
  };
7134
7229
  });
7230
+ state.applyStylexEnv(identifiers);
7135
7231
  const {
7136
7232
  confident,
7137
7233
  value
@@ -7203,6 +7299,7 @@ function transformStyleXPositionTry(path, state) {
7203
7299
  fn: firstThatWorks
7204
7300
  };
7205
7301
  });
7302
+ state.applyStylexEnv(identifiers);
7206
7303
  const {
7207
7304
  confident,
7208
7305
  value
@@ -7257,6 +7354,12 @@ function transformStyleXMerge(path, state) {
7257
7354
  if (node == null || node.callee.type !== 'Identifier' || !state.stylexImport.has(node.callee.name)) {
7258
7355
  return;
7259
7356
  }
7357
+ const evaluatePathFnConfig = {
7358
+ identifiers: {},
7359
+ memberExpressions: {},
7360
+ disableImports: true
7361
+ };
7362
+ state.applyStylexEnv(evaluatePathFnConfig.identifiers);
7260
7363
  let bailOut = false;
7261
7364
  let conditional = 0;
7262
7365
  let currentIndex = -1;
@@ -7363,7 +7466,7 @@ function transformStyleXMerge(path, state) {
7363
7466
  const {
7364
7467
  confident,
7365
7468
  value: styleValue
7366
- } = evaluate(path, state);
7469
+ } = evaluate(path, state, evaluatePathFnConfig);
7367
7470
  if (!confident || styleValue == null) {
7368
7471
  nonNullProps = true;
7369
7472
  styleNonNullProps = true;
@@ -7499,6 +7602,7 @@ function transformStylexProps(path, state) {
7499
7602
  }
7500
7603
  };
7501
7604
  });
7605
+ state.applyStylexEnv(identifiers);
7502
7606
  const evaluatePathFnConfig = {
7503
7607
  identifiers,
7504
7608
  memberExpressions,
@@ -7824,6 +7928,7 @@ function transformStyleXViewTransitionClass(path, state) {
7824
7928
  fn: keyframes$1
7825
7929
  };
7826
7930
  });
7931
+ state.applyStylexEnv(identifiers);
7827
7932
  const {
7828
7933
  confident,
7829
7934
  value
@@ -47,6 +47,7 @@ export type StyleXOptions = $ReadOnly<{
47
47
  classNamePrefix: string,
48
48
  debug: ?boolean,
49
49
  definedStylexCSSVariables?: { [key: string]: mixed },
50
+ env?: $ReadOnly<{ [string]: any }>,
50
51
  dev: boolean,
51
52
  propertyValidationMode?: 'throw' | 'warn' | 'silent',
52
53
  enableDebugClassNames?: ?boolean,
@@ -35,8 +35,6 @@ export declare const ILLEGAL_PROP_ARRAY_VALUE: 'A style array value can only con
35
35
  export declare type ILLEGAL_PROP_ARRAY_VALUE = typeof ILLEGAL_PROP_ARRAY_VALUE;
36
36
  export declare const ILLEGAL_NAMESPACE_VALUE: 'A StyleX namespace must be an object.';
37
37
  export declare type ILLEGAL_NAMESPACE_VALUE = typeof ILLEGAL_NAMESPACE_VALUE;
38
- export declare const INVALID_CONST_KEY: 'Keys in defineConsts() cannot start with "--".';
39
- export declare type INVALID_CONST_KEY = typeof INVALID_CONST_KEY;
40
38
  export declare const INVALID_PSEUDO: 'Invalid pseudo selector, not on the whitelist.';
41
39
  export declare type INVALID_PSEUDO = typeof INVALID_PSEUDO;
42
40
  export declare const INVALID_PSEUDO_OR_AT_RULE: 'Invalid pseudo or at-rule.';
@@ -26,7 +26,6 @@ declare export const ILLEGAL_NESTED_PSEUDO: "Pseudo objects can't be nested more
26
26
  declare export const ILLEGAL_PROP_VALUE: 'A style value can only contain an array, string or number.';
27
27
  declare export const ILLEGAL_PROP_ARRAY_VALUE: 'A style array value can only contain strings or numbers.';
28
28
  declare export const ILLEGAL_NAMESPACE_VALUE: 'A StyleX namespace must be an object.';
29
- declare export const INVALID_CONST_KEY: 'Keys in defineConsts() cannot start with "--".';
30
29
  declare export const INVALID_PSEUDO: 'Invalid pseudo selector, not on the whitelist.';
31
30
  declare export const INVALID_PSEUDO_OR_AT_RULE: 'Invalid pseudo or at-rule.';
32
31
  declare export const INVALID_MEDIA_QUERY_SYNTAX: 'Invalid media query syntax.';
@@ -8,6 +8,7 @@
8
8
  */
9
9
 
10
10
  import type { StyleXOptions } from '../common-types';
11
+ type WhenSelector = `:${string}` | `[${string}`;
11
12
  /**
12
13
  * Creates selector that observes if the given pseudo-class is
13
14
  * active on an ancestor with the "defaultMarker"
@@ -17,7 +18,7 @@ import type { StyleXOptions } from '../common-types';
17
18
  * @returns A :where() clause for the ancestor observer
18
19
  */
19
20
  export declare function ancestor(
20
- pseudo: `:${string}`,
21
+ pseudo: WhenSelector,
21
22
  options?: string | StyleXOptions,
22
23
  ): string;
23
24
  /**
@@ -28,7 +29,7 @@ export declare function ancestor(
28
29
  * @returns A :has() clause for the descendant observer
29
30
  */
30
31
  export declare function descendant(
31
- pseudo: `:${string}`,
32
+ pseudo: WhenSelector,
32
33
  options?: string | StyleXOptions,
33
34
  ): string;
34
35
  /**
@@ -39,7 +40,7 @@ export declare function descendant(
39
40
  * @returns A :where() clause for the previous sibling observer
40
41
  */
41
42
  export declare function siblingBefore(
42
- pseudo: `:${string}`,
43
+ pseudo: WhenSelector,
43
44
  options?: string | StyleXOptions,
44
45
  ): string;
45
46
  /**
@@ -50,7 +51,7 @@ export declare function siblingBefore(
50
51
  * @returns A :has() clause for the next sibling observer
51
52
  */
52
53
  export declare function siblingAfter(
53
- pseudo: `:${string}`,
54
+ pseudo: WhenSelector,
54
55
  options?: string | StyleXOptions,
55
56
  ): string;
56
57
  /**
@@ -61,6 +62,6 @@ export declare function siblingAfter(
61
62
  * @returns A :where() clause for the any sibling observer
62
63
  */
63
64
  export declare function anySibling(
64
- pseudo: `:${string}`,
65
+ pseudo: WhenSelector,
65
66
  options?: string | StyleXOptions,
66
67
  ): string;
@@ -9,6 +9,8 @@
9
9
 
10
10
  import type { StyleXOptions } from '../common-types';
11
11
 
12
+ type WhenSelector = StringPrefix<':'> | StringPrefix<'['>;
13
+
12
14
  /**
13
15
  * Creates selector that observes if the given pseudo-class is
14
16
  * active on an ancestor with the "defaultMarker"
@@ -18,7 +20,7 @@ import type { StyleXOptions } from '../common-types';
18
20
  * @returns A :where() clause for the ancestor observer
19
21
  */
20
22
  declare export function ancestor(
21
- pseudo: StringPrefix<':'>,
23
+ pseudo: WhenSelector,
22
24
  options?: string | StyleXOptions,
23
25
  ): string;
24
26
 
@@ -30,7 +32,7 @@ declare export function ancestor(
30
32
  * @returns A :has() clause for the descendant observer
31
33
  */
32
34
  declare export function descendant(
33
- pseudo: StringPrefix<':'>,
35
+ pseudo: WhenSelector,
34
36
  options?: string | StyleXOptions,
35
37
  ): string;
36
38
 
@@ -42,7 +44,7 @@ declare export function descendant(
42
44
  * @returns A :where() clause for the previous sibling observer
43
45
  */
44
46
  declare export function siblingBefore(
45
- pseudo: StringPrefix<':'>,
47
+ pseudo: WhenSelector,
46
48
  options?: string | StyleXOptions,
47
49
  ): string;
48
50
 
@@ -54,7 +56,7 @@ declare export function siblingBefore(
54
56
  * @returns A :has() clause for the next sibling observer
55
57
  */
56
58
  declare export function siblingAfter(
57
- pseudo: StringPrefix<':'>,
59
+ pseudo: WhenSelector,
58
60
  options?: string | StyleXOptions,
59
61
  ): string;
60
62
 
@@ -66,6 +68,6 @@ declare export function siblingAfter(
66
68
  * @returns A :where() clause for the any sibling observer
67
69
  */
68
70
  declare export function anySibling(
69
- pseudo: StringPrefix<':'>,
71
+ pseudo: WhenSelector,
70
72
  options?: string | StyleXOptions,
71
73
  ): string;
@@ -13,6 +13,7 @@ import type {
13
13
  CompiledNamespaces,
14
14
  StyleXOptions as RuntimeOptions,
15
15
  } from '../shared';
16
+ import type { FunctionConfig } from './evaluate-path';
16
17
  import * as t from '@babel/types';
17
18
  export type ImportPathResolution =
18
19
  | false
@@ -104,6 +105,7 @@ type StyleXStateOptions = Readonly<
104
105
  Omit<
105
106
  StyleXOptions,
106
107
  | keyof {
108
+ env: Readonly<{ [$$Key$$: string]: any }>;
107
109
  runtimeInjection:
108
110
  | (null | undefined | string)
109
111
  | Readonly<{ from: string; as: null | undefined | string }>;
@@ -114,6 +116,7 @@ type StyleXStateOptions = Readonly<
114
116
  rewriteAliases: boolean;
115
117
  }
116
118
  > & {
119
+ env: Readonly<{ [$$Key$$: string]: any }>;
117
120
  runtimeInjection:
118
121
  | (null | undefined | string)
119
122
  | Readonly<{ from: string; as: null | undefined | string }>;
@@ -143,6 +146,7 @@ declare class StateManager {
143
146
  readonly stylexViewTransitionClassImport: Set<string>;
144
147
  readonly stylexDefaultMarkerImport: Set<string>;
145
148
  readonly stylexWhenImport: Set<string>;
149
+ readonly stylexEnvImport: Set<string>;
146
150
  injectImportInserted: null | undefined | t.Identifier;
147
151
  readonly styleMap: Map<string, CompiledNamespaces>;
148
152
  readonly styleVars: Map<string, NodePath>;
@@ -156,6 +160,7 @@ declare class StateManager {
156
160
  get importPathString(): string;
157
161
  get importSources(): ReadonlyArray<string>;
158
162
  importAs(source: string): null | string;
163
+ applyStylexEnv(identifiers: FunctionConfig['identifiers']): void;
159
164
  get canReferenceTheme(): boolean;
160
165
  get metadata(): { [key: string]: any };
161
166
  get runtimeInjection():
@@ -13,6 +13,8 @@ import type {
13
13
  CompiledNamespaces,
14
14
  StyleXOptions as RuntimeOptions,
15
15
  } from '../shared';
16
+ import type { FunctionConfig } from './evaluate-path';
17
+
16
18
  import * as t from '@babel/types';
17
19
  export type ImportPathResolution =
18
20
  | false
@@ -70,6 +72,7 @@ export type StyleXOptions = $ReadOnly<{
70
72
 
71
73
  type StyleXStateOptions = $ReadOnly<{
72
74
  ...StyleXOptions,
75
+ env: $ReadOnly<{ [string]: any }>,
73
76
  runtimeInjection: ?string | $ReadOnly<{ from: string, as: ?string }>,
74
77
  aliases?: ?$ReadOnly<{ [string]: $ReadOnlyArray<string> }>,
75
78
  rewriteAliases: boolean,
@@ -96,6 +99,7 @@ declare export default class StateManager {
96
99
  +stylexViewTransitionClassImport: Set<string>;
97
100
  +stylexDefaultMarkerImport: Set<string>;
98
101
  +stylexWhenImport: Set<string>;
102
+ +stylexEnvImport: Set<string>;
99
103
  injectImportInserted: ?t.Identifier;
100
104
  // `stylex.create` calls
101
105
  +styleMap: Map<string, CompiledNamespaces>;
@@ -109,6 +113,7 @@ declare export default class StateManager {
109
113
  get importPathString(): string;
110
114
  get importSources(): $ReadOnlyArray<string>;
111
115
  importAs(source: string): null | string;
116
+ applyStylexEnv(identifiers: FunctionConfig['identifiers']): void;
112
117
  get canReferenceTheme(): boolean;
113
118
  get metadata(): { [key: string]: any };
114
119
  get runtimeInjection(): ?$ReadOnly<{ from: string, as?: ?string }>;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ *
8
+ */
9
+
10
+ import type { NodePath } from '@babel/traverse';
11
+ import * as t from '@babel/types';
12
+ import StateManager from '../utils/state-manager';
13
+ /**
14
+ * Transform inline-css call expressions like `css.color(value)`.
15
+ * These become arrow functions that return [compiledObj, inlineObj].
16
+ */
17
+ export declare function transformInlineCSSCall(
18
+ path: NodePath<t.CallExpression>,
19
+ state: StateManager,
20
+ ): void;
21
+ /**
22
+ * Transform inline-css member expressions like `css.display.flex`.
23
+ * These become compiled namespace objects: { [key]: className, $$css: true }
24
+ */
25
+ export declare function transformInlineCSSMemberExpression(
26
+ path: NodePath<t.MemberExpression>,
27
+ state: StateManager,
28
+ ): void;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict
8
+ */
9
+
10
+ import type { NodePath } from '@babel/traverse';
11
+
12
+ import * as t from '@babel/types';
13
+ import StateManager from '../utils/state-manager';
14
+ /**
15
+ * Transform inline-css call expressions like `css.color(value)`.
16
+ * These become arrow functions that return [compiledObj, inlineObj].
17
+ */
18
+ declare export function transformInlineCSSCall(
19
+ path: NodePath<t.CallExpression>,
20
+ state: StateManager,
21
+ ): void;
22
+
23
+ /**
24
+ * Transform inline-css member expressions like `css.display.flex`.
25
+ * These become compiled namespace objects: { [key]: className, $$css: true }
26
+ */
27
+ declare export function transformInlineCSSMemberExpression(
28
+ path: NodePath<t.MemberExpression>,
29
+ state: StateManager,
30
+ ): void;
@@ -8,7 +8,6 @@
8
8
  */
9
9
 
10
10
  import type { NodePath } from '@babel/traverse';
11
-
12
11
  import * as t from '@babel/types';
13
12
  import StateManager from '../utils/state-manager';
14
13
  /// This function looks for `stylex.defineConsts` calls and transforms them.
@@ -8,7 +8,6 @@
8
8
  */
9
9
 
10
10
  import type { NodePath } from '@babel/traverse';
11
-
12
11
  import * as t from '@babel/types';
13
12
  import StateManager from '../utils/state-manager';
14
13
  declare export function skipStylexMergeChildren(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stylexjs/babel-plugin",
3
- "version": "0.17.5",
3
+ "version": "0.18.0",
4
4
  "description": "StyleX babel plugin.",
5
5
  "main": "lib/index.js",
6
6
  "browser": "lib/index.browser.js",
@@ -23,8 +23,8 @@
23
23
  "@babel/traverse": "^7.26.8",
24
24
  "@babel/types": "^7.26.8",
25
25
  "@dual-bundle/import-meta-resolve": "^4.1.0",
26
- "@stylexjs/shared": "0.17.5",
27
- "@stylexjs/stylex": "0.17.5",
26
+ "@stylexjs/shared": "0.18.0",
27
+ "@stylexjs/stylex": "0.18.0",
28
28
  "postcss-value-parser": "^4.1.0"
29
29
  },
30
30
  "devDependencies": {
@@ -37,7 +37,7 @@
37
37
  "babel-plugin-syntax-hermes-parser": "^0.32.1",
38
38
  "path-browserify": "^1.0.1",
39
39
  "rollup": "^4.24.0",
40
- "scripts": "0.17.5"
40
+ "scripts": "0.18.0"
41
41
  },
42
42
  "files": [
43
43
  "flow_modules/*",