@drskillissue/ganko 0.2.61 → 0.2.72

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.
@@ -142,9 +142,29 @@ function canonicalPath(path) {
142
142
  return canonical;
143
143
  }
144
144
  var LOG_LEVELS = ["trace", "debug", "info", "warning", "error", "critical", "off"];
145
+ var Level = {
146
+ Trace: 0,
147
+ Debug: 1,
148
+ Info: 2,
149
+ Warning: 3,
150
+ Error: 4,
151
+ Critical: 5,
152
+ Off: 6
153
+ };
154
+ var LOG_LEVEL_ORDER = {
155
+ trace: Level.Trace,
156
+ debug: Level.Debug,
157
+ info: Level.Info,
158
+ warning: Level.Warning,
159
+ error: Level.Error,
160
+ critical: Level.Critical,
161
+ off: Level.Off
162
+ };
145
163
  var noopLogger = {
146
- enabled: false,
147
164
  level: "off",
165
+ isLevelEnabled() {
166
+ return false;
167
+ },
148
168
  trace() {
149
169
  },
150
170
  debug() {
@@ -2913,6 +2933,35 @@ var TypeResolver = class {
2913
2933
  return false;
2914
2934
  }
2915
2935
  }
2936
+ /**
2937
+ * Strict array check: only matches Array<T>, T[], ReadonlyArray<T>, and tuples.
2938
+ * Does NOT match typed arrays (Uint8Array, Buffer, etc.) or other types with
2939
+ * a numeric index signature.
2940
+ */
2941
+ isStrictArrayType(node) {
2942
+ try {
2943
+ const tsType = this.checker.getTypeAtLocation(node);
2944
+ return this.checkIsStrictArrayType(tsType);
2945
+ } catch {
2946
+ return false;
2947
+ }
2948
+ }
2949
+ checkIsStrictArrayType(tsType) {
2950
+ if (tsType.flags & 524288) {
2951
+ const objFlags = getObjectFlags(tsType);
2952
+ if (objFlags & 8) return true;
2953
+ if (objFlags & 4) {
2954
+ const name = tsType.getSymbol()?.getName();
2955
+ if (name === "Array" || name === "ReadonlyArray") return true;
2956
+ }
2957
+ }
2958
+ if (tsType.isUnion()) {
2959
+ for (const t of tsType.types) {
2960
+ if (this.checkIsStrictArrayType(t)) return true;
2961
+ }
2962
+ }
2963
+ return false;
2964
+ }
2916
2965
  checkIsArrayType(tsType) {
2917
2966
  if (tsType.flags & 524288) {
2918
2967
  const objFlags = getObjectFlags(tsType);
@@ -2964,7 +3013,7 @@ var TypeResolver = class {
2964
3013
  if (exprTsType.flags & import_typescript2.default.TypeFlags.Any) return false;
2965
3014
  if (targetTsType.flags & import_typescript2.default.TypeFlags.Any) return false;
2966
3015
  const result = this.checker.isTypeAssignableTo(exprTsType, targetTsType);
2967
- if (this.logger.enabled) {
3016
+ if (this.logger.isLevelEnabled(Level.Debug)) {
2968
3017
  const exprStr = this.checker.typeToString(exprTsType);
2969
3018
  const targetStr = this.checker.typeToString(targetTsType);
2970
3019
  this.logger.debug(`isUnnecessaryCast: expr="${exprStr.slice(0, 120)}" target="${targetStr.slice(0, 120)}" assignable=${result} exprFlags=${exprTsType.flags} targetFlags=${targetTsType.flags}`);
@@ -3481,6 +3530,7 @@ function getStaticStringFromJSXValue(node) {
3481
3530
  const expression = node.expression;
3482
3531
  if (!expression) return null;
3483
3532
  if (import_typescript4.default.isStringLiteral(expression)) return expression.text;
3533
+ if (import_typescript4.default.isNumericLiteral(expression)) return expression.text;
3484
3534
  if (import_typescript4.default.isNoSubstitutionTemplateLiteral(expression)) return expression.text;
3485
3535
  if (import_typescript4.default.isTemplateExpression(expression) && expression.templateSpans.length === 0) {
3486
3536
  return expression.head.text;
@@ -9928,6 +9978,9 @@ function typeIncludesString(graph, node) {
9928
9978
  function typeIsArray(graph, node) {
9929
9979
  return graph.typeResolver.isArrayType(node);
9930
9980
  }
9981
+ function typeIsStrictArray(graph, node) {
9982
+ return graph.typeResolver.isStrictArrayType(node);
9983
+ }
9931
9984
  function getArrayElementKind(graph, node) {
9932
9985
  return graph.typeResolver.getArrayElementKind(node);
9933
9986
  }
@@ -19723,6 +19776,7 @@ var preferSetLookupInLoop = defineSolidRule({
19723
19776
  options: options77,
19724
19777
  check(graph, emit) {
19725
19778
  const reported = /* @__PURE__ */ new Set();
19779
+ const graphHasTypes = hasTypeInfo(graph);
19726
19780
  for (const method of LINEAR_SEARCH_METHODS) {
19727
19781
  const calls = getCallsByMethodName(graph, method);
19728
19782
  for (let i = 0, len = calls.length; i < len; i++) {
@@ -19740,6 +19794,7 @@ var preferSetLookupInLoop = defineSolidRule({
19740
19794
  const loop = getEnclosingLoop(call.node);
19741
19795
  if (!loop) continue;
19742
19796
  if (!isDeclaredOutsideLoop2(loop, variable)) continue;
19797
+ if (graphHasTypes && !typeIsStrictArray(graph, callee.expression)) continue;
19743
19798
  if (isStringLikeReceiver(graph, callee.expression, variable)) continue;
19744
19799
  const key = `${loop.pos}:var:${variable.id}`;
19745
19800
  if (reported.has(key)) continue;
@@ -29483,148 +29538,8 @@ function checkParagraphSpacing(graph, emit, policy, name) {
29483
29538
  }
29484
29539
  }
29485
29540
 
29486
- // src/css/rules/a11y/css-policy-touch-target.ts
29487
- var messages125 = {
29488
- heightTooSmall: "`{{property}}` of `{{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for `{{element}}` elements in policy `{{policy}}`.",
29489
- widthTooSmall: "`{{property}}` of `{{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for `{{element}}` elements in policy `{{policy}}`.",
29490
- paddingTooSmall: "Horizontal padding `{{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for `{{element}}` elements in policy `{{policy}}`."
29491
- };
29492
- function classifyRule(rule) {
29493
- if (rule.elementKinds.has("button")) return "button";
29494
- if (rule.elementKinds.has("input")) return "input";
29495
- return null;
29496
- }
29497
- var HEIGHT_PROPERTIES = /* @__PURE__ */ new Set(["height", "min-height"]);
29498
- var WIDTH_PROPERTIES = /* @__PURE__ */ new Set(["width", "min-width"]);
29499
- var HPADDING_PROPERTIES = /* @__PURE__ */ new Set(["padding-left", "padding-right", "padding-inline", "padding-inline-start", "padding-inline-end"]);
29500
- var cssPolicyTouchTarget = defineCSSRule({
29501
- id: "css-policy-touch-target",
29502
- severity: "warn",
29503
- messages: messages125,
29504
- meta: {
29505
- description: "Enforce minimum interactive element sizes per accessibility policy.",
29506
- fixable: false,
29507
- category: "css-a11y"
29508
- },
29509
- options: {},
29510
- check(graph, emit) {
29511
- const policy = getActivePolicy();
29512
- if (policy === null) return;
29513
- const name = getActivePolicyName() ?? "";
29514
- const decls = graph.declarationsForProperties(
29515
- "height",
29516
- "min-height",
29517
- "width",
29518
- "min-width",
29519
- "padding-left",
29520
- "padding-right",
29521
- "padding-inline",
29522
- "padding-inline-start",
29523
- "padding-inline-end"
29524
- );
29525
- for (let i = 0; i < decls.length; i++) {
29526
- const d = decls[i];
29527
- if (!d) continue;
29528
- if (!d.rule) continue;
29529
- const prop = d.property.toLowerCase();
29530
- const kind = classifyRule(d.rule);
29531
- if (!kind) continue;
29532
- if (isVisuallyHiddenInput(d.rule)) continue;
29533
- const px = parsePxValue(d.value);
29534
- if (px === null) continue;
29535
- if (HEIGHT_PROPERTIES.has(prop)) {
29536
- const min = kind === "button" ? policy.minButtonHeight : policy.minInputHeight;
29537
- if (px >= min) continue;
29538
- emitCSSDiagnostic(
29539
- emit,
29540
- d.file.path,
29541
- d.startLine,
29542
- d.startColumn,
29543
- cssPolicyTouchTarget,
29544
- "heightTooSmall",
29545
- resolveMessage(messages125.heightTooSmall, {
29546
- property: d.property,
29547
- value: d.value.trim(),
29548
- resolved: String(Math.round(px * 100) / 100),
29549
- min: String(min),
29550
- element: kind,
29551
- policy: name
29552
- })
29553
- );
29554
- continue;
29555
- }
29556
- if (WIDTH_PROPERTIES.has(prop)) {
29557
- const min = kind === "button" ? policy.minButtonWidth : policy.minTouchTarget;
29558
- if (px >= min) continue;
29559
- emitCSSDiagnostic(
29560
- emit,
29561
- d.file.path,
29562
- d.startLine,
29563
- d.startColumn,
29564
- cssPolicyTouchTarget,
29565
- "widthTooSmall",
29566
- resolveMessage(messages125.widthTooSmall, {
29567
- property: d.property,
29568
- value: d.value.trim(),
29569
- resolved: String(Math.round(px * 100) / 100),
29570
- min: String(min),
29571
- element: kind,
29572
- policy: name
29573
- })
29574
- );
29575
- continue;
29576
- }
29577
- if (kind === "button" && HPADDING_PROPERTIES.has(prop)) {
29578
- if (px >= policy.minButtonHorizontalPadding) continue;
29579
- emitCSSDiagnostic(
29580
- emit,
29581
- d.file.path,
29582
- d.startLine,
29583
- d.startColumn,
29584
- cssPolicyTouchTarget,
29585
- "paddingTooSmall",
29586
- resolveMessage(messages125.paddingTooSmall, {
29587
- value: d.value.trim(),
29588
- resolved: String(Math.round(px * 100) / 100),
29589
- min: String(policy.minButtonHorizontalPadding),
29590
- element: kind,
29591
- policy: name
29592
- })
29593
- );
29594
- }
29595
- }
29596
- }
29597
- });
29598
- function isVisuallyHiddenInput(rule) {
29599
- if (!hasPositionAbsoluteOrFixed(rule)) return false;
29600
- if (!hasOpacityZero(rule)) return false;
29601
- return true;
29602
- }
29603
- function hasPositionAbsoluteOrFixed(rule) {
29604
- const positionDecls = rule.declarationIndex.get("position");
29605
- if (!positionDecls || positionDecls.length === 0) return false;
29606
- for (let i = 0; i < positionDecls.length; i++) {
29607
- const decl = positionDecls[i];
29608
- if (!decl) continue;
29609
- const v = decl.value.trim().toLowerCase();
29610
- if (v === "absolute" || v === "fixed") return true;
29611
- }
29612
- return false;
29613
- }
29614
- function hasOpacityZero(rule) {
29615
- const opacityDecls = rule.declarationIndex.get("opacity");
29616
- if (!opacityDecls || opacityDecls.length === 0) return false;
29617
- for (let i = 0; i < opacityDecls.length; i++) {
29618
- const decl = opacityDecls[i];
29619
- if (!decl) continue;
29620
- const v = decl.value.trim();
29621
- if (v === "0") return true;
29622
- }
29623
- return false;
29624
- }
29625
-
29626
29541
  // src/css/rules/a11y/css-policy-typography.ts
29627
- var messages126 = {
29542
+ var messages125 = {
29628
29543
  fontTooSmall: "Font size `{{value}}` ({{resolved}}px) is below the `{{context}}` minimum of `{{min}}px` for policy `{{policy}}`.",
29629
29544
  lineHeightTooSmall: "Line height `{{value}}` is below the `{{context}}` minimum of `{{min}}` for policy `{{policy}}`."
29630
29545
  };
@@ -29660,7 +29575,7 @@ function resolveLineHeightContext(d, p) {
29660
29575
  var cssPolicyTypography = defineCSSRule({
29661
29576
  id: "css-policy-typography",
29662
29577
  severity: "warn",
29663
- messages: messages126,
29578
+ messages: messages125,
29664
29579
  meta: {
29665
29580
  description: "Enforce minimum font sizes and line heights per accessibility policy.",
29666
29581
  fixable: false,
@@ -29687,7 +29602,7 @@ var cssPolicyTypography = defineCSSRule({
29687
29602
  d.startColumn,
29688
29603
  cssPolicyTypography,
29689
29604
  "fontTooSmall",
29690
- resolveMessage(messages126.fontTooSmall, {
29605
+ resolveMessage(messages125.fontTooSmall, {
29691
29606
  value: d.value.trim(),
29692
29607
  resolved: String(Math.round(px * 100) / 100),
29693
29608
  context,
@@ -29714,7 +29629,7 @@ var cssPolicyTypography = defineCSSRule({
29714
29629
  d.startColumn,
29715
29630
  cssPolicyTypography,
29716
29631
  "lineHeightTooSmall",
29717
- resolveMessage(messages126.lineHeightTooSmall, {
29632
+ resolveMessage(messages125.lineHeightTooSmall, {
29718
29633
  value: d.value.trim(),
29719
29634
  context,
29720
29635
  min: String(min),
@@ -29732,7 +29647,7 @@ var ZERO_S = /(^|\s|,)0s($|\s|,)/;
29732
29647
  var TIME_VALUE_G = /([0-9]*\.?[0-9]+)(ms|s)/g;
29733
29648
  var AMPERSAND_G = /&/g;
29734
29649
  var WHITESPACE_G = /\s+/g;
29735
- var messages127 = {
29650
+ var messages126 = {
29736
29651
  missingReducedMotion: "Animated selector `{{selector}}` lacks prefers-reduced-motion override."
29737
29652
  };
29738
29653
  function isAnimationDecl(p) {
@@ -29836,7 +29751,7 @@ function normalizeSelector2(s) {
29836
29751
  var cssRequireReducedMotionOverride = defineCSSRule({
29837
29752
  id: "css-require-reduced-motion-override",
29838
29753
  severity: "warn",
29839
- messages: messages127,
29754
+ messages: messages126,
29840
29755
  meta: {
29841
29756
  description: "Require reduced-motion override for animated selectors.",
29842
29757
  fixable: false,
@@ -29899,20 +29814,20 @@ var cssRequireReducedMotionOverride = defineCSSRule({
29899
29814
  d.startColumn,
29900
29815
  cssRequireReducedMotionOverride,
29901
29816
  "missingReducedMotion",
29902
- resolveMessage(messages127.missingReducedMotion, { selector: r.selectorText })
29817
+ resolveMessage(messages126.missingReducedMotion, { selector: r.selectorText })
29903
29818
  );
29904
29819
  }
29905
29820
  }
29906
29821
  });
29907
29822
 
29908
29823
  // src/css/rules/structure/css-no-empty-rule.ts
29909
- var messages128 = {
29824
+ var messages127 = {
29910
29825
  emptyRule: "Empty rule `{{selector}}` should be removed."
29911
29826
  };
29912
29827
  var cssNoEmptyRule = defineCSSRule({
29913
29828
  id: "css-no-empty-rule",
29914
29829
  severity: "warn",
29915
- messages: messages128,
29830
+ messages: messages127,
29916
29831
  meta: {
29917
29832
  description: "Disallow empty CSS rules.",
29918
29833
  fixable: false,
@@ -29930,20 +29845,20 @@ var cssNoEmptyRule = defineCSSRule({
29930
29845
  rule.startColumn,
29931
29846
  cssNoEmptyRule,
29932
29847
  "emptyRule",
29933
- resolveMessage(messages128.emptyRule, { selector: rule.selectorText })
29848
+ resolveMessage(messages127.emptyRule, { selector: rule.selectorText })
29934
29849
  );
29935
29850
  }
29936
29851
  }
29937
29852
  });
29938
29853
 
29939
29854
  // src/css/rules/structure/css-no-unknown-container-name.ts
29940
- var messages129 = {
29855
+ var messages128 = {
29941
29856
  unknownContainer: "Unknown container name `{{name}}` in @container query."
29942
29857
  };
29943
29858
  var cssNoUnknownContainerName = defineCSSRule({
29944
29859
  id: "css-no-unknown-container-name",
29945
29860
  severity: "error",
29946
- messages: messages129,
29861
+ messages: messages128,
29947
29862
  meta: {
29948
29863
  description: "Disallow unknown named containers in @container queries.",
29949
29864
  fixable: false,
@@ -29963,20 +29878,20 @@ var cssNoUnknownContainerName = defineCSSRule({
29963
29878
  1,
29964
29879
  cssNoUnknownContainerName,
29965
29880
  "unknownContainer",
29966
- resolveMessage(messages129.unknownContainer, { name })
29881
+ resolveMessage(messages128.unknownContainer, { name })
29967
29882
  );
29968
29883
  }
29969
29884
  }
29970
29885
  });
29971
29886
 
29972
29887
  // src/css/rules/structure/css-no-unused-container-name.ts
29973
- var messages130 = {
29888
+ var messages129 = {
29974
29889
  unusedContainer: "Container name `{{name}}` is declared but never queried."
29975
29890
  };
29976
29891
  var cssNoUnusedContainerName = defineCSSRule({
29977
29892
  id: "css-no-unused-container-name",
29978
29893
  severity: "warn",
29979
- messages: messages130,
29894
+ messages: messages129,
29980
29895
  meta: {
29981
29896
  description: "Disallow unused named containers.",
29982
29897
  fixable: false,
@@ -29999,7 +29914,7 @@ var cssNoUnusedContainerName = defineCSSRule({
29999
29914
  d.startColumn,
30000
29915
  cssNoUnusedContainerName,
30001
29916
  "unusedContainer",
30002
- resolveMessage(messages130.unusedContainer, { name })
29917
+ resolveMessage(messages129.unusedContainer, { name })
30003
29918
  );
30004
29919
  }
30005
29920
  }
@@ -30007,13 +29922,13 @@ var cssNoUnusedContainerName = defineCSSRule({
30007
29922
  });
30008
29923
 
30009
29924
  // src/css/rules/structure/layer-requirement-for-component-rules.ts
30010
- var messages131 = {
29925
+ var messages130 = {
30011
29926
  missingLayer: "Rule `{{selector}}` is not inside any @layer block while this file uses @layer. Place component rules inside an explicit layer."
30012
29927
  };
30013
29928
  var layerRequirementForComponentRules = defineCSSRule({
30014
29929
  id: "layer-requirement-for-component-rules",
30015
29930
  severity: "warn",
30016
- messages: messages131,
29931
+ messages: messages130,
30017
29932
  meta: {
30018
29933
  description: "Require style rules to be inside @layer when the file defines layers.",
30019
29934
  fixable: false,
@@ -30032,7 +29947,7 @@ var layerRequirementForComponentRules = defineCSSRule({
30032
29947
  rule.startColumn,
30033
29948
  layerRequirementForComponentRules,
30034
29949
  "missingLayer",
30035
- resolveMessage(messages131.missingLayer, {
29950
+ resolveMessage(messages130.missingLayer, {
30036
29951
  selector: rule.selectorText
30037
29952
  })
30038
29953
  );
@@ -30072,7 +29987,6 @@ var rules2 = [
30072
29987
  selectorMaxAttributeAndUniversal,
30073
29988
  selectorMaxSpecificity,
30074
29989
  cssPolicyTypography,
30075
- cssPolicyTouchTarget,
30076
29990
  cssPolicySpacing,
30077
29991
  cssPolicyContrast
30078
29992
  ];
@@ -31012,6 +30926,9 @@ function readBaselineOffsetFacts(graph, node) {
31012
30926
  function readElementRef(graph, node) {
31013
30927
  return readElementRefById(graph, node.solidFile, node.elementId);
31014
30928
  }
30929
+ function readHostElementRef(graph, node) {
30930
+ return graph.hostElementRefsByNode.get(node) ?? null;
30931
+ }
31015
30932
  function readElementRefById(graph, solidFile, elementId) {
31016
30933
  const refs = graph.elementRefsBySolidFileAndId.get(solidFile);
31017
30934
  if (!refs) return null;
@@ -32077,7 +31994,7 @@ function publishLayoutPerfStatsForTest(stats) {
32077
31994
  }
32078
31995
  function maybeLogLayoutPerf(stats, log) {
32079
31996
  if (process.env["SOLID_LINT_LAYOUT_PROFILE"] !== "1") return;
32080
- if (!log || !log.enabled) return;
31997
+ if (!log || !log.isLevelEnabled(Level.Debug)) return;
32081
31998
  const view = snapshotLayoutPerfStats(stats);
32082
31999
  log.debug(
32083
32000
  `[layout] elements=${view.elementsScanned} candidates=${view.selectorCandidatesChecked} compiledSelectors=${view.compiledSelectorCount} unsupportedSelectors=${view.selectorsRejectedUnsupported} conditionalSelectors=${view.selectorsGuardedConditional} ancestryChecks=${view.ancestryChecks} edges=${view.matchEdgesCreated} collected=${view.casesCollected} cases=${view.casesScored} rejectLowEvidence=${view.casesRejectedLowEvidence} rejectThreshold=${view.casesRejectedThreshold} rejectUndecidable=${view.casesRejectedUndecidable} rejectIdentifiability=${view.casesRejectedIdentifiability} undecidableInterval=${view.undecidableInterval} conditionalSignalRatio=${Math.round(view.conditionalSignalRatio * 1e3) / 1e3} conditionalSignals=${view.conditionalSignals} totalSignals=${view.totalSignals} cohortUnimodalFalse=${view.cohortUnimodalFalse} factorCoverageMean=${Math.round(view.factorCoverageMean * 1e3) / 1e3} posteriorWidthP95=${Math.round(view.posteriorWidthP95 * 1e3) / 1e3} uncertaintyEscalations=${view.uncertaintyEscalations} snapshots=${view.signalSnapshotsBuilt} snapshotHits=${view.signalSnapshotCacheHits} measurementIndexHits=${view.measurementIndexHits} contexts=${view.contextsClassified} diagnostics=${view.diagnosticsEmitted} selectorIndexMs=${Math.round(view.selectorIndexMs * 100) / 100} selectorMatchMs=${Math.round(view.selectorMatchMs * 100) / 100} cascadeBuildMs=${Math.round(view.cascadeBuildMs * 100) / 100} caseBuildMs=${Math.round(view.caseBuildMs * 100) / 100} scoringMs=${Math.round(view.scoringMs * 100) / 100} elapsedMs=${Math.round(view.elapsedMs * 100) / 100}`
@@ -32142,17 +32059,17 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
32142
32059
  if (cached !== void 0) return cached;
32143
32060
  const binding = resolveTagBinding(normalizedFile, tag);
32144
32061
  if (binding === null) {
32145
- if (logger.enabled) logger.trace(`[component-host] resolveHost(${tag}): binding=null`);
32062
+ if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] resolveHost(${tag}): binding=null`);
32146
32063
  hostByTagCache.set(cacheKey, null);
32147
32064
  return null;
32148
32065
  }
32149
32066
  if (binding.kind === "component") {
32150
- if (logger.enabled) logger.trace(`[component-host] resolveHost(${tag}): component, tagName=${binding.host.tagName}, attrs=[${[...binding.host.staticAttributes.keys()]}]`);
32067
+ if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] resolveHost(${tag}): component, tagName=${binding.host.descriptor.tagName}, attrs=[${[...binding.host.descriptor.staticAttributes.keys()]}]`);
32151
32068
  hostByTagCache.set(cacheKey, binding.host);
32152
32069
  return binding.host;
32153
32070
  }
32154
32071
  const host = binding.base ? binding.base.host : null;
32155
- if (logger.enabled) logger.trace(`[component-host] resolveHost(${tag}): namespace, base=${host?.tagName ?? "null"}`);
32072
+ if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] resolveHost(${tag}): namespace, base=${host?.descriptor.tagName ?? "null"}`);
32156
32073
  hostByTagCache.set(cacheKey, host);
32157
32074
  return host;
32158
32075
  },
@@ -32165,26 +32082,26 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
32165
32082
  }
32166
32083
  };
32167
32084
  function resolveComponentHostEntry(entry) {
32168
- if (entry.resolution === "resolved") return entry.descriptor;
32169
- if (logger.enabled) logger.trace(`[component-host] resolveComponentHostEntry: deferred innerTag=${entry.innerTag}, file=${entry.filePath}, attrs=[${[...entry.staticAttributes.keys()]}]`);
32085
+ if (entry.resolution === "resolved") {
32086
+ return { descriptor: entry.descriptor, hostElementRef: entry.hostElementRef };
32087
+ }
32088
+ if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] resolveComponentHostEntry: deferred innerTag=${entry.innerTag}, file=${entry.filePath}, attrs=[${[...entry.staticAttributes.keys()]}]`);
32170
32089
  const innerBinding = resolveLocalIdentifierBinding(entry.filePath, entry.innerTag);
32171
- if (logger.enabled) logger.trace(`[component-host] innerBinding=${innerBinding === null ? "null" : innerBinding.kind}`);
32090
+ if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] innerBinding=${innerBinding === null ? "null" : innerBinding.kind}`);
32172
32091
  const innerHost = extractHostFromBinding(innerBinding);
32173
- if (logger.enabled) logger.trace(`[component-host] innerHost=${innerHost === null ? "null" : `tagName=${innerHost.tagName}, attrs=[${[...innerHost.staticAttributes.keys()]}]`}`);
32174
- let tagName = innerHost !== null ? innerHost.tagName : null;
32092
+ if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] innerHost=${innerHost === null ? "null" : `tagName=${innerHost.descriptor.tagName}, attrs=[${[...innerHost.descriptor.staticAttributes.keys()]}]`}`);
32093
+ let tagName = innerHost !== null ? innerHost.descriptor.tagName : null;
32175
32094
  if (tagName === null) {
32176
32095
  tagName = resolveTagNameFromPolymorphicProp(entry.staticAttributes);
32177
- if (logger.enabled) logger.trace(`[component-host] polymorphic fallback: tagName=${tagName}`);
32096
+ if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] polymorphic fallback: tagName=${tagName}`);
32178
32097
  }
32179
- const staticAttributes = innerHost !== null ? mergeStaticAttributes(entry.staticAttributes, innerHost.staticAttributes) : entry.staticAttributes;
32180
- const staticClassTokens = innerHost !== null ? mergeStaticClassTokens(entry.staticClassTokens, innerHost.staticClassTokens) : entry.staticClassTokens;
32181
- const forwardsChildren = entry.forwardsChildren || innerHost !== null && innerHost.forwardsChildren;
32182
- if (logger.enabled) logger.trace(`[component-host] resolved: tagName=${tagName}, attrs=[${[...staticAttributes.keys()]}], classes=[${staticClassTokens}]`);
32098
+ const staticAttributes = innerHost !== null ? mergeStaticAttributes(entry.staticAttributes, innerHost.descriptor.staticAttributes) : entry.staticAttributes;
32099
+ const staticClassTokens = innerHost !== null ? mergeStaticClassTokens(entry.staticClassTokens, innerHost.descriptor.staticClassTokens) : entry.staticClassTokens;
32100
+ const forwardsChildren = entry.forwardsChildren || innerHost !== null && innerHost.descriptor.forwardsChildren;
32101
+ if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] resolved: tagName=${tagName}, attrs=[${[...staticAttributes.keys()]}], classes=[${staticClassTokens}]`);
32183
32102
  return {
32184
- tagName,
32185
- staticAttributes,
32186
- staticClassTokens,
32187
- forwardsChildren
32103
+ descriptor: { tagName, staticAttributes, staticClassTokens, forwardsChildren },
32104
+ hostElementRef: innerHost?.hostElementRef ?? null
32188
32105
  };
32189
32106
  }
32190
32107
  function extractHostFromBinding(binding) {
@@ -32225,10 +32142,7 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
32225
32142
  if (hostEntry) {
32226
32143
  const resolved = resolveComponentHostEntry(hostEntry);
32227
32144
  if (resolved !== null) {
32228
- const binding = {
32229
- kind: "component",
32230
- host: resolved
32231
- };
32145
+ const binding = { kind: "component", host: resolved };
32232
32146
  localBindingCache.set(key, binding);
32233
32147
  resolvingLocal.delete(key);
32234
32148
  return binding;
@@ -32289,7 +32203,7 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
32289
32203
  const baseExpression = toExpressionArgument(firstArg);
32290
32204
  if (baseExpression === null) return null;
32291
32205
  const baseBinding = resolveBindingFromExpression(filePath, baseExpression);
32292
- if (logger.enabled) logger.trace(`[component-host] Object.assign base: ${baseBinding === null ? "null" : baseBinding.kind}${baseBinding?.kind === "component" ? `, tagName=${baseBinding.host.tagName}` : ""}`);
32206
+ if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] Object.assign base: ${baseBinding === null ? "null" : baseBinding.kind}${baseBinding?.kind === "component" ? `, tagName=${baseBinding.host.descriptor.tagName}` : ""}`);
32293
32207
  let baseComponent = null;
32294
32208
  const members = /* @__PURE__ */ new Map();
32295
32209
  if (baseBinding && baseBinding.kind === "component") {
@@ -32315,7 +32229,7 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
32315
32229
  if (!import_typescript125.default.isObjectLiteralExpression(argument)) continue;
32316
32230
  appendObjectExpressionMembers(filePath, argument, members);
32317
32231
  }
32318
- if (logger.enabled) logger.trace(`[component-host] Object.assign result: base=${baseComponent === null ? "null" : `tagName=${baseComponent.host.tagName}`}, members=[${[...members.keys()]}]`);
32232
+ if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] Object.assign result: base=${baseComponent === null ? "null" : `tagName=${baseComponent.host.descriptor.tagName}`}, members=[${[...members.keys()]}]`);
32319
32233
  if (baseComponent === null && members.size === 0) return null;
32320
32234
  return {
32321
32235
  kind: "namespace",
@@ -32357,7 +32271,7 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
32357
32271
  }
32358
32272
  function resolveBindingFromImport(filePath, importBinding) {
32359
32273
  const resolvedModule = moduleResolver.resolveSolid(filePath, importBinding.source) ?? resolveAndIndexExternalModule(filePath, importBinding.source);
32360
- if (logger.enabled) logger.trace(`[component-host] resolveBindingFromImport: source=${importBinding.source}, kind=${importBinding.kind}, resolvedModule=${resolvedModule}`);
32274
+ if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] resolveBindingFromImport: source=${importBinding.source}, kind=${importBinding.kind}, resolvedModule=${resolvedModule}`);
32361
32275
  if (resolvedModule === null) return null;
32362
32276
  const normalized = (0, import_node_path3.resolve)(resolvedModule);
32363
32277
  if (importBinding.kind === "namespace") {
@@ -32366,7 +32280,7 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
32366
32280
  const exportName = importBinding.kind === "default" ? "default" : importBinding.importedName;
32367
32281
  if (exportName === null) return null;
32368
32282
  const result = resolveExportBinding(normalized, exportName);
32369
- if (logger.enabled) logger.trace(`[component-host] export ${exportName}: ${result === null ? "null" : result.kind}`);
32283
+ if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] export ${exportName}: ${result === null ? "null" : result.kind}`);
32370
32284
  return result;
32371
32285
  }
32372
32286
  function resolveAndIndexExternalModule(importerFile, importSource) {
@@ -32560,6 +32474,7 @@ function collectComponentHosts(graph) {
32560
32474
  }
32561
32475
  function resolveComponentHostEntryForFunction(graph, fn) {
32562
32476
  let entry = null;
32477
+ let hostElementRefAgreed = true;
32563
32478
  const bodyEntry = resolveHostEntryFromFunctionBody(graph, fn);
32564
32479
  if (bodyEntry !== null) {
32565
32480
  entry = bodyEntry;
@@ -32575,9 +32490,17 @@ function resolveComponentHostEntryForFunction(graph, fn) {
32575
32490
  entry = returnEntry;
32576
32491
  continue;
32577
32492
  }
32578
- if (areComponentHostEntriesEqual(entry, returnEntry)) continue;
32493
+ if (areComponentHostEntriesEqual(entry, returnEntry)) {
32494
+ if (hostElementRefAgreed && entry.resolution === "resolved" && returnEntry.resolution === "resolved" && entry.hostElementRef !== returnEntry.hostElementRef) {
32495
+ hostElementRefAgreed = false;
32496
+ }
32497
+ continue;
32498
+ }
32579
32499
  return null;
32580
32500
  }
32501
+ if (!hostElementRefAgreed && entry !== null && entry.resolution === "resolved") {
32502
+ return { resolution: "resolved", descriptor: entry.descriptor, hostElementRef: null };
32503
+ }
32581
32504
  return entry;
32582
32505
  }
32583
32506
  function resolveHostEntryFromFunctionBody(graph, fn) {
@@ -32605,7 +32528,8 @@ function resolveHostEntryFromJSXElement(graph, node) {
32605
32528
  staticAttributes: collectStaticAttributes(element),
32606
32529
  staticClassTokens: getStaticClassTokensForElementEntity(graph, element),
32607
32530
  forwardsChildren: detectChildrenForwarding(element)
32608
- }
32531
+ },
32532
+ hostElementRef: { solid: graph, element }
32609
32533
  };
32610
32534
  }
32611
32535
  if (isContextProviderTag(element.tag)) {
@@ -33315,7 +33239,7 @@ function matchesChain(matcher, node, index, perf, fileRootElements, logger) {
33315
33239
  ancestor = ancestor.parentElementNode;
33316
33240
  }
33317
33241
  if (fileRootElements !== null) {
33318
- if (logger.enabled) {
33242
+ if (logger.isLevelEnabled(Level.Trace)) {
33319
33243
  const compoundDesc = describeCompound(targetCompound);
33320
33244
  logger.trace(`[selector-match] fallback: node=${node.key} tag=${node.tagName} checking ${fileRootElements.length} roots for compound=${compoundDesc}`);
33321
33245
  }
@@ -33326,11 +33250,11 @@ function matchesChain(matcher, node, index, perf, fileRootElements, logger) {
33326
33250
  if (root.solidFile !== node.solidFile) continue;
33327
33251
  perf.ancestryChecks++;
33328
33252
  const compoundResult = matchesCompound(root, targetCompound);
33329
- if (logger.enabled && compoundResult === "no-match") {
33253
+ if (logger.isLevelEnabled(Level.Trace) && compoundResult === "no-match") {
33330
33254
  logger.trace(`[selector-match] fallback MISS: root=${root.key} tag=${root.tagName} attrs=[${[...root.attributes.entries()].map(([k, v]) => `${k}=${v}`).join(",")}]`);
33331
33255
  }
33332
33256
  if (compoundResult !== "no-match") {
33333
- if (logger.enabled) {
33257
+ if (logger.isLevelEnabled(Level.Debug)) {
33334
33258
  const compoundDesc = describeCompound(targetCompound);
33335
33259
  logger.debug(`[selector-match] fallback HIT: node=${node.key} tag=${node.tagName} matched root=${root.key} tag=${root.tagName} compound=${compoundDesc} isFinal=${isFinal}`);
33336
33260
  }
@@ -36532,7 +36456,7 @@ function appendMatchingEdgesFromSelectorIds(ctx, selectorIds, node, applies, app
36532
36456
  };
36533
36457
  applies.push(edge);
36534
36458
  ctx.perf.matchEdgesCreated++;
36535
- if (ctx.logger.enabled) {
36459
+ if (ctx.logger.isLevelEnabled(Level.Trace)) {
36536
36460
  ctx.logger.trace(
36537
36461
  `[cascade] edge node=${node.key} selector=${selector.id} match=${matchResult} conditional=${edge.conditionalMatch} selector-raw=${selector.raw.slice(0, 80)}`
36538
36462
  );
@@ -36975,7 +36899,7 @@ function getTextualContentState(element, memo, compositionMetaByElementId, logge
36975
36899
  if (!child) continue;
36976
36900
  if (child.kind === "expression") {
36977
36901
  if (isStructuralExpression(child.node)) {
36978
- if (logger.enabled) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id} \u2192 unknown (structural expression child)`);
36902
+ if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id} \u2192 unknown (structural expression child)`);
36979
36903
  memo.set(element.id, 2 /* Unknown */);
36980
36904
  return 2 /* Unknown */;
36981
36905
  }
@@ -36997,11 +36921,11 @@ function getTextualContentState(element, memo, compositionMetaByElementId, logge
36997
36921
  if (!child.isDomElement) {
36998
36922
  const childMeta = compositionMetaByElementId.get(child.id);
36999
36923
  if (childMeta !== void 0 && isControlTag(childMeta.tagName)) {
37000
- if (logger.enabled) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id}: non-DOM child ${child.tag}#${child.id} resolves to control tag=${childMeta.tagName}, skipping`);
36924
+ if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id}: non-DOM child ${child.tag}#${child.id} resolves to control tag=${childMeta.tagName}, skipping`);
37001
36925
  continue;
37002
36926
  }
37003
36927
  if (childState !== 1 /* No */) {
37004
- if (logger.enabled) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id}: non-DOM child ${child.tag ?? child.id}#${child.id} has state=${childState} \u2192 childHasUnknown`);
36928
+ if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id}: non-DOM child ${child.tag ?? child.id}#${child.id} has state=${childState} \u2192 childHasUnknown`);
37005
36929
  childHasUnknown = true;
37006
36930
  }
37007
36931
  continue;
@@ -37014,12 +36938,12 @@ function getTextualContentState(element, memo, compositionMetaByElementId, logge
37014
36938
  if (childState === 3 /* DynamicText */) childHasDynamicText = true;
37015
36939
  }
37016
36940
  if (childHasUnknown) {
37017
- if (logger.enabled) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id} \u2192 unknown (child has unknown)`);
36941
+ if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id} \u2192 unknown (child has unknown)`);
37018
36942
  memo.set(element.id, 2 /* Unknown */);
37019
36943
  return 2 /* Unknown */;
37020
36944
  }
37021
36945
  if (hasTextOnlyExpression || childHasDynamicText) {
37022
- if (logger.enabled) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id} \u2192 dynamic-text`);
36946
+ if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id} \u2192 dynamic-text`);
37023
36947
  memo.set(element.id, 3 /* DynamicText */);
37024
36948
  return 3 /* DynamicText */;
37025
36949
  }
@@ -37041,15 +36965,16 @@ function collectLayoutElementRecordsForSolid(solid, selectorRequirements, inline
37041
36965
  const meta = compositionMetaByElementId.get(element.id);
37042
36966
  if (!meta || !meta.participates) continue;
37043
36967
  const localClassTokens = selectorRequirements.needsClassTokens ? getStaticClassTokensForElementEntity(solid, element) : EMPTY_STRING_LIST3;
37044
- const classTokens = mergeClassTokens(localClassTokens, meta.hostDescriptor?.staticClassTokens);
36968
+ const classTokens = mergeClassTokens(localClassTokens, meta.resolvedHost?.descriptor.staticClassTokens);
37045
36969
  const classTokenSet = classTokens.length === 0 ? EMPTY_CLASS_TOKEN_SET : createClassTokenSet(classTokens);
37046
36970
  const inlineStyleKeys = getStaticStyleKeysForElement(solid, element.id);
37047
36971
  const localAttributes = selectorRequirements.needsAttributes ? collectStaticAttributes(element) : EMPTY_ATTRIBUTES2;
37048
- const attributes = mergeAttributes(localAttributes, meta.hostDescriptor?.staticAttributes);
36972
+ const attributes = mergeAttributes(localAttributes, meta.resolvedHost?.descriptor.staticAttributes);
37049
36973
  const selectorDispatchKeys = buildSelectorDispatchKeys(attributes, classTokens);
37050
36974
  const inlineStyleValues = inlineStyleValuesByElementId.get(element.id) ?? EMPTY_INLINE_STYLE_VALUES;
37051
36975
  const textualContent = getTextualContentState(element, textContentMemo, compositionMetaByElementId, logger);
37052
36976
  const parentElementId = resolveComposedParentElementId(element, compositionMetaByElementId);
36977
+ const hostElementRef = meta.resolvedHost?.hostElementRef ?? null;
37053
36978
  out.push({
37054
36979
  element,
37055
36980
  key: toLayoutElementKey(solid.file, element.id),
@@ -37062,7 +36987,8 @@ function collectLayoutElementRecordsForSolid(solid, selectorRequirements, inline
37062
36987
  selectorDispatchKeys,
37063
36988
  inlineStyleValues,
37064
36989
  textualContent,
37065
- parentElementId
36990
+ parentElementId,
36991
+ hostElementRef
37066
36992
  });
37067
36993
  }
37068
36994
  return out;
@@ -37072,7 +36998,7 @@ function collectCompositionMetaByElementId(solid, componentHostResolver) {
37072
36998
  for (let i = 0; i < solid.jsxElements.length; i++) {
37073
36999
  const element = solid.jsxElements[i];
37074
37000
  if (!element) continue;
37075
- const hostDescriptor = resolveHostDescriptorForElement(
37001
+ const resolvedHost = resolveHostForElement(
37076
37002
  componentHostResolver,
37077
37003
  solid.file,
37078
37004
  element
@@ -37081,30 +37007,30 @@ function collectCompositionMetaByElementId(solid, componentHostResolver) {
37081
37007
  componentHostResolver,
37082
37008
  solid.file,
37083
37009
  element,
37084
- hostDescriptor
37010
+ resolvedHost
37085
37011
  );
37086
37012
  const participates = element.tag !== null && !isTransparentPrimitive;
37087
- const tag = resolveEffectiveTag(element, hostDescriptor);
37013
+ const tag = resolveEffectiveTag(element, resolvedHost?.descriptor ?? null);
37088
37014
  const tagName = tag ? tag.toLowerCase() : null;
37089
37015
  out.set(element.id, {
37090
37016
  element,
37091
37017
  participates,
37092
37018
  tag,
37093
37019
  tagName,
37094
- hostDescriptor
37020
+ resolvedHost
37095
37021
  });
37096
37022
  }
37097
37023
  return out;
37098
37024
  }
37099
- function resolveHostDescriptorForElement(componentHostResolver, solidFile, element) {
37025
+ function resolveHostForElement(componentHostResolver, solidFile, element) {
37100
37026
  if (element.tag === null) return null;
37101
37027
  if (element.isDomElement) return null;
37102
37028
  return componentHostResolver.resolveHost(solidFile, element.tag);
37103
37029
  }
37104
- function resolveTransparentPrimitiveStatus(componentHostResolver, solidFile, element, hostDescriptor) {
37030
+ function resolveTransparentPrimitiveStatus(componentHostResolver, solidFile, element, resolvedHost) {
37105
37031
  if (element.tag === null) return false;
37106
37032
  if (element.isDomElement) return false;
37107
- if (hostDescriptor !== null) return false;
37033
+ if (resolvedHost !== null) return false;
37108
37034
  return componentHostResolver.isTransparentPrimitive(solidFile, element.tag);
37109
37035
  }
37110
37036
  function resolveEffectiveTag(element, hostDescriptor) {
@@ -37222,6 +37148,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
37222
37148
  const childrenByParentNodeMutable = /* @__PURE__ */ new Map();
37223
37149
  const elementBySolidFileAndIdMutable = /* @__PURE__ */ new Map();
37224
37150
  const elementRefsBySolidFileAndIdMutable = /* @__PURE__ */ new Map();
37151
+ const hostElementRefsByNodeMutable = /* @__PURE__ */ new Map();
37225
37152
  const appliesByElementNodeMutable = /* @__PURE__ */ new Map();
37226
37153
  const selectorsById = /* @__PURE__ */ new Map();
37227
37154
  const monitoredDeclarationsBySelectorId = /* @__PURE__ */ new Map();
@@ -37258,7 +37185,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
37258
37185
  const moduleResolver = createLayoutModuleResolver(solids, css);
37259
37186
  const componentHostResolver = createLayoutComponentHostResolver(solids, moduleResolver, logger);
37260
37187
  const cssScopeBySolidFile = collectCSSScopeBySolidFile(solids, css, moduleResolver);
37261
- if (logger.enabled) {
37188
+ if (logger.isLevelEnabled(Level.Trace)) {
37262
37189
  for (const [solidFile, scopePaths] of cssScopeBySolidFile) {
37263
37190
  if (scopePaths.length > 0) {
37264
37191
  let names = "";
@@ -37353,6 +37280,9 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
37353
37280
  isControl: isControlTag(record.tagName),
37354
37281
  isReplaced: isReplacedTag(record.tagName)
37355
37282
  };
37283
+ if (record.hostElementRef !== null) {
37284
+ hostElementRefsByNodeMutable.set(node, record.hostElementRef);
37285
+ }
37356
37286
  elements.push(node);
37357
37287
  elementById.set(record.element.id, node);
37358
37288
  nodeByElementId.set(record.element.id, node);
@@ -37374,7 +37304,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
37374
37304
  }
37375
37305
  }
37376
37306
  }
37377
- if (logger.enabled) {
37307
+ if (logger.isLevelEnabled(Level.Debug)) {
37378
37308
  for (const [file, roots] of rootElementsByFile) {
37379
37309
  const descs = roots.map((r) => `${r.key}(tag=${r.tagName}, attrs=[${[...r.attributes.entries()].map(([k, v]) => `${k}=${v}`).join(",")}])`);
37380
37310
  logger.debug(`[build] rootElementsByFile file=${file} count=${roots.length}: ${descs.join(", ")}`);
@@ -37417,7 +37347,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
37417
37347
  appliesByNode.set(node, edges);
37418
37348
  }
37419
37349
  perf.cascadeBuildMs = performance.now() - cascadeStartedAt;
37420
- if (logger.enabled) {
37350
+ if (logger.isLevelEnabled(Level.Trace)) {
37421
37351
  for (let i = 0; i < elements.length; i++) {
37422
37352
  const node = elements[i];
37423
37353
  if (!node) continue;
@@ -37473,6 +37403,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
37473
37403
  childrenByParentNode: childrenByParentNodeMutable,
37474
37404
  elementBySolidFileAndId: elementBySolidFileAndIdMutable,
37475
37405
  elementRefsBySolidFileAndId: elementRefsBySolidFileAndIdMutable,
37406
+ hostElementRefsByNode: hostElementRefsByNodeMutable,
37476
37407
  appliesByNode,
37477
37408
  selectorCandidatesByNode,
37478
37409
  selectorsById,
@@ -37873,7 +37804,7 @@ function computeFlowParticipationFact(snapshot) {
37873
37804
  }
37874
37805
  function buildContextIndex(childrenByParentNode, snapshotByElementNode, perf, logger) {
37875
37806
  const out = /* @__PURE__ */ new Map();
37876
- const trace = logger.enabled;
37807
+ const trace = logger.isLevelEnabled(Level.Trace);
37877
37808
  for (const [parent, children] of childrenByParentNode) {
37878
37809
  if (children.length < 2) continue;
37879
37810
  const snapshot = snapshotByElementNode.get(parent);
@@ -38692,7 +38623,7 @@ function runLayoutDetector(context, detector) {
38692
38623
  result.evidence.posteriorLower,
38693
38624
  result.evidence.posteriorUpper
38694
38625
  );
38695
- if (log.enabled) {
38626
+ if (log.isLevelEnabled(Level.Debug)) {
38696
38627
  log.debug(
38697
38628
  `[${detector.id}] accept case=${i} severity=${result.evidence.severity.toFixed(2)} confidence=${result.evidence.confidence.toFixed(2)} posterior=[${result.evidence.posteriorLower.toFixed(3)},${result.evidence.posteriorUpper.toFixed(3)}] evidenceMass=${result.evidence.evidenceMass.toFixed(3)} context=${result.evidence.contextKind} offset=${result.evidence.estimatedOffsetPx?.toFixed(2) ?? "null"} topFactors=[${result.evidence.topFactors.join(",")}] causes=[${result.evidence.causes.join("; ")}]`
38698
38629
  );
@@ -38701,7 +38632,7 @@ function runLayoutDetector(context, detector) {
38701
38632
  continue;
38702
38633
  }
38703
38634
  recordPolicyMetrics(context, result.evidenceMass, result.posteriorLower, result.posteriorUpper);
38704
- if (log.enabled) {
38635
+ if (log.isLevelEnabled(Level.Debug)) {
38705
38636
  log.debug(
38706
38637
  `[${detector.id}] reject case=${i} reason=${result.reason} detail=${result.detail ?? "none"} posterior=[${result.posteriorLower.toFixed(3)},${result.posteriorUpper.toFixed(3)}] evidenceMass=${result.evidenceMass.toFixed(3)}`
38707
38638
  );
@@ -38892,13 +38823,13 @@ function emitLayoutDiagnostic(layout, node, emit, ruleId, messageId, template, s
38892
38823
  }
38893
38824
 
38894
38825
  // src/cross-file/rules/undefined-css-class.ts
38895
- var messages132 = {
38826
+ var messages131 = {
38896
38827
  undefinedClass: "CSS class '{{className}}' is not defined in project CSS files"
38897
38828
  };
38898
38829
  var jsxNoUndefinedCssClass = defineCrossRule({
38899
38830
  id: "jsx-no-undefined-css-class",
38900
38831
  severity: "error",
38901
- messages: messages132,
38832
+ messages: messages131,
38902
38833
  meta: {
38903
38834
  description: "Detect undefined CSS class names in JSX",
38904
38835
  fixable: false,
@@ -38917,7 +38848,7 @@ var jsxNoUndefinedCssClass = defineCrossRule({
38917
38848
  ref.solid.sourceFile,
38918
38849
  jsxNoUndefinedCssClass.id,
38919
38850
  "undefinedClass",
38920
- resolveMessage(messages132.undefinedClass, { className: item.className }),
38851
+ resolveMessage(messages131.undefinedClass, { className: item.className }),
38921
38852
  "error"
38922
38853
  ));
38923
38854
  }
@@ -38925,13 +38856,13 @@ var jsxNoUndefinedCssClass = defineCrossRule({
38925
38856
  });
38926
38857
 
38927
38858
  // src/cross-file/rules/unreferenced-css-class.ts
38928
- var messages133 = {
38859
+ var messages132 = {
38929
38860
  unreferencedClass: "CSS class '{{className}}' is defined but not referenced by static JSX class attributes"
38930
38861
  };
38931
38862
  var cssNoUnreferencedComponentClass = defineCrossRule({
38932
38863
  id: "css-no-unreferenced-component-class",
38933
38864
  severity: "warn",
38934
- messages: messages133,
38865
+ messages: messages132,
38935
38866
  meta: {
38936
38867
  description: "Detect CSS classes that are never referenced by static JSX class attributes.",
38937
38868
  fixable: false,
@@ -38955,7 +38886,7 @@ var cssNoUnreferencedComponentClass = defineCrossRule({
38955
38886
  },
38956
38887
  cssNoUnreferencedComponentClass.id,
38957
38888
  "unreferencedClass",
38958
- resolveMessage(messages133.unreferencedClass, { className }),
38889
+ resolveMessage(messages132.unreferencedClass, { className }),
38959
38890
  "warn"
38960
38891
  )
38961
38892
  );
@@ -38964,13 +38895,13 @@ var cssNoUnreferencedComponentClass = defineCrossRule({
38964
38895
  });
38965
38896
 
38966
38897
  // src/cross-file/rules/jsx-no-duplicate-class-token-class-classlist.ts
38967
- var messages134 = {
38898
+ var messages133 = {
38968
38899
  duplicateClassToken: "Class token `{{name}}` appears in both class and classList."
38969
38900
  };
38970
38901
  var jsxNoDuplicateClassTokenClassClasslist = defineCrossRule({
38971
38902
  id: "jsx-no-duplicate-class-token-class-classlist",
38972
38903
  severity: "warn",
38973
- messages: messages134,
38904
+ messages: messages133,
38974
38905
  meta: {
38975
38906
  description: "Disallow duplicate class tokens between class and classList on the same JSX element.",
38976
38907
  fixable: false,
@@ -39012,7 +38943,7 @@ var jsxNoDuplicateClassTokenClassClasslist = defineCrossRule({
39012
38943
  solid.sourceFile,
39013
38944
  jsxNoDuplicateClassTokenClassClasslist.id,
39014
38945
  "duplicateClassToken",
39015
- resolveMessage(messages134.duplicateClassToken, { name: token }),
38946
+ resolveMessage(messages133.duplicateClassToken, { name: token }),
39016
38947
  "warn"
39017
38948
  ));
39018
38949
  }
@@ -39023,13 +38954,13 @@ var jsxNoDuplicateClassTokenClassClasslist = defineCrossRule({
39023
38954
 
39024
38955
  // src/cross-file/rules/jsx-classlist-static-keys.ts
39025
38956
  var import_typescript128 = __toESM(require("typescript"), 1);
39026
- var messages135 = {
38957
+ var messages134 = {
39027
38958
  nonStaticKey: "classList key must be statically known for reliable class mapping."
39028
38959
  };
39029
38960
  var jsxClasslistStaticKeys = defineCrossRule({
39030
38961
  id: "jsx-classlist-static-keys",
39031
38962
  severity: "error",
39032
- messages: messages135,
38963
+ messages: messages134,
39033
38964
  meta: {
39034
38965
  description: "Require classList keys to be static and non-computed.",
39035
38966
  fixable: false,
@@ -39040,26 +38971,26 @@ var jsxClasslistStaticKeys = defineCrossRule({
39040
38971
  forEachClassListPropertyAcross(solids, (solid, p) => {
39041
38972
  if (import_typescript128.default.isSpreadAssignment(p)) return;
39042
38973
  if (!import_typescript128.default.isPropertyAssignment(p)) {
39043
- emit(createDiagnostic(solid.file, p, solid.sourceFile, jsxClasslistStaticKeys.id, "nonStaticKey", resolveMessage(messages135.nonStaticKey), "error"));
38974
+ emit(createDiagnostic(solid.file, p, solid.sourceFile, jsxClasslistStaticKeys.id, "nonStaticKey", resolveMessage(messages134.nonStaticKey), "error"));
39044
38975
  return;
39045
38976
  }
39046
38977
  if (import_typescript128.default.isComputedPropertyName(p.name)) return;
39047
38978
  if (import_typescript128.default.isIdentifier(p.name)) return;
39048
38979
  if (import_typescript128.default.isStringLiteral(p.name)) return;
39049
- emit(createDiagnostic(solid.file, p.name, solid.sourceFile, jsxClasslistStaticKeys.id, "nonStaticKey", resolveMessage(messages135.nonStaticKey), "error"));
38980
+ emit(createDiagnostic(solid.file, p.name, solid.sourceFile, jsxClasslistStaticKeys.id, "nonStaticKey", resolveMessage(messages134.nonStaticKey), "error"));
39050
38981
  });
39051
38982
  }
39052
38983
  });
39053
38984
 
39054
38985
  // src/cross-file/rules/jsx-classlist-no-constant-literals.ts
39055
38986
  var import_typescript129 = __toESM(require("typescript"), 1);
39056
- var messages136 = {
38987
+ var messages135 = {
39057
38988
  constantEntry: "classList entry `{{name}}: {{value}}` is constant; move it to static class."
39058
38989
  };
39059
38990
  var jsxClasslistNoConstantLiterals = defineCrossRule({
39060
38991
  id: "jsx-classlist-no-constant-literals",
39061
38992
  severity: "warn",
39062
- messages: messages136,
38993
+ messages: messages135,
39063
38994
  meta: {
39064
38995
  description: "Disallow classList entries with constant true/false values.",
39065
38996
  fixable: false,
@@ -39079,7 +39010,7 @@ var jsxClasslistNoConstantLiterals = defineCrossRule({
39079
39010
  solid.sourceFile,
39080
39011
  jsxClasslistNoConstantLiterals.id,
39081
39012
  "constantEntry",
39082
- resolveMessage(messages136.constantEntry, { name: n, value: val.kind === import_typescript129.default.SyntaxKind.TrueKeyword ? "true" : "false" }),
39013
+ resolveMessage(messages135.constantEntry, { name: n, value: val.kind === import_typescript129.default.SyntaxKind.TrueKeyword ? "true" : "false" }),
39083
39014
  "warn"
39084
39015
  ));
39085
39016
  });
@@ -39114,13 +39045,13 @@ function isDefinitelyNonBooleanType(solid, node) {
39114
39045
  }
39115
39046
 
39116
39047
  // src/cross-file/rules/jsx-classlist-boolean-values.ts
39117
- var messages137 = {
39048
+ var messages136 = {
39118
39049
  nonBooleanValue: "classList value for `{{name}}` must be boolean."
39119
39050
  };
39120
39051
  var jsxClasslistBooleanValues = defineCrossRule({
39121
39052
  id: "jsx-classlist-boolean-values",
39122
39053
  severity: "error",
39123
- messages: messages137,
39054
+ messages: messages136,
39124
39055
  meta: {
39125
39056
  description: "Require classList values to be boolean-like expressions.",
39126
39057
  fixable: false,
@@ -39134,25 +39065,25 @@ var jsxClasslistBooleanValues = defineCrossRule({
39134
39065
  if (!n) return;
39135
39066
  if (isBooleanish(p.initializer)) return;
39136
39067
  if (isDefinitelyNonBoolean(p.initializer)) {
39137
- emit(createDiagnostic(solid.file, p.initializer, solid.sourceFile, jsxClasslistBooleanValues.id, "nonBooleanValue", resolveMessage(messages137.nonBooleanValue, { name: n }), "error"));
39068
+ emit(createDiagnostic(solid.file, p.initializer, solid.sourceFile, jsxClasslistBooleanValues.id, "nonBooleanValue", resolveMessage(messages136.nonBooleanValue, { name: n }), "error"));
39138
39069
  return;
39139
39070
  }
39140
39071
  if (isBooleanType(solid, p.initializer)) return;
39141
39072
  if (!isDefinitelyNonBooleanType(solid, p.initializer)) return;
39142
- emit(createDiagnostic(solid.file, p.initializer, solid.sourceFile, jsxClasslistBooleanValues.id, "nonBooleanValue", resolveMessage(messages137.nonBooleanValue, { name: n }), "error"));
39073
+ emit(createDiagnostic(solid.file, p.initializer, solid.sourceFile, jsxClasslistBooleanValues.id, "nonBooleanValue", resolveMessage(messages136.nonBooleanValue, { name: n }), "error"));
39143
39074
  });
39144
39075
  }
39145
39076
  });
39146
39077
 
39147
39078
  // src/cross-file/rules/jsx-classlist-no-accessor-reference.ts
39148
39079
  var import_typescript131 = __toESM(require("typescript"), 1);
39149
- var messages138 = {
39080
+ var messages137 = {
39150
39081
  accessorReference: "Signal accessor `{{name}}` must be called in classList value (use {{name}}())."
39151
39082
  };
39152
39083
  var jsxClasslistNoAccessorReference = defineCrossRule({
39153
39084
  id: "jsx-classlist-no-accessor-reference",
39154
39085
  severity: "error",
39155
- messages: messages138,
39086
+ messages: messages137,
39156
39087
  meta: {
39157
39088
  description: "Disallow passing accessor references directly as classList values.",
39158
39089
  fixable: false,
@@ -39184,7 +39115,7 @@ var jsxClasslistNoAccessorReference = defineCrossRule({
39184
39115
  solid.sourceFile,
39185
39116
  jsxClasslistNoAccessorReference.id,
39186
39117
  "accessorReference",
39187
- resolveMessage(messages138.accessorReference, { name: v.text }),
39118
+ resolveMessage(messages137.accessorReference, { name: v.text }),
39188
39119
  "error"
39189
39120
  ));
39190
39121
  });
@@ -39193,13 +39124,13 @@ var jsxClasslistNoAccessorReference = defineCrossRule({
39193
39124
 
39194
39125
  // src/cross-file/rules/jsx-style-kebab-case-keys.ts
39195
39126
  var import_typescript132 = __toESM(require("typescript"), 1);
39196
- var messages139 = {
39127
+ var messages138 = {
39197
39128
  kebabStyleKey: "Style key `{{name}}` should be `{{kebab}}` in Solid style objects."
39198
39129
  };
39199
39130
  var jsxStyleKebabCaseKeys = defineCrossRule({
39200
39131
  id: "jsx-style-kebab-case-keys",
39201
39132
  severity: "error",
39202
- messages: messages139,
39133
+ messages: messages138,
39203
39134
  meta: {
39204
39135
  description: "Require kebab-case keys in JSX style object literals.",
39205
39136
  fixable: false,
@@ -39220,7 +39151,7 @@ var jsxStyleKebabCaseKeys = defineCrossRule({
39220
39151
  solid.sourceFile,
39221
39152
  jsxStyleKebabCaseKeys.id,
39222
39153
  "kebabStyleKey",
39223
- resolveMessage(messages139.kebabStyleKey, { name: n, kebab }),
39154
+ resolveMessage(messages138.kebabStyleKey, { name: n, kebab }),
39224
39155
  "error"
39225
39156
  ));
39226
39157
  });
@@ -39229,13 +39160,13 @@ var jsxStyleKebabCaseKeys = defineCrossRule({
39229
39160
 
39230
39161
  // src/cross-file/rules/jsx-style-no-function-values.ts
39231
39162
  var import_typescript133 = __toESM(require("typescript"), 1);
39232
- var messages140 = {
39163
+ var messages139 = {
39233
39164
  functionStyleValue: "Style value for `{{name}}` is a function; pass computed value instead."
39234
39165
  };
39235
39166
  var jsxStyleNoFunctionValues = defineCrossRule({
39236
39167
  id: "jsx-style-no-function-values",
39237
39168
  severity: "error",
39238
- messages: messages140,
39169
+ messages: messages139,
39239
39170
  meta: {
39240
39171
  description: "Disallow function values in JSX style objects.",
39241
39172
  fixable: false,
@@ -39249,11 +39180,11 @@ var jsxStyleNoFunctionValues = defineCrossRule({
39249
39180
  if (!n) return;
39250
39181
  const v = p.initializer;
39251
39182
  if (import_typescript133.default.isArrowFunction(v) || import_typescript133.default.isFunctionExpression(v)) {
39252
- emit(createDiagnostic(solid.file, v, solid.sourceFile, jsxStyleNoFunctionValues.id, "functionStyleValue", resolveMessage(messages140.functionStyleValue, { name: n }), "error"));
39183
+ emit(createDiagnostic(solid.file, v, solid.sourceFile, jsxStyleNoFunctionValues.id, "functionStyleValue", resolveMessage(messages139.functionStyleValue, { name: n }), "error"));
39253
39184
  return;
39254
39185
  }
39255
39186
  if (import_typescript133.default.isIdentifier(v) && solid.typeResolver.isCallableType(v)) {
39256
- emit(createDiagnostic(solid.file, v, solid.sourceFile, jsxStyleNoFunctionValues.id, "functionStyleValue", resolveMessage(messages140.functionStyleValue, { name: n }), "error"));
39187
+ emit(createDiagnostic(solid.file, v, solid.sourceFile, jsxStyleNoFunctionValues.id, "functionStyleValue", resolveMessage(messages139.functionStyleValue, { name: n }), "error"));
39257
39188
  }
39258
39189
  });
39259
39190
  }
@@ -39261,13 +39192,13 @@ var jsxStyleNoFunctionValues = defineCrossRule({
39261
39192
 
39262
39193
  // src/cross-file/rules/jsx-style-no-unused-custom-prop.ts
39263
39194
  var import_typescript134 = __toESM(require("typescript"), 1);
39264
- var messages141 = {
39195
+ var messages140 = {
39265
39196
  unusedInlineVar: "Inline custom property `{{name}}` is never read via var({{name}})."
39266
39197
  };
39267
39198
  var jsxStyleNoUnusedCustomProp = defineCrossRule({
39268
39199
  id: "jsx-style-no-unused-custom-prop",
39269
39200
  severity: "warn",
39270
- messages: messages141,
39201
+ messages: messages140,
39271
39202
  meta: {
39272
39203
  description: "Detect inline style custom properties that are never consumed by CSS var() references.",
39273
39204
  fixable: false,
@@ -39308,7 +39239,7 @@ var jsxStyleNoUnusedCustomProp = defineCrossRule({
39308
39239
  solid.sourceFile,
39309
39240
  jsxStyleNoUnusedCustomProp.id,
39310
39241
  "unusedInlineVar",
39311
- resolveMessage(messages141.unusedInlineVar, { name: n }),
39242
+ resolveMessage(messages140.unusedInlineVar, { name: n }),
39312
39243
  "warn"
39313
39244
  ));
39314
39245
  }
@@ -39318,7 +39249,7 @@ var jsxStyleNoUnusedCustomProp = defineCrossRule({
39318
39249
 
39319
39250
  // src/cross-file/rules/jsx-style-policy.ts
39320
39251
  var import_typescript135 = __toESM(require("typescript"), 1);
39321
- var messages142 = {
39252
+ var messages141 = {
39322
39253
  fontTooSmall: "Inline style `{{prop}}: {{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for policy `{{policy}}`.",
39323
39254
  lineHeightTooSmall: "Inline style `line-height: {{value}}` is below the minimum `{{min}}` for policy `{{policy}}`.",
39324
39255
  heightTooSmall: "Inline style `{{prop}}: {{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for interactive elements in policy `{{policy}}`.",
@@ -39329,28 +39260,54 @@ var INLINE_TOUCH_TARGET_KEYS = /* @__PURE__ */ new Set([
39329
39260
  "height",
39330
39261
  "min-height",
39331
39262
  "width",
39332
- "min-width",
39333
- "padding-left",
39334
- "padding-right",
39335
- "padding-inline",
39336
- "padding-inline-start",
39337
- "padding-inline-end"
39263
+ "min-width"
39338
39264
  ]);
39265
+ var INTERACTIVE_HTML_TAGS = /* @__PURE__ */ new Set(["button", "a", "input", "select", "textarea", "label", "summary"]);
39266
+ var INTERACTIVE_ARIA_ROLES = /* @__PURE__ */ new Set([
39267
+ "button",
39268
+ "link",
39269
+ "checkbox",
39270
+ "radio",
39271
+ "combobox",
39272
+ "listbox",
39273
+ "menuitem",
39274
+ "menuitemcheckbox",
39275
+ "menuitemradio",
39276
+ "option",
39277
+ "switch",
39278
+ "tab"
39279
+ ]);
39280
+ function isInteractiveElement(solid, element, hostElementRef) {
39281
+ if (element.tagName !== null && INTERACTIVE_HTML_TAGS.has(element.tagName)) return true;
39282
+ const roleAttr = getJSXAttributeEntity(solid, element, "role");
39283
+ if (roleAttr !== null && roleAttr.valueNode !== null) {
39284
+ const role = getStaticStringFromJSXValue(roleAttr.valueNode);
39285
+ if (role !== null && INTERACTIVE_ARIA_ROLES.has(role)) return true;
39286
+ }
39287
+ if (hostElementRef !== null && hostElementRef.element.tagName !== null) {
39288
+ if (INTERACTIVE_HTML_TAGS.has(hostElementRef.element.tagName)) return true;
39289
+ }
39290
+ return false;
39291
+ }
39292
+ function readNodeHostElementRef(layout, solid, element) {
39293
+ const node = layout.elementBySolidFileAndId.get(solid.file)?.get(element.id) ?? null;
39294
+ return node !== null ? readHostElementRef(layout, node) : null;
39295
+ }
39339
39296
  var jsxStylePolicy = defineCrossRule({
39340
39297
  id: "jsx-style-policy",
39341
39298
  severity: "warn",
39342
- messages: messages142,
39299
+ messages: messages141,
39343
39300
  meta: {
39344
39301
  description: "Enforce accessibility policy thresholds on inline JSX style objects.",
39345
39302
  fixable: false,
39346
39303
  category: "css-jsx"
39347
39304
  },
39348
39305
  check(context, emit) {
39349
- const { solids } = context;
39306
+ const { solids, layout } = context;
39350
39307
  const policy = getActivePolicy();
39351
39308
  if (policy === null) return;
39352
39309
  const name = getActivePolicyName() ?? "";
39353
- forEachStylePropertyAcross(solids, (solid, p) => {
39310
+ forEachStylePropertyAcross(solids, (solid, p, element) => {
39354
39311
  if (!import_typescript135.default.isPropertyAssignment(p)) return;
39355
39312
  const key = objectKeyName(p.name);
39356
39313
  if (!key) return;
@@ -39366,7 +39323,7 @@ var jsxStylePolicy = defineCrossRule({
39366
39323
  solid.sourceFile,
39367
39324
  jsxStylePolicy.id,
39368
39325
  "fontTooSmall",
39369
- resolveMessage(messages142.fontTooSmall, {
39326
+ resolveMessage(messages141.fontTooSmall, {
39370
39327
  prop: key,
39371
39328
  value: strVal,
39372
39329
  resolved: formatRounded(px),
@@ -39388,7 +39345,7 @@ var jsxStylePolicy = defineCrossRule({
39388
39345
  solid.sourceFile,
39389
39346
  jsxStylePolicy.id,
39390
39347
  "lineHeightTooSmall",
39391
- resolveMessage(messages142.lineHeightTooSmall, {
39348
+ resolveMessage(messages141.lineHeightTooSmall, {
39392
39349
  value: String(lh),
39393
39350
  min: String(policy.minLineHeight),
39394
39351
  policy: name
@@ -39398,6 +39355,8 @@ var jsxStylePolicy = defineCrossRule({
39398
39355
  return;
39399
39356
  }
39400
39357
  if (INLINE_TOUCH_TARGET_KEYS.has(normalizedKey)) {
39358
+ const hostRef = readNodeHostElementRef(layout, solid, element);
39359
+ if (!isInteractiveElement(solid, element, hostRef)) return;
39401
39360
  const strVal = getStaticStringValue(p.initializer);
39402
39361
  if (!strVal) return;
39403
39362
  const px = parsePxValue(strVal);
@@ -39410,7 +39369,7 @@ var jsxStylePolicy = defineCrossRule({
39410
39369
  solid.sourceFile,
39411
39370
  jsxStylePolicy.id,
39412
39371
  "heightTooSmall",
39413
- resolveMessage(messages142.heightTooSmall, {
39372
+ resolveMessage(messages141.heightTooSmall, {
39414
39373
  prop: key,
39415
39374
  value: strVal,
39416
39375
  resolved: formatRounded(px),
@@ -39432,7 +39391,7 @@ var jsxStylePolicy = defineCrossRule({
39432
39391
  solid.sourceFile,
39433
39392
  jsxStylePolicy.id,
39434
39393
  "letterSpacingTooSmall",
39435
- resolveMessage(messages142.letterSpacingTooSmall, {
39394
+ resolveMessage(messages141.letterSpacingTooSmall, {
39436
39395
  value: strVal,
39437
39396
  resolved: String(em),
39438
39397
  min: String(policy.minLetterSpacing),
@@ -39453,7 +39412,7 @@ var jsxStylePolicy = defineCrossRule({
39453
39412
  solid.sourceFile,
39454
39413
  jsxStylePolicy.id,
39455
39414
  "wordSpacingTooSmall",
39456
- resolveMessage(messages142.wordSpacingTooSmall, {
39415
+ resolveMessage(messages141.wordSpacingTooSmall, {
39457
39416
  value: strVal,
39458
39417
  resolved: String(em),
39459
39418
  min: String(policy.minWordSpacing),
@@ -39467,7 +39426,7 @@ var jsxStylePolicy = defineCrossRule({
39467
39426
  });
39468
39427
 
39469
39428
  // src/cross-file/rules/css-layout-sibling-alignment-outlier.ts
39470
- var messages143 = {
39429
+ var messages142 = {
39471
39430
  misalignedSibling: "Vertically misaligned '{{subject}}' in '{{parent}}'.{{fix}}{{offsetClause}}"
39472
39431
  };
39473
39432
  var MIN_CONFIDENCE_THRESHOLD = 0.48;
@@ -39476,7 +39435,7 @@ var siblingAlignmentDetector = {
39476
39435
  id: "sibling-alignment-outlier",
39477
39436
  collect: collectAlignmentCases,
39478
39437
  evaluate(input, context) {
39479
- if (context.logger.enabled) {
39438
+ if (context.logger.isLevelEnabled(Level.Trace)) {
39480
39439
  const ctx = input.context;
39481
39440
  context.logger.trace(
39482
39441
  `[sibling-alignment] evaluate subject=${input.subject.elementKey} tag=${input.subject.tag} parent=${ctx.parentElementKey} parentTag=${ctx.parentTag} context.kind=${ctx.kind} certainty=${ctx.certainty} display=${ctx.parentDisplay} alignItems=${ctx.parentAlignItems} crossAxisIsBlockAxis=${ctx.crossAxisIsBlockAxis} crossAxisCertainty=${ctx.crossAxisIsBlockAxisCertainty} baseline=${ctx.baselineRelevance}`
@@ -39515,7 +39474,7 @@ var siblingAlignmentDetector = {
39515
39474
  var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
39516
39475
  id: "css-layout-sibling-alignment-outlier",
39517
39476
  severity: "warn",
39518
- messages: messages143,
39477
+ messages: messages142,
39519
39478
  meta: {
39520
39479
  description: "Detect vertical alignment outliers between sibling elements in shared layout containers.",
39521
39480
  fixable: false,
@@ -39525,7 +39484,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
39525
39484
  const log = context.logger;
39526
39485
  const detections = runLayoutDetector(context, siblingAlignmentDetector);
39527
39486
  const uniqueDetections = dedupeDetectionsBySubject(detections);
39528
- if (log.enabled) {
39487
+ if (log.isLevelEnabled(Level.Debug)) {
39529
39488
  log.debug(
39530
39489
  `[sibling-alignment] raw=${detections.length} deduped=${uniqueDetections.length}`
39531
39490
  );
@@ -39539,7 +39498,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
39539
39498
  const subjectId = detection.caseData.subject.elementId;
39540
39499
  const logPrefix = `[sibling-alignment] <${subjectTag}> in <${parentTag}> (${subjectFile}#${subjectId})`;
39541
39500
  if (detection.evidence.confidence < MIN_CONFIDENCE_THRESHOLD) {
39542
- if (log.enabled) {
39501
+ if (log.isLevelEnabled(Level.Debug)) {
39543
39502
  log.debug(
39544
39503
  `${logPrefix} SKIP: confidence=${detection.evidence.confidence.toFixed(2)} < threshold=${MIN_CONFIDENCE_THRESHOLD}`
39545
39504
  );
@@ -39548,7 +39507,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
39548
39507
  }
39549
39508
  const estimatedOffset = detection.evidence.estimatedOffsetPx;
39550
39509
  if (estimatedOffset !== null && Math.abs(estimatedOffset) < MIN_OFFSET_PX_THRESHOLD && !hasNonOffsetPrimaryEvidence(detection.evidence.topFactors)) {
39551
- if (log.enabled) {
39510
+ if (log.isLevelEnabled(Level.Debug)) {
39552
39511
  log.debug(
39553
39512
  `${logPrefix} SKIP: offset=${estimatedOffset.toFixed(2)}px < ${MIN_OFFSET_PX_THRESHOLD}px (no non-offset primary evidence, topFactors=[${detection.evidence.topFactors.join(",")}])`
39554
39513
  );
@@ -39560,7 +39519,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
39560
39519
  detection.caseData.cohort.parentElementKey,
39561
39520
  detection.caseData.subject.solidFile
39562
39521
  )) {
39563
- if (log.enabled) {
39522
+ if (log.isLevelEnabled(Level.Debug)) {
39564
39523
  log.debug(`${logPrefix} SKIP: out-of-flow ancestor`);
39565
39524
  }
39566
39525
  continue;
@@ -39571,7 +39530,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
39571
39530
  detection.caseData.subject.elementId
39572
39531
  );
39573
39532
  if (!subjectRef) {
39574
- if (log.enabled) {
39533
+ if (log.isLevelEnabled(Level.Debug)) {
39575
39534
  log.debug(`${logPrefix} SKIP: no node ref`);
39576
39535
  }
39577
39536
  continue;
@@ -39587,7 +39546,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
39587
39546
  const primaryFix = detection.evidence.primaryFix;
39588
39547
  const firstChar = primaryFix.length > 0 ? primaryFix[0] : void 0;
39589
39548
  const fix = firstChar !== void 0 ? ` ${firstChar.toUpperCase()}${primaryFix.slice(1)}.` : "";
39590
- if (log.enabled) {
39549
+ if (log.isLevelEnabled(Level.Debug)) {
39591
39550
  log.debug(
39592
39551
  `${logPrefix} EMIT: severity=${severity} confidence=${confidence} offset=${offset?.toFixed(2) ?? "null"} posterior=[${detection.evidence.posteriorLower.toFixed(3)},${detection.evidence.posteriorUpper.toFixed(3)}] evidenceMass=${detection.evidence.evidenceMass.toFixed(3)} topFactors=[${detection.evidence.topFactors.join(",")}] causes=[${causes}]`
39593
39552
  );
@@ -39599,7 +39558,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
39599
39558
  subjectRef.solid.sourceFile,
39600
39559
  cssLayoutSiblingAlignmentOutlier.id,
39601
39560
  "misalignedSibling",
39602
- resolveMessage(messages143.misalignedSibling, {
39561
+ resolveMessage(messages142.misalignedSibling, {
39603
39562
  subject,
39604
39563
  parent,
39605
39564
  fix,
@@ -39683,13 +39642,13 @@ function hasNonOffsetPrimaryEvidence(topFactors) {
39683
39642
  }
39684
39643
 
39685
39644
  // src/cross-file/rules/css-layout-transition-layout-property.ts
39686
- var messages144 = {
39645
+ var messages143 = {
39687
39646
  transitionLayoutProperty: "Transition '{{property}}' in '{{declaration}}' animates layout-affecting geometry. Prefer transform/opacity to avoid CLS."
39688
39647
  };
39689
39648
  var cssLayoutTransitionLayoutProperty = defineCrossRule({
39690
39649
  id: "css-layout-transition-layout-property",
39691
39650
  severity: "warn",
39692
- messages: messages144,
39651
+ messages: messages143,
39693
39652
  meta: {
39694
39653
  description: "Disallow transitions that animate layout-affecting geometry properties.",
39695
39654
  fixable: false,
@@ -39713,7 +39672,7 @@ var cssLayoutTransitionLayoutProperty = defineCrossRule({
39713
39672
  },
39714
39673
  cssLayoutTransitionLayoutProperty.id,
39715
39674
  "transitionLayoutProperty",
39716
- resolveMessage(messages144.transitionLayoutProperty, {
39675
+ resolveMessage(messages143.transitionLayoutProperty, {
39717
39676
  property: target,
39718
39677
  declaration: declaration.property
39719
39678
  }),
@@ -39728,13 +39687,13 @@ function findLayoutTransitionTarget(raw) {
39728
39687
  }
39729
39688
 
39730
39689
  // src/cross-file/rules/css-layout-animation-layout-property.ts
39731
- var messages145 = {
39690
+ var messages144 = {
39732
39691
  animationLayoutProperty: "Animation '{{animation}}' mutates layout-affecting '{{property}}', which can trigger CLS. Prefer transform/opacity or reserve geometry."
39733
39692
  };
39734
39693
  var cssLayoutAnimationLayoutProperty = defineCrossRule({
39735
39694
  id: "css-layout-animation-layout-property",
39736
39695
  severity: "warn",
39737
- messages: messages145,
39696
+ messages: messages144,
39738
39697
  meta: {
39739
39698
  description: "Disallow keyframe animations that mutate layout-affecting properties and can trigger CLS.",
39740
39699
  fixable: false,
@@ -39762,7 +39721,7 @@ var cssLayoutAnimationLayoutProperty = defineCrossRule({
39762
39721
  },
39763
39722
  cssLayoutAnimationLayoutProperty.id,
39764
39723
  "animationLayoutProperty",
39765
- resolveMessage(messages145.animationLayoutProperty, {
39724
+ resolveMessage(messages144.animationLayoutProperty, {
39766
39725
  animation: match.name,
39767
39726
  property: match.property
39768
39727
  }),
@@ -39832,13 +39791,13 @@ function firstRiskyAnimationName(names, riskyKeyframes) {
39832
39791
  }
39833
39792
 
39834
39793
  // src/cross-file/rules/css-layout-stateful-box-model-shift.ts
39835
- var messages146 = {
39794
+ var messages145 = {
39836
39795
  statefulBoxModelShift: "State selector '{{selector}}' changes layout-affecting '{{property}}'. Keep geometry stable across states to avoid CLS."
39837
39796
  };
39838
39797
  var cssLayoutStatefulBoxModelShift = defineCrossRule({
39839
39798
  id: "css-layout-stateful-box-model-shift",
39840
39799
  severity: "warn",
39841
- messages: messages146,
39800
+ messages: messages145,
39842
39801
  meta: {
39843
39802
  description: "Disallow stateful selector changes that alter element geometry and trigger layout shifts.",
39844
39803
  fixable: false,
@@ -39879,7 +39838,7 @@ var cssLayoutStatefulBoxModelShift = defineCrossRule({
39879
39838
  },
39880
39839
  cssLayoutStatefulBoxModelShift.id,
39881
39840
  "statefulBoxModelShift",
39882
- resolveMessage(messages146.statefulBoxModelShift, {
39841
+ resolveMessage(messages145.statefulBoxModelShift, {
39883
39842
  selector: match.raw,
39884
39843
  property: declaration.property
39885
39844
  }),
@@ -39973,14 +39932,14 @@ function lookupBaseByProperty(baseValueIndex, selectorKeys) {
39973
39932
 
39974
39933
  // src/cross-file/rules/css-layout-unsized-replaced-element.ts
39975
39934
  var import_typescript136 = __toESM(require("typescript"), 1);
39976
- var messages147 = {
39935
+ var messages146 = {
39977
39936
  unsizedReplacedElement: "Replaced element '{{tag}}' has no stable reserved size (width/height or aspect-ratio with a dimension), which can cause CLS."
39978
39937
  };
39979
39938
  var REPLACED_MEDIA_TAGS = /* @__PURE__ */ new Set(["img", "video", "iframe", "canvas", "svg"]);
39980
39939
  var cssLayoutUnsizedReplacedElement = defineCrossRule({
39981
39940
  id: "css-layout-unsized-replaced-element",
39982
39941
  severity: "warn",
39983
- messages: messages147,
39942
+ messages: messages146,
39984
39943
  meta: {
39985
39944
  description: "Require stable reserved geometry for replaced media elements to prevent layout shifts.",
39986
39945
  fixable: false,
@@ -39996,7 +39955,8 @@ var cssLayoutUnsizedReplacedElement = defineCrossRule({
39996
39955
  const ref = readNodeRef(context.layout, node);
39997
39956
  if (!ref) continue;
39998
39957
  const reservedSpace = readReservedSpaceFact(context.layout, node);
39999
- if (hasReservedSize(ref.solid, node.attributes, ref.element, reservedSpace)) continue;
39958
+ const hostRef = readHostElementRef(context.layout, node);
39959
+ if (hasReservedSize(ref.solid, node.attributes, ref.element, reservedSpace, hostRef)) continue;
40000
39960
  emit(
40001
39961
  createDiagnostic(
40002
39962
  ref.solid.file,
@@ -40004,22 +39964,24 @@ var cssLayoutUnsizedReplacedElement = defineCrossRule({
40004
39964
  ref.solid.sourceFile,
40005
39965
  cssLayoutUnsizedReplacedElement.id,
40006
39966
  "unsizedReplacedElement",
40007
- resolveMessage(messages147.unsizedReplacedElement, { tag }),
39967
+ resolveMessage(messages146.unsizedReplacedElement, { tag }),
40008
39968
  "warn"
40009
39969
  )
40010
39970
  );
40011
39971
  }
40012
39972
  }
40013
39973
  });
40014
- function hasReservedSize(solid, attributes, element, reservedSpaceFact) {
39974
+ function hasReservedSize(solid, attributes, element, reservedSpaceFact, hostElementRef) {
40015
39975
  if (reservedSpaceFact.hasReservedSpace) return true;
40016
39976
  const attrWidth = parsePositiveLength(attributes.get("width"));
40017
39977
  const attrHeight = parsePositiveLength(attributes.get("height"));
40018
39978
  const jsxAttrWidth = readPositiveJsxAttribute(solid, element, "width");
40019
39979
  const jsxAttrHeight = readPositiveJsxAttribute(solid, element, "height");
40020
- if (attrWidth && attrHeight || jsxAttrWidth && jsxAttrHeight) return true;
40021
- const hasAnyWidth = attrWidth || jsxAttrWidth || reservedSpaceFact.hasUsableInlineDimension;
40022
- const hasAnyHeight = attrHeight || jsxAttrHeight || reservedSpaceFact.hasUsableBlockDimension || reservedSpaceFact.hasContainIntrinsicSize;
39980
+ const hostJsxWidth = hostElementRef !== null ? readPositiveJsxAttribute(hostElementRef.solid, hostElementRef.element, "width") : false;
39981
+ const hostJsxHeight = hostElementRef !== null ? readPositiveJsxAttribute(hostElementRef.solid, hostElementRef.element, "height") : false;
39982
+ if (attrWidth && attrHeight || jsxAttrWidth && jsxAttrHeight || hostJsxWidth && hostJsxHeight) return true;
39983
+ const hasAnyWidth = attrWidth || jsxAttrWidth || hostJsxWidth || reservedSpaceFact.hasUsableInlineDimension;
39984
+ const hasAnyHeight = attrHeight || jsxAttrHeight || hostJsxHeight || reservedSpaceFact.hasUsableBlockDimension || reservedSpaceFact.hasContainIntrinsicSize;
40023
39985
  if (reservedSpaceFact.hasUsableAspectRatio && (hasAnyWidth || hasAnyHeight)) return true;
40024
39986
  if (reservedSpaceFact.hasContainIntrinsicSize && (hasAnyWidth || hasAnyHeight)) return true;
40025
39987
  return false;
@@ -40055,7 +40017,7 @@ function readPositiveJsxAttribute(solid, element, name) {
40055
40017
  }
40056
40018
 
40057
40019
  // src/cross-file/rules/css-layout-dynamic-slot-no-reserved-space.ts
40058
- var messages148 = {
40020
+ var messages147 = {
40059
40021
  dynamicSlotNoReservedSpace: "Dynamic content container '{{tag}}' does not reserve block space (min-height/height/aspect-ratio/contain-intrinsic-size), which can cause CLS."
40060
40022
  };
40061
40023
  var INLINE_DISPLAYS = /* @__PURE__ */ new Set(["inline", "contents"]);
@@ -40077,7 +40039,7 @@ function hasOutOfFlowAncestor(layout, node) {
40077
40039
  var cssLayoutDynamicSlotNoReservedSpace = defineCrossRule({
40078
40040
  id: "css-layout-dynamic-slot-no-reserved-space",
40079
40041
  severity: "warn",
40080
- messages: messages148,
40042
+ messages: messages147,
40081
40043
  meta: {
40082
40044
  description: "Require reserved block space for dynamic content containers to avoid layout shifts.",
40083
40045
  fixable: false,
@@ -40100,19 +40062,19 @@ var cssLayoutDynamicSlotNoReservedSpace = defineCrossRule({
40100
40062
  const reservedSpace = readReservedSpaceFact(context.layout, node);
40101
40063
  if (reservedSpace.hasReservedSpace) continue;
40102
40064
  if (hasBlockAxisPadding(snapshot)) continue;
40103
- if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutDynamicSlotNoReservedSpace.id, "dynamicSlotNoReservedSpace", messages148.dynamicSlotNoReservedSpace, cssLayoutDynamicSlotNoReservedSpace.severity)) continue;
40065
+ if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutDynamicSlotNoReservedSpace.id, "dynamicSlotNoReservedSpace", messages147.dynamicSlotNoReservedSpace, cssLayoutDynamicSlotNoReservedSpace.severity)) continue;
40104
40066
  }
40105
40067
  }
40106
40068
  });
40107
40069
 
40108
40070
  // src/cross-file/rules/css-layout-scrollbar-gutter-instability.ts
40109
- var messages149 = {
40071
+ var messages148 = {
40110
40072
  missingScrollbarGutter: "Scrollable container '{{tag}}' uses overflow auto/scroll without `scrollbar-gutter: stable`, which can trigger CLS when scrollbars appear."
40111
40073
  };
40112
40074
  var cssLayoutScrollbarGutterInstability = defineCrossRule({
40113
40075
  id: "css-layout-scrollbar-gutter-instability",
40114
40076
  severity: "warn",
40115
- messages: messages149,
40077
+ messages: messages148,
40116
40078
  meta: {
40117
40079
  description: "Require stable scrollbar gutters for scrollable containers to reduce layout shifts.",
40118
40080
  fixable: false,
@@ -40131,19 +40093,19 @@ var cssLayoutScrollbarGutterInstability = defineCrossRule({
40131
40093
  if (scrollbarWidth === "none") continue;
40132
40094
  const gutter = readKnownNormalized(snapshot, "scrollbar-gutter");
40133
40095
  if (gutter !== null && gutter.startsWith("stable")) continue;
40134
- if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutScrollbarGutterInstability.id, "missingScrollbarGutter", messages149.missingScrollbarGutter, cssLayoutScrollbarGutterInstability.severity)) continue;
40096
+ if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutScrollbarGutterInstability.id, "missingScrollbarGutter", messages148.missingScrollbarGutter, cssLayoutScrollbarGutterInstability.severity)) continue;
40135
40097
  }
40136
40098
  }
40137
40099
  });
40138
40100
 
40139
40101
  // src/cross-file/rules/css-layout-overflow-anchor-instability.ts
40140
- var messages150 = {
40102
+ var messages149 = {
40141
40103
  unstableOverflowAnchor: "Element '{{tag}}' sets `overflow-anchor: none` on a {{context}} container; disabling scroll anchoring can amplify visible layout shifts."
40142
40104
  };
40143
40105
  var cssLayoutOverflowAnchorInstability = defineCrossRule({
40144
40106
  id: "css-layout-overflow-anchor-instability",
40145
40107
  severity: "warn",
40146
- messages: messages150,
40108
+ messages: messages149,
40147
40109
  meta: {
40148
40110
  description: "Disallow overflow-anchor none on dynamic or scrollable containers prone to visible layout shifts.",
40149
40111
  fixable: false,
@@ -40161,20 +40123,20 @@ var cssLayoutOverflowAnchorInstability = defineCrossRule({
40161
40123
  const isDynamicContainer = isDynamicContainerLike(node);
40162
40124
  if (!isScrollable && !isDynamicContainer) continue;
40163
40125
  const containerContext = isScrollable ? "scrollable" : "dynamic";
40164
- if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutOverflowAnchorInstability.id, "unstableOverflowAnchor", messages150.unstableOverflowAnchor, cssLayoutOverflowAnchorInstability.severity, { context: containerContext })) continue;
40126
+ if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutOverflowAnchorInstability.id, "unstableOverflowAnchor", messages149.unstableOverflowAnchor, cssLayoutOverflowAnchorInstability.severity, { context: containerContext })) continue;
40165
40127
  }
40166
40128
  }
40167
40129
  });
40168
40130
 
40169
40131
  // src/cross-file/rules/css-layout-font-swap-instability.ts
40170
- var messages151 = {
40132
+ var messages150 = {
40171
40133
  unstableFontSwap: "`@font-face` for '{{family}}' uses `font-display: {{display}}` without metric overrides (for example `size-adjust`), which can cause CLS when the webfont swaps in."
40172
40134
  };
40173
40135
  var SWAP_DISPLAYS = /* @__PURE__ */ new Set(["swap", "fallback"]);
40174
40136
  var cssLayoutFontSwapInstability = defineCrossRule({
40175
40137
  id: "css-layout-font-swap-instability",
40176
40138
  severity: "warn",
40177
- messages: messages151,
40139
+ messages: messages150,
40178
40140
  meta: {
40179
40141
  description: "Require metric overrides for swapping webfonts to reduce layout shifts during font load.",
40180
40142
  fixable: false,
@@ -40221,7 +40183,7 @@ var cssLayoutFontSwapInstability = defineCrossRule({
40221
40183
  },
40222
40184
  cssLayoutFontSwapInstability.id,
40223
40185
  "unstableFontSwap",
40224
- resolveMessage(messages151.unstableFontSwap, {
40186
+ resolveMessage(messages150.unstableFontSwap, {
40225
40187
  family,
40226
40188
  display: report.display
40227
40189
  }),
@@ -40234,14 +40196,14 @@ var cssLayoutFontSwapInstability = defineCrossRule({
40234
40196
  });
40235
40197
 
40236
40198
  // src/cross-file/rules/css-layout-conditional-display-collapse.ts
40237
- var messages152 = {
40199
+ var messages151 = {
40238
40200
  conditionalDisplayCollapse: "Conditional display sets '{{display}}' on '{{tag}}' without stable reserved space, which can collapse/expand layout and cause CLS."
40239
40201
  };
40240
40202
  var COLLAPSING_DISPLAYS = /* @__PURE__ */ new Set(["none", "contents"]);
40241
40203
  var cssLayoutConditionalDisplayCollapse = defineCrossRule({
40242
40204
  id: "css-layout-conditional-display-collapse",
40243
40205
  severity: "warn",
40244
- messages: messages152,
40206
+ messages: messages151,
40245
40207
  meta: {
40246
40208
  description: "Disallow conditional display collapse in flow without reserved geometry.",
40247
40209
  fixable: false,
@@ -40262,13 +40224,13 @@ var cssLayoutConditionalDisplayCollapse = defineCrossRule({
40262
40224
  if (!isFlowRelevantBySiblingsOrText(node, snapshot.node.textualContent)) continue;
40263
40225
  const reservedSpace = readReservedSpaceFact(context.layout, node);
40264
40226
  if (reservedSpace.hasReservedSpace) continue;
40265
- if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutConditionalDisplayCollapse.id, "conditionalDisplayCollapse", messages152.conditionalDisplayCollapse, cssLayoutConditionalDisplayCollapse.severity, { display })) continue;
40227
+ if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutConditionalDisplayCollapse.id, "conditionalDisplayCollapse", messages151.conditionalDisplayCollapse, cssLayoutConditionalDisplayCollapse.severity, { display })) continue;
40266
40228
  }
40267
40229
  }
40268
40230
  });
40269
40231
 
40270
40232
  // src/cross-file/rules/css-layout-conditional-white-space-wrap-shift.ts
40271
- var messages153 = {
40233
+ var messages152 = {
40272
40234
  conditionalWhiteSpaceShift: "Conditional white-space '{{whiteSpace}}' on '{{tag}}' can reflow text and shift siblings; keep wrapping behavior stable or reserve geometry."
40273
40235
  };
40274
40236
  var WRAP_SHIFT_VALUES = /* @__PURE__ */ new Set(["nowrap", "pre"]);
@@ -40277,7 +40239,7 @@ var BLOCK_SIZE_PROPERTIES = ["height", "min-height"];
40277
40239
  var cssLayoutConditionalWhiteSpaceWrapShift = defineCrossRule({
40278
40240
  id: "css-layout-conditional-white-space-wrap-shift",
40279
40241
  severity: "warn",
40280
- messages: messages153,
40242
+ messages: messages152,
40281
40243
  meta: {
40282
40244
  description: "Disallow conditional white-space wrapping mode toggles that can trigger CLS.",
40283
40245
  fixable: false,
@@ -40300,7 +40262,7 @@ var cssLayoutConditionalWhiteSpaceWrapShift = defineCrossRule({
40300
40262
  if (!flow.inFlow) continue;
40301
40263
  if (!isFlowRelevantBySiblingsOrText(node, snapshot.node.textualContent)) continue;
40302
40264
  if (hasStableTextShell(snapshot)) continue;
40303
- if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutConditionalWhiteSpaceWrapShift.id, "conditionalWhiteSpaceShift", messages153.conditionalWhiteSpaceShift, cssLayoutConditionalWhiteSpaceWrapShift.severity, { whiteSpace })) continue;
40265
+ if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutConditionalWhiteSpaceWrapShift.id, "conditionalWhiteSpaceShift", messages152.conditionalWhiteSpaceShift, cssLayoutConditionalWhiteSpaceWrapShift.severity, { whiteSpace })) continue;
40304
40266
  }
40305
40267
  }
40306
40268
  });
@@ -40322,13 +40284,13 @@ function hasWrapShiftDelta(delta) {
40322
40284
  }
40323
40285
 
40324
40286
  // src/cross-file/rules/css-layout-overflow-mode-toggle-instability.ts
40325
- var messages154 = {
40287
+ var messages153 = {
40326
40288
  overflowModeToggle: "Conditional overflow mode changes scrolling ('{{overflow}}') on '{{tag}}' without `scrollbar-gutter: stable`, which can trigger CLS."
40327
40289
  };
40328
40290
  var cssLayoutOverflowModeToggleInstability = defineCrossRule({
40329
40291
  id: "css-layout-overflow-mode-toggle-instability",
40330
40292
  severity: "warn",
40331
- messages: messages154,
40293
+ messages: messages153,
40332
40294
  meta: {
40333
40295
  description: "Disallow conditional overflow mode switches that can introduce scrollbar-induced layout shifts.",
40334
40296
  fixable: false,
@@ -40353,7 +40315,7 @@ var cssLayoutOverflowModeToggleInstability = defineCrossRule({
40353
40315
  const gutter = readKnownNormalizedWithGuard(snapshot, "scrollbar-gutter");
40354
40316
  if (gutter !== null && gutter.startsWith("stable")) continue;
40355
40317
  const overflowValue = scrollFact.overflowY ?? scrollFact.overflow ?? "auto";
40356
- if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutOverflowModeToggleInstability.id, "overflowModeToggle", messages154.overflowModeToggle, cssLayoutOverflowModeToggleInstability.severity, { overflow: overflowValue })) continue;
40318
+ if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutOverflowModeToggleInstability.id, "overflowModeToggle", messages153.overflowModeToggle, cssLayoutOverflowModeToggleInstability.severity, { overflow: overflowValue })) continue;
40357
40319
  }
40358
40320
  }
40359
40321
  });
@@ -40373,7 +40335,7 @@ function hasAnyScrollValue(delta) {
40373
40335
  }
40374
40336
 
40375
40337
  // src/cross-file/rules/css-layout-box-sizing-toggle-with-chrome.ts
40376
- var messages155 = {
40338
+ var messages154 = {
40377
40339
  boxSizingToggleWithChrome: "Conditional `box-sizing` toggle on '{{tag}}' combines with non-zero padding/border, which can shift layout and trigger CLS."
40378
40340
  };
40379
40341
  var BOX_SIZING_VALUES = /* @__PURE__ */ new Set(["content-box", "border-box"]);
@@ -40390,7 +40352,7 @@ var CHROME_PROPERTIES = [
40390
40352
  var cssLayoutBoxSizingToggleWithChrome = defineCrossRule({
40391
40353
  id: "css-layout-box-sizing-toggle-with-chrome",
40392
40354
  severity: "warn",
40393
- messages: messages155,
40355
+ messages: messages154,
40394
40356
  meta: {
40395
40357
  description: "Disallow conditional box-sizing mode toggles when box chrome contributes to geometry shifts.",
40396
40358
  fixable: false,
@@ -40408,7 +40370,7 @@ var cssLayoutBoxSizingToggleWithChrome = defineCrossRule({
40408
40370
  if (!boxSizingDelta.hasConditional) continue;
40409
40371
  if (!boxSizingDelta.hasDelta) continue;
40410
40372
  if (!hasNonZeroChrome(snapshot)) continue;
40411
- if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutBoxSizingToggleWithChrome.id, "boxSizingToggleWithChrome", messages155.boxSizingToggleWithChrome, cssLayoutBoxSizingToggleWithChrome.severity)) continue;
40373
+ if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutBoxSizingToggleWithChrome.id, "boxSizingToggleWithChrome", messages154.boxSizingToggleWithChrome, cssLayoutBoxSizingToggleWithChrome.severity)) continue;
40412
40374
  }
40413
40375
  }
40414
40376
  });
@@ -40417,13 +40379,13 @@ function hasNonZeroChrome(snapshot) {
40417
40379
  }
40418
40380
 
40419
40381
  // src/cross-file/rules/css-layout-content-visibility-no-intrinsic-size.ts
40420
- var messages156 = {
40382
+ var messages155 = {
40421
40383
  missingIntrinsicSize: "`content-visibility: auto` on '{{tag}}' lacks intrinsic size reservation (`contain-intrinsic-size`/min-height/height/aspect-ratio), which can cause CLS."
40422
40384
  };
40423
40385
  var cssLayoutContentVisibilityNoIntrinsicSize = defineCrossRule({
40424
40386
  id: "css-layout-content-visibility-no-intrinsic-size",
40425
40387
  severity: "warn",
40426
- messages: messages156,
40388
+ messages: messages155,
40427
40389
  meta: {
40428
40390
  description: "Require intrinsic size reservation when using content-visibility auto to avoid late layout shifts.",
40429
40391
  fixable: false,
@@ -40438,19 +40400,19 @@ var cssLayoutContentVisibilityNoIntrinsicSize = defineCrossRule({
40438
40400
  if (!isDeferredContainerLike(node, snapshot.node.textualContent)) continue;
40439
40401
  const reservedSpace = readReservedSpaceFact(context.layout, node);
40440
40402
  if (reservedSpace.hasReservedSpace) continue;
40441
- if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutContentVisibilityNoIntrinsicSize.id, "missingIntrinsicSize", messages156.missingIntrinsicSize, cssLayoutContentVisibilityNoIntrinsicSize.severity)) continue;
40403
+ if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutContentVisibilityNoIntrinsicSize.id, "missingIntrinsicSize", messages155.missingIntrinsicSize, cssLayoutContentVisibilityNoIntrinsicSize.severity)) continue;
40442
40404
  }
40443
40405
  }
40444
40406
  });
40445
40407
 
40446
40408
  // src/cross-file/rules/css-layout-conditional-offset-shift.ts
40447
- var messages157 = {
40409
+ var messages156 = {
40448
40410
  conditionalOffsetShift: "Conditional style applies non-zero '{{property}}' offset ({{value}}), which can cause layout shifts when conditions toggle."
40449
40411
  };
40450
40412
  var cssLayoutConditionalOffsetShift = defineCrossRule({
40451
40413
  id: "css-layout-conditional-offset-shift",
40452
40414
  severity: "warn",
40453
- messages: messages157,
40415
+ messages: messages156,
40454
40416
  meta: {
40455
40417
  description: "Disallow conditional non-zero block-axis offsets that can trigger layout shifts.",
40456
40418
  fixable: false,
@@ -40476,7 +40438,7 @@ var cssLayoutConditionalOffsetShift = defineCrossRule({
40476
40438
  ref.solid.sourceFile,
40477
40439
  cssLayoutConditionalOffsetShift.id,
40478
40440
  "conditionalOffsetShift",
40479
- resolveMessage(messages157.conditionalOffsetShift, {
40441
+ resolveMessage(messages156.conditionalOffsetShift, {
40480
40442
  property: match.property,
40481
40443
  value: `${formatFixed(match.value)}px`
40482
40444
  }),
@@ -40537,7 +40499,7 @@ function hasStableBaseline(baselineBySignal, property, expectedPx) {
40537
40499
 
40538
40500
  // src/cross-file/rules/jsx-layout-unstable-style-toggle.ts
40539
40501
  var import_typescript137 = __toESM(require("typescript"), 1);
40540
- var messages158 = {
40502
+ var messages157 = {
40541
40503
  unstableLayoutStyleToggle: "Dynamic style value for '{{property}}' can toggle layout geometry at runtime and cause CLS."
40542
40504
  };
40543
40505
  var PX_NUMBER_PROPERTIES = /* @__PURE__ */ new Set([
@@ -40560,7 +40522,7 @@ var POSITIONED_OFFSET_PROPERTIES = /* @__PURE__ */ new Set([
40560
40522
  var jsxLayoutUnstableStyleToggle = defineCrossRule({
40561
40523
  id: "jsx-layout-unstable-style-toggle",
40562
40524
  severity: "warn",
40563
- messages: messages158,
40525
+ messages: messages157,
40564
40526
  meta: {
40565
40527
  description: "Flag dynamic inline style values on layout-sensitive properties that can trigger CLS.",
40566
40528
  fixable: false,
@@ -40582,7 +40544,7 @@ var jsxLayoutUnstableStyleToggle = defineCrossRule({
40582
40544
  solid.sourceFile,
40583
40545
  jsxLayoutUnstableStyleToggle.id,
40584
40546
  "unstableLayoutStyleToggle",
40585
- resolveMessage(messages158.unstableLayoutStyleToggle, { property: normalized }),
40547
+ resolveMessage(messages157.unstableLayoutStyleToggle, { property: normalized }),
40586
40548
  "warn"
40587
40549
  )
40588
40550
  );
@@ -40699,14 +40661,14 @@ function unwrapTypeWrapper(node) {
40699
40661
 
40700
40662
  // src/cross-file/rules/jsx-layout-classlist-geometry-toggle.ts
40701
40663
  var import_typescript138 = __toESM(require("typescript"), 1);
40702
- var messages159 = {
40664
+ var messages158 = {
40703
40665
  classListGeometryToggle: "classList toggles '{{className}}', and matching CSS changes layout-affecting '{{property}}', which can cause CLS."
40704
40666
  };
40705
40667
  var OUT_OF_FLOW_POSITIONS2 = /* @__PURE__ */ new Set(["fixed", "absolute"]);
40706
40668
  var jsxLayoutClasslistGeometryToggle = defineCrossRule({
40707
40669
  id: "jsx-layout-classlist-geometry-toggle",
40708
40670
  severity: "warn",
40709
- messages: messages159,
40671
+ messages: messages158,
40710
40672
  meta: {
40711
40673
  description: "Flag classList-driven class toggles that map to layout-affecting CSS geometry changes.",
40712
40674
  fixable: false,
@@ -40732,7 +40694,7 @@ var jsxLayoutClasslistGeometryToggle = defineCrossRule({
40732
40694
  solid.sourceFile,
40733
40695
  jsxLayoutClasslistGeometryToggle.id,
40734
40696
  "classListGeometryToggle",
40735
- resolveMessage(messages159.classListGeometryToggle, {
40697
+ resolveMessage(messages158.classListGeometryToggle, {
40736
40698
  className,
40737
40699
  property
40738
40700
  }),
@@ -40781,14 +40743,14 @@ function isDynamicallyToggleable(node) {
40781
40743
  }
40782
40744
 
40783
40745
  // src/cross-file/rules/jsx-layout-picture-source-ratio-consistency.ts
40784
- var messages160 = {
40746
+ var messages159 = {
40785
40747
  inconsistentPictureRatio: "`<picture>` source ratio {{sourceRatio}} differs from fallback img ratio {{imgRatio}}, which can cause reserved-space mismatch and CLS."
40786
40748
  };
40787
40749
  var RATIO_DELTA_THRESHOLD = 0.02;
40788
40750
  var jsxLayoutPictureSourceRatioConsistency = defineCrossRule({
40789
40751
  id: "jsx-layout-picture-source-ratio-consistency",
40790
40752
  severity: "warn",
40791
- messages: messages160,
40753
+ messages: messages159,
40792
40754
  meta: {
40793
40755
  description: "Require consistent intrinsic aspect ratios across <picture> sources and fallback image.",
40794
40756
  fixable: false,
@@ -40811,7 +40773,7 @@ var jsxLayoutPictureSourceRatioConsistency = defineCrossRule({
40811
40773
  solid.sourceFile,
40812
40774
  jsxLayoutPictureSourceRatioConsistency.id,
40813
40775
  "inconsistentPictureRatio",
40814
- resolveMessage(messages160.inconsistentPictureRatio, {
40776
+ resolveMessage(messages159.inconsistentPictureRatio, {
40815
40777
  sourceRatio: mismatch.sourceRatio,
40816
40778
  imgRatio: mismatch.imgRatio
40817
40779
  }),
@@ -40881,13 +40843,13 @@ function formatRatio(value2) {
40881
40843
  }
40882
40844
 
40883
40845
  // src/cross-file/rules/jsx-layout-fill-image-parent-must-be-sized.ts
40884
- var messages161 = {
40846
+ var messages160 = {
40885
40847
  unsizedFillParent: "Fill-image component '{{component}}' is inside a parent without stable size/position; add parent sizing (height/min-height/aspect-ratio) and non-static position to avoid CLS."
40886
40848
  };
40887
40849
  var jsxLayoutFillImageParentMustBeSized = defineCrossRule({
40888
40850
  id: "jsx-layout-fill-image-parent-must-be-sized",
40889
40851
  severity: "warn",
40890
- messages: messages161,
40852
+ messages: messages160,
40891
40853
  meta: {
40892
40854
  description: "Require stable parent size and positioning for fill-image component usage.",
40893
40855
  fixable: false,
@@ -40917,7 +40879,7 @@ var jsxLayoutFillImageParentMustBeSized = defineCrossRule({
40917
40879
  solid.sourceFile,
40918
40880
  jsxLayoutFillImageParentMustBeSized.id,
40919
40881
  "unsizedFillParent",
40920
- resolveMessage(messages161.unsizedFillParent, {
40882
+ resolveMessage(messages160.unsizedFillParent, {
40921
40883
  component: element.tag ?? "Image"
40922
40884
  }),
40923
40885
  "warn"
@@ -40928,6 +40890,210 @@ var jsxLayoutFillImageParentMustBeSized = defineCrossRule({
40928
40890
  }
40929
40891
  });
40930
40892
 
40893
+ // src/cross-file/rules/jsx-layout-policy-touch-target.ts
40894
+ var messages161 = {
40895
+ heightTooSmall: "`{{signal}}` of `{{value}}px` is below the minimum `{{min}}px` for interactive element `<{{tag}}>` in policy `{{policy}}`.",
40896
+ widthTooSmall: "`{{signal}}` of `{{value}}px` is below the minimum `{{min}}px` for interactive element `<{{tag}}>` in policy `{{policy}}`.",
40897
+ paddingTooSmall: "Horizontal padding `{{signal}}` of `{{value}}px` is below the minimum `{{min}}px` for interactive element `<{{tag}}>` in policy `{{policy}}`.",
40898
+ noReservedBlockSize: "Interactive element `<{{tag}}>` has no declared height (minimum `{{min}}px` required by policy `{{policy}}`). The element is content-sized and may not meet the touch-target threshold.",
40899
+ noReservedInlineSize: "Interactive element `<{{tag}}>` has no declared width (minimum `{{min}}px` required by policy `{{policy}}`). The element is content-sized and may not meet the touch-target threshold."
40900
+ };
40901
+ var INTERACTIVE_HTML_TAGS2 = /* @__PURE__ */ new Set(["button", "a", "input", "select", "textarea", "label", "summary"]);
40902
+ var INTERACTIVE_ARIA_ROLES2 = /* @__PURE__ */ new Set([
40903
+ "button",
40904
+ "link",
40905
+ "checkbox",
40906
+ "radio",
40907
+ "combobox",
40908
+ "listbox",
40909
+ "menuitem",
40910
+ "menuitemcheckbox",
40911
+ "menuitemradio",
40912
+ "option",
40913
+ "switch",
40914
+ "tab"
40915
+ ]);
40916
+ function classifyInteractive(node, solid, element, layout) {
40917
+ const tag = node.tagName;
40918
+ if (tag !== null && INTERACTIVE_HTML_TAGS2.has(tag)) {
40919
+ if (tag === "input" || tag === "select" || tag === "textarea") return "input";
40920
+ return "button";
40921
+ }
40922
+ const roleAttr = getJSXAttributeEntity(solid, element, "role");
40923
+ if (roleAttr !== null && roleAttr.valueNode !== null) {
40924
+ const role = getStaticStringFromJSXValue(roleAttr.valueNode);
40925
+ if (role !== null && INTERACTIVE_ARIA_ROLES2.has(role)) return "button";
40926
+ }
40927
+ const hostRef = layout.hostElementRefsByNode.get(node) ?? null;
40928
+ if (hostRef !== null && hostRef.element.tagName !== null) {
40929
+ const hostTag = hostRef.element.tagName;
40930
+ if (INTERACTIVE_HTML_TAGS2.has(hostTag)) {
40931
+ if (hostTag === "input" || hostTag === "select" || hostTag === "textarea") return "input";
40932
+ return "button";
40933
+ }
40934
+ }
40935
+ return null;
40936
+ }
40937
+ function isVisuallyHidden(snapshot) {
40938
+ const position = readKnownNormalized(snapshot, "position");
40939
+ if (position !== "absolute" && position !== "fixed") return false;
40940
+ const node = snapshot.node;
40941
+ const opacityAttr = node.inlineStyleValues.get("opacity");
40942
+ if (opacityAttr === "0") return true;
40943
+ if (node.classTokenSet.has("opacity-0")) return true;
40944
+ return false;
40945
+ }
40946
+ var jsxLayoutPolicyTouchTarget = defineCrossRule({
40947
+ id: "jsx-layout-policy-touch-target",
40948
+ severity: "warn",
40949
+ messages: messages161,
40950
+ meta: {
40951
+ description: "Enforce minimum interactive element sizes per accessibility policy via resolved layout signals.",
40952
+ fixable: false,
40953
+ category: "css-a11y"
40954
+ },
40955
+ check(context, emit) {
40956
+ const policy = getActivePolicy();
40957
+ if (policy === null) return;
40958
+ const policyName = getActivePolicyName() ?? "";
40959
+ const { layout } = context;
40960
+ const elements = layout.elements;
40961
+ for (let i = 0; i < elements.length; i++) {
40962
+ const node = elements[i];
40963
+ if (!node) continue;
40964
+ const ref = readElementRef(layout, node);
40965
+ if (!ref) continue;
40966
+ const kind = classifyInteractive(node, ref.solid, ref.element, layout);
40967
+ if (kind === null) continue;
40968
+ const snapshot = collectSignalSnapshot(context, node);
40969
+ if (isVisuallyHidden(snapshot)) continue;
40970
+ const tag = node.tagName ?? node.tag ?? "element";
40971
+ checkDimension(
40972
+ snapshot,
40973
+ "height",
40974
+ kind === "button" ? policy.minButtonHeight : policy.minInputHeight,
40975
+ layout,
40976
+ node,
40977
+ emit,
40978
+ "heightTooSmall",
40979
+ messages161.heightTooSmall,
40980
+ tag,
40981
+ policyName
40982
+ );
40983
+ checkDimension(
40984
+ snapshot,
40985
+ "min-height",
40986
+ kind === "button" ? policy.minButtonHeight : policy.minInputHeight,
40987
+ layout,
40988
+ node,
40989
+ emit,
40990
+ "heightTooSmall",
40991
+ messages161.heightTooSmall,
40992
+ tag,
40993
+ policyName
40994
+ );
40995
+ checkDimension(
40996
+ snapshot,
40997
+ "width",
40998
+ kind === "button" ? policy.minButtonWidth : policy.minTouchTarget,
40999
+ layout,
41000
+ node,
41001
+ emit,
41002
+ "widthTooSmall",
41003
+ messages161.widthTooSmall,
41004
+ tag,
41005
+ policyName
41006
+ );
41007
+ checkDimension(
41008
+ snapshot,
41009
+ "min-width",
41010
+ kind === "button" ? policy.minButtonWidth : policy.minTouchTarget,
41011
+ layout,
41012
+ node,
41013
+ emit,
41014
+ "widthTooSmall",
41015
+ messages161.widthTooSmall,
41016
+ tag,
41017
+ policyName
41018
+ );
41019
+ if (kind === "button") {
41020
+ checkDimension(
41021
+ snapshot,
41022
+ "padding-left",
41023
+ policy.minButtonHorizontalPadding,
41024
+ layout,
41025
+ node,
41026
+ emit,
41027
+ "paddingTooSmall",
41028
+ messages161.paddingTooSmall,
41029
+ tag,
41030
+ policyName
41031
+ );
41032
+ checkDimension(
41033
+ snapshot,
41034
+ "padding-right",
41035
+ policy.minButtonHorizontalPadding,
41036
+ layout,
41037
+ node,
41038
+ emit,
41039
+ "paddingTooSmall",
41040
+ messages161.paddingTooSmall,
41041
+ tag,
41042
+ policyName
41043
+ );
41044
+ }
41045
+ const reservedSpace = readReservedSpaceFact(layout, node);
41046
+ const minBlock = kind === "button" ? policy.minButtonHeight : policy.minInputHeight;
41047
+ const minInline = kind === "button" ? policy.minButtonWidth : policy.minTouchTarget;
41048
+ if (!reservedSpace.hasUsableBlockDimension) {
41049
+ emitLayoutDiagnostic(
41050
+ layout,
41051
+ node,
41052
+ emit,
41053
+ jsxLayoutPolicyTouchTarget.id,
41054
+ "noReservedBlockSize",
41055
+ messages161.noReservedBlockSize,
41056
+ "warn",
41057
+ { tag, min: String(minBlock), policy: policyName }
41058
+ );
41059
+ }
41060
+ if (!reservedSpace.hasUsableInlineDimension) {
41061
+ emitLayoutDiagnostic(
41062
+ layout,
41063
+ node,
41064
+ emit,
41065
+ jsxLayoutPolicyTouchTarget.id,
41066
+ "noReservedInlineSize",
41067
+ messages161.noReservedInlineSize,
41068
+ "warn",
41069
+ { tag, min: String(minInline), policy: policyName }
41070
+ );
41071
+ }
41072
+ }
41073
+ }
41074
+ });
41075
+ function checkDimension(snapshot, signal, min, layout, node, emit, messageId, template, tag, policyName) {
41076
+ const px = readKnownPx(snapshot, signal);
41077
+ if (px === null) return;
41078
+ if (px >= min) return;
41079
+ emitLayoutDiagnostic(
41080
+ layout,
41081
+ node,
41082
+ emit,
41083
+ jsxLayoutPolicyTouchTarget.id,
41084
+ messageId,
41085
+ template,
41086
+ "warn",
41087
+ {
41088
+ signal,
41089
+ value: formatRounded(px),
41090
+ min: String(min),
41091
+ tag,
41092
+ policy: policyName
41093
+ }
41094
+ );
41095
+ }
41096
+
40931
41097
  // src/cross-file/rules/index.ts
40932
41098
  var rules3 = [
40933
41099
  jsxNoUndefinedCssClass,
@@ -40959,7 +41125,8 @@ var rules3 = [
40959
41125
  cssLayoutOverflowModeToggleInstability,
40960
41126
  cssLayoutBoxSizingToggleWithChrome,
40961
41127
  cssLayoutContentVisibilityNoIntrinsicSize,
40962
- cssLayoutConditionalOffsetShift
41128
+ cssLayoutConditionalOffsetShift,
41129
+ jsxLayoutPolicyTouchTarget
40963
41130
  ];
40964
41131
 
40965
41132
  // src/cross-file/plugin.ts