feat(site): add util reference pipeline (#537)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Darius Cepulis
2026-02-24 15:34:34 -06:00
committed by GitHub
co-authored by Claude Opus 4.6
parent c11395ece1
commit 78112fbefd
143 changed files with 7031 additions and 481 deletions
@@ -0,0 +1,24 @@
.react-create-player-basic {
position: relative;
}
.react-create-player-basic video {
width: 100%;
}
.react-create-player-basic__controls {
position: absolute;
bottom: 10px;
left: 10px;
}
.react-create-player-basic__button {
padding-block: 8px;
background: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(10px);
color: black;
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 9999px;
padding-inline: 20px;
cursor: pointer;
}
@@ -0,0 +1,41 @@
import { createPlayer, features } from '@videojs/react';
import { Video } from '@videojs/react/video';
import './BasicUsage.css';
const { Provider, Container, usePlayer } = createPlayer({
features: features.video,
});
function Controls() {
const store = usePlayer();
const paused = usePlayer((s) => s.paused);
return (
<div className="react-create-player-basic__controls">
<button
type="button"
className="react-create-player-basic__button"
onClick={() => (paused ? store.play() : store.pause())}
>
{paused ? 'Play' : 'Pause'}
</button>
</div>
);
}
export default function BasicUsage() {
return (
<Provider>
<Container className="react-create-player-basic">
<Video
src="https://stream.mux.com/lhnU49l1VGi3zrTAZhDm9LUUxSjpaPW9BL4jY25Kwo4/highest.mp4"
autoPlay
muted
playsInline
/>
<Controls />
</Container>
</Provider>
);
}
@@ -0,0 +1,10 @@
---
import HtmlDemo from '@/components/docs/demos/HtmlDemo.astro';
import html from './BasicUsage.html?raw';
import './BasicUsage.css';
---
<HtmlDemo html={html} />
<script>
import './BasicUsage.ts';
</script>
@@ -0,0 +1,37 @@
.html-create-player-basic {
position: relative;
}
.html-create-player-basic video {
width: 100%;
}
.html-create-player-basic__button {
padding-block: 8px;
position: absolute;
bottom: 10px;
left: 10px;
background: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(10px);
color: black;
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 9999px;
padding-inline: 20px;
cursor: pointer;
}
.html-create-player-basic__button .show-when-paused {
display: none;
}
.html-create-player-basic__button .show-when-playing {
display: none;
}
.html-create-player-basic__button[data-paused] .show-when-paused {
display: inline;
}
.html-create-player-basic__button:not([data-paused]) .show-when-playing {
display: inline;
}
@@ -0,0 +1,12 @@
<demo-video-player class="html-create-player-basic">
<video
src="https://stream.mux.com/lhnU49l1VGi3zrTAZhDm9LUUxSjpaPW9BL4jY25Kwo4/highest.mp4"
autoplay
muted
playsinline
></video>
<demo-play-toggle class="html-create-player-basic__button">
<span class="show-when-paused">Play</span>
<span class="show-when-playing">Pause</span>
</demo-play-toggle>
</demo-video-player>
@@ -0,0 +1,57 @@
import {
applyElementProps,
applyStateDataAttrs,
createButton,
createPlayer,
features,
MediaElement,
selectPlayback,
} from '@videojs/html';
const { PlayerElement, PlayerController, context } = createPlayer({
features: [...features.video],
});
class VideoPlayer extends PlayerElement {
static readonly tagName = 'demo-video-player';
}
class PlayToggle extends MediaElement {
static readonly tagName = 'demo-play-toggle';
readonly #player = new PlayerController(this, context, selectPlayback);
#disconnect: AbortController | null = null;
override connectedCallback(): void {
super.connectedCallback();
this.#disconnect = new AbortController();
const buttonProps = createButton({
onActivate: () => {
const state = this.#player.value;
if (!state) return;
state.paused ? state.play() : state.pause();
},
isDisabled: () => !this.#player.value,
});
applyElementProps(this, buttonProps, this.#disconnect.signal);
}
override disconnectedCallback(): void {
super.disconnectedCallback();
this.#disconnect?.abort();
this.#disconnect = null;
}
protected override update(): void {
super.update();
const state = this.#player.value;
if (!state) return;
applyStateDataAttrs(this, state, { paused: 'data-paused', ended: 'data-ended' });
}
}
customElements.define(VideoPlayer.tagName, VideoPlayer);
customElements.define(PlayToggle.tagName, PlayToggle);
@@ -0,0 +1,10 @@
---
import HtmlDemo from '@/components/docs/demos/HtmlDemo.astro';
import html from './BasicUsage.html?raw';
import './BasicUsage.css';
---
<HtmlDemo html={html} />
<script>
import './BasicUsage.ts';
</script>
@@ -0,0 +1,36 @@
.html-player-controller-basic {
position: relative;
}
.html-player-controller-basic video {
width: 100%;
}
.html-player-controller-basic__panel {
display: flex;
gap: 16px;
padding: 12px;
background: rgba(0, 0, 0, 0.05);
border-top: 1px solid rgba(0, 0, 0, 0.1);
align-items: center;
}
.html-player-controller-basic__actions {
display: flex;
gap: 6px;
}
.html-player-controller-basic__actions button {
padding: 4px 12px;
border-radius: 6px;
border: 1px solid #ccc;
background: white;
cursor: pointer;
font-size: 0.8125rem;
}
.html-player-controller-basic__state {
font-size: 0.8125rem;
color: #374151;
font-variant-numeric: tabular-nums;
}
@@ -0,0 +1,18 @@
<demo-ctrl-player class="html-player-controller-basic">
<video
src="https://stream.mux.com/lhnU49l1VGi3zrTAZhDm9LUUxSjpaPW9BL4jY25Kwo4/highest.mp4"
autoplay
muted
playsinline
></video>
<div class="html-player-controller-basic__panel">
<demo-ctrl-actions class="html-player-controller-basic__actions">
<button class="action-play">Play</button>
<button class="action-pause">Pause</button>
<button class="action-volume">50% Volume</button>
</demo-ctrl-actions>
<demo-ctrl-state class="html-player-controller-basic__state">
<span class="state-text">Paused: Yes | Time: 0.0s | Volume: 100%</span>
</demo-ctrl-state>
</div>
</demo-ctrl-player>
@@ -0,0 +1,67 @@
import { applyElementProps, createButton, createPlayer, features, MediaElement } from '@videojs/html';
const { PlayerElement, PlayerController, context } = createPlayer({
features: [...features.video],
});
class DemoPlayer extends PlayerElement {
static readonly tagName = 'demo-ctrl-player';
}
class PlayerActions extends MediaElement {
static readonly tagName = 'demo-ctrl-actions';
readonly #player = new PlayerController(this, context);
#disconnect: AbortController | null = null;
override connectedCallback(): void {
super.connectedCallback();
this.#disconnect = new AbortController();
const signal = this.#disconnect.signal;
const playBtn = this.querySelector<HTMLButtonElement>('.action-play')!;
const pauseBtn = this.querySelector<HTMLButtonElement>('.action-pause')!;
const volumeBtn = this.querySelector<HTMLButtonElement>('.action-volume')!;
const bind = (el: HTMLElement, action: () => void) => {
const props = createButton({ onActivate: action, isDisabled: () => !this.#player.value });
applyElementProps(el, props, signal);
};
bind(playBtn, () => this.#player.value?.play());
bind(pauseBtn, () => this.#player.value?.pause());
bind(volumeBtn, () => this.#player.value?.changeVolume(0.5));
}
override disconnectedCallback(): void {
super.disconnectedCallback();
this.#disconnect?.abort();
this.#disconnect = null;
}
}
class PlayerState extends MediaElement {
static readonly tagName = 'demo-ctrl-state';
readonly #state = new PlayerController(this, context, (s) => ({
paused: s.paused,
currentTime: s.currentTime,
volume: s.volume,
}));
protected override update(): void {
super.update();
const state = this.#state.value;
if (!state) return;
const el = this.querySelector('.state-text');
if (el) {
el.textContent = `Paused: ${state.paused ? 'Yes' : 'No'} | Time: ${state.currentTime.toFixed(1)}s | Volume: ${Math.round(state.volume * 100)}%`;
}
}
}
customElements.define(DemoPlayer.tagName, DemoPlayer);
customElements.define(PlayerActions.tagName, PlayerActions);
customElements.define(PlayerState.tagName, PlayerState);
@@ -0,0 +1,36 @@
.react-render-element-basic {
display: flex;
flex-direction: column;
gap: 16px;
padding: 16px;
}
.react-render-element-basic__toggle {
align-self: flex-start;
padding: 6px 16px;
border-radius: 6px;
border: 1px solid #ccc;
background: #f5f5f5;
cursor: pointer;
}
.react-render-element-basic__tags {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
.react-render-element-basic__tag {
display: inline-flex;
align-items: center;
padding: 6px 12px;
border-radius: 9999px;
background: #e5e7eb;
color: #374151;
transition: all 0.2s ease;
}
.react-render-element-basic__tag--active {
background: #3b82f6;
color: white;
}
@@ -0,0 +1,64 @@
import { renderElement } from '@videojs/react';
import { type ReactNode, useState } from 'react';
import './BasicUsage.css';
interface TagState {
active: boolean;
}
function Tag({
className,
style,
render,
active,
children,
}: renderElement.ComponentProps<TagState> & { active: boolean; children?: ReactNode }) {
const state: TagState = { active };
return renderElement(
'span',
{ className, style, render },
{
state,
props: { children },
stateAttrMap: { active: 'data-active' },
}
);
}
export default function BasicUsage() {
const [active, setActive] = useState(false);
const className = (state: TagState) =>
`react-render-element-basic__tag${state.active ? ' react-render-element-basic__tag--active' : ''}`;
const style = (state: TagState) => ({
fontSize: state.active ? '1.125rem' : '0.875rem',
});
return (
<div className="react-render-element-basic">
<button type="button" className="react-render-element-basic__toggle" onClick={() => setActive((prev) => !prev)}>
{active ? 'Deactivate' : 'Activate'}
</button>
<div className="react-render-element-basic__tags">
<Tag active={active} className={className} style={style}>
Default &lt;span&gt;
</Tag>
<Tag active={active} className={className} style={style} render={<strong />}>
Element &lt;strong&gt;
</Tag>
<Tag
active={active}
className={className}
style={style}
render={(props, state) => <em {...props}>{state.active ? 'Active!' : 'Inactive'}</em>}
/>
</div>
</div>
);
}
@@ -0,0 +1,30 @@
.react-use-button-basic {
display: flex;
flex-direction: column;
gap: 12px;
padding: 16px;
}
.react-use-button-basic__button {
align-self: flex-start;
padding: 8px 20px;
border-radius: 6px;
border: 1px solid #ccc;
background: #f5f5f5;
cursor: pointer;
font-variant-numeric: tabular-nums;
transition: opacity 0.2s;
}
.react-use-button-basic__button[disabled] {
opacity: 0.5;
cursor: not-allowed;
}
.react-use-button-basic__label {
display: flex;
align-items: center;
gap: 6px;
font-size: 0.875rem;
color: #6b7280;
}
@@ -0,0 +1,27 @@
import { useButton } from '@videojs/react';
import { useState } from 'react';
import './BasicUsage.css';
export default function BasicUsage() {
const [count, setCount] = useState(0);
const [disabled, setDisabled] = useState(false);
const { getButtonProps, buttonRef } = useButton({
displayName: 'ActivateButton',
onActivate: () => setCount((c) => c + 1),
isDisabled: () => disabled,
});
return (
<div className="react-use-button-basic">
<button ref={buttonRef} {...getButtonProps()} className="react-use-button-basic__button" disabled={disabled}>
Activated {count} times
</button>
<label className="react-use-button-basic__label">
<input type="checkbox" checked={disabled} onChange={(e) => setDisabled(e.target.checked)} />
Disabled
</label>
</div>
);
}
@@ -0,0 +1,36 @@
.react-use-media-basic {
position: relative;
}
.react-use-media-basic video {
width: 100%;
}
.react-use-media-basic__info {
display: flex;
flex-direction: column;
gap: 4px;
margin: 0;
padding: 12px;
background: rgba(0, 0, 0, 0.05);
border-top: 1px solid rgba(0, 0, 0, 0.1);
font-size: 0.8125rem;
}
.react-use-media-basic__info div {
display: flex;
gap: 8px;
}
.react-use-media-basic__info dt {
color: #6b7280;
min-width: 80px;
}
.react-use-media-basic__info dd {
margin: 0;
font-variant-numeric: tabular-nums;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
@@ -0,0 +1,52 @@
import { createPlayer, features, useMedia } from '@videojs/react';
import { Video } from '@videojs/react/video';
import './BasicUsage.css';
const { Provider, Container } = createPlayer({
features: features.video,
});
function MediaInfo() {
const media = useMedia();
if (!media) return null;
return (
<dl className="react-use-media-basic__info">
<div>
<dt>tagName</dt>
<dd>{media.tagName.toLowerCase()}</dd>
</div>
<div>
<dt>src</dt>
<dd>{media.currentSrc || '—'}</dd>
</div>
<div>
<dt>videoWidth</dt>
<dd>{media.videoWidth}px</dd>
</div>
<div>
<dt>videoHeight</dt>
<dd>{media.videoHeight}px</dd>
</div>
</dl>
);
}
export default function BasicUsage() {
return (
<Provider>
<Container className="react-use-media-basic">
<Video
src="https://stream.mux.com/lhnU49l1VGi3zrTAZhDm9LUUxSjpaPW9BL4jY25Kwo4/highest.mp4"
autoPlay
muted
playsInline
loop
/>
<MediaInfo />
</Container>
</Provider>
);
}
@@ -0,0 +1,31 @@
.react-use-player-selector {
position: relative;
}
.react-use-player-selector video {
width: 100%;
}
.react-use-player-selector__state {
display: flex;
gap: 16px;
padding: 12px;
margin: 0;
font-size: 0.8125rem;
background: rgba(0, 0, 0, 0.05);
border-top: 1px solid rgba(0, 0, 0, 0.1);
}
.react-use-player-selector__state div {
display: flex;
gap: 8px;
}
.react-use-player-selector__state dt {
color: #6b7280;
}
.react-use-player-selector__state dd {
margin: 0;
font-variant-numeric: tabular-nums;
}
@@ -0,0 +1,48 @@
import { createPlayer, features, usePlayer } from '@videojs/react';
import { Video } from '@videojs/react/video';
import './Selector.css';
const { Provider, Container } = createPlayer({
features: features.video,
});
function StateDisplay() {
const state = usePlayer((s) => ({
paused: s.paused,
currentTime: s.currentTime,
duration: s.duration,
}));
return (
<dl className="react-use-player-selector__state">
<div>
<dt>Paused</dt>
<dd>{String(state.paused)}</dd>
</div>
<div>
<dt>Time</dt>
<dd>
{state.currentTime.toFixed(1)}s / {state.duration.toFixed(1)}s
</dd>
</div>
</dl>
);
}
export default function Selector() {
return (
<Provider>
<Container className="react-use-player-selector">
<Video
src="https://stream.mux.com/lhnU49l1VGi3zrTAZhDm9LUUxSjpaPW9BL4jY25Kwo4/highest.mp4"
autoPlay
muted
playsInline
loop
/>
<StateDisplay />
</Container>
</Provider>
);
}
@@ -0,0 +1,24 @@
.react-use-player-store {
position: relative;
}
.react-use-player-store video {
width: 100%;
}
.react-use-player-store__controls {
display: flex;
gap: 6px;
padding: 12px;
background: rgba(0, 0, 0, 0.05);
border-top: 1px solid rgba(0, 0, 0, 0.1);
}
.react-use-player-store__controls button {
padding: 4px 12px;
border-radius: 6px;
border: 1px solid #ccc;
background: white;
cursor: pointer;
font-size: 0.8125rem;
}
@@ -0,0 +1,40 @@
import { createPlayer, features, usePlayer } from '@videojs/react';
import { Video } from '@videojs/react/video';
import './StoreAccess.css';
const { Provider, Container } = createPlayer({
features: features.video,
});
function Controls() {
const store = usePlayer();
return (
<div className="react-use-player-store__controls">
<button type="button" onClick={() => store.play()}>
Play
</button>
<button type="button" onClick={() => store.pause()}>
Pause
</button>
</div>
);
}
export default function StoreAccess() {
return (
<Provider>
<Container className="react-use-player-store">
<Video
src="https://stream.mux.com/lhnU49l1VGi3zrTAZhDm9LUUxSjpaPW9BL4jY25Kwo4/highest.mp4"
autoPlay
muted
playsInline
loop
/>
<Controls />
</Container>
</Provider>
);
}
@@ -0,0 +1,31 @@
.react-use-store-selector {
position: relative;
}
.react-use-store-selector video {
width: 100%;
}
.react-use-store-selector__state {
display: flex;
gap: 16px;
padding: 12px;
margin: 0;
font-size: 0.8125rem;
background: rgba(0, 0, 0, 0.05);
border-top: 1px solid rgba(0, 0, 0, 0.1);
}
.react-use-store-selector__state div {
display: flex;
gap: 8px;
}
.react-use-store-selector__state dt {
color: #6b7280;
}
.react-use-store-selector__state dd {
margin: 0;
font-variant-numeric: tabular-nums;
}
@@ -0,0 +1,46 @@
import { createPlayer, features, usePlayer, useStore } from '@videojs/react';
import { Video } from '@videojs/react/video';
import './Selector.css';
const { Provider, Container } = createPlayer({
features: features.video,
});
function DerivedState() {
const store = usePlayer();
const derived = useStore(store, (s) => ({
remaining: s.duration - s.currentTime,
progress: s.duration > 0 ? (s.currentTime / s.duration) * 100 : 0,
}));
return (
<dl className="react-use-store-selector__state">
<div>
<dt>Remaining</dt>
<dd>{derived.remaining.toFixed(1)}s</dd>
</div>
<div>
<dt>Progress</dt>
<dd>{derived.progress.toFixed(1)}%</dd>
</div>
</dl>
);
}
export default function Selector() {
return (
<Provider>
<Container className="react-use-store-selector">
<Video
src="https://stream.mux.com/lhnU49l1VGi3zrTAZhDm9LUUxSjpaPW9BL4jY25Kwo4/highest.mp4"
autoPlay
muted
playsInline
loop
/>
<DerivedState />
</Container>
</Provider>
);
}
@@ -0,0 +1,24 @@
.react-use-store-access {
position: relative;
}
.react-use-store-access video {
width: 100%;
}
.react-use-store-access__controls {
display: flex;
gap: 6px;
padding: 12px;
background: rgba(0, 0, 0, 0.05);
border-top: 1px solid rgba(0, 0, 0, 0.1);
}
.react-use-store-access__controls button {
padding: 4px 12px;
border-radius: 6px;
border: 1px solid #ccc;
background: white;
cursor: pointer;
font-size: 0.8125rem;
}
@@ -0,0 +1,41 @@
import { createPlayer, features, usePlayer, useStore } from '@videojs/react';
import { Video } from '@videojs/react/video';
import './StoreAccess.css';
const { Provider, Container } = createPlayer({
features: features.video,
});
function SeekControls() {
const store = usePlayer();
const s = useStore(store);
return (
<div className="react-use-store-access__controls">
<button type="button" onClick={() => s.seek(0)}>
Go to start
</button>
<button type="button" onClick={() => s.seek(s.state.duration / 2)}>
Go to middle
</button>
</div>
);
}
export default function StoreAccess() {
return (
<Provider>
<Container className="react-use-store-access">
<Video
src="https://stream.mux.com/lhnU49l1VGi3zrTAZhDm9LUUxSjpaPW9BL4jY25Kwo4/highest.mp4"
autoPlay
muted
playsInline
loop
/>
<SeekControls />
</Container>
</Provider>
);
}