From d535282f0318562303e9db1546d2d90dd535f177 Mon Sep 17 00:00:00 2001 From: rahim Date: Tue, 17 Mar 2026 15:50:39 -0700 Subject: [PATCH] refactor(packages): move store attach lifecycle to provider (#975) Co-authored-by: Claude Opus 4.6 --- .claude/plans/player-api-implementation.md | 12 +- internal/decisions/provider-attach.md | 48 ++++++ packages/html/src/media/container-element.ts | 4 +- packages/html/src/player/context.ts | 28 +++- packages/html/src/player/create-player.ts | 17 ++- packages/html/src/store/container-mixin.ts | 141 ++++-------------- packages/html/src/store/provider-mixin.ts | 118 +++++++++++++-- packages/react/src/index.ts | 3 +- packages/react/src/media/audio.tsx | 16 +- .../src/media/background-video/index.tsx | 4 +- packages/react/src/media/dash-video/index.tsx | 5 +- packages/react/src/media/hls-video/index.tsx | 5 +- .../src/media/simple-hls-video/index.tsx | 5 +- packages/react/src/media/tests/audio.test.tsx | 6 +- packages/react/src/media/tests/video.test.tsx | 6 +- packages/react/src/media/video.tsx | 16 +- packages/react/src/player/context.tsx | 19 ++- packages/react/src/player/create-player.tsx | 10 +- .../react/src/player/tests/context.test.tsx | 90 +++++++---- packages/react/src/testing/mocks.tsx | 2 +- .../templates/simple-hls-react/main.tsx | 2 +- .../docs/reference/use-media-attach.mdx | 33 ++++ .../docs/reference/use-media-registration.mdx | 47 ------ site/src/content/docs/reference/use-media.mdx | 2 +- .../docs/reference/use-player-context.mdx | 2 +- site/src/docs.config.ts | 2 +- 26 files changed, 378 insertions(+), 265 deletions(-) create mode 100644 internal/decisions/provider-attach.md create mode 100644 site/src/content/docs/reference/use-media-attach.mdx delete mode 100644 site/src/content/docs/reference/use-media-registration.mdx diff --git a/.claude/plans/player-api-implementation.md b/.claude/plans/player-api-implementation.md index 522bf4e7..56fa3be1 100644 --- a/.claude/plans/player-api-implementation.md +++ b/.claude/plans/player-api-implementation.md @@ -708,8 +708,8 @@ export function useMedia(): Media | null { return media; } -/** Register a media element (for Video/Audio primitives). Returns undefined if outside provider (standalone media). */ -export function useMediaRegistration(): Dispatch> | undefined { +/** Access the media attach setter for connecting a media element to the player. */ +export function useMediaAttach(): Dispatch> | undefined { const ctx = useContext(PlayerContext); return ctx?.setMedia; } @@ -725,7 +725,7 @@ Factory that creates typed provider and hooks. Update existing Video component t ``` packages/react/src/player/create-player.tsx (new) -packages/react/src/media/video.tsx (update - use useMediaRegistration) +packages/react/src/media/video.tsx (update - use useMediaAttach) packages/react/src/index.ts packages/react/src/player/tests/create-player.test.tsx (new) ``` @@ -809,14 +809,14 @@ export function createPlayer[]>( import type { Ref, VideoHTMLAttributes } from 'react'; import { useCallback } from 'react'; import { useComposedRefs } from '../utils/use-composed-refs'; -import { useMediaRegistration } from '../player/context'; +import { useMediaAttach } from '../player/context'; export interface VideoProps extends VideoHTMLAttributes { ref?: Ref | React.RefObject; } export function Video({ children, ref: refProp, ...props }: VideoProps): React.JSX.Element { - const setMedia = useMediaRegistration(); + const setMedia = useMediaAttach(); const attachRef = useCallback( (el: HTMLVideoElement): (() => void) | void => { @@ -1303,7 +1303,7 @@ UI primitives (PlayButton, VolumeSlider, etc.) need store access without knowing - `usePlayer()` — returns current state snapshot (untyped `Record`) - `usePlayer(selector)` — returns selected state via selector - `useMedia()` — returns current media element -- `useMediaRegistration()` — for Video/Audio primitives to register +- `useMediaAttach()` — for Video/Audio primitives to attach `createPlayer()` wraps this base with typed hooks for app code. diff --git a/internal/decisions/provider-attach.md b/internal/decisions/provider-attach.md new file mode 100644 index 00000000..1f0a7b72 --- /dev/null +++ b/internal/decisions/provider-attach.md @@ -0,0 +1,48 @@ +--- +status: decided +date: 2026-03-13 +--- + +# Provider Owns Media Attachment + +## Decision + +The provider (`` / React `Provider`) owns the `store.attach()` lifecycle. The container (`` / React `Container`) no longer discovers media or calls `store.attach()` — it registers itself with the provider via context and serves only as a layout reference element. + +Media and container elements register themselves with the provider through attach contexts — setter callbacks that flow downward from provider to descendants. The provider calls `store.attach({ media, container })` when it has a media element. As a fallback for plain `