From d74e4e6701e5de2a03cf76e4ceff96d230790e3f Mon Sep 17 00:00:00 2001 From: rahim Date: Fri, 2 Jan 2026 14:41:58 +1100 Subject: [PATCH] feat(store): initial release (#279) --- .claude/agents/dx-reviewer.md | 117 +++ .claude/settings.json | 3 +- .vscode/settings.json | 3 +- CLAUDE.md | 43 +- commitlint.config.js | 1 + package.json | 1 + packages/store/README.md | 671 +++++++++++++++++- packages/store/package.json | 22 +- packages/store/src/dom/index.ts | 1 + packages/store/src/dom/schedulers.ts | 75 ++ packages/store/src/errors.ts | 17 + packages/store/src/guard.ts | 87 +++ packages/store/src/index.ts | 7 + packages/store/src/lit/index.ts | 1 + packages/store/src/lit/tsconfig.json | 8 + packages/store/src/queue.ts | 428 +++++++++++ packages/store/src/request.ts | 230 ++++++ packages/store/src/slice.ts | 142 ++++ packages/store/src/state.ts | 89 +++ packages/store/src/store.ts | 381 ++++++++++ packages/store/test/dom/schedulers.test.ts | 176 +++++ packages/store/test/errors.test.ts | 28 + packages/store/test/guard.test.ts | 154 ++++ packages/store/test/integration/store.test.ts | 321 +++++++++ packages/store/test/queue.test.ts | 507 +++++++++++++ packages/store/test/request.test.ts | 151 ++++ packages/store/test/slice.test.ts | 74 ++ packages/store/test/state.test.ts | 144 ++++ packages/store/test/store.test.ts | 370 ++++++++++ packages/store/tsconfig.json | 4 +- packages/store/tsdown.config.ts | 1 + packages/store/vitest.config.ts | 24 + packages/utils/package.json | 6 +- packages/utils/src/disposer.test.ts | 212 ++++++ packages/utils/src/disposer.ts | 62 ++ .../utils/src/dom/animation-frame.test.ts | 83 +++ packages/utils/src/dom/animation-frame.ts | 20 + packages/utils/src/dom/event.test.ts | 129 ++++ packages/utils/src/dom/event.ts | 124 ++++ packages/utils/src/dom/idle-callback.test.ts | 97 +++ packages/utils/src/dom/idle-callback.ts | 44 ++ packages/utils/src/dom/index.ts | 5 + packages/utils/src/dom/listen.test.ts | 121 ++++ packages/utils/src/dom/listen.ts | 113 +++ packages/utils/src/dom/supports.test.ts | 25 + packages/utils/src/dom/supports.ts | 17 + packages/utils/src/event-like.test.ts | 77 ++ packages/utils/src/event-like.ts | 22 + packages/utils/src/index.ts | 3 + packages/utils/src/predicate.test.ts | 203 ++++++ packages/utils/src/predicate.ts | 48 ++ packages/utils/vitest.config.ts | 24 + pnpm-lock.yaml | 395 +++++++++-- turbo.json | 2 +- 54 files changed, 6047 insertions(+), 66 deletions(-) create mode 100644 .claude/agents/dx-reviewer.md create mode 100644 packages/store/src/dom/schedulers.ts create mode 100644 packages/store/src/errors.ts create mode 100644 packages/store/src/guard.ts create mode 100644 packages/store/src/lit/index.ts create mode 100644 packages/store/src/lit/tsconfig.json create mode 100644 packages/store/src/queue.ts create mode 100644 packages/store/src/request.ts create mode 100644 packages/store/src/slice.ts create mode 100644 packages/store/src/state.ts create mode 100644 packages/store/src/store.ts create mode 100644 packages/store/test/dom/schedulers.test.ts create mode 100644 packages/store/test/errors.test.ts create mode 100644 packages/store/test/guard.test.ts create mode 100644 packages/store/test/integration/store.test.ts create mode 100644 packages/store/test/queue.test.ts create mode 100644 packages/store/test/request.test.ts create mode 100644 packages/store/test/slice.test.ts create mode 100644 packages/store/test/state.test.ts create mode 100644 packages/store/test/store.test.ts create mode 100644 packages/store/vitest.config.ts create mode 100644 packages/utils/src/disposer.test.ts create mode 100644 packages/utils/src/disposer.ts create mode 100644 packages/utils/src/dom/animation-frame.test.ts create mode 100644 packages/utils/src/dom/animation-frame.ts create mode 100644 packages/utils/src/dom/event.test.ts create mode 100644 packages/utils/src/dom/event.ts create mode 100644 packages/utils/src/dom/idle-callback.test.ts create mode 100644 packages/utils/src/dom/idle-callback.ts create mode 100644 packages/utils/src/dom/listen.test.ts create mode 100644 packages/utils/src/dom/listen.ts create mode 100644 packages/utils/src/dom/supports.test.ts create mode 100644 packages/utils/src/dom/supports.ts create mode 100644 packages/utils/src/event-like.test.ts create mode 100644 packages/utils/src/event-like.ts create mode 100644 packages/utils/src/predicate.test.ts create mode 100644 packages/utils/src/predicate.ts create mode 100644 packages/utils/vitest.config.ts diff --git a/.claude/agents/dx-reviewer.md b/.claude/agents/dx-reviewer.md new file mode 100644 index 00000000..7b424ec7 --- /dev/null +++ b/.claude/agents/dx-reviewer.md @@ -0,0 +1,117 @@ +--- +name: dx-reviewer +description: Reviews APIs for developer experience, consistency, and framework-agnostic design. Use when designing or finalizing public interfaces. +tools: Glob, Grep, Read, WebFetch, TodoWrite, WebSearch, ListMcpResourcesTool, ReadMcpResourceTool +model: opus +color: purple +--- + +You review public APIs for developer experience, consistency, and framework-agnostic architecture. + +## Reference Points + +Study these before reviewing: + +- `packages/store/README.md` — our quality bar for API design +- JavaScript/Web platform standards — naming conventions, patterns, APIs +- TanStack ecosystem — framework-agnostic core + thin adapters +- Zustand/nanostores — minimal reactive state +- Base UI / Radix — headless component patterns, compound components +- Zod — chainable configuration, inference-heavy APIs + +## JavaScript Ecosystem Alignment + +**Follow platform conventions first**: Before inventing, check how the web platform and established libraries solve it. + +- Event naming: `volumechange` not `onVolumeChange` in core +- Method naming: `addEventListener`, `removeEventListener` patterns +- Options objects: Web APIs use them (`fetch(url, options)`) +- Promises: Standard async patterns, not callbacks +- Iterators/generators: Where appropriate for sequences +- AbortSignal: Standard cancellation pattern + +**Borrow from familiar libraries**: Users shouldn't need to learn new patterns. + +## Video.js 10 Architecture + +### Package Layout + +```text +utils ← shared utilities +utils/dom ← DOM-specific helpers + +core ← runtime-agnostic logic +core/dom ← DOM bindings + +store ← state management +store/dom ← DOM platform APIs +store/react ← React bindings + +html ← Web player (DOM/Browser) +react ← React player +react-native ← React Native player +``` + +### Dependency Flow + +```text +utils ← store ← core ← html / react / react-native +``` + +Core packages have no framework dependencies. Platform packages (`html`, `react`, `react-native`) are thin adapters. + +### Principles + +**Common core**: State logic in core, DOM in separate subpath. Core maps to Web, React, React Native. + +**Composition-first**: Compound component patterns. Render props for full control. + +```tsx + { + { /* ... */ } + }} +/> +``` + +**Style-agnostic**: No CSS in core. Stable `data-*` attributes and CSS vars for theming. + +**Accessibility non-negotiable**: Core owns ARIA roles, labels, keyboard nav, focus management. WCAG 2.2 / CVAA compliance. + +**SSR/hydration safe**: No DOM assumptions in core. Hydration-optimized. + +**Tree-shakeable**: Modular exports. Users pay only for what they use. + +## TanStack Patterns + +**Core/Adapter split**: Pure logic in core, thin framework bindings. + +**Adapters are thin**: No logic duplication across frameworks. + +**Core is testable**: Business logic tested without framework overhead. + +**Consistent API across frameworks**: Same mental model, framework-native feel. + +## Review Checklist + +1. **Platform alignment**: Does it follow JS/Web conventions? Familiar to ecosystem? +2. **Naming**: Match platform standards? Consistent internally? +3. **Signatures**: Options objects where appropriate? Matches similar Web APIs? +4. **Generics**: Minimal? Good inference? +5. **Package boundaries**: Logic in core? `/dom` subpaths for DOM code? Adapters thin? +6. **Composition**: Compound patterns? Render props where needed? +7. **Styling hooks**: Data attributes? CSS vars? No baked-in styles? +8. **Accessibility**: ARIA roles? Keyboard support? Focus management? +9. **SSR safety**: DOM assumptions isolated to `/dom` subpaths? +10. **Tree-shaking**: Modular exports? Dead code eliminable? + +## Output Format + +For each issue: + +- **What**: the problem +- **Where**: file and line +- **Why**: impact on users +- **Fix**: concrete suggestion with code + +Prioritize by impact. Skip style nitpicks. diff --git a/.claude/settings.json b/.claude/settings.json index 6c8064d1..15a2cb1b 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -1,3 +1,4 @@ { - "enabledMcpjsonServers": ["astro-docs"] + "enabledMcpjsonServers": ["astro-docs"], + "enableAllProjectMcpServers": true } diff --git a/.vscode/settings.json b/.vscode/settings.json index e38602d4..0f3b1612 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -50,5 +50,6 @@ "postcss", "svg" ], - "editor.defaultFormatter": "dbaeumer.vscode-eslint" + "editor.defaultFormatter": "dbaeumer.vscode-eslint", + "typescript.tsdk": "node_modules/typescript/lib" } diff --git a/CLAUDE.md b/CLAUDE.md index 69be436e..90007f94 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,21 +9,38 @@ Refer to **[`CONTRIBUTING.md`](./CONTRIBUTING.md)** for setup, development, and ## Package Layout -| Package Path | Purpose | -| ----------------------- | ---------------------------------------------------- | -| `packages/core` | Core runtime‑agnostic logic and state. | -| `packages/html` | DOM/Browser‑specific implementations. | -| `packages/react` | React package—adapts core state to React components. | -| `packages/react-native` | React Native integration layer. | -| `packages/utils` | Shared utilities. | -| `examples/*` | Demo apps for various runtimes. | -| `site/` | Astro‑based docs and website. | +| Package Path | Purpose | +| ----------------------- | ------------------------------------------------------------------ | +| `packages/utils` | Shared utilities (`/dom` subpath for DOM‑specific helpers). | +| `packages/core` | Core runtime‑agnostic logic (`/dom` subpath for DOM bindings). | +| `packages/store` | State management (`/dom` and `/react` subpaths for platform APIs). | +| `packages/html` | Web player—DOM/Browser‑specific implementation. | +| `packages/react` | React player—adapts core state to React components. | +| `packages/react-native` | React Native player integration layer. | +| `examples/*` | Demo apps for various runtimes. | +| `site/` | Astro‑based docs and website. | ### Dependency Hierarchy -- Core → (no internal deps) -- HTML / React / React‑Native → depend only on Core -- Prevents circular dependencies and maximizes reusability. +```text +utils ← shared utilities +utils/dom ← DOM-specific helpers + +store ← state management +store/dom ← DOM platform APIs +store/react ← React bindings + +core ← runtime-agnostic logic +core/dom ← DOM bindings + +html ← Web player (DOM/Browser) +react ← React player +react-native ← React Native player +``` + +```text +utils ← store ← core ← html / react / react-native +``` ## Workspace @@ -72,7 +89,7 @@ Examples: Breaking changes use `!`: -``` +```text feat(core)!: remove deprecated playback API ``` diff --git a/commitlint.config.js b/commitlint.config.js index bdf9fdce..567afbdf 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -28,6 +28,7 @@ export default { 'root', 'site', 'skins', + 'store', 'test', 'utils', ]], diff --git a/package.json b/package.json index 782851ac..78bb49df 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "react-compiler-runtime": "^1.0.0", "react-dom": "^18.0.0", "simple-git-hooks": "^2.13.1", + "tsx": "^4.21.0", "turbo": "^2.5.8", "typescript": "^5.9.3" }, diff --git a/packages/store/README.md b/packages/store/README.md index a3713d72..3fd0b4be 100644 --- a/packages/store/README.md +++ b/packages/store/README.md @@ -4,9 +4,676 @@ > **⚠️ Alpha - SUBJECT TO CHANGE** Not recommended for production use. -## Overview +A reactive store for managing state owned by external systems. Built for media players, streaming libraries, and real-time systems where you don't own the state. -Coming soon. +```bash +npm install @videojs/store +``` + +## Why? + +[Traditional state management](#how-its-different) assumes you own the state. But when working with a `