api/internal/pip/pip_config library

Typed config for a pip campaign — a small, draggable media window scoped to one screen that expands to full screen on tap.

Wire shape (see ai_docs/pip-properties.md, the normative contract):

templateConfig
  templateType: "pip"
  media      { kind, url, aspectRatio, autoplay, loop,
               startMuted, volume }
  collapsed  { widthFraction, position, heightDp?, marginDp{t,r,b,l},
               cornerRadiusDp, border?, shadow, entryAnimation, exitAnimation }
  expanded   { layout: "overlay", mediaFit, backgroundColor, scrimOpacity,
               showCloseButton, closePlacement, onClose, onBack,
               showPlaybackControls, showMute, unmuteOnExpand,
               transitionMs, iconSize, controlsMarginDp{t,r,b,l},
               designWidth, canvas }
  controls   { draggable, snapToEdge, showClose, showMute, showExpand,
               showCollapse, showPlayPause, showProgress, iconSize,
               marginDp }
  behavior   { onTap, initialState, scope, onMediaEnd, autoDismissAfterMs,
               reshowOnReturn, pauseWhenObscured }

Every field is optional on the wire and falls back to the default here, so a payload written by an older dashboard still renders instead of throwing — the lenient-parse convention the other campaign configs follow.

expanded.canvas is a campaign canvas: the full-screen region is drawn by the shared canvas renderer, so this holds a CampaignCanvas rather than inventing a second content model. There is no layoutMode discriminator — a nudge carries one because it has two authoring modes to choose between; a PiP's expanded content is a canvas and nothing else.

Classes

PipBehavior
Lifecycle and interaction behaviour.
PipCollapsed
The small, draggable window.
PipConfig
A fully parsed PiP campaign.
PipControls
Collapsed-state affordances.
PipEdges
Per-side spacing in logical pixels. Absolute, unlike the fractional width: a margin is a gap from an edge, and a gap that scales with the screen looks wrong on a tablet.
PipEntryAnimation
How the collapsed window arrives on screen.
PipExitAnimation
How the collapsed window leaves. none tears down instantly.
PipExpanded
Full screen: the media fills the screen and content is composited on top.
PipMedia
The media surface, shared by both states. Created once and never re-parented, so playback is continuous across the grow/shrink transition.

Enums

PipCorner
Which corner the window starts in.
PipEntryAnimationType
PipExitAnimationType
PipExpandedClose
What the × / back gesture does in the expanded state.
PipFlyDirection
The edge a fly_in window travels from.
PipMediaKind
PipOnMediaEnd
What happens when non-looping media reaches its end.