rn-tv-focus-debugger
v0.1.0
Published
Lightweight dev-only focus and spatial navigation debugger for React Native TV apps
Maintainers
Readme
rn-tv-focus-debugger
Lightweight, dev-only focus and spatial navigation debugger for React Native TV apps. Diagnose focus issues on LG webOS, Samsung Tizen, Vidaa OS, Android TV, and tvOS.
Features
- Logs focus transitions (gain/loss, direction, screen) in human-readable format
- Detects common misconfigurations:
- Missing
hasTVPreferredFocuson initial-focus elements - Broken or circular
nextFocusUp/Down/Left/Rightchains - Focus lost after re-render/remount
- Duplicate or missing focus refs
- Missing
- Lite mode — warnings only, no verbose transition logs (for low-end TV QA)
- Zero production impact — tree-shakeable, gated behind
__DEV__and an explicitenabledflag - Platform-aware AI prompt templates for deeper debugging
Installation
npm install rn-tv-focus-debugger
# or
yarn add rn-tv-focus-debuggerPeer dependencies
{
"react": ">=18.0.0",
"react-native": ">=0.73.0"
}react-native-tvos
If your app uses the TV fork, alias react-native to react-native-tvos in package.json:
{
"dependencies": {
"react-native": "npm:[email protected]"
}
}This package peers on react-native only and works with both the fork and built-in TV support.
Quick start
import { Pressable, Text } from 'react-native';
import {
FocusDebugProvider,
enableTVFocusDebugger,
useTVFocusDebug,
} from 'rn-tv-focus-debugger';
// Call once at app startup (dev/QA builds only)
enableTVFocusDebugger({
platform: 'tizen', // 'webos' | 'tizen' | 'vidaa' | 'androidtv' | 'tvos' | 'auto'
lite: false,
});
export default function App() {
return (
<FocusDebugProvider screenName="Home">
<HomeScreen />
</FocusDebugProvider>
);
}
function HomeScreen() {
return <Card title="Featured" />;
}
function Card({ title }: { title: string }) {
const focusDebug = useTVFocusDebug({ label: title, testID: 'home-card' });
return (
<Pressable {...focusDebug} onPress={() => {}}>
<Text>{title}</Text>
</Pressable>
);
}Lite mode (low-end devices)
On QA devices with limited RAM/CPU (512MB–1GB, older WebKit on Tizen/webOS), enable lite mode to suppress transition logs and keep only critical warnings:
enableTVFocusDebugger({ lite: true, platform: 'webos' });| Mode | Transition logs | Warnings/errors | |------|----------------|-----------------| | Default | Yes (debounced) | Yes | | Lite | No | Yes |
Production build safety
All diagnostic logic is:
- Compile-time gated — Metro/babel strip
__DEV__blocks in release builds - Runtime gated —
enableddefaults to__DEV__; setenabled: falseto force off - Tree-shakeable —
"sideEffects": falsein package.json
In production, useTVFocusDebug returns no-op handlers with near-zero overhead. Do not call enableTVFocusDebugger({ enabled: true }) in production.
API
enableTVFocusDebugger(config?)
| Option | Default | Description |
|--------|---------|-------------|
| enabled | __DEV__ | Master switch |
| lite | false | Warnings only |
| maxHistory | 50 | Ring buffer size |
| logDebounceMs | 150 | Debounce transition logs |
| validateDebounceMs | 300 | Debounce validation runs |
| platform | 'auto' | Target TV platform |
| logSink | console.* | Custom log output |
disableTVFocusDebugger()
Disables the debugger and tears down timers/registry.
getFocusDiagnostics()
Returns a snapshot: history, warnings, nodeCount, focusedNodeId.
FocusDebugProvider
Wraps a screen. Tracks mount/unmount and optional re-renders (trackRerender).
useTVFocusDebug(options)
Returns { onFocus, onBlur } handlers to spread onto focusable components.
withTVFocusDebug(Component, defaultOptions?)
HOC for class or legacy components.
AI prompt templates
import {
FOCUS_NAVIGATION_DEBUGGER_PROMPT,
buildFocusDebugPrompt,
getFocusDiagnostics,
} from 'rn-tv-focus-debugger';
const prompt = buildFocusDebugPrompt({
platform: 'vidaa',
diagnostics: getFocusDiagnostics(),
codeSnippet: myComponentSource,
additionalContext: 'Focus disappears after FlatList scroll',
});
Platform notes
| Platform | Focus engine | Tips |
|----------|-------------|------|
| LG webOS | JS spatial nav (often Norigin) | Pass explicit direction in useTVFocusDebug if needed |
| Samsung Tizen | JS spatial nav | Use lite: true on older models; test in Tizen Studio Emulator |
| Vidaa OS | JS spatial nav | Same as webOS/Tizen |
| Android TV | Cartesian proximity | Verify off-screen items don't steal focus |
| tvOS | UIFocusEngine | Prefer TVFocusGuideView over nextFocus* for complex layouts |
Manual QA checklist
LG webOS TV Simulator
- Install webOS TV Simulator
- Enable debugger:
enableTVFocusDebugger({ platform: 'webos' }) - Navigate a grid with D-pad; verify transition logs in Web Inspector console
- Navigate 10+ screens; confirm no slowdown (registry cleans up on unmount)
- Run 5+ minutes; check memory in Web Inspector stays stable
Samsung Tizen Studio Emulator
- Install Tizen Studio
- Enable debugger with
lite: trueon older emulator images - Repeat navigation and memory checks above
- Test rapid D-pad input; logs should be debounced, not per-keypress
Vidaa SDK
- Use Vidaa SDK simulator if available for your target SDK version
- If no simulator, test on hardware with
lite: true - Verify focus warnings appear for broken
nextFocus*chains
Prolonged navigation test (all platforms)
- Navigate between 10+ screens over 5–10 minutes
- Confirm
getFocusDiagnostics().nodeCountreturns to 0 after leaving a screen - No increasing lag on key presses
Development
npm install
npm run lint
npm test
npm run test:benchmark
npm run benchmark # standalone 10s rapid-key simulation
npm run buildLicense
MIT
