{"id":46843449,"url":"https://github.com/pelagornis/swift-layout","last_synced_at":"2026-03-10T14:04:34.433Z","repository":{"id":298565701,"uuid":"736944566","full_name":"pelagornis/swift-layout","owner":"pelagornis","description":"A manual layout system for UIKit based on a SwiftUI-like declarative DSL","archived":false,"fork":false,"pushed_at":"2026-01-12T15:55:04.000Z","size":6724,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-12T19:11:49.067Z","etag":null,"topics":["ios","layout","layout-engine","manual-layout","pelagornis","swift","swift-library"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pelagornis.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-12-29T10:32:07.000Z","updated_at":"2026-01-12T15:55:31.000Z","dependencies_parsed_at":"2025-06-11T20:15:14.328Z","dependency_job_id":"9572f318-43ab-4fa8-8880-f62028ef4f70","html_url":"https://github.com/pelagornis/swift-layout","commit_stats":null,"previous_names":["pelagornis/swift-layout"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/pelagornis/swift-layout","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pelagornis%2Fswift-layout","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pelagornis%2Fswift-layout/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pelagornis%2Fswift-layout/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pelagornis%2Fswift-layout/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pelagornis","download_url":"https://codeload.github.com/pelagornis/swift-layout/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pelagornis%2Fswift-layout/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30336105,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T12:41:07.687Z","status":"ssl_error","status_checked_at":"2026-03-10T12:41:06.728Z","response_time":106,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ios","layout","layout-engine","manual-layout","pelagornis","swift","swift-library"],"created_at":"2026-03-10T14:04:31.521Z","updated_at":"2026-03-10T14:04:34.414Z","avatar_url":"https://github.com/pelagornis.png","language":"Swift","readme":"# Layout\n\n![Official](https://badge.pelagornis.com/official.svg)\n[![Swift Version](https://img.shields.io/badge/Swift-6.0+-orange.svg)](https://swift.org)\n[![iOS Version](https://img.shields.io/badge/iOS-13.0+-blue.svg)](https://developer.apple.com/ios/)\n[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)\n[![CodeCov](https://img.shields.io/codecov/c/github/pelagornis/swift-layout)](https://codecov.io/gh/pelagornis/swift-layout)\n[![Swift Package Manager](https://img.shields.io/badge/SwiftPM-compatible-brightgreen.svg)](https://swift.org/package-manager)\n\nA high-performance, SwiftUI-style declarative layout system built on **frame-based calculations** — no Auto Layout constraints. Layout combines the readability of SwiftUI with the blazing speed of direct frame manipulation.\n\n## Why Layout?\n\n| Feature            | Auto Layout                  | Layout                    |\n| ------------------ | ---------------------------- | ------------------------- |\n| **Performance**    | Constraint solving overhead  | Direct frame calculation  |\n| **Syntax**         | Imperative constraints       | Declarative SwiftUI-style |\n| **Debugging**      | Complex constraint conflicts | Simple frame inspection   |\n| **Learning Curve** | Steep                        | Familiar to SwiftUI users |\n\n## ✨ Features\n\n### Core Features\n\n🚀 **High Performance** - Pure frame-based calculations, zero Auto Layout overhead  \n📱 **SwiftUI-Style API** - Familiar declarative syntax with `@LayoutBuilder`  \n🔄 **Automatic View Management** - Smart view hierarchy handling with automatic add/remove  \n🎯 **Zero Dependencies** - Pure UIKit with optional SwiftUI integration  \n⚙️ **Two-Phase Layout** - Separate measure and layout phases for optimal performance  \n🎯 **Efficient Modifiers** - Modifiers stored as properties, not new nodes\n\n### Layout Components\n\n📦 **VStack** - Vertical stacking with spacing and alignment options  \n📦 **HStack** - Horizontal stacking with spacing and alignment options  \n📦 **ZStack** - Z-axis stacking with multiple alignment options  \n📜 **ScrollView** - Vertical and horizontal scrolling with content offset preservation  \n📏 **Spacer** - Flexible space component with minimum length support  \n🔄 **ForEach** - Dynamic list generation with identity-based diffing\n\n### Layout Modifiers\n\n📐 **Size** - Fixed or flexible width/height sizing  \n📦 **Padding** - Uniform or edge-specific padding  \n📍 **Offset** - Position adjustment from calculated layout  \n🎨 **Background** - Background color and view support  \n🔲 **Corner Radius** - Rounded corner styling  \n🆔 **Identity** - View identity for efficient diffing and reuse\n\n### Advanced Features\n\n📐 **GeometryReader** - Access container size and position dynamically  \n⚡ **Animation Engine** - Built-in spring and timing animations with `withAnimation`  \n🔧 **Environment System** - Color scheme, layout direction, and custom environment values  \n🌉 **UIKit ↔ SwiftUI Bridge** - Seamless integration between frameworks  \n🎨 **Preferences System** - Pass values up the view hierarchy  \n🌳 **Layout Tree \u0026 Dirty Propagation** - Incremental layout updates with partial recalculation  \n🆔 **Identity \u0026 Diff** - Efficient view updates based on identity tracking  \n🔄 **Layout Invalidation Rules** - Clear rules for when and how layouts update\n\n### Performance Features\n\n💾 **Layout Caching** - Intelligent caching for repeated layouts  \n📊 **Performance Profiler** - Real-time FPS and layout metrics  \n📏 **SwiftUI-Style Size Proposals** - Accurate size negotiation with unconstrained dimensions  \n⚡ **Incremental Layout** - Only recalculate changed parts of the layout tree\n\n### Developer Tools\n\n🐛 **Debugging Hooks** - Custom hooks for debugging and monitoring  \n🔍 **View Hierarchy Analysis** - Detailed layout structure inspection  \n📊 **Frame Rate Monitor** - Real-time FPS tracking  \n🔗 **UIKit Lifecycle Integration** - Seamless integration with view controller lifecycle\n\n---\n\n## 📦 Installation\n\n### Swift Package Manager\n\nAdd the following to your `Package.swift`:\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/pelagornis/swift-layout.git\", from: \"vTag\")\n]\n```\n\nThen add `Layout` to your target dependencies:\n\n```swift\n.target(\n    name: \"YourTarget\",\n    dependencies: [\"Layout\"]\n)\n```\n\n### Xcode\n\n1. File → Add Package Dependencies\n2. Enter: `https://github.com/pelagornis/swift-layout.git`\n3. Select version and add to your project\n\n---\n\n## 🚀 Quick Start\n\n### Basic Setup\n\n```swift\nimport Layout\n\nclass MyViewController: UIViewController, Layout {\n    // 1. Create a layout container\n    let layoutContainer = LayoutContainer()\n\n    // 2. Create your UI components\n    let titleLabel = UILabel()\n    let subtitleLabel = UILabel()\n    let actionButton = UIButton(type: .system)\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        // 3. Configure views\n        titleLabel.text = \"Welcome to Layout!\"\n        titleLabel.font = .systemFont(ofSize: 28, weight: .bold)\n\n        subtitleLabel.text = \"High-performance declarative layouts\"\n        subtitleLabel.font = .systemFont(ofSize: 16)\n        subtitleLabel.textColor = .secondaryLabel\n\n        actionButton.setTitle(\"Get Started\", for: .normal)\n        actionButton.backgroundColor = .systemBlue\n        actionButton.setTitleColor(.white, for: .normal)\n        actionButton.layer.cornerRadius = 12\n\n        // 4. Setup container using pure Manual Layout (no Auto Layout)\n        setupLayoutContainer(layoutContainer)\n\n        // 5. Set and update the layout body\n        layoutContainer.updateBody { self.body }\n    }\n\n    override func viewDidLayoutSubviews() {\n        super.viewDidLayoutSubviews()\n        // Update container frame when bounds change\n        updateLayoutContainer(layoutContainer)\n    }\n\n    // 6. Define your layout declaratively\n    @LayoutBuilder var body: some Layout {\n        VStack(alignment: .center, spacing: 16) {\n            Spacer(minLength: 100)\n\n            titleLabel.layout()\n                .size(width: 300, height: 34)\n\n            subtitleLabel.layout()\n                .size(width: 300, height: 20)\n\n            Spacer(minLength: 40)\n\n            actionButton.layout()\n                .size(width: 280, height: 50)\n\n            Spacer()\n        }\n        .padding(20)\n    }\n}\n```\n\n### Using BaseViewController (Recommended)\n\nFor the cleanest code, inherit from `BaseViewController`:\n\n```swift\nclass MyViewController: BaseViewController, Layout {\n    let titleLabel = UILabel()\n    let actionButton = UIButton()\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        // Setup views\n        titleLabel.text = \"Welcome\"\n        actionButton.setTitle(\"Get Started\", for: .normal)\n\n        // Layout container is automatically set up\n        // Just override setLayout() to define your layout\n    }\n\n    override func setLayout() {\n        layoutContainer.updateBody { self.body }\n    }\n\n    @LayoutBuilder var body: some Layout {\n        VStack(alignment: .center, spacing: 24) {\n            titleLabel.layout().size(width: 280, height: 30)\n            actionButton.layout().size(width: 240, height: 50)\n        }\n    }\n}\n```\n\n### Using UIViewController Extension\n\nFor minimal integration without a base class:\n\n```swift\nclass MyViewController: UIViewController, Layout {\n    let layoutContainer = LayoutContainer()\n    let titleLabel = UILabel()\n    let actionButton = UIButton()\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        // Setup views\n        titleLabel.text = \"Welcome\"\n        actionButton.setTitle(\"Get Started\", for: .normal)\n\n        // Setup container (pure Manual Layout, no Auto Layout)\n        setupLayoutContainer(layoutContainer)\n\n        // Set and update layout\n        layoutContainer.updateBody { self.body }\n    }\n\n    override func viewDidLayoutSubviews() {\n        super.viewDidLayoutSubviews()\n        updateLayoutContainer(layoutContainer)\n    }\n\n    @LayoutBuilder var body: some Layout {\n        VStack(alignment: .center, spacing: 24) {\n            titleLabel.layout().size(width: 280, height: 30)\n            actionButton.layout().size(width: 240, height: 50)\n        }\n    }\n}\n```\n\n---\n\n## 📦 LayoutContainer\n\n`LayoutContainer` is the main container that manages your layout hierarchy. It provides automatic view management, content centering, and animation protection.\n\n### Key Features\n\n- **Automatic View Management**: Views are automatically added/removed based on layout changes\n- **Content Centering**: Content is automatically centered like SwiftUI\n- **Animation Protection**: Prevents layout system from overriding animated views\n- **Layout Updates**: Smart layout invalidation with clear rules\n- **Two-Phase Layout**: Separate measure and layout phases for optimal performance\n- **Pure Manual Layout**: Zero Auto Layout constraints, only frame-based calculations\n\n### Animation Protection\n\nWhen animating views directly, use `startAnimating` and `stopAnimating` to prevent the layout system from overriding your animations:\n\n```swift\n// Mark view as animating\nlayoutContainer.startAnimating(myView)\n\n// Animate the view\nwithAnimation(.easeInOut(duration: 0.3)) {\n    myView.frame.size = CGSize(width: 300, height: 200)\n}\n\n// Stop animating after completion\nwithAnimation(.easeInOut(duration: 0.3), {\n    myView.frame.size = CGSize(width: 300, height: 200)\n}, completion: { _ in\n    layoutContainer.stopAnimating(myView)\n})\n\n// Check if any views are animating\nif layoutContainer.isAnimating {\n    // Layout updates are automatically paused\n}\n```\n\n### Layout Updates\n\n```swift\n// Set body and update immediately (recommended)\nlayoutContainer.updateBody { self.body }\n\n// Or set body first, then update separately\nlayoutContainer.setBody { self.body }\nlayoutContainer.updateBody()\n\n// Update existing body without changing it\nlayoutContainer.updateBody()\n\n// Force layout update\nlayoutContainer.setNeedsLayout()\nlayoutContainer.layoutIfNeeded()\n\n// Update layout for orientation changes\nlayoutContainer.updateLayoutForOrientationChange()\n```\n\n### Layout Invalidation Rules\n\nLayout uses clear invalidation rules to determine when layouts need to be recalculated:\n\n```swift\n// Invalidation rules are automatically applied\nlet rules = LayoutInvalidationRules.default\n\n// Check if a reason should trigger invalidation\nif rules.shouldInvalidate(for: .hierarchyChanged) {\n    // Layout will be invalidated\n}\n\n// Check invalidation priority\nlet priority = rules.priority(for: .sizeChanged) // Returns 3\n```\n\n---\n\n## 🎨 Layout Components\n\n### VStack (Vertical Stack)\n\nArranges children vertically from top to bottom.\n\n```swift\nVStack(alignment: .center, spacing: 16) {\n    headerView.layout()\n        .size(width: 300, height: 60)\n\n    contentView.layout()\n        .size(width: 300, height: 200)\n\n    footerView.layout()\n        .size(width: 300, height: 40)\n}\n```\n\n**Parameters:**\n\n- `alignment`: `.leading`, `.center`, `.trailing` (default: `.center`)\n- `spacing`: Space between children (default: `0`)\n\n### HStack (Horizontal Stack)\n\nArranges children horizontally from leading to trailing.\n\n```swift\nHStack(alignment: .center, spacing: 12) {\n    iconView.layout()\n        .size(width: 44, height: 44)\n\n    VStack(alignment: .leading, spacing: 4) {\n        titleLabel.layout().size(width: 200, height: 20)\n        subtitleLabel.layout().size(width: 200, height: 16)\n    }\n\n    Spacer()\n\n    chevronIcon.layout()\n        .size(width: 24, height: 24)\n}\n.padding(16)\n```\n\n**Parameters:**\n\n- `alignment`: `.top`, `.center`, `.bottom` (default: `.center`)\n- `spacing`: Space between children (default: `0`)\n\n### ZStack (Overlay Stack)\n\nOverlays children on top of each other.\n\n```swift\nZStack(alignment: .topTrailing) {\n    // Background (bottom layer)\n    backgroundImage.layout()\n        .size(width: 300, height: 200)\n\n    // Content (middle layer)\n    contentView.layout()\n        .size(width: 280, height: 180)\n\n    // Badge (top layer, positioned at top-trailing)\n    badgeView.layout()\n        .size(width: 30, height: 30)\n        .offset(x: -10, y: 10)\n}\n```\n\n**Parameters:**\n\n- `alignment`: Any combination of vertical (`.top`, `.center`, `.bottom`) and horizontal (`.leading`, `.center`, `.trailing`)\n\n### ScrollView\n\nAdds scrolling capability to content with automatic content offset preservation.\n\n```swift\n// Vertical scrolling (default)\nScrollView {\n    VStack(alignment: .center, spacing: 20) {\n        // Header\n        headerView.layout()\n            .size(width: 350, height: 200)\n\n        // Multiple content sections\n        ForEach(sections) { section in\n            sectionView.layout()\n                .size(width: 350, height: 150)\n        }\n\n        // Bottom spacing\n        Spacer(minLength: 100)\n    }\n}\n\n// Horizontal scrolling\nScrollView(.horizontal) {\n    HStack(spacing: 16) {\n        ForEach(items) { item in\n            itemView.layout()\n                .size(width: 200, height: 150)\n        }\n    }\n}\n\n// With safe area offset adjustment\nlet scrollView = ScrollView {\n    contentView.layout()\n}\nscrollView.adjustsContentOffsetForSafeArea = true\n```\n\n### Spacer\n\nFlexible space that expands to fill available room.\n\n```swift\nVStack(alignment: .center, spacing: 0) {\n    Spacer(minLength: 20)  // At least 20pt, can grow\n\n    titleLabel.layout()\n\n    Spacer()  // Flexible space, takes remaining room\n\n    buttonView.layout()\n\n    Spacer(minLength: 40)  // Safe area padding\n}\n```\n\n---\n\n## 🎛️ Layout Modifiers\n\n### Size\n\n```swift\n// Fixed size\nmyView.layout()\n    .size(width: 200, height: 100)\n\n// Width only (height flexible)\nmyView.layout()\n    .size(width: 200)\n\n// Height only (width flexible)\nmyView.layout()\n    .size(height: 50)\n\n// Percentage-based size\nmyView.layout()\n    .size(width: 90%, height: 100)\n\n// Mixed fixed and percentage\nmyView.layout()\n    .size(width: 80%, height: 50)\n\n// Percentage syntax with postfix operator\nlet width: Percent = 80%  // Using postfix % operator\nmyView.layout()\n    .size(width: width, height: 100)\n```\n\n**Percentage-based Sizing:**\n\nLayout supports percentage-based sizing using the `%` postfix operator:\n\n```swift\n// Direct percentage syntax\nmyView.layout()\n    .size(width: 90%, height: 100)\n\n// Percentage is calculated relative to parent container's size\nVStack(alignment: .center, spacing: 16) {\n    headerView.layout()\n        .size(width: 90%, height: 60)  // 90% of VStack's width\n\n    contentView.layout()\n        .size(width: 80%, height: 200)  // 80% of VStack's width\n}\n\n// Mix percentage and fixed sizes\ncardView.layout()\n    .size(width: 50%, height: 140)  // 50% width, fixed 140pt height\n```\n\n**Edge Positioning with Percentages:**\n\n```swift\n// Position views using percentage offsets\nmyView.layout()\n    .size(width: 100, height: 100)\n    .top(10%)      // 10% from top\n    .leading(20%)  // 20% from leading edge\n    .centerX()     // Center horizontally\n```\n\n### Padding\n\n```swift\n// Uniform padding\nVStack { ... }\n    .padding(20)\n\n// Edge-specific padding\nVStack { ... }\n    .padding(UIEdgeInsets(top: 20, left: 16, bottom: 40, right: 16))\n```\n\n### Offset\n\n```swift\n// Move view from its calculated position\nmyView.layout()\n    .size(width: 100, height: 100)\n    .offset(x: 10, y: -5)\n```\n\n### Background \u0026 Corner Radius\n\n```swift\nVStack { ... }\n    .layout()\n    .size(width: 300, height: 200)\n    .background(.systemBlue)\n    .cornerRadius(16)\n```\n\n### Chaining Modifiers\n\n```swift\ncardView.layout()\n    .size(width: 320, height: 180)\n    .padding(16)\n    .background(.tertiarySystemBackground)\n    .cornerRadius(20)\n    .offset(y: 10)\n```\n\n**Performance Note**: Modifiers are stored as properties on the view itself (using Associated Objects), not as new nodes. This means modifier chains don't create new `ViewLayout` instances, providing optimal performance.\n\n---\n\n## 📐 GeometryReader\n\n`GeometryReader` provides access to its container's size and position, enabling dynamic layouts.\n\n### Declarative Style (with @LayoutBuilder)\n\n```swift\nGeometryReader { proxy in\n    // Use proxy.size for dynamic sizing\n    VStack(alignment: .center, spacing: 8) {\n        topBox.layout()\n            .size(width: proxy.size.width * 0.8, height: 60)\n\n        bottomBox.layout()\n            .size(width: proxy.size.width * 0.6, height: 40)\n    }\n}\n.layout()\n.size(width: 360, height: 140)\n```\n\n### Imperative Style (for Complex Layouts)\n\nWhen you need direct control over view placement:\n\n```swift\nGeometryReader { proxy, container in\n    // Calculate dimensions based on container size\n    let availableWidth = proxy.size.width - 32\n    let columnWidth = (availableWidth - 16) / 2\n\n    // Create and position views manually\n    let leftColumn = createColumn()\n    leftColumn.frame = CGRect(x: 16, y: 16, width: columnWidth, height: 100)\n    container.addSubview(leftColumn)\n\n    let rightColumn = createColumn()\n    rightColumn.frame = CGRect(x: 16 + columnWidth + 16, y: 16, width: columnWidth, height: 100)\n    container.addSubview(rightColumn)\n}\n```\n\n### GeometryProxy Properties\n\n```swift\nGeometryReader { proxy, container in\n    // Container dimensions\n    let width = proxy.size.width      // CGFloat\n    let height = proxy.size.height    // CGFloat\n\n    // Safe area information\n    let topInset = proxy.safeAreaInsets.top\n    let bottomInset = proxy.safeAreaInsets.bottom\n\n    // Position in global coordinate space\n    let globalX = proxy.globalFrame.minX\n    let globalY = proxy.globalFrame.minY\n\n    // Local bounds (origin is always 0,0)\n    let bounds = proxy.bounds  // CGRect\n}\n```\n\n### Geometry Change Callback\n\nReact to size changes:\n\n```swift\nlet geometryReader = GeometryReader { proxy in\n    contentView.layout()\n        .size(width: proxy.size.width, height: proxy.size.height)\n}\n.onGeometryChange { proxy in\n    print(\"Size changed: \\(proxy.size)\")\n    print(\"Global position: \\(proxy.globalFrame.origin)\")\n}\n\n// Use in layout\ngeometryReader.layout()\n    .size(width: 300, height: 200)\n```\n\n---\n\n## ⚡ Animation Engine\n\nLayout provides SwiftUI-style animation support with `withAnimation` and animation modifiers.\n\n### withAnimation Function\n\nThe `withAnimation` function provides SwiftUI-like animation blocks:\n\n```swift\n// Basic animation\nwithAnimation {\n    self.view.alpha = 1.0\n    self.view.frame.size = CGSize(width: 200, height: 200)\n}\n\n// Custom animation\nwithAnimation(.spring(damping: 0.7, velocity: 0.5)) {\n    self.cardView.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)\n}\n\n// With completion handler\nwithAnimation(.easeInOut(duration: 0.3), {\n    self.view.frame.origin = CGPoint(x: 100, y: 100)\n}, completion: { finished in\n    print(\"Animation completed: \\(finished)\")\n})\n```\n\n### Animation Presets\n\n```swift\n// Predefined animations\nwithAnimation(.default)      // 0.3s easeInOut\nwithAnimation(.spring)        // Spring animation with damping 0.7\nwithAnimation(.quick)         // 0.15s easeOut\n\n// Custom timing functions\nwithAnimation(.easeIn(duration: 0.4))\nwithAnimation(.easeOut(duration: 0.3))\nwithAnimation(.easeInOut(duration: 0.5))\nwithAnimation(.linear(duration: 0.3))\n\n// Custom spring\nwithAnimation(.spring(damping: 0.6, velocity: 0.8))\n```\n\n### Protecting Animations from Layout System\n\nWhen animating views directly, protect them from layout system interference:\n\n```swift\n// Mark view as animating\nlayoutContainer.startAnimating(myView)\n\n// Animate the view\nwithAnimation(.easeInOut(duration: 0.3)) {\n    myView.frame.size = CGSize(width: 300, height: 200)\n}\n\n// Stop animating after completion\nwithAnimation(.easeInOut(duration: 0.3), {\n    myView.frame.size = CGSize(width: 300, height: 200)\n}, completion: { _ in\n    layoutContainer.stopAnimating(myView)\n})\n\n// Check if any views are animating\nif layoutContainer.isAnimating {\n    // Layout updates are paused\n}\n```\n\n### LayoutAnimation Structure\n\n```swift\n// Create custom animation\nlet customAnimation = LayoutAnimation(\n    duration: 0.5,\n    delay: 0.1,\n    timingFunction: .easeInOut,\n    repeatCount: 1,\n    autoreverses: false\n)\n\n// Use with withAnimation\nwithAnimation(customAnimation) {\n    // Your animations\n}\n```\n\n---\n\n## 🔧 Environment System\n\n### Color Scheme Detection\n\n```swift\n// Get current color scheme\nlet colorScheme = ColorScheme.current\n\nswitch colorScheme {\ncase .light:\n    view.backgroundColor = .white\ncase .dark:\n    view.backgroundColor = .black\n}\n\n// React to changes\noverride func traitCollectionDidChange(_ previous: UITraitCollection?) {\n    super.traitCollectionDidChange(previous)\n    EnvironmentProvider.shared.updateSystemEnvironment()\n\n    // Update your UI based on new color scheme\n    updateColorsForCurrentScheme()\n}\n```\n\n### Layout Direction\n\n```swift\n// Check for RTL languages\nlet direction = LayoutDirection.current\n\nif direction == .rightToLeft {\n    // Adjust layout for RTL\n    stackView.semanticContentAttribute = .forceRightToLeft\n}\n```\n\n### Environment Values\n\n```swift\n// Access shared environment\nlet env = EnvironmentValues.shared\n\n// Custom environment keys\nextension EnvironmentValues {\n    var customSpacing: CGFloat {\n        get { self[CustomSpacingKey.self] }\n        set { self[CustomSpacingKey.self] = newValue }\n    }\n}\n\nstruct CustomSpacingKey: EnvironmentKey {\n    static let defaultValue: CGFloat = 16\n}\n```\n\n---\n\n## 📊 Performance Monitoring\n\n### Frame Rate Monitor\n\n```swift\n// Start monitoring\nFrameRateMonitor.shared.start()\n\n// Check current FPS (updated in real-time)\nlet currentFPS = FrameRateMonitor.shared.currentFPS\nlet averageFPS = FrameRateMonitor.shared.averageFPS\n\n// Display in UI\nTimer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in\n    let fps = FrameRateMonitor.shared.averageFPS\n    self.fpsLabel.text = String(format: \"%.0f FPS\", fps)\n    self.fpsLabel.textColor = fps \u003e= 55 ? .systemGreen : .systemRed\n}\n\n// Stop when done\nFrameRateMonitor.shared.stop()\n```\n\n### Layout Cache\n\n```swift\n// Check cache performance\nlet hitRate = LayoutCache.shared.hitRate  // 0.0 - 1.0\nprint(\"Cache hit rate: \\(Int(hitRate * 100))%\")\n\n// Clear cache if needed\nLayoutCache.shared.clearCache()\n\n// Get cache statistics\nlet stats = LayoutCache.shared.statistics\nprint(\"Hits: \\(stats.hits), Misses: \\(stats.misses)\")\n```\n\n### Performance Profiler\n\n```swift\n// Profile a layout operation\nlet profiler = PerformanceProfiler.shared\n\nprofiler.startProfiling(name: \"ComplexLayout\")\n\n// ... perform layout operations ...\n\nprofiler.endProfiling(name: \"ComplexLayout\")\n\n// Get all profiles\nlet profiles = profiler.allProfiles\nfor profile in profiles {\n    print(\"\\(profile.name): \\(profile.duration)ms\")\n}\n\n// Check for warnings\nlet warnings = profiler.allWarnings\nfor warning in warnings {\n    print(\"⚠️ \\(warning.message)\")\n}\n```\n\n---\n\n## 🌉 UIKit ↔ SwiftUI Bridge\n\n### UIKit View in SwiftUI\n\n```swift\nimport SwiftUI\nimport Layout\n\nstruct MySwiftUIView: View {\n    var body: some View {\n        VStack {\n            Text(\"SwiftUI Header\")\n                .font(.title)\n\n            // Use any UIKit view in SwiftUI\n            createCustomChart()\n                .swiftui  // ← Converts to SwiftUI View\n                .frame(height: 200)\n\n            // UIKit labels, buttons, etc.\n            UILabel().configure {\n                $0.text = \"UIKit Label\"\n                $0.textAlignment = .center\n            }\n            .swiftui\n            .frame(height: 44)\n        }\n    }\n\n    func createCustomChart() -\u003e UIView {\n        let chart = CustomChartView()\n        chart.data = [10, 20, 30, 40, 50]\n        return chart\n    }\n}\n```\n\n### SwiftUI View in UIKit\n\n```swift\nclass MyViewController: UIViewController {\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        // Create SwiftUI view\n        let swiftUIContent = MySwiftUIView()\n\n        // Convert to UIKit hosting controller\n        let hostingController = swiftUIContent.uikit\n\n        // Add as child view controller\n        addChild(hostingController)\n        view.addSubview(hostingController.view)\n        hostingController.view.frame = view.bounds\n        hostingController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]\n        hostingController.didMove(toParent: self)\n    }\n}\n```\n\n---\n\n## 🌳 Layout Tree \u0026 Dirty Propagation\n\nLayout provides an incremental layout system that only recalculates parts of the layout that have changed, significantly improving performance for complex UIs.\n\n### Key Concepts\n\n- **Layout Tree**: A hierarchical representation of layout components, allowing efficient traversal and targeted updates\n- **Dirty Propagation**: When a child layout changes, it marks its parent and ancestors as \"dirty,\" indicating they need recalculation\n- **Incremental Layout**: Only dirty nodes are recalculated, avoiding full layout passes\n\n### Enabling Incremental Layout\n\nBy default, incremental layout is enabled. You can toggle it:\n\n```swift\n// Enable incremental layout (default)\nlayoutContainer.useIncrementalLayout = true\n\n// Disable for full recalculation every time\nlayoutContainer.useIncrementalLayout = false\n```\n\n### Marking Views as Dirty\n\nWhen a view's content changes, mark it as dirty to trigger incremental recalculation:\n\n```swift\n// Mark a specific view as dirty\nlayoutContainer.markViewDirty(myLabel)\n\n// The layout system will:\n// 1. Find the LayoutNode containing this view\n// 2. Mark that node and its ancestors as dirty\n// 3. Recalculate only the dirty parts in the next layout pass\n```\n\n### Example: Dynamic Content Updates\n\n```swift\nclass MyViewController: BaseViewController, Layout {\n    let layoutContainer = LayoutContainer()\n    let cardLabels: [UILabel] = (0..\u003c6).map { _ in UILabel() }\n    var cardCounts = Array(repeating: 0, count: 6)\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        layoutContainer.useIncrementalLayout = true\n        setupLayoutContainer(layoutContainer)\n        layoutContainer.updateBody { self.body }\n    }\n\n    @LayoutBuilder var body: some Layout {\n        VStack(alignment: .center, spacing: 16) {\n            // Multiple cards in a grid\n            VStack(alignment: .center, spacing: 12) {\n                HStack(alignment: .center, spacing: 12) {\n                    createCard(index: 0).layout()\n                    createCard(index: 1).layout()\n                }\n                HStack(alignment: .center, spacing: 12) {\n                    createCard(index: 2).layout()\n                    createCard(index: 3).layout()\n                }\n            }\n\n            // Update buttons\n            createUpdateButton(title: \"Update Card 1\") {\n                self.updateCard(at: 0)\n            }\n        }\n    }\n\n    private func updateCard(at index: Int) {\n        // Update the card's content\n        cardCounts[index] += 1\n        cardLabels[index].text = \"Count: \\(cardCounts[index])\"\n\n        // Mark only this view as dirty - only this card will be recalculated!\n        layoutContainer.markViewDirty(cardLabels[index])\n    }\n}\n```\n\n### Invalidating the Entire Tree\n\nFor major changes, invalidate the entire layout tree:\n\n```swift\n// Invalidate entire tree (forces full recalculation)\nlayoutContainer.invalidateLayoutTree()\n\n// Rebuild the layout tree (useful when toggling incremental layout)\nlayoutContainer.rebuildLayoutTree()\n```\n\n### Performance Benefits\n\nWith incremental layout enabled:\n\n- **Partial Recalculation**: Only changed nodes are recalculated\n- **Cached Results**: Clean nodes use cached layout results\n- **Dirty Propagation**: Changes automatically propagate up the tree\n- **View Preservation**: Views remain in the hierarchy during updates\n\n### When to Use\n\n✅ **Use incremental layout when:**\n\n- You have complex layouts with many views\n- Only small parts of the UI change frequently\n- You want optimal performance for dynamic content\n\n❌ **Disable incremental layout when:**\n\n- Layout structure changes frequently\n- You need full recalculation for debugging\n- Performance is not a concern\n\n### Layout Tree Structure\n\nThe layout tree mirrors your layout hierarchy:\n\n```\nLayoutContainer (rootNode)\n└── VStack (LayoutNode)\n    ├── HStack (LayoutNode)\n    │   ├── Card 1 (LayoutNode)\n    │   └── Card 2 (LayoutNode)\n    └── HStack (LayoutNode)\n        ├── Card 3 (LayoutNode)\n        └── Card 4 (LayoutNode)\n```\n\nEach `LayoutNode` tracks:\n\n- **Dirty State**: Whether the node needs recalculation (new nodes start dirty)\n- **Cached Result**: Layout result when node is clean\n- **Parent-Child Relationships**: Tree structure for efficient traversal\n- **Child Nodes**: Automatically built from layout hierarchy (VStack, HStack, etc.)\n\n### Dirty Propagation\n\nWhen a child node is marked dirty, it automatically propagates to its parent:\n\n```swift\n// Child node becomes dirty\nchildNode.markDirty()\n\n// Parent is automatically marked dirty due to propagation\n// This ensures parent layout is recalculated when child changes\n```\n\n### Layout Calculation Flow\n\n1. **Initial State**: New `LayoutNode` instances start with `isDirty = true`\n2. **Calculation**: `calculateLayout()` is called, node is marked clean\n3. **Children Cleanup**: After parent calculation, dirty children are marked clean\n4. **Incremental Updates**: Only dirty nodes are recalculated in subsequent passes\n\n---\n\n## 🆔 Identity \u0026 Diff\n\nLayout provides identity-based diffing to efficiently update views when layout changes. By assigning identities to views, the system can track and reuse views across updates, minimizing unnecessary view creation and removal.\n\n### Setting View Identity\n\nUse the `.id()` modifier to assign an identity to a view:\n\n```swift\n@LayoutBuilder var body: some Layout {\n    VStack(spacing: 10) {\n        // Use item ID as identity\n        ForEach(items) { item in\n            ItemView(item: item)\n                .layout()\n                .id(item.id)  // Identity based on item ID\n        }\n\n        // Use string identity\n        headerView.layout()\n            .id(\"header\")\n\n        // Use any Hashable type\n        footerView.layout()\n            .id(123)  // Integer identity\n    }\n}\n```\n\n### How Identity Diffing Works\n\n1. **View Tracking**: Views with identities are tracked in a map\n2. **Diff Calculation**: When layout updates, the system compares old and new identity maps\n3. **Efficient Updates**:\n   - **Same Identity**: Reuses existing view instance (no removal/addition)\n   - **New Identity**: Adds new view\n   - **Removed Identity**: Removes view that no longer exists\n   - **Changed Identity**: Replaces view when identity changes\n\n### Benefits\n\n✅ **View Reuse**: Views with matching identities are reused, preserving state  \n✅ **Efficient Updates**: Only changed views are added/removed  \n✅ **State Preservation**: View state (scroll position, selection, etc.) is maintained  \n✅ **Performance**: Reduces view creation/destruction overhead\n\n### Example: Dynamic List\n\n```swift\nclass ItemListViewController: BaseViewController, Layout {\n    var items: [Item] = []\n\n    @LayoutBuilder var body: some Layout {\n        ScrollView {\n            VStack(spacing: 12) {\n                ForEach(items) { item in\n                    ItemCard(item: item)\n                        .layout()\n                        .id(item.id)  // Identity ensures efficient updates\n                        .size(width: 350, height: 80)\n                }\n            }\n        }\n    }\n\n    func updateItems(_ newItems: [Item]) {\n        items = newItems\n        layoutContainer.updateBody { self.body }\n        // Only changed items are updated, others are reused!\n    }\n}\n```\n\n### Identity Best Practices\n\n- **Use Stable Identifiers**: Use IDs that don't change for the same logical view\n- **Unique Identities**: Each view should have a unique identity within its parent\n- **Optional Identity**: Views without identity still work, but won't benefit from diffing\n- **Hashable Types**: Any `Hashable` type can be used as identity (String, Int, UUID, etc.)\n\n### Integration with Layout Tree\n\nIdentity diffing works seamlessly with the Layout Tree system:\n\n- Identity-based updates trigger dirty propagation\n- Only views with changed identities cause recalculation\n- Clean views with matching identities use cached results\n\n---\n\n## 🔍 Debugging\n\n### Enable Debugging\n\n```swift\n// Enable all debugging\nLayoutDebugger.shared.enableAll()\n\n// Enable specific features\nLayoutDebugger.shared.isEnabled = true\nLayoutDebugger.shared.enableViewHierarchy = true\nLayoutDebugger.shared.enableSpacerCalculation = true\nLayoutDebugger.shared.enableFrameSettings = true\n\n// Disable all\nLayoutDebugger.shared.disableAll()\n```\n\n### Custom Debugging Hooks\n\nSet custom hooks to intercept and customize debug output:\n\n```swift\n// Set a custom hook for layout calculations\nLayoutDebugger.shared.setDebuggingHook({ message, component in\n    // Custom logging logic\n    MyCustomLogger.log(\"\\(component): \\(message)\")\n}, for: .layout)\n\n// Set a hook for view hierarchy\nLayoutDebugger.shared.setDebuggingHook({ message, component in\n    // Send to analytics\n    Analytics.track(\"LayoutHierarchy\", parameters: [\"message\": message])\n}, for: .hierarchy)\n```\n\n### View Hierarchy Analysis\n\n```swift\nLayoutDebugger.shared.analyzeViewHierarchy(\n    layoutContainer,\n    title: \"MY LAYOUT\"\n)\n```\n\n**Output:**\n\n```\n🔍 ===== MY LAYOUT =====\n🔍 LayoutContainer\n├─ Frame: (20.0, 100.0, 350.0, 600.0)\n├─ Background: systemBackground\n├─ Hidden: false\n└─ Alpha: 1.0\n  └─ VStack\n    ├─ Frame: (0.0, 20.0, 350.0, 560.0)\n    ├─ Spacing: 16.0\n    └─ Alignment: center\n      ├─ UILabel \"Welcome\"\n      │   ├─ Frame: (25.0, 0.0, 300.0, 34.0)\n      │   └─ Font: .boldSystemFont(28)\n      ├─ Spacer\n      │   └─ Frame: (0.0, 50.0, 350.0, 400.0)\n      └─ UIButton \"Get Started\"\n          ├─ Frame: (35.0, 466.0, 280.0, 50.0)\n          └─ Background: systemBlue\n```\n\n### Debug Categories\n\n| Category       | Description                |\n| -------------- | -------------------------- |\n| 🔧 Layout      | Layout calculation process |\n| 🏗️ Hierarchy   | View hierarchy structure   |\n| 📐 Frame       | Frame setting and changes  |\n| 🔲 Spacer      | Spacer calculation details |\n| ⚡ Performance | Performance metrics        |\n\n---\n\n## 🏗️ Architecture\n\n### Overview\n\nLayout is built on a **frame-based calculation system** that separates measurement from placement, enabling high-performance declarative layouts without Auto Layout constraints. The architecture is designed to be modular, extensible, and performant.\n\n### Architecture Diagram\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│                        User Code Layer                          │\n├─────────────────────────────────────────────────────────────────┤\n│                                                                 │\n│  ┌────────────────┐       ┌──────────────┐                      │\n│  │UIViewController│──────►│@LayoutBuilder│                      │\n│  │                │       │    body      │                      │\n│  └────────────────┘       └──────────────┘                      │\n│         │                        │                              │\n│         └────────────┬───────────┘                              │\n│                      ▼                                          │\n└─────────────────────────────────────────────────────────────────┘\n                      │\n                      ▼\n┌─────────────────────────────────────────────────────────────────┐\n│                      LayoutContainer                            │\n├─────────────────────────────────────────────────────────────────┤\n│                                                                 │\n│  ┌──────────────────────────────────────────────────────────┐   │\n│  │  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐    │   │\n│  │  │View Hierarchy│  │Layout Calc   │  │Identity Map  │    │   │\n│  │  │  Management  │  │Orchestration │  │   Tracking   │    │   │\n│  │  └──────────────┘  └──────────────┘  └──────────────┘    │   │\n│  │                                                          │   │\n│  │  ┌──────────────┐  ┌──────────────┐                      │   │\n│  │  │Animation     │  │Incremental   │                      │   │\n│  │  │Protection    │  │Layout Updates│                      │   │\n│  │  └──────────────┘  └──────────────┘                      │   │\n│  └──────────────────────────────────────────────────────────┘   │\n│                                                                 │\n└─────────────────────────────────────────────────────────────────┘\n                      │\n                      ▼\n┌─────────────────────────────────────────────────────────────────┐\n│                      Layout System                              │\n├─────────────────────────────────────────────────────────────────┤\n│                                                                 │\n│  ┌──────────────┐         ┌──────────────┐                      │\n│  │ Layout Tree  │────────►│ LayoutNodes  │                      │\n│  │              │         │              │                      │\n│  └──────────────┘         └──────────────┘                      │\n│         │                        │                              │\n│         │                        ▼                              │\n│         │              ┌──────────────────┐                     │\n│         │              │ Dirty State      │                     │\n│         │              │ Cache Management │                     │\n│         │              └──────────────────┘                     │\n│         │                                                       │\n└─────────┼───────────────────────────────────────────────────────┘\n          │\n          ▼\n┌─────────────────────────────────────────────────────────────────┐\n│                    Layout Components                            │\n├─────────────────────────────────────────────────────────────────┤\n│                                                                 │\n│  ┌────────┐  ┌────────┐  ┌────────┐  ┌──────────┐  ┌───────────┐│\n│  │ VStack │  │ HStack │  │ ZStack │  │ScrollView│  │ViewLayout ││\n│  └────────┘  └────────┘  └────────┘  └──────────┘  └───────────┘│\n│                                                                 │\n│  ┌────────┐  ┌────────┐                                         │\n│  │ Spacer │  │ForEach │                                         │\n│  └────────┘  └────────┘                                         │\n│                                                                 │\n└─────────────────────────────────────────────────────────────────┘\n                      │\n                      ▼\n┌─────────────────────────────────────────────────────────────────┐\n│                  Two-Phase Layout System                        │\n├─────────────────────────────────────────────────────────────────┤\n│                                                                 │\n│  ┌──────────────────────┐         ┌──────────────────────┐      │\n│  │  Measure Phase       │────────►│  Layout Phase        │      │\n│  │  Calculate Size      │         │  Calculate Position  │      │\n│  │                      │         │                      │      │\n│  │  • Intrinsic Size    │         │  • Alignment         │      │\n│  │  • Size Modifiers    │         │  • Position Mods     │      │\n│  │  • Percentage Calc   │         │  • Final Frame       │      │\n│  └──────────────────────┘         └──────────────────────┘      │\n│                                                                 │\n└─────────────────────────────────────────────────────────────────┘\n                      │\n                      ▼\n┌─────────────────────────────────────────────────────────────────┐\n│                    Modifier System                              │\n├─────────────────────────────────────────────────────────────────┤\n│                                                                 │\n│  UIView ──(Associated Object)──► layoutModifiers[]              │\n│                                    │                            │\n│                                    ├─► SizeModifier             │\n│                                    ├─► OffsetModifier           │\n│                                    ├─► BackgroundModifier       │\n│                                    └─► PaddingModifier          │\n│                                                                 │\n└─────────────────────────────────────────────────────────────────┘\n```\n\n### Layout Calculation Flow\n\n```mermaid\nsequenceDiagram\n    participant User\n    participant LC as LayoutContainer\n    participant Tree as Layout Tree\n    participant Node as LayoutNode\n    participant Measure as Measure Phase\n    participant Layout as Layout Phase\n    participant Views as Views\n\n    User-\u003e\u003eLC: updateBody { body }\n    LC-\u003e\u003eTree: Build Layout Tree\n    Tree-\u003e\u003eNode: Create LayoutNodes\n    Node-\u003e\u003eNode: Check Dirty State\n\n    alt Node is Dirty\n        Node-\u003e\u003eMeasure: Calculate Size\n        Measure-\u003e\u003eNode: Return Measured Size\n        Node-\u003e\u003eLayout: Calculate Position\n        Layout-\u003e\u003eNode: Return Final Frame\n        Node-\u003e\u003eNode: Mark as Clean\n        Node-\u003e\u003eNode: Cache Result\n    else Node is Clean\n        Node-\u003e\u003eNode: Use Cached Result\n    end\n\n    Node-\u003e\u003eViews: Apply Frames\n    Views-\u003e\u003eUser: UI Updated\n```\n\n### Layout Tree Structure\n\n```mermaid\ngraph TD\n    Root[LayoutContainer\u003cbr/\u003erootNode]\n\n    Root --\u003e V1[VStack\u003cbr/\u003eLayoutNode]\n    V1 --\u003e|Child| H1[HStack\u003cbr/\u003eLayoutNode]\n    V1 --\u003e|Child| SV1[ScrollView\u003cbr/\u003eLayoutNode]\n\n    H1 --\u003e|Child| VL1[ViewLayout\u003cbr/\u003eLabel\u003cbr/\u003eLayoutNode]\n    H1 --\u003e|Child| VL2[ViewLayout\u003cbr/\u003eButton\u003cbr/\u003eLayoutNode]\n\n    SV1 --\u003e|Child| V2[VStack\u003cbr/\u003eLayoutNode]\n    V2 --\u003e|Child| VL3[ViewLayout\u003cbr/\u003eCard\u003cbr/\u003eLayoutNode]\n    V2 --\u003e|Child| FE1[ForEach\u003cbr/\u003eLayoutNode]\n\n    FE1 --\u003e|Child| VL4[ViewLayout\u003cbr/\u003eItem 1\u003cbr/\u003eLayoutNode]\n    FE1 --\u003e|Child| VL5[ViewLayout\u003cbr/\u003eItem 2\u003cbr/\u003eLayoutNode]\n\n    style Root fill:#e1f5ff\n    style V1 fill:#fff4e1\n    style H1 fill:#fff4e1\n    style SV1 fill:#fff4e1\n    style V2 fill:#fff4e1\n    style VL1 fill:#e8f5e9\n    style VL2 fill:#e8f5e9\n    style VL3 fill:#e8f5e9\n    style VL4 fill:#e8f5e9\n    style VL5 fill:#e8f5e9\n    style FE1 fill:#f3e5f5\n```\n\n### Two-Phase Layout System\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│                    Phase 1: Measure                         │\n├─────────────────────────────────────────────────────────────┤\n│                                                             │\n│  Proposed Bounds                                            │\n│       │                                                     │\n│       ▼                                                     │\n│  Intrinsic Size                                             │\n│       │                                                     │\n│       ▼                                                     │\n│  Size Modifiers                                             │\n│  (Fixed, Percentage, Flexible)                              │\n│       │                                                     │\n│       ▼                                                     │\n│  Measured Size ───────────────────┐                         │\n│                                   │                         │\n└───────────────────────────────────┼─────────────────────────┘\n                                    │\n                                    ▼\n┌─────────────────────────────────────────────────────────────┐\n│                    Phase 2: Layout                          │\n├─────────────────────────────────────────────────────────────┤\n│                                                             │\n│  Measured Size                                              │\n│       │                                                     │\n│       ▼                                                     │\n│  Position Modifiers                                         │\n│  (Offset, Center, Alignment)                                │\n│       │                                                     │\n│       ▼                                                     │\n│  Alignment Rules                                            │\n│       │                                                     │\n│       ▼                                                     │\n│  Final Frame                                                │\n│                                                             │\n└─────────────────────────────────────────────────────────────┘\n```\n\n### Incremental Layout System\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│                    Initial State                            │\n├─────────────────────────────────────────────────────────────┤\n│                                                             │\n│  All Nodes Clean ✓                                          │\n│       │                                                     │\n│       ▼                                                     │\n│  Layout Calculated                                          │\n│       │                                                     │\n│       ▼                                                     │\n│  Results Cached                                             │\n│                                                             │\n└─────────────────────────────────────────────────────────────┘\n                    │\n                    │ Change Detected\n                    ▼\n┌─────────────────────────────────────────────────────────────┐\n│                  Change Detected                            │\n├─────────────────────────────────────────────────────────────┤\n│                                                             │\n│  View Content Changes                                       │\n│       │                                                     │\n│       ▼                                                     │\n│  Mark View as Dirty                                         │\n│       │                                                     │\n│       ▼                                                     │\n│  Propagate to Parent                                        │\n│  (Dirty State Propagation)                                  │\n│                                                             │\n└─────────────────────────────────────────────────────────────┘\n                    │\n                    ▼\n┌─────────────────────────────────────────────────────────────┐\n│                Incremental Update                           │\n├─────────────────────────────────────────────────────────────┤\n│                                                             │\n│  Find Dirty Nodes                                           │\n│       │                                                     │\n│       ├──────────────────┬──────────────────┐               │\n│       │                  │                  │               │\n│       ▼                  ▼                  ▼               │\n│  Recalculate        Use Cache          Skip Clean           │\n│  Only Dirty         for Clean          Nodes                │\n│       │                  │                  │               │\n│       └──────────────────┴──────────────────┘               │\n│                       │                                     │\n│                       ▼                                     │\n│              Update Frames                                  │\n│                       │                                     │\n│                       ▼                                     │\n│              Mark as Clean ✓                                │\n│                                                             │\n└─────────────────────────────────────────────────────────────┘\n                    │\n                    │ (Loop back)\n                    ▼\n            Return to Initial State\n```\n\n### Identity-Based Diffing\n\n```\n┌──────────────┐         ┌──────────────┐         ┌──────────────┐\n│ Old Layout   │         │ Diff Engine  │         │ New Layout   │\n│              │         │              │         │              │\n│ View A (id:  │────────►│ Extract      │◄────────│ View A (id:  │\n│  'header')   │         │ Identities   │         │  'header')   │\n│              │         │              │         │              │\n│ View B (id:  │────────►│              │◄────────│ View D (id:  │\n│  'content')  │         │ Compare      │         │  'content')  │\n│              │         │ Maps         │         │              │\n│ View C (id:  │────────►│              │◄────────│ View E (id:  │\n│  'footer')   │         │              │         │  'sidebar')  │\n└──────────────┘         └──────────────┘         └──────────────┘\n                                │\n                                │ Calculate Diff\n                                ▼\n                    ┌───────────────────────┐\n                    │   Diff Results        │\n                    ├───────────────────────┤\n                    │                       │\n                    │ Match: View A ────────┼──► Reuse (State Preserved)\n                    │                       │\n                    │ Changed: B → D ───────┼──► Replace\n                    │                       │\n                    │ New: View E ──────────┼──► Create\n                    │                       │\n                    │ Removed: View C ──────┼──► Remove\n                    │                       │\n                    └───────────────────────┘\n                                │\n                                ▼\n                    ┌───────────────────────┐\n                    │ Updated View          │\n                    │ Hierarchy             │\n                    └───────────────────────┘\n```\n\n### Core Architecture Principles\n\n1. **Two-Phase Layout System**: Separates measurement (size calculation) from placement (position calculation)\n2. **Incremental Updates**: Only recalculates parts of the layout that have changed\n3. **Identity-Based Diffing**: Efficiently updates views by tracking identities\n4. **Modifier Storage**: Modifiers stored as properties, not as new layout nodes\n5. **Platform Abstraction**: Supports both UIKit and AppKit through conditional compilation\n\n### Core Components\n\n#### 1. Layout Protocol\n\nThe `Layout` protocol is the foundation of the entire system. All layout components conform to this protocol:\n\n```swift\n@MainActor\npublic protocol Layout {\n    func calculateLayout(in bounds: CGRect) -\u003e LayoutResult\n    func extractViews() -\u003e [UIView]\n    var intrinsicContentSize: CGSize { get }\n}\n```\n\n**Key Responsibilities:**\n\n- **`calculateLayout(in:)`**: Calculates frame positions for all managed views\n- **`extractViews()`**: Returns the views managed by this layout\n- **`intrinsicContentSize`**: Provides natural size for the layout\n\n#### 2. LayoutContainer\n\n`LayoutContainer` is the main orchestrator that manages the entire layout hierarchy:\n\n**Responsibilities:**\n\n- View hierarchy management (automatic add/remove)\n- Layout calculation orchestration\n- Identity-based view diffing\n- Animation protection\n- Incremental layout updates\n- Content centering\n\n**Key Properties:**\n\n- `body`: The root layout definition\n- `useIncrementalLayout`: Enables incremental updates\n- `rootNode`: Root of the layout tree for incremental updates\n\n#### 3. ViewLayout\n\n`ViewLayout` wraps individual `UIView` instances and provides modifier support:\n\n**Two-Phase Layout:**\n\n1. **Measure Phase**: Calculates the size the view wants based on modifiers\n2. **Layout Phase**: Calculates the final position based on size and alignment\n\n**Modifier Storage:**\n\n- Modifiers stored as associated objects on the view itself\n- No new `ViewLayout` instances created for modifier chains\n- Efficient property-based storage\n\n#### 4. Layout Components\n\n**Stack Components:**\n\n- `VStack`: Vertical stacking with spacing and alignment\n- `HStack`: Horizontal stacking with spacing and alignment\n- `ZStack`: Z-axis stacking with multiple alignment options\n\n**Container Components:**\n\n- `ScrollView`: Scrollable container with content offset preservation\n- `Spacer`: Flexible space component\n\n**Dynamic Components:**\n\n- `ForEach`: Dynamic list generation with identity-based diffing\n\n### Layout Calculation Flow\n\nThe following diagram shows the complete flow from user code to rendered UI:\n\n```\nUser Code\n    │\n    │ @LayoutBuilder body\n    ▼\n┌─────────────────────┐\n│ LayoutContainer     │\n│   updateBody()      │\n└─────────────────────┘\n    │\n    │ Build Layout Tree\n    ▼\n┌─────────────────────┐\n│ Layout Tree         │\n│ (LayoutNode         │\n│  hierarchy)         │\n└─────────────────────┘\n    │\n    │ View Hierarchy Diffing\n    ▼\n┌─────────────────────┐\n│ Identity-based      │\n│ Diffing             │\n└─────────────────────┘\n    │\n    │ Incremental Layout?\n    ├─────────┬─────────┐\n    │ Yes     │ No      │\n    ▼         ▼         ▼\n┌─────────┐ ┌─────────────────┐\n│ Check   │ │ Full            │\n│ Dirty   │ │ Calculation     │\n│ State   │ └─────────────────┘\n└─────────┘\n    │\n    ├─────────┬─────────┐\n    │ Dirty   │ Clean   │\n    ▼         ▼         │\n┌─────────┐ ┌─────────┐ │\n│ Measure │ │ Use     │ │\n│ Phase   │ │ Cached  │ │\n└─────────┘ └─────────┘ │\n    │         │         │\n    └─────────┴─────────┘\n              │\n              ▼\n    ┌─────────────────┐\n    │ Layout Phase    │\n    │ (Calculate      │\n    │  Positions)     │\n    └─────────────────┘\n              │\n              ▼\n    ┌─────────────────┐\n    │ Apply Frames    │\n    │ to Views        │\n    └─────────────────┘\n              │\n              ▼\n    ┌─────────────────┐\n    │ Update View     │\n    │ Hierarchy       │\n    └─────────────────┘\n              │\n              ▼\n         UI Rendered\n```\n\n### Two-Phase Layout System\n\nThe layout system separates measurement from placement:\n\n**Phase 1: Measure**\n\n- Calculate desired size for each view\n- Respects size modifiers (fixed, percentage, flexible)\n- Uses intrinsic content size as base\n- Results cached for reuse\n\n**Phase 2: Layout**\n\n- Calculate final position based on measured size\n- Applies alignment and positioning modifiers\n- Respects parent container constraints\n- Sets final frame on views\n\n**Benefits:**\n\n- Measurement can be cached independently\n- Placement can be recalculated without remeasuring\n- Supports responsive layouts with percentage-based sizing\n- Enables efficient incremental updates\n\n### Incremental Layout System\n\nThe incremental layout system only recalculates parts of the layout that have changed:\n\n**Layout Tree Structure:**\n\nThe layout tree mirrors your view hierarchy, with each component represented as a `LayoutNode`:\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│                    LayoutContainer                              │\n│                    (rootNode)                                   │\n│                    isDirty: false ✓                             │\n└────────────────────────────┬────────────────────────────────────┘\n                             │\n                             ▼\n              ┌───────────────────────────────┐\n              │      VStack (LayoutNode)      │\n              │      isDirty: false ✓         │\n              └───────────────┬───────────────┘\n                              │\n                ┌─────────────┴─────────────┐\n                │                           │\n                ▼                           ▼\n┌───────────────────────────┐  ┌───────────────────────────┐\n│  HStack (LayoutNode)      │  │  ScrollView (LayoutNode)  │\n│  isDirty: true            │  │  isDirty: false ✓         │\n└───────────┬───────────────┘  └─────────────┬─────────────┘\n            │                                │\n    ┌───────┴───────┐                        │\n    │               │                        │\n    ▼               ▼                        ▼\n┌──────────┐  ┌──────────┐          ┌────────────────────┐\n│ViewLayout│  │ViewLayout│          │ VStack (LayoutNode)│\n│  Label   │  │  Button  │          │ isDirty: false ✓   │\n│          │  │          │          └──────────┬─────────┘\n│isDirty:  │  │isDirty:  │                     │\n│true      │  │false ✓   │                     ▼\n└──────────┘  └──────────┘          ┌──────────────────┐\n                                    │ ViewLayout Card  │\n                                    │                  │\n                                    │ isDirty: false ✓ │\n                                    └──────────────────┘\n\n┌─────────────────────────────────────────────────────────────────┐\n│                            Legend                               │\n├─────────────────────────────────────────────────────────────────┤\n│                                                                 │\n│  Dirty (will be recalculated in next layout pass)               │\n│  Clean (uses cached result, skipped in calculation)             │\n│                                                                 │\n│  When a node is dirty:                                          │\n│    • It and all its children are recalculated                   │\n│    • Results are cached after calculation                       │\n│    • Parent nodes are marked dirty (propagation)                │\n│                                                                 │\n│  When a node is clean:                                          │\n│    • Uses cached layout result                                  │\n│    • Skips calculation entirely                                 │\n│    • Improves performance significantly                         │\n│                                                                 │\n└─────────────────────────────────────────────────────────────────┘\n```\n\n**Dirty Propagation:**\n\n- When a child node changes, it marks itself as dirty\n- Dirty state propagates up to parent nodes\n- Only dirty nodes are recalculated\n- Clean nodes use cached results\n\n**Key Components:**\n\n- `LayoutNode`: Represents a node in the layout tree\n- `IncrementalLayoutCache`: Caches layout results\n- `DirtyRegionTracker`: Tracks which regions need recalculation\n\n### Identity-Based Diffing\n\nViews are tracked by identity for efficient updates:\n\n**Identity System:**\n\n- Views can have explicit identity via `.id()` modifier\n- Identity used for view reuse across layout updates\n- Views with matching identities are reused (not recreated)\n- Enables state preservation (scroll position, selection, etc.)\n\n**Diffing Process:**\n\nThe identity-based diffing process efficiently updates views:\n\n```mermaid\nflowchart LR\n    subgraph \"Old Layout\"\n        O1[View A\u003cbr/\u003eid: 'header']\n        O2[View B\u003cbr/\u003eid: 'content']\n        O3[View C\u003cbr/\u003eid: 'footer']\n    end\n\n    subgraph \"Diff Engine\"\n        D1[Extract Identities]\n        D2[Compare Maps]\n        D3[Calculate Diff]\n    end\n\n    subgraph \"New Layout\"\n        N1[View A\u003cbr/\u003eid: 'header']\n        N2[View D\u003cbr/\u003eid: 'content']\n        N3[View E\u003cbr/\u003eid: 'sidebar']\n    end\n\n    subgraph \"Actions\"\n        A1[Reuse: View A]\n        A2[Replace: B → D]\n        A3[Add: View E]\n        A4[Remove: View C]\n    end\n\n    O1 --\u003e D1\n    O2 --\u003e D1\n    O3 --\u003e D1\n    N1 --\u003e D1\n    N2 --\u003e D1\n    N3 --\u003e D1\n\n    D1 --\u003e D2\n    D2 --\u003e D3\n\n    D3 --\u003e|Match| A1\n    D3 --\u003e|Changed| A2\n    D3 --\u003e|New| A3\n    D3 --\u003e|Removed| A4\n\n    style A1 fill:#e8f5e9\n    style A2 fill:#fff4e1\n    style A3 fill:#e1f5ff\n    style A4 fill:#ffebee\n```\n\n### Modifier System\n\nModifiers are stored as properties on views, not as new layout nodes:\n\n**Storage Mechanism:**\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│                    View Instance                            │\n├─────────────────────────────────────────────────────────────┤\n│                                                             │\n│  UIView                                                     │\n│    │                                                        │\n│    │ (Associated Object)                                    │\n│    ▼                                                        │\n│  ┌──────────────────────┐                                   │\n│  │ layoutModifiers[]    │                                   │\n│  ├──────────────────────┤                                   │\n│  │ • SizeModifier       │                                   │\n│  │ • OffsetModifier     │                                   │\n│  │ • BackgroundModifier │                                   │\n│  │ • PaddingModifier    │                                   │\n│  └──────────────────────┘                                   │\n│                                                             │\n└─────────────────────────────────────────────────────────────┘\n                    ▲\n                    │\n┌───────────────────┴───────────────────────────────────────────┐\n│              Modifier Chain (User Code)                       │\n├───────────────────────────────────────────────────────────────┤\n│                                                               │\n│  view.ui()                                                    │\n│    .size(width: 200, height: 100)  ────┐                      │\n│    .offset(x: 10, y: 20)            ────┤                     │\n│    .background(.systemBlue)         ────┼──► Stores in        │\n│    .padding(16)                      ────┤   layoutModifiers[]│\n│                                         │                     │\n└─────────────────────────────────────────┼─────────────────────┘\n                                          │\n                                          ▼\n┌─────────────────────────────────────────────────────────────┐\n│            Layout Calculation                               │\n├─────────────────────────────────────────────────────────────┤\n│                                                             │\n│  calculateLayout(in:)                                       │\n│    │                                                        │\n│    │ Reads layoutModifiers[]                                │\n│    ▼                                                        │\n│  Applies modifiers in order:                                │\n│    1. Size modifiers (Measure Phase)                        │\n│    2. Position modifiers (Layout Phase)                     │\n│    3. Style modifiers                                       │\n│    │                                                        │\n│    ▼                                                        │\n│  Final Frame                                                │\n│                                                             │\n└─────────────────────────────────────────────────────────────┘\n```\n\n**Key Benefits:**\n\n- Uses Associated Objects to store modifiers\n- Modifiers stored in `view.layoutModifiers` array\n- No new `ViewLayout` instances for modifier chains\n- Efficient property-based access\n- Modifiers persist across layout updates\n\n**Modifier Types:**\n\n```\n                    Modifiers\n                         │\n        ┌────────────────┼────────────────┐\n        │                │                │\n        ▼                ▼                ▼\n┌──────────────┐ ┌──────────────┐ ┌──────────────┐\n│ Size         │ │ Position     │ │ Style        │\n│ Modifiers    │ │ Modifiers    │ │ Modifiers    │\n├──────────────┤ ├──────────────┤ ├──────────────┤\n│              │ │              │ │              │\n│ • Fixed      │ │ • Offset     │ │ • Background │\n│   width: 200 │ │   x: 10      │ │   .systemBlue│\n│              │ │   y: 20      │ │              │\n│ • Percentage │ │              │ │ • Corner     │\n│   width: 80% │ │ • Center     │ │   Radius: 12 │\n│              │ │   centerX    │ │              │\n│ • Flexible   │ │   centerY    │ │ • Padding    │\n│   height: nil│ │              │ │   insets: 16 │\n│              │ │ • Alignment  │ │              │\n│              │ │   leading    │ │              │\n│              │ │   trailing   │ │              │\n└──────────────┘ └──────────────┘ └──────────────┘\n        │                │                │\n        └────────────────┼────────────────┘\n                         │\n                         ▼\n              ┌──────────────────┐\n              │ Identity         │\n              │ Modifiers        │\n              ├──────────────────┤\n              │ • .id('unique')  │\n              └──────────────────┘\n```\n\n### Animation System\n\nThe animation system protects animated views from layout interference:\n\n**Animation Protection Flow:**\n\n```\nUser Code\n    │\n    │ startAnimating(view)\n    ▼\n┌─────────────────────┐\n│ LayoutContainer     │\n│                     │\n│ Add to              │\n│ animatingViews set  │\n└─────────────────────┘\n    │\n    │ withAnimation { ... }\n    ▼\n┌─────────────────────┐\n│ Animation Engine    │\n│                     │\n│ Apply animation     │\n│ to view             │\n└─────────────────────┘\n    │\n    │ Animate frame/transform\n    ▼\n┌─────────────────────┐\n│ Animated View       │\n│ (frame changing)    │\n└─────────────────────┘\n    ▲\n    │\n    │ Layout System attempts\n    │ frame update\n    │\n┌─────────────────────┐\n│ LayoutContainer     │\n│                     │\n│ Check isAnimating   │\n│                     │\n│ Skip frame update   │\n│ (view is animating) │\n└─────────────────────┘\n    │\n    │ Animation completes\n    │ stopAnimating(view)\n    ▼\n┌─────────────────────┐\n│ LayoutContainer     │\n│                     │\n│ Remove from         │\n│ animatingViews      │\n│                     │\n│ Resume frame        │\n│ updates             │\n└─────────────────────┘\n```\n\n**Animation Architecture:**\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│                    User API                                 │\n├─────────────────────────────────────────────────────────────┤\n│                                                             │\n│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐       │\n│  │withAnimation │  │startAnimating│  │stopAnimating │       │\n│  └──────────────┘  └──────────────┘  └──────────────┘       │\n│         │                │                │                 │\n│         └────────────────┼────────────────┘                 │\n│                         │                                   │\n└─────────────────────────┼───────────────────────────────────┘\n                          │\n                          ▼\n┌─────────────────────────────────────────────────────────────┐\n│                LayoutContainer                              │\n├─────────────────────────────────────────────────────────────┤\n│                                                             │\n│  ┌──────────────────────┐  ┌────────────────────────┐       │\n│  │ animatingViews Set   │  │animatingViewIdentifiers│       │\n│  │                      │  │                        │       │\n│  │ • Tracks animating   │  │ • ObjectIdentifier     │       │\n│  │   views              │  │   tracking             │       │\n│  └──────────────────────┘  └────────────────────────┘       │\n│         │                                                   │\n│         │ Protects from layout updates                      │\n│         ▼                                                   │\n└─────────────────────────────────────────────────────────────┘\n                          │\n                          ▼\n┌─────────────────────────────────────────────────────────────┐\n│              Animation Engine                               │\n├─────────────────────────────────────────────────────────────┤\n│                                                             │\n│  ┌──────────────────────┐                                   │\n│  │LayoutAnimationEngine │                                   │\n│  │                      │                                   │\n│  │ • Manages animation  │                                   │\n│  │   state              │                                   │\n│  │ • Coordinates timing │                                   │\n│  └──────────────────────┘                                   │\n│         │                                                   │\n│         ├──────────────┬──────────────┐                     │\n│         ▼              ▼              ▼                     │\n│  ┌──────────┐  ┌──────────┐  ┌──────────┐                   │\n│  │Layout    │  │Timing    │  │Platform  │                   │\n│  │Animation │  │Function  │  │APIs      │                   │\n│  └──────────┘  └──────────┘  └──────────┘                   │\n│                                                             │\n│         │              │              │                     │\n│         └──────────────┴──────────────┘                     │\n│                          │                                  │\n│                          ▼                                  │\n│              ┌──────────────────────┐                       │\n│              │ UIView.animate       │                       │\n│              │ NSAnimationContext   │                       │\n│              └──────────────────────┘                       │\n│                                                             │\n└─────────────────────────────────────────────────────────────┘\n```\n\n**Key Features:**\n\n- `startAnimating(_:)`: Marks view as animating\n- `stopAnimating(_:)`: Removes animation protection\n- Layout system skips frame updates for animating views\n- `withAnimation` provides SwiftUI-style animation blocks\n- `LayoutAnimationEngine`: Manages animation state\n- `LayoutAnimation`: Defines animation parameters\n- `AnimationTimingFunction`: Timing functions (ease, spring, etc.)\n- Platform-specific animation APIs (UIView.animate / NSAnimationContext)\n\n### Environment System\n\nThe environment system provides context values throughout the layout hierarchy:\n\n**Environment Values:**\n\n- `ColorScheme`: Light/dark mode detection\n- `LayoutDirection`: RTL/LTR support\n- `Font`: Typography settings\n- `ForegroundColor`: Text color\n- Custom environment keys\n\n**Propagation:**\n\n- Environment values flow down the layout tree\n- Child layouts inherit parent environment\n- Can be overridden at any level\n- Platform-specific detection (UITraitCollection / NSApp.effectiveAppearance)\n\n### Caching System\n\nMultiple caching layers optimize performance:\n\n**Layout Cache:**\n\n- Caches `LayoutResult` for repeated calculations\n- Keyed by layout type and bounds\n- Reduces redundant calculations\n\n**Incremental Cache:**\n\n- Caches results for clean nodes in layout tree\n- Only dirty nodes recalculated\n- Enables partial updates\n\n**View Layout Cache:**\n\n- Caches modifier calculations\n- Stores measured sizes\n- Reuses measurements when possible\n\n### Platform Support\n\nThe library is built on UIKit and designed for iOS applications:\n\n**UIKit Foundation:**\n\n- Uses `UIView` as the base view type\n- Leverages UIKit's view hierarchy and lifecycle\n- Integrates with `UIViewController` lifecycle methods\n- Supports UIKit-specific features (safe areas, trait collections, etc.)\n\n**Future Platform Support:**\n\n- Architecture designed to support platform abstraction\n- Conditional compilation patterns in place for future expansion\n- Can be extended to support AppKit/macOS with platform-specific types\n\n### Performance Optimizations\n\n**Frame-Based Calculations:**\n\n- Direct frame manipulation (no constraint solver)\n- O(n) complexity for most layouts\n- No Auto Layout overhead\n\n**Incremental Updates:**\n\n- Only dirty nodes recalculated\n- Cached results for clean nodes\n- Minimal view hierarchy changes\n\n**Efficient Modifiers:**\n\n- Property-based storage (no new nodes)\n- Lazy evaluation when possible\n- Cached measurements\n\n**View Reuse:**\n\n- Identity-based view reuse\n- Minimal view creation/destruction\n- State preservation across updates\n\n**Value-Type Layout Buffer:**\n\nThe library implements `LayoutNodeBuffer`, a high-performance layout tree buffer using a contiguous memory array instead of object references. This provides significant performance benefits for complex layouts.\n\n```\nCurrent (Object-Based):\n┌──────────┐    ┌──────────┐    ┌──────────┐\n│ Node 1   │───►│ Node 2   │───►│ Node 3   │\n│ (Heap)   │    │ (Heap)   │    │ (Heap)   │\n└──────────┘    └──────────┘    └──────────┘\n   │              │              │\n   └──────────────┴──────────────┘\n   (Non-contiguous memory, cache misses)\n\nOptimized (Array-Based):\n┌─────────────────────────────────────────┐\n│ [Node 1] [Node 2] [Node 3] [Node 4] ... │\n│  (Contiguous memory, cache-friendly)    │\n└─────────────────────────────────────────┘\n```\n\n**Benefits:**\n\n1. **CPU Cache Efficiency**:\n\n   - Contiguous memory improves cache locality\n   - Sequential access patterns are significantly faster\n   - Reduced cache misses during tree traversal\n   - Better CPU prefetching behavior\n\n2. **Memory Allocation**:\n\n   - Single allocation instead of many small heap allocations\n   - Reduced ARC overhead (no reference counting needed)\n   - More efficient memory utilization\n\n3. **SIMD Optimization**:\n\n   - Vector operations possible on contiguous arrays\n   - Parallel processing of layout calculations\n   - Batch operations on multiple nodes\n\n4. **Memory Access Patterns**:\n   - Predictable access patterns enable CPU optimizations\n   - Better branch prediction\n   - Reduced pointer chasing\n\n**Trade-offs:**\n\n- More complex tree structure representation (indices instead of pointers)\n- Dynamic resizing requires array reallocation\n- Parent-child relationships managed via indices\n- More complex implementation and debugging\n\n**Implementation:**\n\n`LayoutNodeBuffer` is automatically used by `LayoutContainer` when `useIncrementalLayout` is enabled. The buffer manages layout nodes in a contiguous array, providing efficient tree operations:\n\n```swift\n// LayoutContainer automatically uses LayoutNodeBuffer internally\nlayoutContainer.useIncrementalLayout = true\n\n// The buffer is managed automatically:\n// - Created when layout tree is built\n// - Updated on layout changes\n// - Cleared when hierarchy changes\n```\n\n**API Overview:**\n\n```swift\npublic class LayoutNodeBuffer {\n    // Node management\n    func addNode(layout: any Layout, parentIndex: Int?) -\u003e Int\n    func removeNode(at index: Int)\n    func getNode(at index: Int) -\u003e LayoutNodeData?\n\n    // Tree operations\n    func buildTree(rootIndex: Int)\n    func calculateLayout(at index: Int, in bounds: CGRect) -\u003e LayoutResult\n\n    // Dirty state management\n    func markDirty(at index: Int, propagateToParent: Bool)\n    func invalidate(at index: Int)\n\n    // Statistics\n    func activeNodeCount() -\u003e Int\n    func totalCapacity() -\u003e Int\n}\n```\n\n**Performance Characteristics:**\n\n- Faster layout calculations for complex trees\n- Improved CPU cache utilization through contiguous memory access\n- Reduced memory allocation overhead\n- Better performance for dynamic content updates\n\n**User Experience Benefits:**\n\n- ✅ **Smooth animations**: No choppiness during rotation or transitions\n- ✅ **Faster response**: Layout updates complete more quickly\n- ✅ **Stable performance**: Consistent frame rates even with complex layouts\n- ✅ **Better battery life**: More efficient CPU usage\n\n**Implementation Status:**\n\n`LayoutNodeBuffer` is **currently implemented and used** by `LayoutContainer` when `useIncrementalLayout` is enabled. The library automatically manages the buffer internally, so you don't need to interact with it directly in most cases.\n\n**Usage:**\n\n```swift\n// Enable incremental layout (uses LayoutNodeBuffer internally)\nlayoutContainer.useIncrementalLayout = true\n\n// The buffer is automatically managed:\n// - Created when layout tree is built\n// - Updated on layout changes\n// - Cleared when hierarchy changes\n```\n\n**Best Practices:**\n\n1. **Enable Incremental Layout**: Always enable `useIncrementalLayout` for complex layouts\n\n   ```swift\n   layoutContainer.useIncrementalLayout = true\n   ```\n\n2. **Use Identity for Views**: Provide stable identities for views to enable efficient diffing\n\n   ```swift\n   view.ui().id(\"stable-id\")\n   ```\n\n3. **Minimize Layout Changes**: Batch layout updates when possible\n\n   ```swift\n   // Good: Single update\n   layoutContainer.updateBody { self.body }\n\n   // Avoid: Multiple updates\n   layoutContainer.updateBody { self.body1 }\n   layoutContainer.updateBody { self.body2 }\n   ```\n\n4. **Profile Performance**: Use `PerformanceProfiler` to identify bottlenecks\n   ```swift\n   PerformanceProfiler.shared.startProfiling()\n   // ... layout operations ...\n   let report = PerformanceProfiler.shared.stopProfiling()\n   ```\n\n**Debugging \u0026 Performance Monitoring:**\n\nThe library provides comprehensive debugging and performance monitoring tools:\n\n```swift\n// Enable layout debugging\nLayoutDebugger.shared.enableAll()\n\n// Monitor performance\nPerformanceProfiler.shared.startProfiling()\n// ... layout operations ...\nlet report = PerformanceProfiler.shared.stopProfiling()\n\n// Measure specific layout operations\nLayoutPerformanceMonitor.measureLayout(name: \"Complex Layout\") {\n    layoutContainer.layoutSubviews()\n}\n```\n\n**Troubleshooting Common Issues:**\n\n1. **Layout not updating**: Ensure `layoutContainer.updateBody()` is called after state changes\n2. **Views not appearing**: Check that views are properly added to the layout hierarchy\n3. **Performance issues**: Enable incremental layout and use identity for views\n4. **Animation conflicts**: Use `layoutContainer.startAnimating()` to protect views during animation\n\n**When to Use:**\n\n✅ **Array-based buffer is beneficial for:**\n\n- Complex layouts with many nodes (100+ nodes)\n- Frequent layout updates\n- Performance-critical applications\n- Applications requiring smooth scrolling and animations\n\n❌ **Object-based approach is sufficient for:**\n\n- Simple layouts (\u003c 50 nodes)\n- Infrequent updates\n- Development/prototyping phase\n- Code simplicity is priority\n\n**Note:** The `LayoutNodeBuffer` is automatically used by `LayoutContainer` when incremental layout is enabled. You don't need to interact with it directly in most cases. The library handles buffer management internally.\n\n### Debugging \u0026 Performance Tools\n\nThe library includes comprehensive debugging and performance monitoring tools:\n\n**Layout Debugger:**\n\n```swift\n// Enable debugging\nLayoutDebugger.shared.enableAll()\n\n// Enable specific categories\nLayoutDebugger.shared.enableViewHierarchy = true\nLayoutDebugger.shared.enableLayoutCalculation = true\nLayoutDebugger.shared.enableFrameSettings = true\n\n// Analyze view hierarchy\nLayoutDebugger.shared.analyzeViewHierarchy(\n    layoutContainer,\n    title: \"Layout Analysis\"\n)\n```\n\n**Performance Profiler:**\n\n```swift\n// Profile layout operations\nPerformanceProfiler.shared.startProfiling()\n// ... perform layout operations ...\nlet report = PerformanceProfiler.shared.stopProfiling()\n\n// Get performance statistics\nlet profiles = PerformanceProfiler.shared.allProfiles\nfor profile in profiles {\n    print(\"\\(profile.name): \\(profile.averageTime)ms\")\n}\n```\n\n**Performance Monitor:**\n\n```swift\n// Measure specific operations\nLayoutPerformanceMonitor.measureLayout(name: \"Complex Layout\") {\n    layoutContainer.layoutSubviews()\n}\n\n// Print performance summary\nLayoutPerformanceMonitor.printSummary()\n```\n\n**Frame Rate Monitor:**\n\n```swift\n// Monitor frame rate\nFrameRateMonitor.shared.start()\n// ... later ...\nlet fps = FrameRateMonitor.shared.averageFPS\nFrameRateMonitor.shared.stop()\n```\n\n### Troubleshooting\n\n**Common Issues and Solutions:**\n\n1. **Layout not updating after state change**\n\n   ```swift\n   // Solution: Call updateBody() after state changes\n   @State private var count = 0\n\n   Button(\"Increment\") {\n       count += 1\n       layoutContainer.updateBody { self.body }\n   }\n   ```\n\n2. **Views not appearing**\n\n   ```swift\n   // Solution: Ensure views are in the layout hierarchy\n   layoutContainer.updateBody {\n       VStack {\n           myView.ui()\n       }\n   }\n   ```\n\n3. **Performance issues with complex layouts**\n\n   ```swift\n   // Solution: Enable incremental layout and use identity\n   layoutContainer.useIncrementalLayout = true\n   view.ui().id(\"stable-id\")\n   ```\n\n4. **Animation conflicts with layout**\n\n   ```swift\n   // Solution: Protect views during animation\n   layoutContainer.startAnimating(view)\n   // ... animate view ...\n   layoutContainer.stopAnimating(view)\n   ```\n\n5. **Layout calculations taking too long**\n   ```swift\n   // Solution: Profile and optimize\n   PerformanceProfiler.shared.startProfiling()\n   // ... identify bottlenecks ...\n   PerformanceProfiler.shared.stopProfiling()\n   ```\n\n### Extension Points\n\nThe architecture is designed for extensibility:\n\n**Custom Layouts:**\n\n- Conform to `Layout` protocol\n- Implement `calculateLayout(in:)` and `extractViews()`\n- Integrate with existing layout system\n\n**Custom Modifiers:**\n\n- Conform to `LayoutModifier` protocol\n- Store as associated objects\n- Apply in measure/layout phases\n\n**Custom Components:**\n\n- Build on existing stack components\n- Use `LayoutBuilder` for composition\n- Integrate with environment system\n\n---\n\n## 🏗️ Project Structure\n\n```\nSources/Layout/\n├── Animation/              # Animation engine \u0026 timing functions\n│   ├── AnimationTimingFunction.swift\n│   ├── LayoutAnimation.swift\n│   ├── LayoutAnimationEngine.swift\n│   ├── LayoutTransition.swift\n│   ├── TransitionConfig.swift\n│   ├── AnimatedLayout.swift\n│   ├── Animated.swift\n│   ├── AnimationToken.swift\n│   ├── VectorArithmetic.swift\n│   └── WithAnimation.swift\n│\n├── Cache/                  # Layout caching system\n│   ├── LayoutCache.swift\n│   ├── LayoutCacheKey.swift\n│   ├── IncrementalLayoutCache.swift\n│   ├── CacheableLayout.swift\n│   └── ViewLayoutCache.swift\n│\n├── Components/            # Layout components\n│   ├── VStack.swift\n│   ├── HStack.swift\n│   ├── ZStack.swift\n│   ├── ScrollView.swift\n│   ├── Spacer.swift\n│   └── ForEach.swift\n│\n├── Environment/           # Environment values \u0026 providers\n│   ├── EnvironmentValues.swift\n│   ├── EnvironmentKey.swift\n│   ├── EnvironmentKeys.swift\n│   ├── EnvironmentProvider.swift\n│   ├── EnvironmentObject.swift\n│   ├── EnvironmentPropertyWrapper.swift\n│   ├── EnvironmentModifierLayout.swift\n│   ├── ColorScheme.swift\n│   └── LayoutDirection.swift\n│\n├── Geometry/              # Geometry system\n│   ├── GeometryReader.swift\n│   ├── GeometryProxy.swift\n│   ├── CoordinateSpace.swift\n│   ├── CoordinateSpaceRegistry.swift\n│   ├── Anchor.swift\n│   └── UnitPoint.swift\n│\n├── Invalidation/          # Layout invalidation system\n│   ├── LayoutInvalidating.swift\n│   ├── LayoutInvalidationContext.swift\n│   ├── InvalidationReason.swift\n│   └── DirtyRegionTracker.swift\n│\n├── Layout/                # Core layout protocol \u0026 builders\n│   ├── Layout.swift\n│   ├── LayoutBuilder.swift\n│   ├── LayoutResult.swift\n│   ├── LayoutModifier.swift\n│   ├── LayoutNode.swift   # Layout tree node for incremental updates\n│   ├── LayoutNodeBuffer.swift  # High-performance array-based layout buffer\n│   ├── EmptyLayout.swift\n│   ├── TupleLayout.swift\n│   ├── ArrayLayout.swift\n│   ├── OptionalLayout.swift\n│   ├── ConditionalLayout.swift\n│   ├── BackgroundLayout.swift\n│   ├── OverlayLayout.swift\n│   └── CornerRadius.swift\n│\n├── Modifiers/             # Layout modifiers\n│   ├── SizeModifier.swift\n│   ├── PaddingModifier.swift\n│   ├── OffsetModifier.swift\n│   ├── PositionModifier.swift\n│   ├── CenterModifier.swift\n│   ├── BackgroundModifier.swift\n│   ├── CornerRadiusModifier.swift\n│   ├── AspectRatioModifier.swift\n│   └── AnimationModifier.swift\n│\n├── Performance/           # Performance monitoring\n│   ├── FrameRateMonitor.swift\n│   ├── PerformanceProfiler.swift\n│   ├── PerformanceProfile.swift\n│   ├── PerformanceReport.swift\n│   ├── PerformanceThreshold.swift\n│   ├── PerformanceWarning.swift\n│   └── ProfilingToken.swift\n│\n├── Preferences/           # Preference system\n│   ├── PreferenceKey.swift\n│   ├── PreferenceKeys.swift\n│   ├── PreferenceRegistry.swift\n│   ├── PreferenceValues.swift\n│   └── PreferenceModifierLayout.swift\n│\n├── Priority/              # Layout priority system\n│   ├── LayoutPriority.swift\n│   ├── ContentPriority.swift\n│   ├── PriorityLayout.swift\n│   ├── FlexibleLayout.swift\n│   ├── FixedSizeLayout.swift\n│   ├── LayoutAxis.swift\n│   ├── PrioritySizeCalculator.swift\n│   └── StackPriorityDistributor.swift\n│\n├── Snapshot/              # Snapshot testing\n│   ├── SnapshotConfig.swift\n│   ├── SnapshotEngine.swift\n│   ├── SnapshotResult.swift\n│   └── SnapshotAsserter.swift\n│\n├── Utils/                 # Utility extensions\n│   ├── UIView+Layout.swift\n│   ├── UIView+Modifiers.swift  # Modifier storage (Associated Objects)\n│   ├── UIView+SwiftUI.swift\n│   ├── UIViewController+Layout.swift  # UIKit lifecycle integration\n│   └── ArraryExtension.swift\n│\n├── Invalidation/          # Layout invalidation system\n│   ├── LayoutInvalidating.swift\n│   ├── LayoutInvalidationContext.swift\n│   ├── LayoutInvalidationRules.swift  # Invalidation rules\n│   ├── InvalidationReason.swift\n│   └── DirtyRegionTracker.swift\n│\n├── LayoutContainer.swift  # Main container class\n├── ViewLayout.swift       # View layout wrapper (two-phase layout)\n└── LayoutDebugger.swift   # Debugging utilities with hooks\n```\n\n---\n\n## 🎯 Migration from Auto Layout\n\n### Before (Auto Layout)\n\n```swift\n// Complex constraint setup\ntitleLabel.translatesAutoresizingMaskIntoConstraints = false\nsubtitleLabel.translatesAutoresizingMaskIntoConstraints = false\nbutton.translatesAutoresizingMaskIntoConstraints = false\n\nNSLayoutConstraint.activate([\n    titleLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 40),\n    titleLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),\n    titleLabel.widthAnchor.constraint(equalToConstant: 280),\n\n    subtitleLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 16),\n    subtitleLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),\n    subtitleLabel.widthAnchor.constraint(equalToConstant: 280),\n\n    button.topAnchor.constraint(equalTo: subtitleLabel.bottomAnchor, constant: 40),\n    button.centerXAnchor.constraint(equalTo: view.centerXAnchor),\n    button.widthAnchor.constraint(equalToConstant: 240),\n    button.heightAnchor.constraint(equalToConstant: 50)\n])\n```\n\n### After (Layout - Pure Manual Layout)\n\n```swift\nclass MyViewController: BaseViewController, Layout {\n    let titleLabel = UILabel()\n    let subtitleLabel = UILabel()\n    let button = UIButton()\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        // BaseViewController automatically sets up layoutContainer\n    }\n\n    override func setLayout() {\n        layoutContainer.updateBody { self.body }\n    }\n\n    // Clean, declarative layout\n    @LayoutBuilder var body: some Layout {\n        VStack(alignment: .center, spacing: 16) {\n            Spacer(minLength: 40)\n\n            titleLabel.layout()\n                .size(width: 280, height: 30)\n\n            subtitleLabel.layout()\n                .size(width: 280, height: 20)\n\n            Spacer(minLength: 40)\n\n            button.layout()\n                .size(width: 240, height: 50)\n\n            Spacer()\n        }\n    }\n}\n```\n\n### Benefits\n\n| Aspect        | Auto Layout          | Layout                              |\n| ------------- | -------------------- | ----------------------------------- |\n| Lines of code | ~15 lines            | ~10 lines                           |\n| Readability   | Constraint pairs     | Visual hierarchy                    |\n| Performance   | Constraint solver    | Direct frame calculations           |\n| Debugging     | Constraint conflicts | Simple frame inspection + hooks     |\n| Flexibility   | Rigid constraints    | Dynamic calculations                |\n| Layout System | Auto Layout engine   | Pure Manual Layout (no constraints) |\n| Modifiers     | N/A                  | Stored as properties (no new nodes) |\n| Layout Phases | Single phase         | Two-phase (measure + layout)        |\n\n---\n\n## 🆕 Recent Updates\n\n### Percentage-Based Sizing\n\nLayout now supports percentage-based sizing and positioning:\n\n- **Postfix `%` Operator**: Use `80%` syntax for intuitive percentage values\n- **Mixed Types**: Combine percentage and fixed sizes (e.g., `size(width: 80%, height: 50)`)\n- **Edge Positioning**: Position views using percentage offsets (e.g., `.top(10%)`, `.leading(20%)`)\n- **Responsive Layouts**: Automatically adapts to screen rotation and size changes\n\n```swift\n// Simple percentage syntax\nmyView.layout()\n    .size(width: 90%, height: 100)\n    .centerX()\n\n// Mixed fixed and percentage\ncardView.layout()\n    .size(width: 50%, height: 140)\n```\n\n### DSL-First Approach\n\nExample app components have been refactored to use DSL syntax instead of imperative methods:\n\n- **Before**: UIView creation with manual frame calculations\n- **After**: Declarative VStack/HStack with percentage-based sizing\n- **Benefits**: Better readability, automatic layout updates, responsive design\n\n---\n\n## 🙏 Inspiration\n\nLayout is inspired by:\n\n- [SwiftUI](https://developer.apple.com/xcode/swiftui/) - Declarative syntax and result builders\n- [Yoga](https://yogalayout.com/) - Flexbox layout concepts\n- [ComponentKit](https://componentkit.org/) - Declarative UI for iOS\n\n---\n\n## 📄 License\n\n**swift-layout** is released under the MIT license. See the [LICENSE](LICENSE) file for more info.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpelagornis%2Fswift-layout","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpelagornis%2Fswift-layout","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpelagornis%2Fswift-layout/lists"}