@osiris-smarttv/tv-viewport-frame
v0.1.1
Published
Fixed 1920×1080 TV viewport shell — letterbox, root rem scaling, design-unit math
Readme
@osiris-smarttv/tv-viewport-frame
Fixed 1920x1080 viewport frame for Smart TV apps.
This package keeps your app rendered inside a deterministic Full HD artboard while the host browser window can be any size. It handles center letterboxing, root rem scaling, and design-unit conversion so layout remains stable across TVs, emulator windows, and desktop testing.
Why this package
- Stable TV canvas: one 1920x1080 design stage, centered in the host
- Responsive scale: automatic scale-down for smaller host windows
- Design math helpers: convert design px/rem into real rendered pixels
- Framework split: pure
coreAPI +reactintegration layer - DOM/CSS contract: predictable stage/app attributes for integration and testing
Install
npm i @osiris-smarttv/tv-viewport-frameExports
@osiris-smarttv/tv-viewport-frame(package root)@osiris-smarttv/tv-viewport-frame/core@osiris-smarttv/tv-viewport-frame/react@osiris-smarttv/tv-viewport-frame/styles.css
Quick Start (React)
import { TvViewportFrame } from '@osiris-smarttv/tv-viewport-frame/react'
import '@osiris-smarttv/tv-viewport-frame/styles.css'
export function AppRoot() {
return (
<TvViewportFrame>
<App />
</TvViewportFrame>
)
}With config override
<TvViewportFrame
config={{
fitToWindow: true,
showViewportBadge: false,
}}
onViewportChange={(snapshot) => {
// snapshot.scale, snapshot.host, snapshot.realSize
}}
>
<App />
</TvViewportFrame>Quick Start (Core only, no React)
import { createTvViewportSdk } from '@osiris-smarttv/tv-viewport-frame/core'
const sdk = createTvViewportSdk()
const snapshot = sdk.snapshot({ width: 1280, height: 720 })
const scale = snapshot.scale
const buttonPx = snapshot.realSize.px(96) // design 96px -> rendered pxDOM and CSS contract
When enabled, frame chrome renders:
- root frame:
.tv-viewport-frame(data-tv-viewport-frame-root) - stage:
.tv-viewport-frame__stage(data-tv-viewport-stage) - app shell:
.tv-viewport-frame__app(data-tv-viewport-app)
The style export sets:
html[data-tv-viewport-frame] { font-size: calc(var(--tv-viewport-scale, 1) * 100%); }- stage dimensions via CSS vars (
--tv-viewport-stage-width-rem,--tv-viewport-stage-height-rem)
Import once in app bootstrap:
import '@osiris-smarttv/tv-viewport-frame/styles.css'React hooks
From @osiris-smarttv/tv-viewport-frame/react:
useTvViewport()-> full viewport state (enabled,snapshot,config,sdk)useTvViewportScale()-> current scale onlyuseTvViewportRealSize()-> px/rem conversion helpers bound to current scaleuseTvViewportSelector(selector, isEqual?)-> optimized state selection
Core API highlights
From @osiris-smarttv/tv-viewport-frame/core:
createTvViewportSdk()createTvViewportStore()computeTvViewportScale()designPxToRealPx(),designPxToRem(),designRemToRealPx()applyTvViewportDocumentState(),clearTvViewportDocumentState()- presets/constants:
TV_VIEWPORT_PRESETS,TV_VIEWPORT_FULL_HD,DEFAULT_TV_VIEWPORT_FRAME_CONFIG
Runtime policy
TvViewportFrame defaults to a runtime policy:
- disabled in
testmode - otherwise enabled unless
VITE_TV_VIEWPORT_FRAME=false
You can always override with explicit enabled prop.
Local development
yarn install
yarn build
yarn typecheck
yarn testManual publish (no GitHub Actions)
yarn publish:check
yarn publish:dry-run
yarn publish:manualIf publish returns 404 or permission errors for @osiris-smarttv/*, verify:
- your npm account has publish access to scope
@osiris-smarttv - package name is allowed by org policy
- you are authenticated against
https://registry.npmjs.org/
