🏗️ Arquitetura de 4 Camadas
Layer 1: Launchers (dialogLaunchers.tsx)
Funcoes async retornando Promises tipadas
Layer 2: Helpers (interactiveHelpers.tsx)
Wrappers showDialog / showSetupDialog
Layer 3: Design System
Primitivos: Dialog, Pane, PermissionDialog
Layer 4: Feature Components
Requests de permissao tool-specific e paginas de wizard
🎨 Primitivos do Design System
Dialog
Chrome padrao para interacoes confirm/cancel
Pane
Regiao sem borda para telas de slash-command
PermissionDialog
Frame especializado para requests de permissao de tools
🛡️ Permission Requests
BashPermissionRequest e o mais complexo, com integracao de classifier, regras de "allow prefix", avisos de comandos destrutivos e fallback para sandbox.
⚡ ClassifierCheckingSubtitle
Extraido porque um clock de shimmer a 20fps re-renderizaria a arvore inteira de 535 linhas a cada 50ms. A extracao isola o re-render apenas ao subtitle.
🎛️ CustomSelect Widget
Widget de input universal com duas variantes:
TextOption
Opcao padrao com label e valor
InputOption
Embute campo de texto ao vivo dentro da lista de selecao
🧙 Wizard Pattern
🗺️ Arquitetura Completa
flowchart TD
A["main.tsx\nsetupScreens()"] -->|"await"| B["dialogLaunchers.tsx\nlaunchXxx(root, props)"]
B -->|"dynamic import"| C["Component Module\ne.g. SnapshotUpdateDialog"]
B -->|"calls"| D["interactiveHelpers.tsx\nshowSetupDialog()"]
D -->|"wraps in"| E["AppStateProvider\n+ KeybindingSetup"]
E -->|"root.render()"| F["Dialog / PermissionDialog / Pane\ndesign-system primitives"]
F --> G["Feature Component\ne.g. InvalidSettingsDialog,\nBashPermissionRequest"]
G --> H["CustomSelect\nor TextInput"]
H -->|"user selects"| I["done(result)\nresolves Promise"]
I -->|"returns typed value"| A
🔄 Ciclo de Vida do Dialog
sequenceDiagram
participant M as main.tsx
participant DL as dialogLaunchers.tsx
participant IH as interactiveHelpers.tsx
participant R as Ink Root
participant C as Dialog Component
participant U as User
M->>DL: await launchXxxDialog(root, props)
DL->>DL: dynamic import(component)
DL->>IH: showSetupDialog(root, renderer)
IH->>R: root.render(AppStateProvider + KeybindingSetup)
R->>C: mount Dialog/PermissionDialog with keybindings
C->>U: display in terminal
U-->>C: keypress (Enter / Esc / arrow)
C->>C: useKeybinding fires
C->>IH: done(selectedValue)
IH->>DL: Promise resolves with typed value
DL->>M: returns typed result
📋 Resumo do Modulo
showSetupDialog e o unico local onde AppStateProvider e KeybindingSetup sao adicionados
isCancelActive resolve conflitos de text input
switch unico