@drskillissue/ganko 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1426,6 +1426,9 @@ interface SolidSyntaxTree {
1426
1426
  readonly name: string;
1427
1427
  }>;
1428
1428
  readonly componentFunctions: readonly FunctionEntity[];
1429
+ /** Maps sub-component function scope ID → compound base's children-forwarding JSX element ID.
1430
+ * Built from Object.assign compound component patterns during syntax tree construction. */
1431
+ readonly compoundComponentParents: ReadonlyMap<number, number>;
1429
1432
  readonly functionsWithReactiveCaptures: readonly FunctionEntity[];
1430
1433
  readonly reactiveVariables: readonly VariableEntity$1[];
1431
1434
  readonly propsVariables: readonly VariableEntity$1[];
@@ -1539,6 +1542,7 @@ interface SolidBuildContext {
1539
1542
  name: string;
1540
1543
  }>;
1541
1544
  componentFunctions: FunctionEntity[];
1545
+ compoundComponentParents: ReadonlyMap<number, number>;
1542
1546
  functionsWithReactiveCaptures: FunctionEntity[];
1543
1547
  reactiveVariables: VariableEntity$1[];
1544
1548
  propsVariables: VariableEntity$1[];
@@ -1595,13 +1599,6 @@ interface SolidBuildContext {
1595
1599
  findExpressionAtOffset(offset: number): ts.Node | null;
1596
1600
  }
1597
1601
 
1598
- /**
1599
- * Solid analysis entry point.
1600
- *
1601
- * Builds a SolidSyntaxTree from a SolidInput by running all analysis phases
1602
- * against a mutable SolidBuildContext, then freezing the result.
1603
- */
1604
-
1605
1602
  /**
1606
1603
  * Build a SolidSyntaxTree from input.
1607
1604
  *
package/dist/index.d.ts CHANGED
@@ -1426,6 +1426,9 @@ interface SolidSyntaxTree {
1426
1426
  readonly name: string;
1427
1427
  }>;
1428
1428
  readonly componentFunctions: readonly FunctionEntity[];
1429
+ /** Maps sub-component function scope ID → compound base's children-forwarding JSX element ID.
1430
+ * Built from Object.assign compound component patterns during syntax tree construction. */
1431
+ readonly compoundComponentParents: ReadonlyMap<number, number>;
1429
1432
  readonly functionsWithReactiveCaptures: readonly FunctionEntity[];
1430
1433
  readonly reactiveVariables: readonly VariableEntity$1[];
1431
1434
  readonly propsVariables: readonly VariableEntity$1[];
@@ -1539,6 +1542,7 @@ interface SolidBuildContext {
1539
1542
  name: string;
1540
1543
  }>;
1541
1544
  componentFunctions: FunctionEntity[];
1545
+ compoundComponentParents: ReadonlyMap<number, number>;
1542
1546
  functionsWithReactiveCaptures: FunctionEntity[];
1543
1547
  reactiveVariables: VariableEntity$1[];
1544
1548
  propsVariables: VariableEntity$1[];
@@ -1595,13 +1599,6 @@ interface SolidBuildContext {
1595
1599
  findExpressionAtOffset(offset: number): ts.Node | null;
1596
1600
  }
1597
1601
 
1598
- /**
1599
- * Solid analysis entry point.
1600
- *
1601
- * Builds a SolidSyntaxTree from a SolidInput by running all analysis phases
1602
- * against a mutable SolidBuildContext, then freezing the result.
1603
- */
1604
-
1605
1602
  /**
1606
1603
  * Build a SolidSyntaxTree from input.
1607
1604
  *
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  RULES,
3
3
  RULES_BY_CATEGORY,
4
4
  getRule
5
- } from "./chunk-TNKZGWOR.js";
5
+ } from "./chunk-4W4KAPRH.js";
6
6
  import {
7
7
  ACCESSIBILITY_POLICIES,
8
8
  CSS_EXTENSIONS,
@@ -83,7 +83,7 @@ import {
83
83
  splitTopLevelWhitespace,
84
84
  splitWhitespaceTokens,
85
85
  toKebabCase
86
- } from "./chunk-AXFVBCJD.js";
86
+ } from "./chunk-WJGGSO5O.js";
87
87
  import "./chunk-EGRHWZRV.js";
88
88
 
89
89
  // src/runner.ts
@@ -2715,7 +2715,7 @@ function buildElementNodes(solidTree, compilation) {
2715
2715
  const selectorDispatchKeys = buildSelectorDispatchKeys(attributes, classTokens);
2716
2716
  const inlineStyleValues = inlineStyleValuesByElementId.get(element.id) ?? EMPTY_INLINE_STYLE_VALUES;
2717
2717
  const textualContent = getTextualContentState(element, textContentMemo, compositionMetaByElementId);
2718
- const parentElementId = resolveComposedParentElementId(element, compositionMetaByElementId);
2718
+ const parentElementId = resolveComposedParentElementId(element, compositionMetaByElementId, solidTree.compoundComponentParents);
2719
2719
  records.push({
2720
2720
  element,
2721
2721
  key: `${solidTree.filePath}::${element.id}`,
@@ -2748,12 +2748,32 @@ function buildElementNodes(solidTree, compilation) {
2748
2748
  byType.set(record.tagName, (byType.get(record.tagName) ?? 0) + 1);
2749
2749
  }
2750
2750
  }
2751
+ const recordsByElementId = /* @__PURE__ */ new Map();
2752
+ for (let i = 0; i < records.length; i++) {
2753
+ const r = records[i];
2754
+ if (r) recordsByElementId.set(r.element.id, r);
2755
+ }
2756
+ const sorted = [];
2757
+ const visited = /* @__PURE__ */ new Set();
2758
+ function visitRecord(r) {
2759
+ if (visited.has(r.element.id)) return;
2760
+ visited.add(r.element.id);
2761
+ if (r.parentElementId !== null) {
2762
+ const parent = recordsByElementId.get(r.parentElementId);
2763
+ if (parent) visitRecord(parent);
2764
+ }
2765
+ sorted.push(r);
2766
+ }
2767
+ for (let i = 0; i < records.length; i++) {
2768
+ const r = records[i];
2769
+ if (r) visitRecord(r);
2770
+ }
2751
2771
  const elements = [];
2752
2772
  const nodeByElementId = /* @__PURE__ */ new Map();
2753
2773
  const lastChildByParentId = /* @__PURE__ */ new Map();
2754
2774
  const siblingTypeSeenByParentId = /* @__PURE__ */ new Map();
2755
- for (let i = 0; i < records.length; i++) {
2756
- const record = records[i];
2775
+ for (let i = 0; i < sorted.length; i++) {
2776
+ const record = sorted[i];
2757
2777
  if (!record) continue;
2758
2778
  const parentElementId = record.parentElementId;
2759
2779
  const parentNode = parentElementId === null ? null : nodeByElementId.get(parentElementId) ?? null;
@@ -2917,13 +2937,19 @@ function resolveEffectiveTag(element, hostDescriptor) {
2917
2937
  if (!element.isDomElement) return null;
2918
2938
  return element.tag;
2919
2939
  }
2920
- function resolveComposedParentElementId(element, compositionMetaByElementId) {
2940
+ function resolveComposedParentElementId(element, compositionMetaByElementId, compoundComponentParents) {
2921
2941
  let parent = element.parent;
2922
2942
  while (parent !== null) {
2923
2943
  const meta = compositionMetaByElementId.get(parent.id);
2924
2944
  if (meta && meta.participates) return parent.id;
2925
2945
  parent = parent.parent;
2926
2946
  }
2947
+ let scope = element.scope;
2948
+ while (scope !== null) {
2949
+ const compoundParent = compoundComponentParents.get(scope.id);
2950
+ if (compoundParent !== void 0) return compoundParent;
2951
+ scope = scope.parent;
2952
+ }
2927
2953
  return null;
2928
2954
  }
2929
2955
  function getTextualContentState(element, memo, compositionMetaByElementId, logger = noopLogger) {
@@ -4213,6 +4239,136 @@ function compareCascadePositions(posA, posB) {
4213
4239
  return posA.sourceOrder - posB.sourceOrder;
4214
4240
  }
4215
4241
 
4242
+ // src/compilation/analysis/layout-fact.ts
4243
+ var SCROLLABLE_VALUES = /* @__PURE__ */ new Set(["auto", "scroll"]);
4244
+ var NON_RESERVING_DIMENSION_KEYWORDS = /* @__PURE__ */ new Set(["auto", "none", "fit-content", "min-content", "max-content", "stretch", "inherit", "initial", "unset", "revert", "revert-layer"]);
4245
+ var BLOCK_LEVEL_DISPLAY_VALUES = /* @__PURE__ */ new Set(["block", "flex", "grid", "table", "list-item", "flow-root", "table-row", "table-cell", "table-caption", "table-row-group", "table-header-group", "table-footer-group", "table-column", "table-column-group"]);
4246
+ function computeReservedSpaceFact(snapshot) {
4247
+ const reasons = [];
4248
+ const hasHeight = hasDeclaredDimension(snapshot, "height");
4249
+ if (hasHeight) reasons.push("height");
4250
+ const hasBlockSize = hasDeclaredDimension(snapshot, "block-size");
4251
+ if (hasBlockSize) reasons.push("block-size");
4252
+ const hasMinHeight = hasDeclaredDimension(snapshot, "min-height");
4253
+ if (hasMinHeight) reasons.push("min-height");
4254
+ const hasMinBlockSize = hasDeclaredDimension(snapshot, "min-block-size");
4255
+ if (hasMinBlockSize) reasons.push("min-block-size");
4256
+ const hasContainIntrinsic = hasDeclaredDimension(snapshot, "contain-intrinsic-size");
4257
+ if (hasContainIntrinsic) reasons.push("contain-intrinsic-size");
4258
+ const hasAspectRatio = hasUsableAspectRatio(snapshot);
4259
+ if (hasAspectRatio) {
4260
+ if (hasDeclaredDimension(snapshot, "width")) reasons.push("aspect-ratio+width");
4261
+ if (hasDeclaredDimension(snapshot, "inline-size")) reasons.push("aspect-ratio+inline-size");
4262
+ if (hasDeclaredDimension(snapshot, "min-width")) reasons.push("aspect-ratio+min-width");
4263
+ if (hasMinBlockSize) reasons.push("aspect-ratio+min-block-size");
4264
+ if (hasMinHeight) reasons.push("aspect-ratio+min-height");
4265
+ }
4266
+ return {
4267
+ hasReservedSpace: reasons.length > 0,
4268
+ reasons,
4269
+ hasContainIntrinsicSize: hasContainIntrinsic,
4270
+ hasUsableAspectRatio: hasAspectRatio,
4271
+ hasDeclaredBlockDimension: hasHeight || hasBlockSize || hasMinHeight || hasMinBlockSize,
4272
+ hasDeclaredInlineDimension: hasDeclaredDimension(snapshot, "width") || hasDeclaredDimension(snapshot, "inline-size") || hasDeclaredDimension(snapshot, "min-width") || hasDeclaredDimension(snapshot, "flex-basis") || isBlockLevelDisplay(snapshot)
4273
+ };
4274
+ }
4275
+ function hasDeclaredDimension(snapshot, property) {
4276
+ const signal = snapshot.signals.get(property);
4277
+ if (!signal) return false;
4278
+ if (signal.kind === 0 /* Known */) {
4279
+ if (signal.px !== null) return signal.px > 0;
4280
+ if (signal.normalized.length === 0) return false;
4281
+ return !isNonReservingDimension(signal.normalized);
4282
+ }
4283
+ if (signal.kind === 1 /* Unknown */) {
4284
+ return signal.source !== null;
4285
+ }
4286
+ return false;
4287
+ }
4288
+ function isBlockLevelDisplay(snapshot) {
4289
+ const signal = snapshot.signals.get("display");
4290
+ if (!signal || signal.kind !== 0 /* Known */) return false;
4291
+ return BLOCK_LEVEL_DISPLAY_VALUES.has(signal.normalized);
4292
+ }
4293
+ function hasUsableAspectRatio(snapshot) {
4294
+ const signal = snapshot.signals.get("aspect-ratio");
4295
+ if (!signal) return false;
4296
+ if (signal.guard.kind === 1) return false;
4297
+ if (signal.kind === 1 /* Unknown */) return false;
4298
+ if (signal.kind !== 0 /* Known */) return false;
4299
+ if (signal.normalized.length === 0) return false;
4300
+ return signal.normalized !== "auto";
4301
+ }
4302
+ function isNonReservingDimension(value) {
4303
+ if (NON_RESERVING_DIMENSION_KEYWORDS.has(value)) return true;
4304
+ if (value.startsWith("fit-content(")) return true;
4305
+ return false;
4306
+ }
4307
+ function computeScrollContainerFact(snapshot) {
4308
+ const overflowSignal = snapshot.signals.get("overflow");
4309
+ const overflowYSignal = snapshot.signals.get("overflow-y");
4310
+ const overflow = overflowSignal && overflowSignal.kind === 0 /* Known */ ? overflowSignal.normalized : null;
4311
+ const overflowY = overflowYSignal && overflowYSignal.kind === 0 /* Known */ ? overflowYSignal.normalized : null;
4312
+ const shorthandAxis = parseOverflowShorthandAxis(overflow);
4313
+ const yFromLonghand = parseSingleAxisScroll(overflowY);
4314
+ const xScroll = shorthandAxis.x;
4315
+ const yScroll = yFromLonghand === null ? shorthandAxis.y : yFromLonghand;
4316
+ const hasConditionalScroll = overflowSignal?.guard.kind === 1 && (shorthandAxis.x || shorthandAxis.y) || overflowYSignal?.guard.kind === 1 && yFromLonghand === true;
4317
+ const hasUnconditionalScroll = overflowSignal?.guard.kind === 0 && (shorthandAxis.x || shorthandAxis.y) || overflowYSignal?.guard.kind === 0 && yFromLonghand === true;
4318
+ return {
4319
+ isScrollContainer: xScroll || yScroll,
4320
+ axis: toScrollAxis(xScroll, yScroll),
4321
+ overflow,
4322
+ overflowY,
4323
+ hasConditionalScroll,
4324
+ hasUnconditionalScroll
4325
+ };
4326
+ }
4327
+ var NO_SCROLL = Object.freeze({ x: false, y: false });
4328
+ var BOTH_SCROLL = Object.freeze({ x: true, y: true });
4329
+ function parseOverflowShorthandAxis(value) {
4330
+ if (value === null) return NO_SCROLL;
4331
+ const trimmed = value.trim();
4332
+ const spaceIdx = trimmed.indexOf(" ");
4333
+ if (spaceIdx === -1) {
4334
+ const scroll = SCROLLABLE_VALUES.has(trimmed);
4335
+ return scroll ? BOTH_SCROLL : NO_SCROLL;
4336
+ }
4337
+ const first = trimmed.slice(0, spaceIdx);
4338
+ const second = trimmed.slice(spaceIdx + 1).trimStart();
4339
+ return {
4340
+ x: SCROLLABLE_VALUES.has(first),
4341
+ y: SCROLLABLE_VALUES.has(second)
4342
+ };
4343
+ }
4344
+ function parseSingleAxisScroll(value) {
4345
+ if (value === null) return null;
4346
+ const trimmed = value.trim();
4347
+ const spaceIdx = trimmed.indexOf(" ");
4348
+ const first = spaceIdx === -1 ? trimmed : trimmed.slice(0, spaceIdx);
4349
+ return SCROLLABLE_VALUES.has(first);
4350
+ }
4351
+ function toScrollAxis(x, y) {
4352
+ if (x && y) return 3 /* Both */;
4353
+ if (x) return 1 /* X */;
4354
+ if (y) return 2 /* Y */;
4355
+ return 0 /* None */;
4356
+ }
4357
+ function computeFlowParticipationFact(snapshot) {
4358
+ const signal = snapshot.signals.get("position");
4359
+ if (!signal || signal.kind !== 0 /* Known */) {
4360
+ return { inFlow: true, position: null, hasConditionalOutOfFlow: false, hasUnconditionalOutOfFlow: false };
4361
+ }
4362
+ const position = signal.normalized;
4363
+ const outOfFlow = position === "absolute" || position === "fixed";
4364
+ return {
4365
+ inFlow: !outOfFlow,
4366
+ position,
4367
+ hasConditionalOutOfFlow: signal.guard.kind === 1 && outOfFlow,
4368
+ hasUnconditionalOutOfFlow: signal.guard.kind === 0 && outOfFlow
4369
+ };
4370
+ }
4371
+
4216
4372
  // src/compilation/binding/cascade-binder.ts
4217
4373
  var bindCacheBySymbolTable = /* @__PURE__ */ new WeakMap();
4218
4374
  function getOrBuildBindState(symbolTable) {
@@ -4901,126 +5057,21 @@ function augmentCascadeWithTailwindFromSymbolTable(cascade, element, symbolTable
4901
5057
  }
4902
5058
  }
4903
5059
  }
4904
- var SCROLLABLE_VALUES = /* @__PURE__ */ new Set(["auto", "scroll"]);
4905
- var OUT_OF_FLOW_POSITIONS = /* @__PURE__ */ new Set(["absolute", "fixed", "sticky"]);
4906
- function computeLayoutFact(factKind, elementId, declarations, allElements, getCascadeForElement) {
5060
+ function computeLayoutFact(factKind, elementId, snapshot, allElements, getSnapshotForElement) {
4907
5061
  switch (factKind) {
4908
5062
  case "reservedSpace":
4909
- return computeReservedSpaceFact(declarations);
5063
+ return computeReservedSpaceFact(snapshot);
4910
5064
  case "scrollContainer":
4911
- return computeScrollContainerFact(declarations);
5065
+ return computeScrollContainerFact(snapshot);
4912
5066
  case "flowParticipation":
4913
- return computeFlowParticipationFact(declarations);
5067
+ return computeFlowParticipationFact(snapshot);
4914
5068
  case "containingBlock":
4915
- return computeContainingBlockFact(elementId, allElements, getCascadeForElement);
5069
+ return computeContainingBlockFact(elementId, allElements, getSnapshotForElement);
4916
5070
  default:
4917
5071
  throw new Error(`Unknown layout fact kind: ${factKind}`);
4918
5072
  }
4919
5073
  }
4920
- function getCascadeValue(declarations, property) {
4921
- const decl = declarations.get(property);
4922
- if (!decl) return null;
4923
- return decl.value.trim().toLowerCase();
4924
- }
4925
- function computeReservedSpaceFact(declarations) {
4926
- const reasons = [];
4927
- const height = getCascadeValue(declarations, "height");
4928
- if (height !== null && height !== "auto" && height !== "fit-content" && height !== "min-content" && height !== "max-content") {
4929
- reasons.push("height");
4930
- }
4931
- const blockSize = getCascadeValue(declarations, "block-size");
4932
- if (blockSize !== null && blockSize !== "auto" && blockSize !== "fit-content" && blockSize !== "min-content" && blockSize !== "max-content") {
4933
- reasons.push("block-size");
4934
- }
4935
- const minHeight = getCascadeValue(declarations, "min-height");
4936
- if (minHeight !== null && minHeight !== "0" && minHeight !== "0px" && minHeight !== "auto") {
4937
- reasons.push("min-height");
4938
- }
4939
- const minBlockSize = getCascadeValue(declarations, "min-block-size");
4940
- if (minBlockSize !== null && minBlockSize !== "0" && minBlockSize !== "0px" && minBlockSize !== "auto") {
4941
- reasons.push("min-block-size");
4942
- }
4943
- const containIntrinsicSize = getCascadeValue(declarations, "contain-intrinsic-size");
4944
- const hasContainIntrinsicSize = containIntrinsicSize !== null;
4945
- if (hasContainIntrinsicSize) {
4946
- reasons.push("contain-intrinsic-size");
4947
- }
4948
- const aspectRatio = getCascadeValue(declarations, "aspect-ratio");
4949
- const hasUsableAspectRatio = aspectRatio !== null && aspectRatio !== "auto";
4950
- const width = getCascadeValue(declarations, "width");
4951
- const inlineSize = getCascadeValue(declarations, "inline-size");
4952
- const hasDeclaredInlineDimension = width !== null && width !== "auto" || inlineSize !== null && inlineSize !== "auto";
4953
- const hasDeclaredBlockDimension = height !== null && height !== "auto";
4954
- if (hasUsableAspectRatio && hasDeclaredInlineDimension) {
4955
- if (width !== null) reasons.push("aspect-ratio+width");
4956
- if (inlineSize !== null) reasons.push("aspect-ratio+inline-size");
4957
- }
4958
- return {
4959
- hasReservedSpace: reasons.length > 0,
4960
- reasons,
4961
- hasContainIntrinsicSize,
4962
- hasUsableAspectRatio,
4963
- hasDeclaredInlineDimension,
4964
- hasDeclaredBlockDimension
4965
- };
4966
- }
4967
- function computeScrollContainerFact(declarations) {
4968
- const overflow = getCascadeValue(declarations, "overflow");
4969
- const overflowY = getCascadeValue(declarations, "overflow-y");
4970
- let axis = 0;
4971
- let isScrollContainer = false;
4972
- let hasConditionalScroll = false;
4973
- let hasUnconditionalScroll = false;
4974
- if (overflow !== null && SCROLLABLE_VALUES.has(overflow)) {
4975
- isScrollContainer = true;
4976
- axis = 3;
4977
- const decl = declarations.get("overflow");
4978
- if (decl && decl.guardProvenance.kind === 1 /* Conditional */) {
4979
- hasConditionalScroll = true;
4980
- } else {
4981
- hasUnconditionalScroll = true;
4982
- }
4983
- }
4984
- if (overflowY !== null && SCROLLABLE_VALUES.has(overflowY)) {
4985
- isScrollContainer = true;
4986
- if (axis === 0) axis = 2;
4987
- const decl = declarations.get("overflow-y");
4988
- if (decl && decl.guardProvenance.kind === 1 /* Conditional */) {
4989
- hasConditionalScroll = true;
4990
- } else {
4991
- hasUnconditionalScroll = true;
4992
- }
4993
- }
4994
- return {
4995
- isScrollContainer,
4996
- axis,
4997
- overflow,
4998
- overflowY,
4999
- hasConditionalScroll,
5000
- hasUnconditionalScroll
5001
- };
5002
- }
5003
- function computeFlowParticipationFact(declarations) {
5004
- const position = getCascadeValue(declarations, "position");
5005
- const isOutOfFlow = position !== null && OUT_OF_FLOW_POSITIONS.has(position);
5006
- let hasConditionalOutOfFlow = false;
5007
- let hasUnconditionalOutOfFlow = false;
5008
- if (isOutOfFlow) {
5009
- const decl = declarations.get("position");
5010
- if (decl && decl.guardProvenance.kind === 1 /* Conditional */) {
5011
- hasConditionalOutOfFlow = true;
5012
- } else {
5013
- hasUnconditionalOutOfFlow = true;
5014
- }
5015
- }
5016
- return {
5017
- inFlow: !isOutOfFlow,
5018
- position,
5019
- hasConditionalOutOfFlow,
5020
- hasUnconditionalOutOfFlow
5021
- };
5022
- }
5023
- function computeContainingBlockFact(elementId, allElements, getCascadeForElement) {
5074
+ function computeContainingBlockFact(elementId, allElements, getSnapshotForElement) {
5024
5075
  let current = null;
5025
5076
  for (let i = 0; i < allElements.length; i++) {
5026
5077
  const el = allElements[i];
@@ -5034,10 +5085,11 @@ function computeContainingBlockFact(elementId, allElements, getCascadeForElement
5034
5085
  }
5035
5086
  let ancestor = current.parentElementNode;
5036
5087
  while (ancestor !== null) {
5037
- const ancestorCascade = getCascadeForElement(ancestor.elementId);
5038
- const pos = getCascadeValue(ancestorCascade, "position");
5088
+ const ancestorSnapshot = getSnapshotForElement(ancestor.elementId);
5089
+ const posSignal = ancestorSnapshot.signals.get("position");
5090
+ const pos = posSignal && posSignal.kind === 0 ? posSignal.normalized : null;
5039
5091
  if (pos !== null && pos !== "static") {
5040
- const reservedFact = computeReservedSpaceFact(ancestorCascade);
5092
+ const reservedFact = computeReservedSpaceFact(ancestorSnapshot);
5041
5093
  return {
5042
5094
  nearestPositionedAncestorKey: ancestor.key,
5043
5095
  nearestPositionedAncestorHasReservedSpace: reservedFact.hasReservedSpace
@@ -5096,59 +5148,6 @@ function buildScopedSelectorIndex(scopedCSSFiles, symbolTable) {
5096
5148
  };
5097
5149
  }
5098
5150
 
5099
- // src/compilation/analysis/layout-fact.ts
5100
- var SCROLLABLE_VALUES2 = /* @__PURE__ */ new Set(["auto", "scroll"]);
5101
- function computeScrollContainerFact2(snapshot) {
5102
- const overflowSignal = snapshot.signals.get("overflow");
5103
- const overflowYSignal = snapshot.signals.get("overflow-y");
5104
- const overflow = overflowSignal && overflowSignal.kind === 0 /* Known */ ? overflowSignal.normalized : null;
5105
- const overflowY = overflowYSignal && overflowYSignal.kind === 0 /* Known */ ? overflowYSignal.normalized : null;
5106
- const shorthandAxis = parseOverflowShorthandAxis(overflow);
5107
- const yFromLonghand = parseSingleAxisScroll(overflowY);
5108
- const xScroll = shorthandAxis.x;
5109
- const yScroll = yFromLonghand === null ? shorthandAxis.y : yFromLonghand;
5110
- const hasConditionalScroll = overflowSignal?.guard.kind === 1 && (shorthandAxis.x || shorthandAxis.y) || overflowYSignal?.guard.kind === 1 && yFromLonghand === true;
5111
- const hasUnconditionalScroll = overflowSignal?.guard.kind === 0 && (shorthandAxis.x || shorthandAxis.y) || overflowYSignal?.guard.kind === 0 && yFromLonghand === true;
5112
- return {
5113
- isScrollContainer: xScroll || yScroll,
5114
- axis: toScrollAxis(xScroll, yScroll),
5115
- overflow,
5116
- overflowY,
5117
- hasConditionalScroll,
5118
- hasUnconditionalScroll
5119
- };
5120
- }
5121
- var NO_SCROLL = Object.freeze({ x: false, y: false });
5122
- var BOTH_SCROLL = Object.freeze({ x: true, y: true });
5123
- function parseOverflowShorthandAxis(value) {
5124
- if (value === null) return NO_SCROLL;
5125
- const trimmed = value.trim();
5126
- const spaceIdx = trimmed.indexOf(" ");
5127
- if (spaceIdx === -1) {
5128
- const scroll = SCROLLABLE_VALUES2.has(trimmed);
5129
- return scroll ? BOTH_SCROLL : NO_SCROLL;
5130
- }
5131
- const first = trimmed.slice(0, spaceIdx);
5132
- const second = trimmed.slice(spaceIdx + 1).trimStart();
5133
- return {
5134
- x: SCROLLABLE_VALUES2.has(first),
5135
- y: SCROLLABLE_VALUES2.has(second)
5136
- };
5137
- }
5138
- function parseSingleAxisScroll(value) {
5139
- if (value === null) return null;
5140
- const trimmed = value.trim();
5141
- const spaceIdx = trimmed.indexOf(" ");
5142
- const first = spaceIdx === -1 ? trimmed : trimmed.slice(0, spaceIdx);
5143
- return SCROLLABLE_VALUES2.has(first);
5144
- }
5145
- function toScrollAxis(x, y) {
5146
- if (x && y) return 3 /* Both */;
5147
- if (x) return 1 /* X */;
5148
- if (y) return 2 /* Y */;
5149
- return 0 /* None */;
5150
- }
5151
-
5152
5151
  // src/compilation/analysis/alignment.ts
5153
5152
  var CONTROL_ELEMENT_TAGS2 = /* @__PURE__ */ new Set(["input", "select", "textarea", "button"]);
5154
5153
  var INTRINSIC_REPLACED_TAGS = /* @__PURE__ */ new Set(["img", "svg", "video", "canvas", "iframe", "object", "embed"]);
@@ -6876,7 +6875,7 @@ function formatPrimaryFix(findings) {
6876
6875
  }
6877
6876
 
6878
6877
  // src/compilation/analysis/cascade-analyzer.ts
6879
- var SCROLLABLE_VALUES3 = /* @__PURE__ */ new Set(["auto", "scroll"]);
6878
+ var SCROLLABLE_VALUES2 = /* @__PURE__ */ new Set(["auto", "scroll"]);
6880
6879
  function computeConditionalDelta(elements, cascadeByElementId, monitoredDeclarationsBySelectorId, symbolTable) {
6881
6880
  const deltaByElementId = /* @__PURE__ */ new Map();
6882
6881
  const elementsWithDeltaBySignal = /* @__PURE__ */ new Map();
@@ -7084,7 +7083,7 @@ function containsScrollToken(value) {
7084
7083
  for (let i = 0; i < tokens.length; i++) {
7085
7084
  const token = tokens[i];
7086
7085
  if (token === void 0) continue;
7087
- if (SCROLLABLE_VALUES3.has(token)) return true;
7086
+ if (SCROLLABLE_VALUES2.has(token)) return true;
7088
7087
  }
7089
7088
  return false;
7090
7089
  }
@@ -7531,14 +7530,14 @@ function createFileSemanticModel(solidTree, symbolTable, dependencyGraph, compil
7531
7530
  return out;
7532
7531
  },
7533
7532
  getLayoutFact(elementId, factKind) {
7534
- const cascade = this.getElementCascade(elementId);
7533
+ const snapshot = this.getSignalSnapshot(elementId);
7535
7534
  const allElements = this.getElementNodes();
7536
7535
  return computeLayoutFact(
7537
7536
  factKind,
7538
7537
  elementId,
7539
- cascade.declarations,
7538
+ snapshot,
7540
7539
  allElements,
7541
- (id) => this.getElementCascade(id).declarations
7540
+ (id) => this.getSignalSnapshot(id)
7542
7541
  );
7543
7542
  },
7544
7543
  // ── Tier 4-5: Signal + fact + alignment queries ────────────────────
@@ -7577,7 +7576,7 @@ function createFileSemanticModel(solidTree, symbolTable, dependencyGraph, compil
7577
7576
  if (!el) continue;
7578
7577
  const snapshot = snapshotIndex.get(el.elementId);
7579
7578
  if (!snapshot) continue;
7580
- const fact = computeScrollContainerFact2(snapshot);
7579
+ const fact = computeScrollContainerFact(snapshot);
7581
7580
  if (fact.isScrollContainer) out.push(el);
7582
7581
  }
7583
7582
  return out;
@@ -8565,7 +8564,7 @@ function dispatchCompilationActions(actions, compilation, symbolTable, emit) {
8565
8564
  }
8566
8565
 
8567
8566
  // src/css/rules/animation/layout-animation-exempt.ts
8568
- var OUT_OF_FLOW_POSITIONS2 = /* @__PURE__ */ new Set(["fixed", "absolute"]);
8567
+ var OUT_OF_FLOW_POSITIONS = /* @__PURE__ */ new Set(["fixed", "absolute"]);
8569
8568
  var OVERFLOW_CONTAINMENT_VALUES = /* @__PURE__ */ new Set(["hidden", "clip"]);
8570
8569
  var IDENTITY_ATTRIBUTE_NAMES = /* @__PURE__ */ new Set(["data-component", "data-slot"]);
8571
8570
  function isLayoutAnimationExempt(declaration, layoutProperty) {
@@ -8595,7 +8594,7 @@ function hasOutOfFlowPosition(rule) {
8595
8594
  const decl = positionDecls[i];
8596
8595
  if (!decl) continue;
8597
8596
  const value = decl.value.trim().toLowerCase();
8598
- if (OUT_OF_FLOW_POSITIONS2.has(value)) return true;
8597
+ if (OUT_OF_FLOW_POSITIONS.has(value)) return true;
8599
8598
  }
8600
8599
  return false;
8601
8600
  }
@@ -9318,7 +9317,7 @@ import ts9 from "typescript";
9318
9317
  var messages13 = {
9319
9318
  classListGeometryToggle: "classList toggles '{{className}}', and matching CSS changes layout-affecting '{{property}}', which can cause CLS."
9320
9319
  };
9321
- var OUT_OF_FLOW_POSITIONS3 = /* @__PURE__ */ new Set(["fixed", "absolute"]);
9320
+ var OUT_OF_FLOW_POSITIONS2 = /* @__PURE__ */ new Set(["fixed", "absolute"]);
9322
9321
  var jsxLayoutClasslistGeometryToggle = defineAnalysisRule({
9323
9322
  id: "jsx-layout-classlist-geometry-toggle",
9324
9323
  severity: "warn",
@@ -9371,7 +9370,7 @@ function classEstablishesOutOfFlow(className, symbolTable) {
9371
9370
  const decl = positionDecls[j];
9372
9371
  if (!decl) continue;
9373
9372
  const value = decl.value.trim().toLowerCase();
9374
- if (OUT_OF_FLOW_POSITIONS3.has(value)) return true;
9373
+ if (OUT_OF_FLOW_POSITIONS2.has(value)) return true;
9375
9374
  }
9376
9375
  }
9377
9376
  return false;
@@ -10360,7 +10359,7 @@ var messages25 = {
10360
10359
  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.",
10361
10360
  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."
10362
10361
  };
10363
- var INTERACTIVE_HTML_TAGS2 = /* @__PURE__ */ new Set(["button", "a", "input", "select", "textarea", "label", "summary"]);
10362
+ var INTERACTIVE_HTML_TAGS2 = /* @__PURE__ */ new Set(["button", "a", "input", "select", "textarea", "summary"]);
10364
10363
  var INTERACTIVE_ARIA_ROLES2 = /* @__PURE__ */ new Set([
10365
10364
  "button",
10366
10365
  "link",
@@ -10521,9 +10520,12 @@ var jsxLayoutPolicyTouchTarget = defineAnalysisRule({
10521
10520
  }
10522
10521
  });
10523
10522
  function classifyInteractive(element, semanticModel) {
10523
+ if (element.attributes.has("hidden")) return null;
10524
10524
  const tag = element.tagName;
10525
10525
  if (tag !== null && INTERACTIVE_HTML_TAGS2.has(tag)) {
10526
+ if (tag === "input" && element.attributes.get("type") === "hidden") return null;
10526
10527
  if (tag === "input" || tag === "select" || tag === "textarea") return "input";
10528
+ if (tag === "a" && isInlineTextLink(element)) return null;
10527
10529
  return "button";
10528
10530
  }
10529
10531
  const roleAttr = getJSXAttributeEntity(semanticModel.solidTree, element.jsxEntity, "role");
@@ -10553,6 +10555,14 @@ function isVisuallyHidden(element, snapshot) {
10553
10555
  if (widthSignal && widthSignal.kind === 0 /* Known */ && widthSignal.px === 1 && heightSignal && heightSignal.kind === 0 /* Known */ && heightSignal.px === 1) return true;
10554
10556
  return false;
10555
10557
  }
10558
+ function isInlineTextLink(element) {
10559
+ const content = element.textualContent;
10560
+ if (content !== 0 /* Yes */ && content !== 3 /* DynamicText */) return false;
10561
+ const parent = element.parentElementNode;
10562
+ if (parent === null) return false;
10563
+ const parentContent = parent.textualContent;
10564
+ return parentContent === 0 /* Yes */ || parentContent === 3 /* DynamicText */ || parentContent === 2 /* Unknown */;
10565
+ }
10556
10566
  function checkDimension(snapshot, signal, min, element, semanticModel, emit, messageId, template, tag, policyName) {
10557
10567
  let px = readKnownPx2(snapshot, signal);
10558
10568
  if (px === null) {
@@ -10563,6 +10573,7 @@ function checkDimension(snapshot, signal, min, element, semanticModel, emit, mes
10563
10573
  }
10564
10574
  if (px === null) return;
10565
10575
  if (px >= min) return;
10576
+ if (px === 0 && (signal === "min-width" || signal === "min-height")) return;
10566
10577
  emit(createDiagnostic(
10567
10578
  element.solidFile,
10568
10579
  element.jsxEntity.node,
@@ -12681,10 +12692,8 @@ var cssPolicyTypography = defineAnalysisRule({
12681
12692
  var messages57 = {
12682
12693
  letterSpacingTooSmall: "Letter spacing `{{value}}` ({{resolved}}em) is below the minimum `{{min}}em` for policy `{{policy}}`.",
12683
12694
  wordSpacingTooSmall: "Word spacing `{{value}}` ({{resolved}}em) is below the minimum `{{min}}em` for policy `{{policy}}`.",
12684
- paragraphSpacingTooSmall: "Paragraph spacing `{{value}}` ({{resolved}}em) is below the minimum `{{min}}em` ({{minMultiplier}}\xD7 font-size) for policy `{{policy}}`.",
12685
- touchTargetTooSmall: "`{{property}}: {{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for interactive elements in policy `{{policy}}`."
12695
+ paragraphSpacingTooSmall: "Paragraph spacing `{{value}}` ({{resolved}}em) is below the minimum `{{min}}em` ({{minMultiplier}}\xD7 font-size) for policy `{{policy}}`."
12686
12696
  };
12687
- var INTERACTIVE_SELECTORS = /button|input|select|textarea|\[role=/i;
12688
12697
  var cssPolicySpacing = defineAnalysisRule({
12689
12698
  id: "css-policy-spacing",
12690
12699
  severity: "warn",
@@ -12732,28 +12741,6 @@ var cssPolicySpacing = defineAnalysisRule({
12732
12741
  ));
12733
12742
  }
12734
12743
  }
12735
- for (const prop of ["height", "min-height"]) {
12736
- const decls = tree.declarationsByProperty.get(prop);
12737
- if (!decls) continue;
12738
- for (let i = 0; i < decls.length; i++) {
12739
- const d = decls[i];
12740
- if (!d) continue;
12741
- const rule = d.rule;
12742
- if (!rule) continue;
12743
- if (!INTERACTIVE_SELECTORS.test(rule.selectorText)) continue;
12744
- const px = parsePxValue(d.value);
12745
- if (px === null || px >= policy.minButtonHeight) continue;
12746
- emit(createCSSDiagnostic(
12747
- d.file.path,
12748
- d.startLine,
12749
- d.startColumn,
12750
- cssPolicySpacing.id,
12751
- "touchTargetTooSmall",
12752
- resolveMessage(messages57.touchTargetTooSmall, { property: prop, value: d.value.trim(), resolved: String(Math.round(px * 100) / 100), min: String(policy.minButtonHeight), policy: name }),
12753
- "warn"
12754
- ));
12755
- }
12756
- }
12757
12744
  for (const prop of ["margin-bottom", "margin-block-end"]) {
12758
12745
  const decls = tree.declarationsByProperty.get(prop);
12759
12746
  if (!decls) continue;