philliplm-react-modern-audio-player
v1.4.6
Published
<p align="center"> <img width="20%" src="https://user-images.githubusercontent.com/70849655/180391190-2b268d23-c9f3-4e95-9fce-090897842c04.png" alt="rm-audio-player" /> <h1 align="center">React Modern Audio Player</h1> </p>
Downloads
19
Maintainers
Readme
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?: InitialStates;
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
| InitialStates | 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-defaultwidth: 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;
};
InitialStates
type InitialStates = 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 bycss-variable
ofreact-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
byCustomComponent
you can also setviewProps
toCustomComponent
(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>
);
}