mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
feat(core): add play button component (#383)
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
'use client';
|
||||
|
||||
import { createButton } from '@videojs/core/dom';
|
||||
import type { ComponentPropsWithRef, Ref } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import { mergeProps } from '../../utils/merge-props';
|
||||
|
||||
export interface UseButtonParameters {
|
||||
displayName: string;
|
||||
onActivate: () => void;
|
||||
isDisabled: () => boolean;
|
||||
}
|
||||
|
||||
export interface UseButtonReturnValue {
|
||||
getButtonProps: (externalProps?: ComponentPropsWithRef<'button'>) => ComponentPropsWithRef<'button'>;
|
||||
buttonRef: Ref<HTMLElement>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for button behavior with keyboard and pointer interaction.
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* const { getButtonProps, buttonRef } = useButton({
|
||||
* displayName: 'PlayButton',
|
||||
* onActivate: () => togglePlayback(),
|
||||
* isDisabled: () => disabled,
|
||||
* });
|
||||
*
|
||||
* return useRender('button', componentProps, {
|
||||
* state,
|
||||
* ref: [forwardedRef, buttonRef],
|
||||
* props: [elementProps, getButtonProps],
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function useButton(params: UseButtonParameters): UseButtonReturnValue {
|
||||
const { displayName, onActivate, isDisabled } = params;
|
||||
|
||||
const buttonRef = useCallback(
|
||||
(element: HTMLElement | null) => {
|
||||
if (element && element.tagName !== 'BUTTON') {
|
||||
console.warn(`${displayName} should render a <button> element for accessibility`);
|
||||
}
|
||||
},
|
||||
[displayName]
|
||||
);
|
||||
|
||||
const getButtonProps = useCallback(
|
||||
(externalProps?: ComponentPropsWithRef<'button'>): ComponentPropsWithRef<'button'> => {
|
||||
const buttonProps = createButton({ onActivate, isDisabled });
|
||||
return mergeProps(buttonProps, externalProps);
|
||||
},
|
||||
[onActivate, isDisabled]
|
||||
);
|
||||
|
||||
return { getButtonProps, buttonRef };
|
||||
}
|
||||
|
||||
export namespace useButton {
|
||||
export type Parameters = UseButtonParameters;
|
||||
export type ReturnValue = UseButtonReturnValue;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
'use client';
|
||||
|
||||
import { PlayButtonCore } from '@videojs/core';
|
||||
import { logMissingFeature, selectPlayback } from '@videojs/core/dom';
|
||||
import type { ForwardedRef } from 'react';
|
||||
import { forwardRef, useState } from 'react';
|
||||
|
||||
import { usePlayer } from '../../player/context';
|
||||
import type { UIComponentProps } from '../../utils/types';
|
||||
import { renderElement } from '../../utils/use-render';
|
||||
import { useButton } from '../hooks/use-button';
|
||||
|
||||
export interface PlayButtonProps extends UIComponentProps<'button', PlayButtonCore.State>, PlayButtonCore.Props {}
|
||||
|
||||
/**
|
||||
* A button that toggles playback.
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* <PlayButton />
|
||||
*
|
||||
* <PlayButton
|
||||
* render={(props, state) => (
|
||||
* <button {...props}>
|
||||
* {state.paused ? <PlayIcon /> : <PauseIcon />}
|
||||
* </button>
|
||||
* )}
|
||||
* />
|
||||
* ```
|
||||
*/
|
||||
export const PlayButton = forwardRef(function PlayButton(
|
||||
componentProps: PlayButtonProps,
|
||||
forwardedRef: ForwardedRef<HTMLButtonElement>
|
||||
) {
|
||||
const { render, className, style, label, disabled = false, ...elementProps } = componentProps;
|
||||
|
||||
const playback = usePlayer(selectPlayback);
|
||||
|
||||
const [core] = useState(() => new PlayButtonCore());
|
||||
core.setProps({ label, disabled });
|
||||
|
||||
const { getButtonProps, buttonRef } = useButton({
|
||||
displayName: 'PlayButton',
|
||||
onActivate: () => core.toggle(playback!),
|
||||
isDisabled: () => disabled || !playback,
|
||||
});
|
||||
|
||||
if (!playback) {
|
||||
logMissingFeature('PlayButton', 'playback');
|
||||
return null;
|
||||
}
|
||||
|
||||
return renderElement(
|
||||
'button',
|
||||
{ render, className, style },
|
||||
{
|
||||
state: core.getState(playback),
|
||||
ref: [forwardedRef, buttonRef],
|
||||
props: [core.getAttrs(playback), elementProps, getButtonProps()],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
export namespace PlayButton {
|
||||
export type Props = PlayButtonProps;
|
||||
export type State = PlayButtonCore.State;
|
||||
}
|
||||
Reference in New Issue
Block a user