feat(html): add data-availability to volume slider (#1001)

This commit is contained in:
rahim
2026-03-18 12:44:12 -07:00
committed by GitHub
parent c738498312
commit c95e1343e1
5 changed files with 26 additions and 8 deletions
@@ -115,6 +115,20 @@ describe('VolumeSliderCore', () => {
expect(state.muted).toBe(true);
expect(state.fillPercent).toBe(0);
});
it('projects availability from volumeAvailability', () => {
const core = new VolumeSliderCore();
core.setInput(createInput());
core.setMedia(createMediaState({ volumeAvailability: 'unsupported' }));
expect(core.getState().availability).toBe('unsupported');
});
it('reflects available availability', () => {
const core = new VolumeSliderCore();
core.setInput(createInput());
core.setMedia(createMediaState({ volumeAvailability: 'available' }));
expect(core.getState().availability).toBe('available');
});
});
describe('getAttrs', () => {
@@ -1,7 +1,7 @@
import { defaults } from '@videojs/utils/object';
import type { NonNullableObject } from '@videojs/utils/types';
import type { MediaVolumeState } from '../../media/state';
import type { MediaFeatureAvailability, MediaVolumeState } from '../../media/state';
import { SliderCore, type SliderProps, type SliderState } from '../slider/slider-core';
export interface VolumeSliderProps extends SliderProps {
@@ -13,7 +13,9 @@ export interface VolumeSliderProps extends SliderProps {
max?: number | undefined;
}
export interface VolumeSliderState extends SliderState, Pick<MediaVolumeState, 'volume' | 'muted'> {}
export interface VolumeSliderState extends SliderState, Pick<MediaVolumeState, 'volume' | 'muted'> {
availability: MediaFeatureAvailability;
}
/** Volume-domain slider: maps media volume/mute state to slider state. */
export class VolumeSliderCore extends SliderCore {
@@ -51,6 +53,7 @@ export class VolumeSliderCore extends SliderCore {
fillPercent: effectivelyMuted ? 0 : base.fillPercent,
volume,
muted: effectivelyMuted,
availability: media.volumeAvailability,
};
}
@@ -4,4 +4,5 @@ import type { VolumeSliderState } from './volume-slider-core';
export const VolumeSliderDataAttrs = {
...SliderDataAttrs,
availability: 'data-availability',
} as const satisfies StateAttrMap<VolumeSliderState>;
@@ -1,4 +1,4 @@
import { SliderDataAttrs, VolumeSliderCore } from '@videojs/core';
import { VolumeSliderCore, VolumeSliderDataAttrs } from '@videojs/core';
import {
applyElementProps,
applyStateDataAttrs,
@@ -120,12 +120,12 @@ export class VolumeSliderElement extends MediaElement {
applyStyles(this, cssVars);
// Apply data attributes to root.
applyStateDataAttrs(this, state, SliderDataAttrs);
applyStateDataAttrs(this, state, VolumeSliderDataAttrs);
// Provide context to child elements.
this.#provider.setValue({
state,
stateAttrMap: SliderDataAttrs,
stateAttrMap: VolumeSliderDataAttrs,
pointerValue: this.#core.valueFromPercent(state.pointerPercent),
thumbAttrs: this.#core.getAttrs(state),
thumbProps: this.#slider.thumbProps,
@@ -1,6 +1,6 @@
'use client';
import { SliderDataAttrs, VolumeSliderCore } from '@videojs/core';
import { VolumeSliderCore, VolumeSliderDataAttrs } from '@videojs/core';
import { getSliderCSSVars, logMissingFeature, selectVolume } from '@videojs/core/dom';
import { forwardRef, useState } from 'react';
@@ -85,7 +85,7 @@ export const VolumeSliderRoot = forwardRef<HTMLDivElement, VolumeSliderRootProps
pointerValue: core.valueFromPercent(state.pointerPercent),
thumbRef,
thumbProps,
stateAttrMap: SliderDataAttrs,
stateAttrMap: VolumeSliderDataAttrs,
getAttrs: (sliderState) => core.getAttrs(sliderState as VolumeSliderCore.State),
formatValue: (value) => `${Math.round(value)}%`,
}}
@@ -95,7 +95,7 @@ export const VolumeSliderRoot = forwardRef<HTMLDivElement, VolumeSliderRootProps
{ render, className, style },
{
state,
stateAttrMap: SliderDataAttrs,
stateAttrMap: VolumeSliderDataAttrs,
ref: [forwardedRef, rootRef],
props: [{ style: { ...cssVars, ...rootStyle } }, rootProps, elementProps],
}