import type { LayoutNode, RhythmViolation, ProximityIssue, ContextualGapViolation, BoundaryViolation, GroupingSuggestion, TerminalPaddingViolation, DimensionInconsistency, SectionMergeSuggestion } from './types.js'; import type { SemanticLayoutGraph } from './SemanticLayoutGraph.js'; export interface GapOpportunity { node: LayoutNode; suggestion: string; } export interface MarginStackResult { parent: LayoutNode; child: LayoutNode; totalSpacing: number; } export interface PaddingIssue { node: LayoutNode; property: string; value: number; description: string; } export declare class GraphAnalyzer { private scorer; constructor(); /** * Find nodes that have margin/padding but no gap (gap opportunities). * v1.0.1: Also detects containers using padding as a gap substitute. */ findGapOpportunities(graph: SemanticLayoutGraph): GapOpportunity[]; /** * Find style pollution: custom components with hardcoded margins. * Skips slot components (they're transparent containers). */ findStylePollution(graph: SemanticLayoutGraph): LayoutNode[]; /** * Find margin stacking: parent padding + child margins. */ findMarginStacking(graph: SemanticLayoutGraph): MarginStackResult[]; /** * Find list items missing last-item guards. */ findMissingLastItemGuards(graph: SemanticLayoutGraph): LayoutNode[]; /** * v1.0.1: Find orphan padding — containers with padding values that * serve no clear purpose (no gap, no child margins, single child). */ findOrphanPadding(graph: SemanticLayoutGraph): PaddingIssue[]; /** * v1.1.0 "Rhythm Hierarch": Find containers where child gap >= parent gap. * Kept for backward compatibility. v2.0.0 consumers should use * findContextualGapViolations() instead. */ findRhythmViolations(graph: SemanticLayoutGraph): RhythmViolation[]; /** * v2.0.0: Find contextual gap violations using the Dynamic Rhythm Hierarch. * * Validates gaps based on Proximity Score between consecutive siblings: * * A. Intra-Section Rule (Score > 6): * Target Gap = 8px. Flag if actual gap > 8px → "Loose Rhythm" * * B. Inter-Section Rule (Score < 4 OR Divider detected): * Target Gap = 16px. Flag if actual gap < 16px → "Section Collision" * * C. Score 4-6: Neutral zone — no flag (transitional spacing) * * v2.2.0: Added "Stuck Section" pre-check — flags any 0-gap between * two custom components regardless of proximity score. This catches * the "formSection ↔ buttonWrapper" pattern where siblings are * visually congested with no explicit gap. * * v2.3.1: Added two filters: * 1. Non-visual components (StatusBar, LinearGradient) and * absolutely-positioned elements are excluded from gap audits. * 2. Functional-Role Proximity Capping: siblings with different * functional roles (e.g., "input" vs "action") have their * effective proximity score capped at 3, ensuring they get * Inter-Section (16px) spacing even if lexical/prop/visual * scores are high. */ findContextualGapViolations(graph: SemanticLayoutGraph): ContextualGapViolation[]; /** * Infer the effective gap between two consecutive siblings. * * Priority: * 1. Container's `gap` property (if set) * 2. Child A's marginBottom * 3. Child B's marginTop * 4. Child A's marginVertical * 5. Child A's margin * 6. Fallback: 0 (no gap detected) */ private inferGapBetween; /** * Check if a node is a divider component (HR, Divider, Separator). */ private isDividerComponent; /** * v2.2.1: Check if two consecutive siblings form a label-input pair. * * A label-input pair is one Text/Label component followed by one Input * component (or vice versa). These are functionally coupled form elements * that should use an 8px "Medium Bond" rather than a 16px "Separation." * * Text-type patterns: Text, Label, Title, Caption, Heading, Subtitle, * Description, HelperText, ErrorText, Header, Footer * Input-type patterns: FormInput, TextInput, Input, TextField, SearchBar, * Picker, Select, Dropdown, Checkbox, Radio, Switch, Slider, TextArea */ private isFormInputPair; /** * v2.0.0 "Boundary Rule": Find containers where the last child * has a marginBottom. The last child should rely on container * paddingBottom for a clean edge. * * v2.3.1: Skips absolutely-positioned and non-visual children * (StatusBar, LinearGradient) when determining the last child. */ findBoundaryViolations(graph: SemanticLayoutGraph): BoundaryViolation[]; /** * v2.3.0 "Terminal Padding Auditor": Find containers where the last child * defines its own paddingBottom or marginBottom while the container already * has a gap or padding. This creates "Ghost Margin" layout pollution — * redundant boundary spacing that should be handled by the container alone. * * The key insight: if a container has gap or padding, the last child's * bottom spacing is redundant — the container's own padding/gap already * provides the necessary boundary spacing. * * @param graph - The layout graph * @returns Terminal padding violations */ findTerminalPaddingViolations(graph: SemanticLayoutGraph): TerminalPaddingViolation[]; /** * v1.1.0 "Semantic Proximity Auditor": Find sibling custom components * that share a common name prefix but are not wrapped in a shared container. */ findProximityIssues(graph: SemanticLayoutGraph): ProximityIssue[]; /** * v2.1.0 "Run-Length Cluster Encoding": Find consecutive siblings with high * proximity scores and detect sub-clusters within the run. * * Replaces the v2.0.0 fixed Rule of Three window with a run-length encoding * approach that: * 1. Finds the longest consecutive run of siblings with proximity score > 6 * 2. Detects sub-clusters within the run using name-prefix matching * 3. Emits grouping suggestions per sub-cluster * * Trigger: 3+ consecutive siblings with average score > 6. * Suggestion: Wrap in a
or with gap: 8. * Constraint: Blocked if margin pollution detected on those children. * * @param graph - The layout graph * @param pollutedContainers - Set of container IDs that have margin pollution * (from FoundationCheck). These are excluded from suggestions. */ findGroupingSuggestions(graph: SemanticLayoutGraph, pollutedContainers?: Set): GroupingSuggestion[]; /** * v2.2.0 "Functional Role Clustering": Group siblings by their semantic * functional role (e.g., Input-type, Action-type, Text-type) rather than * by name prefix similarity. * * This catches patterns like: * * where the first two are "input" role and the last two are "action" role, * suggesting they should be in separate sections. * * @param graph - The layout graph * @param pollutedContainers - Set of container IDs that have margin pollution * @returns Grouping suggestions for functional role clusters */ private findFunctionalClusters; /** * v2.2.0: Infer the functional role of a component based on its name. * * Role categories: * - "input": FormInput, TextInput, Input, TextField, SearchBar, Picker, Select, Dropdown, Checkbox, Radio, Switch, Slider * - "action": Button, TouchableOpacity, TouchableHighlight, Pressable, Link, IconButton, Fab, ActionButton * - "text": Text, Label, Title, Heading, Paragraph, Caption, Subtitle, Description, ErrorText, HelperText * - "image": Image, Avatar, Icon, Photo, Thumbnail, Illustration * - "card": Card, Tile, Block, Panel, Section, Container, Box * - "list": List, FlatList, SectionList, ScrollView, Table, Row, Cell, Item * - "divider": Divider, Separator, HR, Spacer * - "other": fallback */ private inferFunctionalRole; /** * v2.1.0: Detect sub-clusters within a run of semantically related siblings. * * Uses name-prefix matching to identify natural groupings: * - Siblings sharing a common prefix >= 3 chars form a sub-cluster * - Consecutive siblings with the same component name form a sub-cluster * - Fallback: the entire run is one cluster */ private detectSubClusters; /** * v2.4.0 "Sibling Dimension Consistency": Find same-type siblings * within a container that have mismatched width or height values. * * Groups siblings by component name, then checks if their numeric * width/height values are consistent. Flags outliers that differ * from the majority value. * * Example: * * → Third Card has height: 180, majority is 200 — flagged as outlier. * * Only checks numeric values (string values like '100%' are skipped). * Only flags when there are 3+ same-type siblings for statistical significance. * * @param graph - The layout graph * @returns Dimension inconsistencies */ findDimensionInconsistencies(graph: SemanticLayoutGraph): DimensionInconsistency[]; /** * Find an outlier in a set of dimension values for same-type siblings. * Uses majority voting: the most common value is the "correct" one. * Flags any sibling whose value differs from the majority. */ private findOutlierInDimension; /** * v2.4.0 "Section Merge": Detect "Unary Section + Multi Section" pairs * where a container with a single custom child sits adjacent to a * container with multiple children, and they have high proximity (> 6). * * This suggests the unary section's child should be merged into the * multi section to reduce unnecessary nesting. * * Algorithm (Step 7 in findGroupingSuggestions): * 1. For each container, find "unary sections" (containers with exactly * 1 custom child) and "multi sections" (containers with 2+ custom children). * 2. For each unary section, check if it's adjacent to a multi section * in the parent container's children list. * 3. If the proximity score between the unary section and multi section * is > 6, emit a SectionMergeSuggestion. * * @param graph - The layout graph * @param pollutedContainers - Set of container IDs that have margin pollution * @returns Section merge suggestions */ findSectionMergeSuggestions(graph: SemanticLayoutGraph, pollutedContainers?: Set): SectionMergeSuggestion[]; /** * Find a multi section adjacent to a unary section in the children list. * Checks the immediate predecessor and successor. */ private findAdjacentMultiSection; /** * Find the longest common prefix between two strings. */ private longestCommonPrefix; /** * Group consecutive prefix pairs into clusters. */ private groupConsecutiveByPrefix; } //# sourceMappingURL=GraphAnalyzer.d.ts.map