Skip to content

slash9494/react-modern-audio-player

main
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

rm-audio-player

React Modern Audio Player

License Version Download BundleSize

DEMO

https://codesandbox.io/s/basic-91y82y?file=/src/App.tsx

Flexible and Customizable UI

This can offer waveform by wavesurfer.js

This can offer various UI and you can also customize each component position

Full View

Position Change

Particular View

Installation

npm install --save react-modern-audio-player

Quick Start

import AudioPlayer from 'react-modern-audio-player';

const playList = [
  {
    name: 'name',
    writer: 'writer',
    img: 'image.jpg',
    src: 'audio.mp3',
    id: 1,
  },
]
function Player (){
	return (
		<AudioPlayer playList={playList} />
	)
}

Props

interface AudioPlayerProps {
  playList: PlayList;
  audioInitialState?: AudioInitialState;
  audioRef?: React.MutableRefObject<HTMLAudioElement>;
  activeUI?: ActiveUI;
  customIcons?: CustomIcons;
  coverImgsCss?: CoverImgsCss;
  placement?: {
    player?: PlayerPlacement;
    playList?: PlayListPlacement;
    interface?: InterfacePlacement;
    volumeSlider?: VolumeSliderPlacement;
  };
  rootContainerProps?: RootContainerProps
}
Prop Type Default
playList PlayList [ ]
audioInitialState AudioInitialState isPlaying: false
repeatType: "ALL"
volume: 1
activeUI ActiveUI playButton : true
customIcons CustomIcons undefined
coverImgsCss CoverImgsCss undefined
placement Placement playListPlacement : "bottom"
interfacePlacement :DefaultInterfacePlacement
rootContainerProps RootContainerProps theme: spectrum-theme-default
width: 100%
position: 'static'
UNSAFE_className: rm-audio-player-provider

PlayList

type PlayList = Array<AudioData>;
type AudioData = {
  src: string;
  id: number;
  name?: string | ReactNode;
  writer?: string | ReactNode;
  img?: string;
  description?: string | ReactNode;
  customTrackInfo?: string | ReactNode;
};

AudioInitialState

type AudioInitialState = Omit<
  React.AudioHTMLAttributes<HTMLAudioElement>,
  "autoPlay"
> & {
	isPlaying?: boolean;
  repeatType?: RepeatType;
  volume?: number;
  currentTime?: number;
  duration?: number;
  curPlayId: number;
};

ActiveUI

type ActiveUI = {
  all: boolean;
  playButton: boolean;
  playList: PlayListUI;
  prevNnext: boolean;
  volume: boolean;
  volumeSlider: boolean;
  repeatType: boolean;
  trackTime: boolean;
  trackInfo: boolean;
  artwork: boolean;
  progress: ProgressUI;
};
type ProgressUI = "waveform" | "bar" | false;
type PlayListUI = "sortable" | "unSortable" | false;

CustomIcons

type CustomIcons = {
  play: ReactNode;
  pause: ReactNode;
  prev: ReactNode;
  next: ReactNode;
  repeatOne: ReactNode;
  repeatAll: ReactNode;
  repeatNone: ReactNode;
  repeatShuffle: ReactNode;
  volumeFull: ReactNode;
  volumeHalf: ReactNode;
  volumeMuted: ReactNode;
  playList: ReactNode;
};

CoverImgsCss

interface CoverImgsCss {
  artwork?: React.CSSProperties;
  listThumbnail?: React.CSSProperties;
}

Placement

type PlayerPlacement =
  | "bottom"
  | "top"
  | "bottom-left"
  | "bottom-right"
  | "top-left"
  | "top-right";

type VolumeSliderPlacement = "bottom" | "top" | 'left' | 'right';

type PlayListPlacement = "bottom" | "top";

type InterfacePlacement = {
  templateArea?: InterfaceGridTemplateArea;
  customComponentsArea?: InterfaceGridCustomComponentsArea<TMaxLength>;
  itemCustomArea?: InterfaceGridItemArea;
};

type InterfacePlacementKey =
  | Exclude<keyof ActiveUI, "all" | "prevNnext" | "trackTime">
  | "trackTimeCurrent"
  | "trackTimeDuration";
  
type InterfacePlacementValue = "row1-1" | "row1-2" | "row1-3" | "row1-4" | ... more ... | "row9-9"
/** if you apply custom components, values must be "row1-1" ~ any more */

type InterfaceGridTemplateArea = Record<InterfacePlacementKey,InterfacePlacementValue>;

type InterfaceGridCustomComponentsArea = Record<componentId,InterfacePlacementValue>;

type InterfaceGridItemArea = Partial<Record<InterfacePlacementKey, string>>;
	/** example
	* progress : 2-4
	* repeatBtn : row1-4 / 2 / row1-4 / 10
	*
	* check MDN - grid area
	* https://developer.mozilla.org/ko/docs/Web/CSS/grid-area
	*/

Default interface placement

const defaultInterfacePlacement = {
  templateArea: {
    artwork: "row1-1",
    trackInfo: "row1-2",
    trackTimeCurrent: "row1-3",
    trackTimeDuration: "row1-4",
    progress: "row1-5",
    repeatType: "row1-6",
    volume: "row1-7",
    playButton: "row1-8",
    playList: "row1-9",
  },
};

RootContainerProps

it is same with spectrum provider props
https://react-spectrum.adobe.com/react-spectrum/Provider.html#themes

Override Style

Theme mode ( dark-mode )

it apply dark-mode depending on system-theme
you can customize color-theme by css-variable of react-spectrum theme-default

ID & Classnames

root ID

  • rm-audio-player

root ClassName

  • rm-audio-player-provider

color variables

--rm-audio-player-interface-container:var(--spectrum-global-color-gray-100);
--rm-audio-player-volume-background: #ccc;
--rm-audio-player-volume-panel-background:#f2f2f2;
--rm-audio-player-volume-panel-border:#ccc;
--rm-audio-player-volume-thumb: #d3d3d3;
--rm-audio-player-volume-fill:rgba(0, 0, 0, 0.5);
--rm-audio-player-volume-track:#ababab;
--rm-audio-player-track-current-time:#0072F5;
--rm-audio-player-track-duration:#8c8c8c;
--rm-audio-player-progress-bar:#0072F5;
--rm-audio-player-progress-bar-background:#D1D1D1;
--rm-audio-player-waveform-cursor:var(--spectrum-global-color-gray-800);
--rm-audio-player-waveform-background:var(--rm-audio-player-progress-bar-background);
--rm-audio-player-waveform-bar:var(--rm-audio-player-progress-bar);
--rm-audio-player-sortable-list:var(--spectrum-global-color-gray-200);
--rm-audio-player-sortable-list-button-active:#0072F5;
--rm-audio-player-selected-list-item-background:var(--spectrum-global-color-gray-500);

// ...spectrum theme palette and so on... //

Custom Component

you can apply custom component to AudioPlayer by CustomComponent
you can also set viewProps to CustomComponent
(https://react-spectrum.adobe.com/react-spectrum/View.html#props)

const activeUI: ActiveUI = {
  all: true,
};

const placement = {
  interface: {
    customComponentsArea: {
      playerCustomComponent: "row1-10",
    },
  } as InterfacePlacement<11>,
  /**
   * you should set generic value of `InterfacePlacement` as interfaces max length for auto-complete aria type such as "row-1-10"
   * generic value must plus 1 than interfaces length because of 0 index
  */
};

/** you can get audioPlayerState by props */
const CustomComponent = ({
  audioPlayerState,
}: {
  audioPlayerState?: AudioPlayerStateContext;
}) => {
  const audioEl = audioPlayerState?.elementRefs?.audioEl;
  const handOverTime = () => {
    if (audioEl) {
      audioEl.currentTime += 30;
    }
  };
  return (
    <>
      <button onClick={handOverTime}>+30</button>
    </>
  );
};

<AudioPlayer
  playList={playList}
  placement={placement}
  activeUI={activeUI}
>
  <AudioPlayer.CustomComponent id="playerCustomComponent">
    <CustomComponent />
  </AudioPlayer.CustomComponent>
</AudioPlayer>

Example

function App() {
  return (
    <div>
      <AudioPlayer
        playList={playList}
        audioInitialState={{
          muted: true,
          volume: 0.2,
          curPlayId: 1,
        }}
        placement={{
          interface: {
            templateArea: {
              trackTimeDuration: "row1-5",
              progress: "row1-4",
              playButton: "row1-6",
              repeatType: "row1-7",
              volume: "row1-8",
            },
          },
          player: "bottom-left",
        }}
        activeUI={{
          all: true,
          progress: "waveform",
        }}
      />
    </div>
  );
}

About

πŸ”Š Simple, accessible and flexible audio player

Resources

License

Stars

Watchers

Forks

Packages

No packages published