@drskillissue/ganko 0.2.71 → 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.
@@ -25260,148 +25260,8 @@ function checkParagraphSpacing(graph, emit, policy, name) {
25260
25260
  }
25261
25261
  }
25262
25262
 
25263
- // src/css/rules/a11y/css-policy-touch-target.ts
25264
- var messages125 = {
25265
- heightTooSmall: "`{{property}}` of `{{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for `{{element}}` elements in policy `{{policy}}`.",
25266
- widthTooSmall: "`{{property}}` of `{{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for `{{element}}` elements in policy `{{policy}}`.",
25267
- paddingTooSmall: "Horizontal padding `{{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for `{{element}}` elements in policy `{{policy}}`."
25268
- };
25269
- function classifyRule(rule) {
25270
- if (rule.elementKinds.has("button")) return "button";
25271
- if (rule.elementKinds.has("input")) return "input";
25272
- return null;
25273
- }
25274
- var HEIGHT_PROPERTIES = /* @__PURE__ */ new Set(["height", "min-height"]);
25275
- var WIDTH_PROPERTIES = /* @__PURE__ */ new Set(["width", "min-width"]);
25276
- var HPADDING_PROPERTIES = /* @__PURE__ */ new Set(["padding-left", "padding-right", "padding-inline", "padding-inline-start", "padding-inline-end"]);
25277
- var cssPolicyTouchTarget = defineCSSRule({
25278
- id: "css-policy-touch-target",
25279
- severity: "warn",
25280
- messages: messages125,
25281
- meta: {
25282
- description: "Enforce minimum interactive element sizes per accessibility policy.",
25283
- fixable: false,
25284
- category: "css-a11y"
25285
- },
25286
- options: {},
25287
- check(graph, emit) {
25288
- const policy = getActivePolicy();
25289
- if (policy === null) return;
25290
- const name = getActivePolicyName() ?? "";
25291
- const decls = graph.declarationsForProperties(
25292
- "height",
25293
- "min-height",
25294
- "width",
25295
- "min-width",
25296
- "padding-left",
25297
- "padding-right",
25298
- "padding-inline",
25299
- "padding-inline-start",
25300
- "padding-inline-end"
25301
- );
25302
- for (let i = 0; i < decls.length; i++) {
25303
- const d = decls[i];
25304
- if (!d) continue;
25305
- if (!d.rule) continue;
25306
- const prop = d.property.toLowerCase();
25307
- const kind = classifyRule(d.rule);
25308
- if (!kind) continue;
25309
- if (isVisuallyHiddenInput(d.rule)) continue;
25310
- const px = parsePxValue(d.value);
25311
- if (px === null) continue;
25312
- if (HEIGHT_PROPERTIES.has(prop)) {
25313
- const min = kind === "button" ? policy.minButtonHeight : policy.minInputHeight;
25314
- if (px >= min) continue;
25315
- emitCSSDiagnostic(
25316
- emit,
25317
- d.file.path,
25318
- d.startLine,
25319
- d.startColumn,
25320
- cssPolicyTouchTarget,
25321
- "heightTooSmall",
25322
- resolveMessage(messages125.heightTooSmall, {
25323
- property: d.property,
25324
- value: d.value.trim(),
25325
- resolved: String(Math.round(px * 100) / 100),
25326
- min: String(min),
25327
- element: kind,
25328
- policy: name
25329
- })
25330
- );
25331
- continue;
25332
- }
25333
- if (WIDTH_PROPERTIES.has(prop)) {
25334
- const min = kind === "button" ? policy.minButtonWidth : policy.minTouchTarget;
25335
- if (px >= min) continue;
25336
- emitCSSDiagnostic(
25337
- emit,
25338
- d.file.path,
25339
- d.startLine,
25340
- d.startColumn,
25341
- cssPolicyTouchTarget,
25342
- "widthTooSmall",
25343
- resolveMessage(messages125.widthTooSmall, {
25344
- property: d.property,
25345
- value: d.value.trim(),
25346
- resolved: String(Math.round(px * 100) / 100),
25347
- min: String(min),
25348
- element: kind,
25349
- policy: name
25350
- })
25351
- );
25352
- continue;
25353
- }
25354
- if (kind === "button" && HPADDING_PROPERTIES.has(prop)) {
25355
- if (px >= policy.minButtonHorizontalPadding) continue;
25356
- emitCSSDiagnostic(
25357
- emit,
25358
- d.file.path,
25359
- d.startLine,
25360
- d.startColumn,
25361
- cssPolicyTouchTarget,
25362
- "paddingTooSmall",
25363
- resolveMessage(messages125.paddingTooSmall, {
25364
- value: d.value.trim(),
25365
- resolved: String(Math.round(px * 100) / 100),
25366
- min: String(policy.minButtonHorizontalPadding),
25367
- element: kind,
25368
- policy: name
25369
- })
25370
- );
25371
- }
25372
- }
25373
- }
25374
- });
25375
- function isVisuallyHiddenInput(rule) {
25376
- if (!hasPositionAbsoluteOrFixed(rule)) return false;
25377
- if (!hasOpacityZero(rule)) return false;
25378
- return true;
25379
- }
25380
- function hasPositionAbsoluteOrFixed(rule) {
25381
- const positionDecls = rule.declarationIndex.get("position");
25382
- if (!positionDecls || positionDecls.length === 0) return false;
25383
- for (let i = 0; i < positionDecls.length; i++) {
25384
- const decl = positionDecls[i];
25385
- if (!decl) continue;
25386
- const v = decl.value.trim().toLowerCase();
25387
- if (v === "absolute" || v === "fixed") return true;
25388
- }
25389
- return false;
25390
- }
25391
- function hasOpacityZero(rule) {
25392
- const opacityDecls = rule.declarationIndex.get("opacity");
25393
- if (!opacityDecls || opacityDecls.length === 0) return false;
25394
- for (let i = 0; i < opacityDecls.length; i++) {
25395
- const decl = opacityDecls[i];
25396
- if (!decl) continue;
25397
- const v = decl.value.trim();
25398
- if (v === "0") return true;
25399
- }
25400
- return false;
25401
- }
25402
-
25403
25263
  // src/css/rules/a11y/css-policy-typography.ts
25404
- var messages126 = {
25264
+ var messages125 = {
25405
25265
  fontTooSmall: "Font size `{{value}}` ({{resolved}}px) is below the `{{context}}` minimum of `{{min}}px` for policy `{{policy}}`.",
25406
25266
  lineHeightTooSmall: "Line height `{{value}}` is below the `{{context}}` minimum of `{{min}}` for policy `{{policy}}`."
25407
25267
  };
@@ -25437,7 +25297,7 @@ function resolveLineHeightContext(d, p) {
25437
25297
  var cssPolicyTypography = defineCSSRule({
25438
25298
  id: "css-policy-typography",
25439
25299
  severity: "warn",
25440
- messages: messages126,
25300
+ messages: messages125,
25441
25301
  meta: {
25442
25302
  description: "Enforce minimum font sizes and line heights per accessibility policy.",
25443
25303
  fixable: false,
@@ -25464,7 +25324,7 @@ var cssPolicyTypography = defineCSSRule({
25464
25324
  d.startColumn,
25465
25325
  cssPolicyTypography,
25466
25326
  "fontTooSmall",
25467
- resolveMessage(messages126.fontTooSmall, {
25327
+ resolveMessage(messages125.fontTooSmall, {
25468
25328
  value: d.value.trim(),
25469
25329
  resolved: String(Math.round(px * 100) / 100),
25470
25330
  context,
@@ -25491,7 +25351,7 @@ var cssPolicyTypography = defineCSSRule({
25491
25351
  d.startColumn,
25492
25352
  cssPolicyTypography,
25493
25353
  "lineHeightTooSmall",
25494
- resolveMessage(messages126.lineHeightTooSmall, {
25354
+ resolveMessage(messages125.lineHeightTooSmall, {
25495
25355
  value: d.value.trim(),
25496
25356
  context,
25497
25357
  min: String(min),
@@ -25509,7 +25369,7 @@ var ZERO_S = /(^|\s|,)0s($|\s|,)/;
25509
25369
  var TIME_VALUE_G = /([0-9]*\.?[0-9]+)(ms|s)/g;
25510
25370
  var AMPERSAND_G = /&/g;
25511
25371
  var WHITESPACE_G = /\s+/g;
25512
- var messages127 = {
25372
+ var messages126 = {
25513
25373
  missingReducedMotion: "Animated selector `{{selector}}` lacks prefers-reduced-motion override."
25514
25374
  };
25515
25375
  function isAnimationDecl(p) {
@@ -25613,7 +25473,7 @@ function normalizeSelector(s) {
25613
25473
  var cssRequireReducedMotionOverride = defineCSSRule({
25614
25474
  id: "css-require-reduced-motion-override",
25615
25475
  severity: "warn",
25616
- messages: messages127,
25476
+ messages: messages126,
25617
25477
  meta: {
25618
25478
  description: "Require reduced-motion override for animated selectors.",
25619
25479
  fixable: false,
@@ -25676,20 +25536,20 @@ var cssRequireReducedMotionOverride = defineCSSRule({
25676
25536
  d.startColumn,
25677
25537
  cssRequireReducedMotionOverride,
25678
25538
  "missingReducedMotion",
25679
- resolveMessage(messages127.missingReducedMotion, { selector: r.selectorText })
25539
+ resolveMessage(messages126.missingReducedMotion, { selector: r.selectorText })
25680
25540
  );
25681
25541
  }
25682
25542
  }
25683
25543
  });
25684
25544
 
25685
25545
  // src/css/rules/structure/css-no-empty-rule.ts
25686
- var messages128 = {
25546
+ var messages127 = {
25687
25547
  emptyRule: "Empty rule `{{selector}}` should be removed."
25688
25548
  };
25689
25549
  var cssNoEmptyRule = defineCSSRule({
25690
25550
  id: "css-no-empty-rule",
25691
25551
  severity: "warn",
25692
- messages: messages128,
25552
+ messages: messages127,
25693
25553
  meta: {
25694
25554
  description: "Disallow empty CSS rules.",
25695
25555
  fixable: false,
@@ -25707,20 +25567,20 @@ var cssNoEmptyRule = defineCSSRule({
25707
25567
  rule.startColumn,
25708
25568
  cssNoEmptyRule,
25709
25569
  "emptyRule",
25710
- resolveMessage(messages128.emptyRule, { selector: rule.selectorText })
25570
+ resolveMessage(messages127.emptyRule, { selector: rule.selectorText })
25711
25571
  );
25712
25572
  }
25713
25573
  }
25714
25574
  });
25715
25575
 
25716
25576
  // src/css/rules/structure/css-no-unknown-container-name.ts
25717
- var messages129 = {
25577
+ var messages128 = {
25718
25578
  unknownContainer: "Unknown container name `{{name}}` in @container query."
25719
25579
  };
25720
25580
  var cssNoUnknownContainerName = defineCSSRule({
25721
25581
  id: "css-no-unknown-container-name",
25722
25582
  severity: "error",
25723
- messages: messages129,
25583
+ messages: messages128,
25724
25584
  meta: {
25725
25585
  description: "Disallow unknown named containers in @container queries.",
25726
25586
  fixable: false,
@@ -25740,20 +25600,20 @@ var cssNoUnknownContainerName = defineCSSRule({
25740
25600
  1,
25741
25601
  cssNoUnknownContainerName,
25742
25602
  "unknownContainer",
25743
- resolveMessage(messages129.unknownContainer, { name })
25603
+ resolveMessage(messages128.unknownContainer, { name })
25744
25604
  );
25745
25605
  }
25746
25606
  }
25747
25607
  });
25748
25608
 
25749
25609
  // src/css/rules/structure/css-no-unused-container-name.ts
25750
- var messages130 = {
25610
+ var messages129 = {
25751
25611
  unusedContainer: "Container name `{{name}}` is declared but never queried."
25752
25612
  };
25753
25613
  var cssNoUnusedContainerName = defineCSSRule({
25754
25614
  id: "css-no-unused-container-name",
25755
25615
  severity: "warn",
25756
- messages: messages130,
25616
+ messages: messages129,
25757
25617
  meta: {
25758
25618
  description: "Disallow unused named containers.",
25759
25619
  fixable: false,
@@ -25776,7 +25636,7 @@ var cssNoUnusedContainerName = defineCSSRule({
25776
25636
  d.startColumn,
25777
25637
  cssNoUnusedContainerName,
25778
25638
  "unusedContainer",
25779
- resolveMessage(messages130.unusedContainer, { name })
25639
+ resolveMessage(messages129.unusedContainer, { name })
25780
25640
  );
25781
25641
  }
25782
25642
  }
@@ -25784,13 +25644,13 @@ var cssNoUnusedContainerName = defineCSSRule({
25784
25644
  });
25785
25645
 
25786
25646
  // src/css/rules/structure/layer-requirement-for-component-rules.ts
25787
- var messages131 = {
25647
+ var messages130 = {
25788
25648
  missingLayer: "Rule `{{selector}}` is not inside any @layer block while this file uses @layer. Place component rules inside an explicit layer."
25789
25649
  };
25790
25650
  var layerRequirementForComponentRules = defineCSSRule({
25791
25651
  id: "layer-requirement-for-component-rules",
25792
25652
  severity: "warn",
25793
- messages: messages131,
25653
+ messages: messages130,
25794
25654
  meta: {
25795
25655
  description: "Require style rules to be inside @layer when the file defines layers.",
25796
25656
  fixable: false,
@@ -25809,7 +25669,7 @@ var layerRequirementForComponentRules = defineCSSRule({
25809
25669
  rule.startColumn,
25810
25670
  layerRequirementForComponentRules,
25811
25671
  "missingLayer",
25812
- resolveMessage(messages131.missingLayer, {
25672
+ resolveMessage(messages130.missingLayer, {
25813
25673
  selector: rule.selectorText
25814
25674
  })
25815
25675
  );
@@ -25849,7 +25709,6 @@ var rules2 = [
25849
25709
  selectorMaxAttributeAndUniversal,
25850
25710
  selectorMaxSpecificity,
25851
25711
  cssPolicyTypography,
25852
- cssPolicyTouchTarget,
25853
25712
  cssPolicySpacing,
25854
25713
  cssPolicyContrast
25855
25714
  ];
@@ -30374,21 +30233,34 @@ function detectTailwindEntry(files) {
30374
30233
  }
30375
30234
  return themeOnlyFallback;
30376
30235
  }
30377
- async function resolveTailwindValidator(files) {
30236
+ async function resolveTailwindValidator(files, logger) {
30378
30237
  const entry = detectTailwindEntry(files);
30379
- if (!entry) return null;
30238
+ if (!entry) {
30239
+ logger?.info('tailwind: no entry file detected (no @import "tailwindcss" or @theme block found in CSS files)');
30240
+ return null;
30241
+ }
30242
+ logger?.info(`tailwind: entry file detected: ${entry.path}`);
30380
30243
  try {
30381
30244
  const base = dirname2(entry.path);
30382
30245
  const resolved = resolveTailwindNodePath(base);
30383
- if (resolved === null) return null;
30246
+ if (resolved === null) {
30247
+ logger?.warning(`tailwind: @tailwindcss/node not resolvable walking up from ${base}`);
30248
+ return null;
30249
+ }
30250
+ logger?.info(`tailwind: @tailwindcss/node resolved to ${resolved}`);
30384
30251
  const mod = await import(resolved);
30385
- if (typeof mod.__unstable__loadDesignSystem !== "function") return null;
30252
+ if (typeof mod.__unstable__loadDesignSystem !== "function") {
30253
+ logger?.warning("tailwind: @tailwindcss/node module missing __unstable__loadDesignSystem export");
30254
+ return null;
30255
+ }
30386
30256
  const design = await mod.__unstable__loadDesignSystem(
30387
30257
  entry.content,
30388
30258
  { base }
30389
30259
  );
30260
+ logger?.info("tailwind: design system loaded successfully");
30390
30261
  return createLiveValidator(design);
30391
- } catch {
30262
+ } catch (err) {
30263
+ logger?.warning(`tailwind: failed to load design system: ${err instanceof Error ? err.message : String(err)}`);
30392
30264
  return null;
30393
30265
  }
30394
30266
  }
@@ -39193,13 +39065,13 @@ function emitLayoutDiagnostic(layout, node, emit, ruleId, messageId, template, s
39193
39065
  }
39194
39066
 
39195
39067
  // src/cross-file/rules/undefined-css-class.ts
39196
- var messages132 = {
39068
+ var messages131 = {
39197
39069
  undefinedClass: "CSS class '{{className}}' is not defined in project CSS files"
39198
39070
  };
39199
39071
  var jsxNoUndefinedCssClass = defineCrossRule({
39200
39072
  id: "jsx-no-undefined-css-class",
39201
39073
  severity: "error",
39202
- messages: messages132,
39074
+ messages: messages131,
39203
39075
  meta: {
39204
39076
  description: "Detect undefined CSS class names in JSX",
39205
39077
  fixable: false,
@@ -39218,7 +39090,7 @@ var jsxNoUndefinedCssClass = defineCrossRule({
39218
39090
  ref.solid.sourceFile,
39219
39091
  jsxNoUndefinedCssClass.id,
39220
39092
  "undefinedClass",
39221
- resolveMessage(messages132.undefinedClass, { className: item.className }),
39093
+ resolveMessage(messages131.undefinedClass, { className: item.className }),
39222
39094
  "error"
39223
39095
  ));
39224
39096
  }
@@ -39226,13 +39098,13 @@ var jsxNoUndefinedCssClass = defineCrossRule({
39226
39098
  });
39227
39099
 
39228
39100
  // src/cross-file/rules/unreferenced-css-class.ts
39229
- var messages133 = {
39101
+ var messages132 = {
39230
39102
  unreferencedClass: "CSS class '{{className}}' is defined but not referenced by static JSX class attributes"
39231
39103
  };
39232
39104
  var cssNoUnreferencedComponentClass = defineCrossRule({
39233
39105
  id: "css-no-unreferenced-component-class",
39234
39106
  severity: "warn",
39235
- messages: messages133,
39107
+ messages: messages132,
39236
39108
  meta: {
39237
39109
  description: "Detect CSS classes that are never referenced by static JSX class attributes.",
39238
39110
  fixable: false,
@@ -39256,7 +39128,7 @@ var cssNoUnreferencedComponentClass = defineCrossRule({
39256
39128
  },
39257
39129
  cssNoUnreferencedComponentClass.id,
39258
39130
  "unreferencedClass",
39259
- resolveMessage(messages133.unreferencedClass, { className }),
39131
+ resolveMessage(messages132.unreferencedClass, { className }),
39260
39132
  "warn"
39261
39133
  )
39262
39134
  );
@@ -39265,13 +39137,13 @@ var cssNoUnreferencedComponentClass = defineCrossRule({
39265
39137
  });
39266
39138
 
39267
39139
  // src/cross-file/rules/jsx-no-duplicate-class-token-class-classlist.ts
39268
- var messages134 = {
39140
+ var messages133 = {
39269
39141
  duplicateClassToken: "Class token `{{name}}` appears in both class and classList."
39270
39142
  };
39271
39143
  var jsxNoDuplicateClassTokenClassClasslist = defineCrossRule({
39272
39144
  id: "jsx-no-duplicate-class-token-class-classlist",
39273
39145
  severity: "warn",
39274
- messages: messages134,
39146
+ messages: messages133,
39275
39147
  meta: {
39276
39148
  description: "Disallow duplicate class tokens between class and classList on the same JSX element.",
39277
39149
  fixable: false,
@@ -39313,7 +39185,7 @@ var jsxNoDuplicateClassTokenClassClasslist = defineCrossRule({
39313
39185
  solid.sourceFile,
39314
39186
  jsxNoDuplicateClassTokenClassClasslist.id,
39315
39187
  "duplicateClassToken",
39316
- resolveMessage(messages134.duplicateClassToken, { name: token }),
39188
+ resolveMessage(messages133.duplicateClassToken, { name: token }),
39317
39189
  "warn"
39318
39190
  ));
39319
39191
  }
@@ -39324,13 +39196,13 @@ var jsxNoDuplicateClassTokenClassClasslist = defineCrossRule({
39324
39196
 
39325
39197
  // src/cross-file/rules/jsx-classlist-static-keys.ts
39326
39198
  import ts126 from "typescript";
39327
- var messages135 = {
39199
+ var messages134 = {
39328
39200
  nonStaticKey: "classList key must be statically known for reliable class mapping."
39329
39201
  };
39330
39202
  var jsxClasslistStaticKeys = defineCrossRule({
39331
39203
  id: "jsx-classlist-static-keys",
39332
39204
  severity: "error",
39333
- messages: messages135,
39205
+ messages: messages134,
39334
39206
  meta: {
39335
39207
  description: "Require classList keys to be static and non-computed.",
39336
39208
  fixable: false,
@@ -39341,26 +39213,26 @@ var jsxClasslistStaticKeys = defineCrossRule({
39341
39213
  forEachClassListPropertyAcross(solids, (solid, p) => {
39342
39214
  if (ts126.isSpreadAssignment(p)) return;
39343
39215
  if (!ts126.isPropertyAssignment(p)) {
39344
- emit(createDiagnostic(solid.file, p, solid.sourceFile, jsxClasslistStaticKeys.id, "nonStaticKey", resolveMessage(messages135.nonStaticKey), "error"));
39216
+ emit(createDiagnostic(solid.file, p, solid.sourceFile, jsxClasslistStaticKeys.id, "nonStaticKey", resolveMessage(messages134.nonStaticKey), "error"));
39345
39217
  return;
39346
39218
  }
39347
39219
  if (ts126.isComputedPropertyName(p.name)) return;
39348
39220
  if (ts126.isIdentifier(p.name)) return;
39349
39221
  if (ts126.isStringLiteral(p.name)) return;
39350
- emit(createDiagnostic(solid.file, p.name, solid.sourceFile, jsxClasslistStaticKeys.id, "nonStaticKey", resolveMessage(messages135.nonStaticKey), "error"));
39222
+ emit(createDiagnostic(solid.file, p.name, solid.sourceFile, jsxClasslistStaticKeys.id, "nonStaticKey", resolveMessage(messages134.nonStaticKey), "error"));
39351
39223
  });
39352
39224
  }
39353
39225
  });
39354
39226
 
39355
39227
  // src/cross-file/rules/jsx-classlist-no-constant-literals.ts
39356
39228
  import ts127 from "typescript";
39357
- var messages136 = {
39229
+ var messages135 = {
39358
39230
  constantEntry: "classList entry `{{name}}: {{value}}` is constant; move it to static class."
39359
39231
  };
39360
39232
  var jsxClasslistNoConstantLiterals = defineCrossRule({
39361
39233
  id: "jsx-classlist-no-constant-literals",
39362
39234
  severity: "warn",
39363
- messages: messages136,
39235
+ messages: messages135,
39364
39236
  meta: {
39365
39237
  description: "Disallow classList entries with constant true/false values.",
39366
39238
  fixable: false,
@@ -39380,7 +39252,7 @@ var jsxClasslistNoConstantLiterals = defineCrossRule({
39380
39252
  solid.sourceFile,
39381
39253
  jsxClasslistNoConstantLiterals.id,
39382
39254
  "constantEntry",
39383
- resolveMessage(messages136.constantEntry, { name: n, value: val.kind === ts127.SyntaxKind.TrueKeyword ? "true" : "false" }),
39255
+ resolveMessage(messages135.constantEntry, { name: n, value: val.kind === ts127.SyntaxKind.TrueKeyword ? "true" : "false" }),
39384
39256
  "warn"
39385
39257
  ));
39386
39258
  });
@@ -39415,13 +39287,13 @@ function isDefinitelyNonBooleanType(solid, node) {
39415
39287
  }
39416
39288
 
39417
39289
  // src/cross-file/rules/jsx-classlist-boolean-values.ts
39418
- var messages137 = {
39290
+ var messages136 = {
39419
39291
  nonBooleanValue: "classList value for `{{name}}` must be boolean."
39420
39292
  };
39421
39293
  var jsxClasslistBooleanValues = defineCrossRule({
39422
39294
  id: "jsx-classlist-boolean-values",
39423
39295
  severity: "error",
39424
- messages: messages137,
39296
+ messages: messages136,
39425
39297
  meta: {
39426
39298
  description: "Require classList values to be boolean-like expressions.",
39427
39299
  fixable: false,
@@ -39435,25 +39307,25 @@ var jsxClasslistBooleanValues = defineCrossRule({
39435
39307
  if (!n) return;
39436
39308
  if (isBooleanish(p.initializer)) return;
39437
39309
  if (isDefinitelyNonBoolean(p.initializer)) {
39438
- emit(createDiagnostic(solid.file, p.initializer, solid.sourceFile, jsxClasslistBooleanValues.id, "nonBooleanValue", resolveMessage(messages137.nonBooleanValue, { name: n }), "error"));
39310
+ emit(createDiagnostic(solid.file, p.initializer, solid.sourceFile, jsxClasslistBooleanValues.id, "nonBooleanValue", resolveMessage(messages136.nonBooleanValue, { name: n }), "error"));
39439
39311
  return;
39440
39312
  }
39441
39313
  if (isBooleanType(solid, p.initializer)) return;
39442
39314
  if (!isDefinitelyNonBooleanType(solid, p.initializer)) return;
39443
- emit(createDiagnostic(solid.file, p.initializer, solid.sourceFile, jsxClasslistBooleanValues.id, "nonBooleanValue", resolveMessage(messages137.nonBooleanValue, { name: n }), "error"));
39315
+ emit(createDiagnostic(solid.file, p.initializer, solid.sourceFile, jsxClasslistBooleanValues.id, "nonBooleanValue", resolveMessage(messages136.nonBooleanValue, { name: n }), "error"));
39444
39316
  });
39445
39317
  }
39446
39318
  });
39447
39319
 
39448
39320
  // src/cross-file/rules/jsx-classlist-no-accessor-reference.ts
39449
39321
  import ts129 from "typescript";
39450
- var messages138 = {
39322
+ var messages137 = {
39451
39323
  accessorReference: "Signal accessor `{{name}}` must be called in classList value (use {{name}}())."
39452
39324
  };
39453
39325
  var jsxClasslistNoAccessorReference = defineCrossRule({
39454
39326
  id: "jsx-classlist-no-accessor-reference",
39455
39327
  severity: "error",
39456
- messages: messages138,
39328
+ messages: messages137,
39457
39329
  meta: {
39458
39330
  description: "Disallow passing accessor references directly as classList values.",
39459
39331
  fixable: false,
@@ -39485,7 +39357,7 @@ var jsxClasslistNoAccessorReference = defineCrossRule({
39485
39357
  solid.sourceFile,
39486
39358
  jsxClasslistNoAccessorReference.id,
39487
39359
  "accessorReference",
39488
- resolveMessage(messages138.accessorReference, { name: v.text }),
39360
+ resolveMessage(messages137.accessorReference, { name: v.text }),
39489
39361
  "error"
39490
39362
  ));
39491
39363
  });
@@ -39494,13 +39366,13 @@ var jsxClasslistNoAccessorReference = defineCrossRule({
39494
39366
 
39495
39367
  // src/cross-file/rules/jsx-style-kebab-case-keys.ts
39496
39368
  import ts130 from "typescript";
39497
- var messages139 = {
39369
+ var messages138 = {
39498
39370
  kebabStyleKey: "Style key `{{name}}` should be `{{kebab}}` in Solid style objects."
39499
39371
  };
39500
39372
  var jsxStyleKebabCaseKeys = defineCrossRule({
39501
39373
  id: "jsx-style-kebab-case-keys",
39502
39374
  severity: "error",
39503
- messages: messages139,
39375
+ messages: messages138,
39504
39376
  meta: {
39505
39377
  description: "Require kebab-case keys in JSX style object literals.",
39506
39378
  fixable: false,
@@ -39521,7 +39393,7 @@ var jsxStyleKebabCaseKeys = defineCrossRule({
39521
39393
  solid.sourceFile,
39522
39394
  jsxStyleKebabCaseKeys.id,
39523
39395
  "kebabStyleKey",
39524
- resolveMessage(messages139.kebabStyleKey, { name: n, kebab }),
39396
+ resolveMessage(messages138.kebabStyleKey, { name: n, kebab }),
39525
39397
  "error"
39526
39398
  ));
39527
39399
  });
@@ -39530,13 +39402,13 @@ var jsxStyleKebabCaseKeys = defineCrossRule({
39530
39402
 
39531
39403
  // src/cross-file/rules/jsx-style-no-function-values.ts
39532
39404
  import ts131 from "typescript";
39533
- var messages140 = {
39405
+ var messages139 = {
39534
39406
  functionStyleValue: "Style value for `{{name}}` is a function; pass computed value instead."
39535
39407
  };
39536
39408
  var jsxStyleNoFunctionValues = defineCrossRule({
39537
39409
  id: "jsx-style-no-function-values",
39538
39410
  severity: "error",
39539
- messages: messages140,
39411
+ messages: messages139,
39540
39412
  meta: {
39541
39413
  description: "Disallow function values in JSX style objects.",
39542
39414
  fixable: false,
@@ -39550,11 +39422,11 @@ var jsxStyleNoFunctionValues = defineCrossRule({
39550
39422
  if (!n) return;
39551
39423
  const v = p.initializer;
39552
39424
  if (ts131.isArrowFunction(v) || ts131.isFunctionExpression(v)) {
39553
- emit(createDiagnostic(solid.file, v, solid.sourceFile, jsxStyleNoFunctionValues.id, "functionStyleValue", resolveMessage(messages140.functionStyleValue, { name: n }), "error"));
39425
+ emit(createDiagnostic(solid.file, v, solid.sourceFile, jsxStyleNoFunctionValues.id, "functionStyleValue", resolveMessage(messages139.functionStyleValue, { name: n }), "error"));
39554
39426
  return;
39555
39427
  }
39556
39428
  if (ts131.isIdentifier(v) && solid.typeResolver.isCallableType(v)) {
39557
- emit(createDiagnostic(solid.file, v, solid.sourceFile, jsxStyleNoFunctionValues.id, "functionStyleValue", resolveMessage(messages140.functionStyleValue, { name: n }), "error"));
39429
+ emit(createDiagnostic(solid.file, v, solid.sourceFile, jsxStyleNoFunctionValues.id, "functionStyleValue", resolveMessage(messages139.functionStyleValue, { name: n }), "error"));
39558
39430
  }
39559
39431
  });
39560
39432
  }
@@ -39562,13 +39434,13 @@ var jsxStyleNoFunctionValues = defineCrossRule({
39562
39434
 
39563
39435
  // src/cross-file/rules/jsx-style-no-unused-custom-prop.ts
39564
39436
  import ts132 from "typescript";
39565
- var messages141 = {
39437
+ var messages140 = {
39566
39438
  unusedInlineVar: "Inline custom property `{{name}}` is never read via var({{name}})."
39567
39439
  };
39568
39440
  var jsxStyleNoUnusedCustomProp = defineCrossRule({
39569
39441
  id: "jsx-style-no-unused-custom-prop",
39570
39442
  severity: "warn",
39571
- messages: messages141,
39443
+ messages: messages140,
39572
39444
  meta: {
39573
39445
  description: "Detect inline style custom properties that are never consumed by CSS var() references.",
39574
39446
  fixable: false,
@@ -39609,7 +39481,7 @@ var jsxStyleNoUnusedCustomProp = defineCrossRule({
39609
39481
  solid.sourceFile,
39610
39482
  jsxStyleNoUnusedCustomProp.id,
39611
39483
  "unusedInlineVar",
39612
- resolveMessage(messages141.unusedInlineVar, { name: n }),
39484
+ resolveMessage(messages140.unusedInlineVar, { name: n }),
39613
39485
  "warn"
39614
39486
  ));
39615
39487
  }
@@ -39619,7 +39491,7 @@ var jsxStyleNoUnusedCustomProp = defineCrossRule({
39619
39491
 
39620
39492
  // src/cross-file/rules/jsx-style-policy.ts
39621
39493
  import ts133 from "typescript";
39622
- var messages142 = {
39494
+ var messages141 = {
39623
39495
  fontTooSmall: "Inline style `{{prop}}: {{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for policy `{{policy}}`.",
39624
39496
  lineHeightTooSmall: "Inline style `line-height: {{value}}` is below the minimum `{{min}}` for policy `{{policy}}`.",
39625
39497
  heightTooSmall: "Inline style `{{prop}}: {{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for interactive elements in policy `{{policy}}`.",
@@ -39666,7 +39538,7 @@ function readNodeHostElementRef(layout, solid, element) {
39666
39538
  var jsxStylePolicy = defineCrossRule({
39667
39539
  id: "jsx-style-policy",
39668
39540
  severity: "warn",
39669
- messages: messages142,
39541
+ messages: messages141,
39670
39542
  meta: {
39671
39543
  description: "Enforce accessibility policy thresholds on inline JSX style objects.",
39672
39544
  fixable: false,
@@ -39693,7 +39565,7 @@ var jsxStylePolicy = defineCrossRule({
39693
39565
  solid.sourceFile,
39694
39566
  jsxStylePolicy.id,
39695
39567
  "fontTooSmall",
39696
- resolveMessage(messages142.fontTooSmall, {
39568
+ resolveMessage(messages141.fontTooSmall, {
39697
39569
  prop: key,
39698
39570
  value: strVal,
39699
39571
  resolved: formatRounded(px),
@@ -39715,7 +39587,7 @@ var jsxStylePolicy = defineCrossRule({
39715
39587
  solid.sourceFile,
39716
39588
  jsxStylePolicy.id,
39717
39589
  "lineHeightTooSmall",
39718
- resolveMessage(messages142.lineHeightTooSmall, {
39590
+ resolveMessage(messages141.lineHeightTooSmall, {
39719
39591
  value: String(lh),
39720
39592
  min: String(policy.minLineHeight),
39721
39593
  policy: name
@@ -39739,7 +39611,7 @@ var jsxStylePolicy = defineCrossRule({
39739
39611
  solid.sourceFile,
39740
39612
  jsxStylePolicy.id,
39741
39613
  "heightTooSmall",
39742
- resolveMessage(messages142.heightTooSmall, {
39614
+ resolveMessage(messages141.heightTooSmall, {
39743
39615
  prop: key,
39744
39616
  value: strVal,
39745
39617
  resolved: formatRounded(px),
@@ -39761,7 +39633,7 @@ var jsxStylePolicy = defineCrossRule({
39761
39633
  solid.sourceFile,
39762
39634
  jsxStylePolicy.id,
39763
39635
  "letterSpacingTooSmall",
39764
- resolveMessage(messages142.letterSpacingTooSmall, {
39636
+ resolveMessage(messages141.letterSpacingTooSmall, {
39765
39637
  value: strVal,
39766
39638
  resolved: String(em),
39767
39639
  min: String(policy.minLetterSpacing),
@@ -39782,7 +39654,7 @@ var jsxStylePolicy = defineCrossRule({
39782
39654
  solid.sourceFile,
39783
39655
  jsxStylePolicy.id,
39784
39656
  "wordSpacingTooSmall",
39785
- resolveMessage(messages142.wordSpacingTooSmall, {
39657
+ resolveMessage(messages141.wordSpacingTooSmall, {
39786
39658
  value: strVal,
39787
39659
  resolved: String(em),
39788
39660
  min: String(policy.minWordSpacing),
@@ -39796,7 +39668,7 @@ var jsxStylePolicy = defineCrossRule({
39796
39668
  });
39797
39669
 
39798
39670
  // src/cross-file/rules/css-layout-sibling-alignment-outlier.ts
39799
- var messages143 = {
39671
+ var messages142 = {
39800
39672
  misalignedSibling: "Vertically misaligned '{{subject}}' in '{{parent}}'.{{fix}}{{offsetClause}}"
39801
39673
  };
39802
39674
  var MIN_CONFIDENCE_THRESHOLD = 0.48;
@@ -39844,7 +39716,7 @@ var siblingAlignmentDetector = {
39844
39716
  var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
39845
39717
  id: "css-layout-sibling-alignment-outlier",
39846
39718
  severity: "warn",
39847
- messages: messages143,
39719
+ messages: messages142,
39848
39720
  meta: {
39849
39721
  description: "Detect vertical alignment outliers between sibling elements in shared layout containers.",
39850
39722
  fixable: false,
@@ -39928,7 +39800,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
39928
39800
  subjectRef.solid.sourceFile,
39929
39801
  cssLayoutSiblingAlignmentOutlier.id,
39930
39802
  "misalignedSibling",
39931
- resolveMessage(messages143.misalignedSibling, {
39803
+ resolveMessage(messages142.misalignedSibling, {
39932
39804
  subject,
39933
39805
  parent,
39934
39806
  fix,
@@ -40012,13 +39884,13 @@ function hasNonOffsetPrimaryEvidence(topFactors) {
40012
39884
  }
40013
39885
 
40014
39886
  // src/cross-file/rules/css-layout-transition-layout-property.ts
40015
- var messages144 = {
39887
+ var messages143 = {
40016
39888
  transitionLayoutProperty: "Transition '{{property}}' in '{{declaration}}' animates layout-affecting geometry. Prefer transform/opacity to avoid CLS."
40017
39889
  };
40018
39890
  var cssLayoutTransitionLayoutProperty = defineCrossRule({
40019
39891
  id: "css-layout-transition-layout-property",
40020
39892
  severity: "warn",
40021
- messages: messages144,
39893
+ messages: messages143,
40022
39894
  meta: {
40023
39895
  description: "Disallow transitions that animate layout-affecting geometry properties.",
40024
39896
  fixable: false,
@@ -40042,7 +39914,7 @@ var cssLayoutTransitionLayoutProperty = defineCrossRule({
40042
39914
  },
40043
39915
  cssLayoutTransitionLayoutProperty.id,
40044
39916
  "transitionLayoutProperty",
40045
- resolveMessage(messages144.transitionLayoutProperty, {
39917
+ resolveMessage(messages143.transitionLayoutProperty, {
40046
39918
  property: target,
40047
39919
  declaration: declaration.property
40048
39920
  }),
@@ -40057,13 +39929,13 @@ function findLayoutTransitionTarget(raw) {
40057
39929
  }
40058
39930
 
40059
39931
  // src/cross-file/rules/css-layout-animation-layout-property.ts
40060
- var messages145 = {
39932
+ var messages144 = {
40061
39933
  animationLayoutProperty: "Animation '{{animation}}' mutates layout-affecting '{{property}}', which can trigger CLS. Prefer transform/opacity or reserve geometry."
40062
39934
  };
40063
39935
  var cssLayoutAnimationLayoutProperty = defineCrossRule({
40064
39936
  id: "css-layout-animation-layout-property",
40065
39937
  severity: "warn",
40066
- messages: messages145,
39938
+ messages: messages144,
40067
39939
  meta: {
40068
39940
  description: "Disallow keyframe animations that mutate layout-affecting properties and can trigger CLS.",
40069
39941
  fixable: false,
@@ -40091,7 +39963,7 @@ var cssLayoutAnimationLayoutProperty = defineCrossRule({
40091
39963
  },
40092
39964
  cssLayoutAnimationLayoutProperty.id,
40093
39965
  "animationLayoutProperty",
40094
- resolveMessage(messages145.animationLayoutProperty, {
39966
+ resolveMessage(messages144.animationLayoutProperty, {
40095
39967
  animation: match.name,
40096
39968
  property: match.property
40097
39969
  }),
@@ -40161,13 +40033,13 @@ function firstRiskyAnimationName(names, riskyKeyframes) {
40161
40033
  }
40162
40034
 
40163
40035
  // src/cross-file/rules/css-layout-stateful-box-model-shift.ts
40164
- var messages146 = {
40036
+ var messages145 = {
40165
40037
  statefulBoxModelShift: "State selector '{{selector}}' changes layout-affecting '{{property}}'. Keep geometry stable across states to avoid CLS."
40166
40038
  };
40167
40039
  var cssLayoutStatefulBoxModelShift = defineCrossRule({
40168
40040
  id: "css-layout-stateful-box-model-shift",
40169
40041
  severity: "warn",
40170
- messages: messages146,
40042
+ messages: messages145,
40171
40043
  meta: {
40172
40044
  description: "Disallow stateful selector changes that alter element geometry and trigger layout shifts.",
40173
40045
  fixable: false,
@@ -40208,7 +40080,7 @@ var cssLayoutStatefulBoxModelShift = defineCrossRule({
40208
40080
  },
40209
40081
  cssLayoutStatefulBoxModelShift.id,
40210
40082
  "statefulBoxModelShift",
40211
- resolveMessage(messages146.statefulBoxModelShift, {
40083
+ resolveMessage(messages145.statefulBoxModelShift, {
40212
40084
  selector: match.raw,
40213
40085
  property: declaration.property
40214
40086
  }),
@@ -40302,14 +40174,14 @@ function lookupBaseByProperty(baseValueIndex, selectorKeys) {
40302
40174
 
40303
40175
  // src/cross-file/rules/css-layout-unsized-replaced-element.ts
40304
40176
  import ts134 from "typescript";
40305
- var messages147 = {
40177
+ var messages146 = {
40306
40178
  unsizedReplacedElement: "Replaced element '{{tag}}' has no stable reserved size (width/height or aspect-ratio with a dimension), which can cause CLS."
40307
40179
  };
40308
40180
  var REPLACED_MEDIA_TAGS = /* @__PURE__ */ new Set(["img", "video", "iframe", "canvas", "svg"]);
40309
40181
  var cssLayoutUnsizedReplacedElement = defineCrossRule({
40310
40182
  id: "css-layout-unsized-replaced-element",
40311
40183
  severity: "warn",
40312
- messages: messages147,
40184
+ messages: messages146,
40313
40185
  meta: {
40314
40186
  description: "Require stable reserved geometry for replaced media elements to prevent layout shifts.",
40315
40187
  fixable: false,
@@ -40334,7 +40206,7 @@ var cssLayoutUnsizedReplacedElement = defineCrossRule({
40334
40206
  ref.solid.sourceFile,
40335
40207
  cssLayoutUnsizedReplacedElement.id,
40336
40208
  "unsizedReplacedElement",
40337
- resolveMessage(messages147.unsizedReplacedElement, { tag }),
40209
+ resolveMessage(messages146.unsizedReplacedElement, { tag }),
40338
40210
  "warn"
40339
40211
  )
40340
40212
  );
@@ -40387,7 +40259,7 @@ function readPositiveJsxAttribute(solid, element, name) {
40387
40259
  }
40388
40260
 
40389
40261
  // src/cross-file/rules/css-layout-dynamic-slot-no-reserved-space.ts
40390
- var messages148 = {
40262
+ var messages147 = {
40391
40263
  dynamicSlotNoReservedSpace: "Dynamic content container '{{tag}}' does not reserve block space (min-height/height/aspect-ratio/contain-intrinsic-size), which can cause CLS."
40392
40264
  };
40393
40265
  var INLINE_DISPLAYS = /* @__PURE__ */ new Set(["inline", "contents"]);
@@ -40409,7 +40281,7 @@ function hasOutOfFlowAncestor(layout, node) {
40409
40281
  var cssLayoutDynamicSlotNoReservedSpace = defineCrossRule({
40410
40282
  id: "css-layout-dynamic-slot-no-reserved-space",
40411
40283
  severity: "warn",
40412
- messages: messages148,
40284
+ messages: messages147,
40413
40285
  meta: {
40414
40286
  description: "Require reserved block space for dynamic content containers to avoid layout shifts.",
40415
40287
  fixable: false,
@@ -40432,19 +40304,19 @@ var cssLayoutDynamicSlotNoReservedSpace = defineCrossRule({
40432
40304
  const reservedSpace = readReservedSpaceFact(context.layout, node);
40433
40305
  if (reservedSpace.hasReservedSpace) continue;
40434
40306
  if (hasBlockAxisPadding(snapshot)) continue;
40435
- if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutDynamicSlotNoReservedSpace.id, "dynamicSlotNoReservedSpace", messages148.dynamicSlotNoReservedSpace, cssLayoutDynamicSlotNoReservedSpace.severity)) continue;
40307
+ if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutDynamicSlotNoReservedSpace.id, "dynamicSlotNoReservedSpace", messages147.dynamicSlotNoReservedSpace, cssLayoutDynamicSlotNoReservedSpace.severity)) continue;
40436
40308
  }
40437
40309
  }
40438
40310
  });
40439
40311
 
40440
40312
  // src/cross-file/rules/css-layout-scrollbar-gutter-instability.ts
40441
- var messages149 = {
40313
+ var messages148 = {
40442
40314
  missingScrollbarGutter: "Scrollable container '{{tag}}' uses overflow auto/scroll without `scrollbar-gutter: stable`, which can trigger CLS when scrollbars appear."
40443
40315
  };
40444
40316
  var cssLayoutScrollbarGutterInstability = defineCrossRule({
40445
40317
  id: "css-layout-scrollbar-gutter-instability",
40446
40318
  severity: "warn",
40447
- messages: messages149,
40319
+ messages: messages148,
40448
40320
  meta: {
40449
40321
  description: "Require stable scrollbar gutters for scrollable containers to reduce layout shifts.",
40450
40322
  fixable: false,
@@ -40463,19 +40335,19 @@ var cssLayoutScrollbarGutterInstability = defineCrossRule({
40463
40335
  if (scrollbarWidth === "none") continue;
40464
40336
  const gutter = readKnownNormalized(snapshot, "scrollbar-gutter");
40465
40337
  if (gutter !== null && gutter.startsWith("stable")) continue;
40466
- if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutScrollbarGutterInstability.id, "missingScrollbarGutter", messages149.missingScrollbarGutter, cssLayoutScrollbarGutterInstability.severity)) continue;
40338
+ if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutScrollbarGutterInstability.id, "missingScrollbarGutter", messages148.missingScrollbarGutter, cssLayoutScrollbarGutterInstability.severity)) continue;
40467
40339
  }
40468
40340
  }
40469
40341
  });
40470
40342
 
40471
40343
  // src/cross-file/rules/css-layout-overflow-anchor-instability.ts
40472
- var messages150 = {
40344
+ var messages149 = {
40473
40345
  unstableOverflowAnchor: "Element '{{tag}}' sets `overflow-anchor: none` on a {{context}} container; disabling scroll anchoring can amplify visible layout shifts."
40474
40346
  };
40475
40347
  var cssLayoutOverflowAnchorInstability = defineCrossRule({
40476
40348
  id: "css-layout-overflow-anchor-instability",
40477
40349
  severity: "warn",
40478
- messages: messages150,
40350
+ messages: messages149,
40479
40351
  meta: {
40480
40352
  description: "Disallow overflow-anchor none on dynamic or scrollable containers prone to visible layout shifts.",
40481
40353
  fixable: false,
@@ -40493,20 +40365,20 @@ var cssLayoutOverflowAnchorInstability = defineCrossRule({
40493
40365
  const isDynamicContainer = isDynamicContainerLike(node);
40494
40366
  if (!isScrollable && !isDynamicContainer) continue;
40495
40367
  const containerContext = isScrollable ? "scrollable" : "dynamic";
40496
- if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutOverflowAnchorInstability.id, "unstableOverflowAnchor", messages150.unstableOverflowAnchor, cssLayoutOverflowAnchorInstability.severity, { context: containerContext })) continue;
40368
+ if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutOverflowAnchorInstability.id, "unstableOverflowAnchor", messages149.unstableOverflowAnchor, cssLayoutOverflowAnchorInstability.severity, { context: containerContext })) continue;
40497
40369
  }
40498
40370
  }
40499
40371
  });
40500
40372
 
40501
40373
  // src/cross-file/rules/css-layout-font-swap-instability.ts
40502
- var messages151 = {
40374
+ var messages150 = {
40503
40375
  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."
40504
40376
  };
40505
40377
  var SWAP_DISPLAYS = /* @__PURE__ */ new Set(["swap", "fallback"]);
40506
40378
  var cssLayoutFontSwapInstability = defineCrossRule({
40507
40379
  id: "css-layout-font-swap-instability",
40508
40380
  severity: "warn",
40509
- messages: messages151,
40381
+ messages: messages150,
40510
40382
  meta: {
40511
40383
  description: "Require metric overrides for swapping webfonts to reduce layout shifts during font load.",
40512
40384
  fixable: false,
@@ -40553,7 +40425,7 @@ var cssLayoutFontSwapInstability = defineCrossRule({
40553
40425
  },
40554
40426
  cssLayoutFontSwapInstability.id,
40555
40427
  "unstableFontSwap",
40556
- resolveMessage(messages151.unstableFontSwap, {
40428
+ resolveMessage(messages150.unstableFontSwap, {
40557
40429
  family,
40558
40430
  display: report.display
40559
40431
  }),
@@ -40566,14 +40438,14 @@ var cssLayoutFontSwapInstability = defineCrossRule({
40566
40438
  });
40567
40439
 
40568
40440
  // src/cross-file/rules/css-layout-conditional-display-collapse.ts
40569
- var messages152 = {
40441
+ var messages151 = {
40570
40442
  conditionalDisplayCollapse: "Conditional display sets '{{display}}' on '{{tag}}' without stable reserved space, which can collapse/expand layout and cause CLS."
40571
40443
  };
40572
40444
  var COLLAPSING_DISPLAYS = /* @__PURE__ */ new Set(["none", "contents"]);
40573
40445
  var cssLayoutConditionalDisplayCollapse = defineCrossRule({
40574
40446
  id: "css-layout-conditional-display-collapse",
40575
40447
  severity: "warn",
40576
- messages: messages152,
40448
+ messages: messages151,
40577
40449
  meta: {
40578
40450
  description: "Disallow conditional display collapse in flow without reserved geometry.",
40579
40451
  fixable: false,
@@ -40594,13 +40466,13 @@ var cssLayoutConditionalDisplayCollapse = defineCrossRule({
40594
40466
  if (!isFlowRelevantBySiblingsOrText(node, snapshot.node.textualContent)) continue;
40595
40467
  const reservedSpace = readReservedSpaceFact(context.layout, node);
40596
40468
  if (reservedSpace.hasReservedSpace) continue;
40597
- if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutConditionalDisplayCollapse.id, "conditionalDisplayCollapse", messages152.conditionalDisplayCollapse, cssLayoutConditionalDisplayCollapse.severity, { display })) continue;
40469
+ if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutConditionalDisplayCollapse.id, "conditionalDisplayCollapse", messages151.conditionalDisplayCollapse, cssLayoutConditionalDisplayCollapse.severity, { display })) continue;
40598
40470
  }
40599
40471
  }
40600
40472
  });
40601
40473
 
40602
40474
  // src/cross-file/rules/css-layout-conditional-white-space-wrap-shift.ts
40603
- var messages153 = {
40475
+ var messages152 = {
40604
40476
  conditionalWhiteSpaceShift: "Conditional white-space '{{whiteSpace}}' on '{{tag}}' can reflow text and shift siblings; keep wrapping behavior stable or reserve geometry."
40605
40477
  };
40606
40478
  var WRAP_SHIFT_VALUES = /* @__PURE__ */ new Set(["nowrap", "pre"]);
@@ -40609,7 +40481,7 @@ var BLOCK_SIZE_PROPERTIES = ["height", "min-height"];
40609
40481
  var cssLayoutConditionalWhiteSpaceWrapShift = defineCrossRule({
40610
40482
  id: "css-layout-conditional-white-space-wrap-shift",
40611
40483
  severity: "warn",
40612
- messages: messages153,
40484
+ messages: messages152,
40613
40485
  meta: {
40614
40486
  description: "Disallow conditional white-space wrapping mode toggles that can trigger CLS.",
40615
40487
  fixable: false,
@@ -40632,7 +40504,7 @@ var cssLayoutConditionalWhiteSpaceWrapShift = defineCrossRule({
40632
40504
  if (!flow.inFlow) continue;
40633
40505
  if (!isFlowRelevantBySiblingsOrText(node, snapshot.node.textualContent)) continue;
40634
40506
  if (hasStableTextShell(snapshot)) continue;
40635
- if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutConditionalWhiteSpaceWrapShift.id, "conditionalWhiteSpaceShift", messages153.conditionalWhiteSpaceShift, cssLayoutConditionalWhiteSpaceWrapShift.severity, { whiteSpace })) continue;
40507
+ if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutConditionalWhiteSpaceWrapShift.id, "conditionalWhiteSpaceShift", messages152.conditionalWhiteSpaceShift, cssLayoutConditionalWhiteSpaceWrapShift.severity, { whiteSpace })) continue;
40636
40508
  }
40637
40509
  }
40638
40510
  });
@@ -40654,13 +40526,13 @@ function hasWrapShiftDelta(delta) {
40654
40526
  }
40655
40527
 
40656
40528
  // src/cross-file/rules/css-layout-overflow-mode-toggle-instability.ts
40657
- var messages154 = {
40529
+ var messages153 = {
40658
40530
  overflowModeToggle: "Conditional overflow mode changes scrolling ('{{overflow}}') on '{{tag}}' without `scrollbar-gutter: stable`, which can trigger CLS."
40659
40531
  };
40660
40532
  var cssLayoutOverflowModeToggleInstability = defineCrossRule({
40661
40533
  id: "css-layout-overflow-mode-toggle-instability",
40662
40534
  severity: "warn",
40663
- messages: messages154,
40535
+ messages: messages153,
40664
40536
  meta: {
40665
40537
  description: "Disallow conditional overflow mode switches that can introduce scrollbar-induced layout shifts.",
40666
40538
  fixable: false,
@@ -40685,7 +40557,7 @@ var cssLayoutOverflowModeToggleInstability = defineCrossRule({
40685
40557
  const gutter = readKnownNormalizedWithGuard(snapshot, "scrollbar-gutter");
40686
40558
  if (gutter !== null && gutter.startsWith("stable")) continue;
40687
40559
  const overflowValue = scrollFact.overflowY ?? scrollFact.overflow ?? "auto";
40688
- if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutOverflowModeToggleInstability.id, "overflowModeToggle", messages154.overflowModeToggle, cssLayoutOverflowModeToggleInstability.severity, { overflow: overflowValue })) continue;
40560
+ if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutOverflowModeToggleInstability.id, "overflowModeToggle", messages153.overflowModeToggle, cssLayoutOverflowModeToggleInstability.severity, { overflow: overflowValue })) continue;
40689
40561
  }
40690
40562
  }
40691
40563
  });
@@ -40705,7 +40577,7 @@ function hasAnyScrollValue(delta) {
40705
40577
  }
40706
40578
 
40707
40579
  // src/cross-file/rules/css-layout-box-sizing-toggle-with-chrome.ts
40708
- var messages155 = {
40580
+ var messages154 = {
40709
40581
  boxSizingToggleWithChrome: "Conditional `box-sizing` toggle on '{{tag}}' combines with non-zero padding/border, which can shift layout and trigger CLS."
40710
40582
  };
40711
40583
  var BOX_SIZING_VALUES = /* @__PURE__ */ new Set(["content-box", "border-box"]);
@@ -40722,7 +40594,7 @@ var CHROME_PROPERTIES = [
40722
40594
  var cssLayoutBoxSizingToggleWithChrome = defineCrossRule({
40723
40595
  id: "css-layout-box-sizing-toggle-with-chrome",
40724
40596
  severity: "warn",
40725
- messages: messages155,
40597
+ messages: messages154,
40726
40598
  meta: {
40727
40599
  description: "Disallow conditional box-sizing mode toggles when box chrome contributes to geometry shifts.",
40728
40600
  fixable: false,
@@ -40740,7 +40612,7 @@ var cssLayoutBoxSizingToggleWithChrome = defineCrossRule({
40740
40612
  if (!boxSizingDelta.hasConditional) continue;
40741
40613
  if (!boxSizingDelta.hasDelta) continue;
40742
40614
  if (!hasNonZeroChrome(snapshot)) continue;
40743
- if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutBoxSizingToggleWithChrome.id, "boxSizingToggleWithChrome", messages155.boxSizingToggleWithChrome, cssLayoutBoxSizingToggleWithChrome.severity)) continue;
40615
+ if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutBoxSizingToggleWithChrome.id, "boxSizingToggleWithChrome", messages154.boxSizingToggleWithChrome, cssLayoutBoxSizingToggleWithChrome.severity)) continue;
40744
40616
  }
40745
40617
  }
40746
40618
  });
@@ -40749,13 +40621,13 @@ function hasNonZeroChrome(snapshot) {
40749
40621
  }
40750
40622
 
40751
40623
  // src/cross-file/rules/css-layout-content-visibility-no-intrinsic-size.ts
40752
- var messages156 = {
40624
+ var messages155 = {
40753
40625
  missingIntrinsicSize: "`content-visibility: auto` on '{{tag}}' lacks intrinsic size reservation (`contain-intrinsic-size`/min-height/height/aspect-ratio), which can cause CLS."
40754
40626
  };
40755
40627
  var cssLayoutContentVisibilityNoIntrinsicSize = defineCrossRule({
40756
40628
  id: "css-layout-content-visibility-no-intrinsic-size",
40757
40629
  severity: "warn",
40758
- messages: messages156,
40630
+ messages: messages155,
40759
40631
  meta: {
40760
40632
  description: "Require intrinsic size reservation when using content-visibility auto to avoid late layout shifts.",
40761
40633
  fixable: false,
@@ -40770,19 +40642,19 @@ var cssLayoutContentVisibilityNoIntrinsicSize = defineCrossRule({
40770
40642
  if (!isDeferredContainerLike(node, snapshot.node.textualContent)) continue;
40771
40643
  const reservedSpace = readReservedSpaceFact(context.layout, node);
40772
40644
  if (reservedSpace.hasReservedSpace) continue;
40773
- if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutContentVisibilityNoIntrinsicSize.id, "missingIntrinsicSize", messages156.missingIntrinsicSize, cssLayoutContentVisibilityNoIntrinsicSize.severity)) continue;
40645
+ if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutContentVisibilityNoIntrinsicSize.id, "missingIntrinsicSize", messages155.missingIntrinsicSize, cssLayoutContentVisibilityNoIntrinsicSize.severity)) continue;
40774
40646
  }
40775
40647
  }
40776
40648
  });
40777
40649
 
40778
40650
  // src/cross-file/rules/css-layout-conditional-offset-shift.ts
40779
- var messages157 = {
40651
+ var messages156 = {
40780
40652
  conditionalOffsetShift: "Conditional style applies non-zero '{{property}}' offset ({{value}}), which can cause layout shifts when conditions toggle."
40781
40653
  };
40782
40654
  var cssLayoutConditionalOffsetShift = defineCrossRule({
40783
40655
  id: "css-layout-conditional-offset-shift",
40784
40656
  severity: "warn",
40785
- messages: messages157,
40657
+ messages: messages156,
40786
40658
  meta: {
40787
40659
  description: "Disallow conditional non-zero block-axis offsets that can trigger layout shifts.",
40788
40660
  fixable: false,
@@ -40808,7 +40680,7 @@ var cssLayoutConditionalOffsetShift = defineCrossRule({
40808
40680
  ref.solid.sourceFile,
40809
40681
  cssLayoutConditionalOffsetShift.id,
40810
40682
  "conditionalOffsetShift",
40811
- resolveMessage(messages157.conditionalOffsetShift, {
40683
+ resolveMessage(messages156.conditionalOffsetShift, {
40812
40684
  property: match.property,
40813
40685
  value: `${formatFixed(match.value)}px`
40814
40686
  }),
@@ -40869,7 +40741,7 @@ function hasStableBaseline(baselineBySignal, property, expectedPx) {
40869
40741
 
40870
40742
  // src/cross-file/rules/jsx-layout-unstable-style-toggle.ts
40871
40743
  import ts135 from "typescript";
40872
- var messages158 = {
40744
+ var messages157 = {
40873
40745
  unstableLayoutStyleToggle: "Dynamic style value for '{{property}}' can toggle layout geometry at runtime and cause CLS."
40874
40746
  };
40875
40747
  var PX_NUMBER_PROPERTIES = /* @__PURE__ */ new Set([
@@ -40892,7 +40764,7 @@ var POSITIONED_OFFSET_PROPERTIES = /* @__PURE__ */ new Set([
40892
40764
  var jsxLayoutUnstableStyleToggle = defineCrossRule({
40893
40765
  id: "jsx-layout-unstable-style-toggle",
40894
40766
  severity: "warn",
40895
- messages: messages158,
40767
+ messages: messages157,
40896
40768
  meta: {
40897
40769
  description: "Flag dynamic inline style values on layout-sensitive properties that can trigger CLS.",
40898
40770
  fixable: false,
@@ -40914,7 +40786,7 @@ var jsxLayoutUnstableStyleToggle = defineCrossRule({
40914
40786
  solid.sourceFile,
40915
40787
  jsxLayoutUnstableStyleToggle.id,
40916
40788
  "unstableLayoutStyleToggle",
40917
- resolveMessage(messages158.unstableLayoutStyleToggle, { property: normalized }),
40789
+ resolveMessage(messages157.unstableLayoutStyleToggle, { property: normalized }),
40918
40790
  "warn"
40919
40791
  )
40920
40792
  );
@@ -41031,14 +40903,14 @@ function unwrapTypeWrapper(node) {
41031
40903
 
41032
40904
  // src/cross-file/rules/jsx-layout-classlist-geometry-toggle.ts
41033
40905
  import ts136 from "typescript";
41034
- var messages159 = {
40906
+ var messages158 = {
41035
40907
  classListGeometryToggle: "classList toggles '{{className}}', and matching CSS changes layout-affecting '{{property}}', which can cause CLS."
41036
40908
  };
41037
40909
  var OUT_OF_FLOW_POSITIONS2 = /* @__PURE__ */ new Set(["fixed", "absolute"]);
41038
40910
  var jsxLayoutClasslistGeometryToggle = defineCrossRule({
41039
40911
  id: "jsx-layout-classlist-geometry-toggle",
41040
40912
  severity: "warn",
41041
- messages: messages159,
40913
+ messages: messages158,
41042
40914
  meta: {
41043
40915
  description: "Flag classList-driven class toggles that map to layout-affecting CSS geometry changes.",
41044
40916
  fixable: false,
@@ -41064,7 +40936,7 @@ var jsxLayoutClasslistGeometryToggle = defineCrossRule({
41064
40936
  solid.sourceFile,
41065
40937
  jsxLayoutClasslistGeometryToggle.id,
41066
40938
  "classListGeometryToggle",
41067
- resolveMessage(messages159.classListGeometryToggle, {
40939
+ resolveMessage(messages158.classListGeometryToggle, {
41068
40940
  className,
41069
40941
  property
41070
40942
  }),
@@ -41113,14 +40985,14 @@ function isDynamicallyToggleable(node) {
41113
40985
  }
41114
40986
 
41115
40987
  // src/cross-file/rules/jsx-layout-picture-source-ratio-consistency.ts
41116
- var messages160 = {
40988
+ var messages159 = {
41117
40989
  inconsistentPictureRatio: "`<picture>` source ratio {{sourceRatio}} differs from fallback img ratio {{imgRatio}}, which can cause reserved-space mismatch and CLS."
41118
40990
  };
41119
40991
  var RATIO_DELTA_THRESHOLD = 0.02;
41120
40992
  var jsxLayoutPictureSourceRatioConsistency = defineCrossRule({
41121
40993
  id: "jsx-layout-picture-source-ratio-consistency",
41122
40994
  severity: "warn",
41123
- messages: messages160,
40995
+ messages: messages159,
41124
40996
  meta: {
41125
40997
  description: "Require consistent intrinsic aspect ratios across <picture> sources and fallback image.",
41126
40998
  fixable: false,
@@ -41143,7 +41015,7 @@ var jsxLayoutPictureSourceRatioConsistency = defineCrossRule({
41143
41015
  solid.sourceFile,
41144
41016
  jsxLayoutPictureSourceRatioConsistency.id,
41145
41017
  "inconsistentPictureRatio",
41146
- resolveMessage(messages160.inconsistentPictureRatio, {
41018
+ resolveMessage(messages159.inconsistentPictureRatio, {
41147
41019
  sourceRatio: mismatch.sourceRatio,
41148
41020
  imgRatio: mismatch.imgRatio
41149
41021
  }),
@@ -41213,13 +41085,13 @@ function formatRatio(value2) {
41213
41085
  }
41214
41086
 
41215
41087
  // src/cross-file/rules/jsx-layout-fill-image-parent-must-be-sized.ts
41216
- var messages161 = {
41088
+ var messages160 = {
41217
41089
  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."
41218
41090
  };
41219
41091
  var jsxLayoutFillImageParentMustBeSized = defineCrossRule({
41220
41092
  id: "jsx-layout-fill-image-parent-must-be-sized",
41221
41093
  severity: "warn",
41222
- messages: messages161,
41094
+ messages: messages160,
41223
41095
  meta: {
41224
41096
  description: "Require stable parent size and positioning for fill-image component usage.",
41225
41097
  fixable: false,
@@ -41249,7 +41121,7 @@ var jsxLayoutFillImageParentMustBeSized = defineCrossRule({
41249
41121
  solid.sourceFile,
41250
41122
  jsxLayoutFillImageParentMustBeSized.id,
41251
41123
  "unsizedFillParent",
41252
- resolveMessage(messages161.unsizedFillParent, {
41124
+ resolveMessage(messages160.unsizedFillParent, {
41253
41125
  component: element.tag ?? "Image"
41254
41126
  }),
41255
41127
  "warn"
@@ -41260,6 +41132,210 @@ var jsxLayoutFillImageParentMustBeSized = defineCrossRule({
41260
41132
  }
41261
41133
  });
41262
41134
 
41135
+ // src/cross-file/rules/jsx-layout-policy-touch-target.ts
41136
+ var messages161 = {
41137
+ heightTooSmall: "`{{signal}}` of `{{value}}px` is below the minimum `{{min}}px` for interactive element `<{{tag}}>` in policy `{{policy}}`.",
41138
+ widthTooSmall: "`{{signal}}` of `{{value}}px` is below the minimum `{{min}}px` for interactive element `<{{tag}}>` in policy `{{policy}}`.",
41139
+ paddingTooSmall: "Horizontal padding `{{signal}}` of `{{value}}px` is below the minimum `{{min}}px` for interactive element `<{{tag}}>` in policy `{{policy}}`.",
41140
+ 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.",
41141
+ 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."
41142
+ };
41143
+ var INTERACTIVE_HTML_TAGS2 = /* @__PURE__ */ new Set(["button", "a", "input", "select", "textarea", "label", "summary"]);
41144
+ var INTERACTIVE_ARIA_ROLES2 = /* @__PURE__ */ new Set([
41145
+ "button",
41146
+ "link",
41147
+ "checkbox",
41148
+ "radio",
41149
+ "combobox",
41150
+ "listbox",
41151
+ "menuitem",
41152
+ "menuitemcheckbox",
41153
+ "menuitemradio",
41154
+ "option",
41155
+ "switch",
41156
+ "tab"
41157
+ ]);
41158
+ function classifyInteractive(node, solid, element, layout) {
41159
+ const tag = node.tagName;
41160
+ if (tag !== null && INTERACTIVE_HTML_TAGS2.has(tag)) {
41161
+ if (tag === "input" || tag === "select" || tag === "textarea") return "input";
41162
+ return "button";
41163
+ }
41164
+ const roleAttr = getJSXAttributeEntity(solid, element, "role");
41165
+ if (roleAttr !== null && roleAttr.valueNode !== null) {
41166
+ const role = getStaticStringFromJSXValue(roleAttr.valueNode);
41167
+ if (role !== null && INTERACTIVE_ARIA_ROLES2.has(role)) return "button";
41168
+ }
41169
+ const hostRef = layout.hostElementRefsByNode.get(node) ?? null;
41170
+ if (hostRef !== null && hostRef.element.tagName !== null) {
41171
+ const hostTag = hostRef.element.tagName;
41172
+ if (INTERACTIVE_HTML_TAGS2.has(hostTag)) {
41173
+ if (hostTag === "input" || hostTag === "select" || hostTag === "textarea") return "input";
41174
+ return "button";
41175
+ }
41176
+ }
41177
+ return null;
41178
+ }
41179
+ function isVisuallyHidden(snapshot) {
41180
+ const position = readKnownNormalized(snapshot, "position");
41181
+ if (position !== "absolute" && position !== "fixed") return false;
41182
+ const node = snapshot.node;
41183
+ const opacityAttr = node.inlineStyleValues.get("opacity");
41184
+ if (opacityAttr === "0") return true;
41185
+ if (node.classTokenSet.has("opacity-0")) return true;
41186
+ return false;
41187
+ }
41188
+ var jsxLayoutPolicyTouchTarget = defineCrossRule({
41189
+ id: "jsx-layout-policy-touch-target",
41190
+ severity: "warn",
41191
+ messages: messages161,
41192
+ meta: {
41193
+ description: "Enforce minimum interactive element sizes per accessibility policy via resolved layout signals.",
41194
+ fixable: false,
41195
+ category: "css-a11y"
41196
+ },
41197
+ check(context, emit) {
41198
+ const policy = getActivePolicy();
41199
+ if (policy === null) return;
41200
+ const policyName = getActivePolicyName() ?? "";
41201
+ const { layout } = context;
41202
+ const elements = layout.elements;
41203
+ for (let i = 0; i < elements.length; i++) {
41204
+ const node = elements[i];
41205
+ if (!node) continue;
41206
+ const ref = readElementRef(layout, node);
41207
+ if (!ref) continue;
41208
+ const kind = classifyInteractive(node, ref.solid, ref.element, layout);
41209
+ if (kind === null) continue;
41210
+ const snapshot = collectSignalSnapshot(context, node);
41211
+ if (isVisuallyHidden(snapshot)) continue;
41212
+ const tag = node.tagName ?? node.tag ?? "element";
41213
+ checkDimension(
41214
+ snapshot,
41215
+ "height",
41216
+ kind === "button" ? policy.minButtonHeight : policy.minInputHeight,
41217
+ layout,
41218
+ node,
41219
+ emit,
41220
+ "heightTooSmall",
41221
+ messages161.heightTooSmall,
41222
+ tag,
41223
+ policyName
41224
+ );
41225
+ checkDimension(
41226
+ snapshot,
41227
+ "min-height",
41228
+ kind === "button" ? policy.minButtonHeight : policy.minInputHeight,
41229
+ layout,
41230
+ node,
41231
+ emit,
41232
+ "heightTooSmall",
41233
+ messages161.heightTooSmall,
41234
+ tag,
41235
+ policyName
41236
+ );
41237
+ checkDimension(
41238
+ snapshot,
41239
+ "width",
41240
+ kind === "button" ? policy.minButtonWidth : policy.minTouchTarget,
41241
+ layout,
41242
+ node,
41243
+ emit,
41244
+ "widthTooSmall",
41245
+ messages161.widthTooSmall,
41246
+ tag,
41247
+ policyName
41248
+ );
41249
+ checkDimension(
41250
+ snapshot,
41251
+ "min-width",
41252
+ kind === "button" ? policy.minButtonWidth : policy.minTouchTarget,
41253
+ layout,
41254
+ node,
41255
+ emit,
41256
+ "widthTooSmall",
41257
+ messages161.widthTooSmall,
41258
+ tag,
41259
+ policyName
41260
+ );
41261
+ if (kind === "button") {
41262
+ checkDimension(
41263
+ snapshot,
41264
+ "padding-left",
41265
+ policy.minButtonHorizontalPadding,
41266
+ layout,
41267
+ node,
41268
+ emit,
41269
+ "paddingTooSmall",
41270
+ messages161.paddingTooSmall,
41271
+ tag,
41272
+ policyName
41273
+ );
41274
+ checkDimension(
41275
+ snapshot,
41276
+ "padding-right",
41277
+ policy.minButtonHorizontalPadding,
41278
+ layout,
41279
+ node,
41280
+ emit,
41281
+ "paddingTooSmall",
41282
+ messages161.paddingTooSmall,
41283
+ tag,
41284
+ policyName
41285
+ );
41286
+ }
41287
+ const reservedSpace = readReservedSpaceFact(layout, node);
41288
+ const minBlock = kind === "button" ? policy.minButtonHeight : policy.minInputHeight;
41289
+ const minInline = kind === "button" ? policy.minButtonWidth : policy.minTouchTarget;
41290
+ if (!reservedSpace.hasUsableBlockDimension) {
41291
+ emitLayoutDiagnostic(
41292
+ layout,
41293
+ node,
41294
+ emit,
41295
+ jsxLayoutPolicyTouchTarget.id,
41296
+ "noReservedBlockSize",
41297
+ messages161.noReservedBlockSize,
41298
+ "warn",
41299
+ { tag, min: String(minBlock), policy: policyName }
41300
+ );
41301
+ }
41302
+ if (!reservedSpace.hasUsableInlineDimension) {
41303
+ emitLayoutDiagnostic(
41304
+ layout,
41305
+ node,
41306
+ emit,
41307
+ jsxLayoutPolicyTouchTarget.id,
41308
+ "noReservedInlineSize",
41309
+ messages161.noReservedInlineSize,
41310
+ "warn",
41311
+ { tag, min: String(minInline), policy: policyName }
41312
+ );
41313
+ }
41314
+ }
41315
+ }
41316
+ });
41317
+ function checkDimension(snapshot, signal, min, layout, node, emit, messageId, template, tag, policyName) {
41318
+ const px = readKnownPx(snapshot, signal);
41319
+ if (px === null) return;
41320
+ if (px >= min) return;
41321
+ emitLayoutDiagnostic(
41322
+ layout,
41323
+ node,
41324
+ emit,
41325
+ jsxLayoutPolicyTouchTarget.id,
41326
+ messageId,
41327
+ template,
41328
+ "warn",
41329
+ {
41330
+ signal,
41331
+ value: formatRounded(px),
41332
+ min: String(min),
41333
+ tag,
41334
+ policy: policyName
41335
+ }
41336
+ );
41337
+ }
41338
+
41263
41339
  // src/cross-file/rules/index.ts
41264
41340
  var rules3 = [
41265
41341
  jsxNoUndefinedCssClass,
@@ -41291,7 +41367,8 @@ var rules3 = [
41291
41367
  cssLayoutOverflowModeToggleInstability,
41292
41368
  cssLayoutBoxSizingToggleWithChrome,
41293
41369
  cssLayoutContentVisibilityNoIntrinsicSize,
41294
- cssLayoutConditionalOffsetShift
41370
+ cssLayoutConditionalOffsetShift,
41371
+ jsxLayoutPolicyTouchTarget
41295
41372
  ];
41296
41373
 
41297
41374
  // src/cross-file/plugin.ts
@@ -41388,4 +41465,4 @@ export {
41388
41465
  rules3,
41389
41466
  runCrossFileRules
41390
41467
  };
41391
- //# sourceMappingURL=chunk-SVX3WRFV.js.map
41468
+ //# sourceMappingURL=chunk-MJKIL7DJ.js.map