Skip to content

feat(store): state subscription primitives#528

Merged
mihar-22 merged 1 commit intomainfrom
feat/store-snapshot
Feb 13, 2026
Merged

feat(store): state subscription primitives#528
mihar-22 merged 1 commit intomainfrom
feat/store-snapshot

Conversation

@mihar-22
Copy link
Copy Markdown
Member

Summary

Add State<T> subscription primitives for both React and HTML platforms, preparing the foundation for slider components that need to subscribe to local state containers (not just stores).

Changes

  • identity() utility — Generic identity function in @videojs/utils/function, replaces inline (s: any) => s and (s) => s as unknown as R patterns
  • useSnapshot React hook — Subscribe to a State<T> container with optional selector and custom comparator, built on useSelector
  • SnapshotController — HTML reactive controller for State<T> with optional selector, shallowEqual diffing, and track() to switch state containers
  • store.$state — Expose the store's internal State<T> container (read-only) on BaseStore, enabling SnapshotController composition
  • StoreController refactored — Now composes SnapshotController internally via store.$state instead of duplicating selector/shallowEqual logic
Implementation details

SnapshotController supports two modes: without selector (re-renders on any state change) and with selector (re-renders only when the selected slice changes via shallowEqual). The track() method allows switching to a different State<T> container, which StoreController uses when the store reconnects.

useStore cannot compose useSnapshot due to React's rules of hooks — the no-selector mode (returns store, no subscription) and selector mode (subscribes to state) require different hook call patterns that can't be conditional.

Testing

pnpm -F @videojs/store test    # 118 tests (14 files)
pnpm typecheck                  # clean

Add State<T> subscription primitives for React and HTML platforms, and
expose the store's internal State container via $state for composition.

- identity() utility in @videojs/utils/function
- useSnapshot React hook with optional selector and custom comparator
- SnapshotController for HTML elements with selector, shallowEqual, and track()
- StoreController refactored to compose SnapshotController internally
- store.$state exposes read-only State<T> container on BaseStore
@vercel
Copy link
Copy Markdown

vercel bot commented Feb 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
vjs-10-demo-react Ignored Ignored Feb 13, 2026 1:26pm

Request Review

@netlify
Copy link
Copy Markdown

netlify bot commented Feb 13, 2026

Deploy Preview for vjs10-site ready!

Name Link
🔨 Latest commit 73300df
🔍 Latest deploy log https://app.netlify.com/projects/vjs10-site/deploys/698f266fcbc5c80008806486
😎 Deploy Preview https://deploy-preview-528--vjs10-site.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions
Copy link
Copy Markdown
Contributor

📦 Bundle Size Report

Package Size Diff %
@videojs/core 4.20 kB +4 B ░░░░░░░░ +0.1% 🔺
@videojs/element 1.60 kB 0 B ░░░░░░░░ 0%
@videojs/html 7.75 kB +75 B ██░░░░░░ +1.0% 🔺
@videojs/react 6.83 kB +16 B ░░░░░░░░ +0.2% 🔺
@videojs/store 1.94 kB +84 B ████████ +4.4% 🔺
@videojs/utils 1.88 kB +16 B ██░░░░░░ +0.8% 🔺

Total: 24.20 kB · +195 B · +0.8%


Entry Breakdown

Subpath sizes are the additional bytes on top of the root entry point, measured by bundling root + subpath together and subtracting the root-only size.

@videojs/core
Entry Base PR Diff %
. 1.52 kB 1.52 kB 0 B 0%
./dom 2.67 kB 2.68 kB +4 B +0.1% 🔺
total 4.20 kB 4.20 kB +4 B +0.1%
@videojs/element
Entry Base PR Diff %
. 817 B 817 B 0 B 0%
./context 823 B 823 B 0 B 0%
total 1.60 kB 1.60 kB 0 B 0%
@videojs/store
Entry Base PR Diff %
. 1.29 kB 1.29 kB +1 B +0.1% 🔺
./html 394 B 468 B +74 B +18.8% 🔴
./react 190 B 199 B +9 B +4.7% 🔺
total 1.86 kB 1.94 kB +84 B +4.4%
@videojs/utils
Entry Base PR Diff %
./array 104 B 104 B 0 B 0%
./dom 553 B 553 B 0 B 0%
./events 227 B 227 B 0 B 0%
./function 181 B 197 B +16 B +8.8% 🔺
./object 119 B 119 B 0 B 0%
./predicate 265 B 265 B 0 B 0%
./time 465 B 465 B 0 B 0%
total 1.87 kB 1.88 kB +16 B +0.8%

ℹ️ How to interpret

Sizes are minified + brotli, measured with esbuild.
Package totals are computed as root size + marginal subpath costs.
Subpath marginal cost = (root + subpath bundled together) − root alone.

Icon Meaning
No change
🔺 Increased ≤ 10%
🔴 Increased > 10%
🔽 Decreased
🆕 New (no baseline)

Run pnpm size locally to check current sizes.

@mihar-22 mihar-22 changed the title feat(store): add useSnapshot hook, SnapshotController, and store.$state feat(store): state subscription primitives Feb 13, 2026
@mihar-22 mihar-22 merged commit 839a7e4 into main Feb 13, 2026
11 checks passed
@mihar-22 mihar-22 deleted the feat/store-snapshot branch February 13, 2026 13:30
@github-actions github-actions bot mentioned this pull request Feb 13, 2026
This was referenced Feb 26, 2026
@github-actions github-actions bot mentioned this pull request Mar 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant