feat(core): add controls component with activity tracking (#514)

This commit is contained in:
rahim
2026-02-13 01:14:16 +11:00
committed by GitHub
parent 33b21906cd
commit 90d881cec2
20 changed files with 787 additions and 0 deletions
@@ -0,0 +1,38 @@
'use client';
import type { ForwardedRef, ReactNode } from 'react';
import { forwardRef } from 'react';
import type { UIComponentProps } from '../../utils/types';
import { renderElement } from '../../utils/use-render';
type GroupState = Record<string, never>;
export interface ControlsGroupProps extends UIComponentProps<'div', GroupState> {
children?: ReactNode | undefined;
}
export const ControlsGroup = forwardRef(function ControlsGroup(
componentProps: ControlsGroupProps,
forwardedRef: ForwardedRef<HTMLDivElement>
) {
const { render, className, style, children, ...elementProps } = componentProps;
const role = elementProps['aria-label'] || elementProps['aria-labelledby'] ? 'group' : undefined;
const state: GroupState = {};
return renderElement(
'div',
{ render, className, style },
{
state,
ref: [forwardedRef],
props: [{ role, children }, elementProps],
}
);
});
export namespace ControlsGroup {
export type Props = ControlsGroupProps;
}
@@ -0,0 +1,48 @@
'use client';
import { ControlsCore, ControlsDataAttrs } from '@videojs/core';
import { logMissingFeature, selectControls } from '@videojs/core/dom';
import type { ForwardedRef, ReactNode } from 'react';
import { forwardRef, useState } from 'react';
import { usePlayer } from '../../player/context';
import type { UIComponentProps } from '../../utils/types';
import { renderElement } from '../../utils/use-render';
export interface ControlsRootProps extends UIComponentProps<'div', ControlsCore.State> {
children?: ReactNode | undefined;
}
export const ControlsRoot = forwardRef(function ControlsRoot(
componentProps: ControlsRootProps,
forwardedRef: ForwardedRef<HTMLDivElement>
) {
const { render, className, style, children, ...elementProps } = componentProps;
const controls = usePlayer(selectControls);
const [core] = useState(() => new ControlsCore());
if (!controls) {
if (__DEV__) logMissingFeature('Controls.Root', 'controls');
return null;
}
const state = core.getState(controls);
return renderElement(
'div',
{ render, className, style },
{
state,
stateAttrMap: ControlsDataAttrs,
ref: [forwardedRef],
props: [{ children }, elementProps],
}
);
});
export namespace ControlsRoot {
export type Props = ControlsRootProps;
export type State = ControlsCore.State;
}
@@ -0,0 +1,2 @@
export { ControlsGroup as Group, type ControlsGroupProps as GroupProps } from './controls-group';
export { ControlsRoot as Root, type ControlsRootProps as RootProps } from './controls-root';
+1
View File
@@ -0,0 +1 @@
export * as Controls from './index.parts';