// 🖥️ TUIKit — Terminal UI Kit for Swift // ContentView.swift // // Created by LAYERED.work // License: MIT import TUIkit // MARK: - Demo Page Enum /// The available demo pages in the example app. enum DemoPage: Int, CaseIterable { case menu case textStyles case colors case containers case overlays case layout case buttons case toggles case textFields case secureFields case radioButtons case spinners case lists case tables case sliders case steppers case splitView case imageFile case imageURL } // MARK: - Content View (Page Router) /// The main content view that switches between pages. /// /// This view acts as a router, displaying the appropriate demo page /// based on the current state. It uses `@State` for all reactive /// properties — exactly like SwiftUI. struct ContentView: View { @State var currentPage: DemoPage = .menu @State var menuSelection: Int = 0 var body: some View { // Capture bindings for use in closures let pageSetter = $currentPage // Show current page based on state // Note: Background color is set by AppRunner using theme.background pageContent(for: currentPage, pageSetter: pageSetter) .onKeyPress { event in switch event.key { case .escape: // ESC goes back to menu (or exits if already on menu) if currentPage != .menu { pageSetter.wrappedValue = .menu return true // Consumed } return false // Let default handler exit the app default: // Quick-jump shortcuts only work from the menu page. // On sub-pages they would conflict with text input // (e.g. TextField, SecureField). guard currentPage == .menu else { return false } return handleMenuShortcut(event.key) } } } @ViewBuilder private func pageContent(for page: DemoPage, pageSetter: Binding) -> some View { switch page { case .menu: MainMenuPage(currentPage: $currentPage, menuSelection: $menuSelection) .statusBarItems { StatusBarItem(shortcut: Shortcut.arrowsUpDown, label: "nav") StatusBarItem(shortcut: Shortcut.enter, label: "select", key: .enter) StatusBarItem(shortcut: Shortcut.range("1", "9") + ", 0", label: "jump") } case .textStyles: TextStylesPage() .statusBarItems(subPageItems(pageSetter: pageSetter)) case .colors: ColorsPage() .statusBarItems(subPageItems(pageSetter: pageSetter)) case .containers: ContainersPage() .statusBarItems(subPageItems(pageSetter: pageSetter)) case .overlays: OverlaysPage(onBack: { pageSetter.wrappedValue = .menu }) case .layout: LayoutPage() .statusBarItems(subPageItems(pageSetter: pageSetter)) case .buttons: ButtonsPage() .statusBarItems(subPageItems(pageSetter: pageSetter)) case .toggles: TogglePage() .statusBarItems(subPageItems(pageSetter: pageSetter)) case .textFields: TextFieldPage() .statusBarItems(subPageItems(pageSetter: pageSetter)) case .secureFields: SecureFieldPage() .statusBarItems(subPageItems(pageSetter: pageSetter)) case .radioButtons: RadioButtonPage() .statusBarItems(subPageItems(pageSetter: pageSetter)) case .spinners: SpinnersPage() .statusBarItems(subPageItems(pageSetter: pageSetter)) case .lists: ListPage() .statusBarItems(subPageItems(pageSetter: pageSetter)) case .tables: TablePage() .statusBarItems(subPageItems(pageSetter: pageSetter)) case .sliders: SliderPage() .statusBarItems(subPageItems(pageSetter: pageSetter)) case .steppers: StepperPage() .statusBarItems(subPageItems(pageSetter: pageSetter)) case .splitView: SplitViewPage() .statusBarItems(subPageItems(pageSetter: pageSetter)) case .imageFile: ImageFilePage() case .imageURL: ImageURLPage() } } /// Common status bar items for sub-pages. private func subPageItems(pageSetter: Binding) -> [any StatusBarItemProtocol] { [ StatusBarItem(shortcut: Shortcut.escape, label: "back") { [pageSetter] in pageSetter.wrappedValue = .menu }, StatusBarItem(shortcut: Shortcut.arrowsUpDown, label: "scroll"), ] } /// Handles quick-jump shortcuts from the menu page. /// /// - Returns: `true` if the key was consumed, `false` otherwise. private func handleMenuShortcut(_ key: Key) -> Bool { let mapping: [Character: DemoPage] = [ "1": .textStyles, "2": .colors, "3": .containers, "4": .overlays, "5": .layout, "6": .buttons, "7": .toggles, "8": .textFields, "\\": .secureFields, "9": .radioButtons, "0": .spinners, "-": .lists, "=": .tables, "[": .sliders, "]": .steppers, ";": .splitView, "'": .imageFile, ",": .imageURL, ] if case .character(let ch) = key, let page = mapping[ch] { currentPage = page return true } return false } }