Giter VIP home page Giter VIP logo

wavesurfer-react's Introduction

Wavesurfer React

A simple wrapper around an awesome library called wavesurfer.js.

The purpose of the package is to provide an abstraction over wavesurfer.js API and to do it as close to react style of doing things as its maintainer(-s) can provide.

LiveDemo:

Static Badge

Table of Contents


User Guide

Components

Package provides the following set of components:

  1. WaveSurfer
  2. WaveForm
  3. Region

WaveSurfer

Core component of the package.
It creates wavesurfer instance and watches for changes in plugins list.
It accepts the following props set:

  1. plugins
  2. onMount
Plugins Prop

It is a list of plugins to use by WaveSurfer and has the following format:

import { WaveSurfer } from 'wavesurfer-react';
import RegionsPlugin from "wavesurfer.js/dist/plugins/regions";
import TimelinePlugin from "wavesurfer.js/dist/plugins/timeline";
import MyCustomPlugin from 'my-custom-plugin-path';

const plugins = [
   {
      plugin: RegionsPlugin,
      key: "regions",
      options: { dragSelection: true }
   },
   {
      plugin: TimelinePlugin,
      key: "timeline",
      options: {
         container: "#timeline"
      }
   },
   {
      plugin: MyCustomPlugin,
      key: "my-custom-plugin",
      options: {
         someGreatOption: 'someGreatValue'
      },
      creator: 'myCustomCreate'
   }
];

<WaveSurfer plugins={plugins} />

The plugins prop is watched inside WaveSurfer.
If plugin was disabled (it's not enlisted in plugins prop) it will be destroyed, otherwise added to wavesurfer plugins list and immediately initialized.

To correctly track initialized plugins, key property is used in item of plugins array.

onMount prop

It is a function, that is called after WaveSurfer instance has been mounted.
It has only one argument - WaveSurfer instance.

WaveSurfer Options

You can pass here all options that is used to configure wavesurfer, i.e. full list of available options.

WaveForm

It is used as an alias for:

<div id="waveform"></div>

Region

Think of it as a some kind of helper component. It can be used to imperatively control regions, appearing on WaveForm if you're using RegionsPlugin.
If region is already present of WaveForm it creation will be avoided and existing instance is used. On mount, it will try to find region with the same region identifier and then attaches itself to it.
If the Region component did not find an appropriate region, then it creates a region itself.

It accepts the following props:

  1. onOver - is called when mouse enters a region
  2. onLeave - is called when moused leaves a region
  3. onClick - is called on a mouse click on a region
  4. onDoubleClick - is called on double click
  5. onIn - is called when playback enters a region
  6. onOut - is called when playback leaves a region
  7. onRemove - is called just before region remove
  8. onUpdate - is called on each region's options update
  9. onUpdateEnd - is called when dragging or resizing are finished

Rest given props are passed as region's data into wavesurfer.

Marker

Special component using Region under the hood to display only markers. Marker await all props of Region except end prop.

Hooks

Package provides the following set of hooks:

  1. useWavesurfer
  2. useRegionEvent
  3. useRegionPluginEvent
  4. useWaveSurferContext

useWavesurfer

This hook is used inside WaveSurfer and its purpose is to create wavesurfer instance and return it.
It also handles a task of creating and destroying wavesurfer plugins, after plugins prop update detection.

You can use it standalone to create you own (more specific) wavesurfer component that will handle more than a component that is provided out-of-the-box.

useRegionEvent

Is used inside the Region component to subscribe to region-related events. Can be used by developers, if they wanna to, inside a HOC-like component over Region component that is provided by the package or any other component, that is rendered inside WaveSurfer component, but for the latter task you will have to get region instance first.

useRegionPluginEvent

Is used inside the Region component to subscribe to region plugin related events. Can be used by developers, if they wanna to, inside a HOC-like component over Region component that is provided by the package or any other component, that is rendered inside WaveSurfer component, but for the latter task you will have to get regions plugin instance first.

useWaveSurferContext

Returns a tuple of:

  1. wavesurfer instance,
  2. mapped object of enabled plugins keyed by the key property passed alongside a plugin,
  3. an array containing these plugins.

Known Issues and Workarounds

Regions desynchronization

Issues with regions synchronization when using redux and Region component. Try to not hard-bind redux-state with wavesurfer-react too tight or use an instance of wavesurfer to operate regions.

Timeline issues

FIXED: Timeline is not visible after removing it from plugins array and adding again. I hope it is a temporal issue with the original package. Comments related to this issue are: Comment #1
Comment #2
Comment #3

INFO: use wavesurfer.js@^7.4.5 to have this issue fixed

Solution to this problem is to execute wavesurfer.setOptions({}), right after Timeline plugin is added again via plugins prop second time and further.

wavesurfer-react's People

Contributors

danielmustafa avatar dependabot[bot] avatar franciscomdelgado avatar jonpacker avatar kushaankapoor avatar shiirochi avatar shreyas-jadhav avatar tslater avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

wavesurfer-react's Issues

Typescript errors

I just added the library into my project with the sample code and it's throwing a load of Typescript errors:

On WaveSurfer
This JSX tag's 'children' prop expects a single child of type 'Element', but multiple children were provided.ts(2746)

Because I added the timeline div

And

Type '{ children: never[]; id: string; hideCursor: true; cursorColor: string; }' is not assignable to type 'IntrinsicAttributes & WaveFormProps'.
  Property 'hideCursor' does not exist on type 'IntrinsicAttributes & WaveFormProps'

Using wavesurfer-react with local (not in server) audio files

Hi!

I have long been working on a website where I could show an audio file waveform, and WaveSurfer seems to be the best option I've seen so far.

However, I'm having a bit of trouble in trying to adapt this to my work. I am trying to make a site with two simple parts, one that lets the user load a local file and another that shows the audio waveform (there will be other functions later). However, when I try to send the data as an URL to the system (the same way I do with other players, such as react-h5-audio-player, it returns an error because it considers the url is empty.

Do you have a suggestion on how to do this? (Basically, it would be the demo you've got on codesandbox.io, but instead of an audio at the server folder, it'd be an audio in a computer opening the website and loading a local file)

Region onDoubleClick not working.

Hey! I wanted to use the double click functionality of the Region Plugin but I wasnt able to.
in the Region component of your package, there's this 1 slight error.

in Region.js, on Line 89,
(0, _useRegionEvent.default)(regionRef, "dbclick", onDoubleClick);

it should be dblclick instead.

I hope you can take out your time to fix this as that would be really helpful!

Thanks.

Cannot use import statement outside a module

Hi,
I upgraded React from v17 to v18 + Next.js from v12 to v13, and now this error happens:

error - unhandledRejection: /Users/mine/Sites/nextjs/myApp/node_modules/wavesurfer-react/dist/index.js:1
import Region from "./components/Region";
"react": "^18.2.0",
"next": "^13.0.6",
"wavesurfer-react": "^2.2.2",
 "wavesurfer.js": "^6.4.0",

I cannot use "type": "module", in my package.json otherwise it Failed to load next.config.js

Thanks in advance for any suggestions!

I can't fire events

Hi,
I tried to fire events as:

     useEffect(() => {
        wavesurferRef.current.on("finish", () => {
            console.log("Track Finished");
          });
      }, []); 

It doesn't work, it doesn't fire when a song is finished.
Is it my fault?

Seeking percentage remains to 0 when behaving as a controlled component

Hello!

Thanks for the amazing work! I am wondering how this component can be used as controlled component when seeking.

Here is the snippet of my code: "seekPercent" is a state that I stored in redux, each time when the audio is played, I want the waveform to seek according to "seekPercent". In order to do that, I define "handleAudioClick" in the component. However, I found props.seekPercent remains to be zero, although it has value outside (in the parent component)

Really appreciate your help!
parent
waveform-component

Align the button- Should be at the bottom of each waveform

image

Can somebody help me with the alignment of the button, on the photo, you see that the button for the first is together with the second button, that should not be the behavior, the button should be after the waveform , and same with the second wavefrom

This is my code:

import React, { useCallback, useRef, useMemo } from "react";
import ReactDOM from "react-dom";
import styled from "styled-components";
import { WaveSurfer, WaveForm } from "wavesurfer-react";

import RegionsPlugin from "wavesurfer.js/dist/plugins/regions";

const Buttons = styled.button`

  display: inline-block;

`;

const Button = styled.button``;

function Waves() {

const plugins = useMemo(() => {
return [
{
plugin: RegionsPlugin,
options: {
dragSelection: false
}
}
].filter(Boolean);
}, []);

const wavesurferRef = useRef();

const handleWSMount = useCallback((waveSurfer) => {
if (waveSurfer.markers) {
waveSurfer.clearMarkers();
}

wavesurferRef.current = waveSurfer;

if (wavesurferRef.current) {
  wavesurferRef.current.load('../../soundsgenere/rocktwo.mp3');

  wavesurferRef.current.on("ready", () => {
    console.log("WaveSurfer is ready");
  });

  wavesurferRef.current.on("region-removed", (region) => {
    console.log("region-removed --> ", region);
  });

  wavesurferRef.current.on("loading", (data) => {
    console.log("loading --> ", data);
  });

  if (window) {
    window.surferidze = wavesurferRef.current;
  }
}

}, []);

const play = useCallback(() => {
wavesurferRef.current.playPause();
}, []);

const next = useCallback(() => {
wavesurferRef.current.skipForward();
}, []);

const back = useCallback(() => {
wavesurferRef.current.skipBackward();
}, []);

return (

<WaveSurfer
    plugins={plugins}
    onMount={handleWSMount}
    progressColor="#DB2C3B"
    barWidth={2.67}
    barGap={4}
   
  >
 
    <WaveForm id="waveform" cursorColor="transparent" />
      
  </WaveSurfer>
   <Buttons>
    <Button onClick={play}>Play / Pause</Button>
  </Buttons>

 
 
  <WaveSurfer
    plugins={plugins}
    onMount={handleWSMount}
    progressColor="#DB2C3B"
    barWidth={2.67}
    barGap={4}
   
  >
 
    <WaveForm id="waveform" cursorColor="transparent" />
      
  </WaveSurfer>
   <Buttons>
    <Button onClick={play}>Play / Pause</Button>
  </Buttons>
 

 






</div>

);
}

export default Waves;

anyone here? who can answer this?

Support for wavesurfer.js 7+

From my testing wavesurfer-react only works up to wavesurfer.js version 6.6.4, but isn't compatible with versions 7.0.0 and up.

Has there been any work done to support the new major version or is it perhaps being planned?

WaveSurfer useEffect's run twice in StrictMode

Hello !
When using React v18 and StrictMode, doing

<WaveSurfer
  onMount={(waveSurfer: WaveSurferType) => {
    waveSurfer.loadBlob(myBlob);
  }}
>
  <WaveForm id="waveform" hideCursor cursorColor="transparent">
    {}
  </WaveForm>
</WaveSurfer>

will render the WaveForm twice as you can see here.

image

After looking at the code of this library, the useEffect that create the instance seems to load twice.

Of course, I have a workaround that is to remove StrictMode, but I want to keep it.

What can be possible is to check if wave has already been rendered in the useEffect by using a useRef.

EDIT

I actually found a way to fix this.

I stored the WaveSurfer instance in a ref, and when React do the re-render, it destroys the old wave and creates a new one. This just seems logic, sorry for the useless issue !

For anyone that is running in the same issue than me, check my code (it is in TypeScript by the way)

import type WaveSuferType from "wavesurfer.js";
import { WaveSurfer, WaveForm } from "wavesurfer-react";

export default function AudioWave () {
  const wavesurferRef = useRef<WaveSuferType>();

  const onMount = useCallback((waveSurfer: WaveSuferType) => {
    wavesurferRef.current = waveSurfer;
    wavesurferRef.current.load("/myFile.wav");
  }, []);

  useEffect(() => {
    return () => {
      if (!wavesurferRef.current) return;
      wavesurferRef.current.destroy();
    };
  }, []);

  return (
    <WaveSurfer
      onMount={onMount}
    >
      <WaveForm id="waveform" hideCursor cursorColor="transparent">
        {/** code here */}
      </WaveForm>
    </WaveSurfer>
  );
}

Multiple audio tracks overlay?

Thank you for making this library!
I want to display the waveforms for multiple tracks overlaid in the same container. I see that wavesurfer.js has an option for splitChannels with overlay: true. I was wondering if I could do something like that with multiple tracks instead? Appreciate any pointers you might have!

Multiple Instances of <Waveform />

@ShiiRochi congrats on v2! - I just got back from the Holiday and i'm ready to hack on this a little more.

Quick question since this defaults to id="waveform" on the DOM how do we create multiple instances?

getCurrentTime without triggering too much re-render on the Component

By following this approach katspaugh/wavesurfer.js#753 (comment), I managed to show the current elapsed time. Then I assign the value to a state to display on the UI.

const [currentTime, setCurrentTime] = useState(0)

const handleWSMount = (waveSurfer: any) => {
        wavesurferRef.current = waveSurfer
        if (wavesurferRef.current) {
            wavesurferRef.current.load('/test.mp3')

            wavesurferRef.current.on('ready', () => {
                setDuration(wavesurferRef.current.getDuration())
            })

            //Show current time
            wavesurferRef.current.on('audioprocess', function () {
                //ISSUE: THIS MAKE COMPONENT RE-RENDERING
                setCurrentTime(wavesurferRef.current.getCurrentTime())
            })

        }
    }
}
return <>{currentTime}</>
...

However, the wavesurfer.on('audioprocess'... triggers so many times, which results in setCurrentTime updates too much, and makes the component re-render redundantly. Is there a way to get the current time that can avoid this behavior?

Add functionality of updatable waveform params

It would be great as the next step in the package development to implement waveform auto-update of fields that can be legally updated using wavesurfer API.

Thus, lets sum up. There are drawBuffer method and a variety of set<TLERS> methods (w/ description):

  • setBackgroundColor(color)
  • setCursorColor(color)
  • setHeight(height)
  • setFilter(filters)
  • setPlaybackRate(rate)
  • setPlayEnd(position)
  • setVolume(newVolume)
  • setMute(mute)
  • setProgressColor(color)
  • setWaveColor(color)

Those fields, that relate to the methods above will be updated by them, all other fields in theory after being changed should result in a drawBuffer or some other method call. It also should be taken into account that some fields can be updated only through reinitialization, if such exist.

Some options don't work.

I've tried to pass the 'barMinHeight' parameter to the "WaveSurfer" component but it didn't work.
How to fix this?

wavesurfer-react with react-beautiful-dnd issue

I have a list of Waveforms and this is my code:

import { WaveSurfer, WaveForm, Region } from "wavesurfer-react";
import RegionsPlugin from "wavesurfer.js/dist/plugin/wavesurfer.regions.min";
import TimelinePlugin from "wavesurfer.js/dist/plugin/wavesurfer.timeline.min";

export default function Wavesurfer({trackId, wavesurferInstances, regions}) {
    const [maxRegions, setMaxRegions] = useState();
    const [backendType, setBackendType] = useState('WebAudio'); // or 'MediaElement'
    const waveformId = 'waveform' + '-' + trackId;
    const timelineId = `timeline-${trackId}`;
    const wavesurferRef = useRef();
    const wavesurferRefs = useRef({});

    const plugins = useMemo(() => {
        return [
            {
                plugin: RegionsPlugin,
                options: { dragSelection: true }
            },
            {
                plugin: TimelinePlugin,
                options: {
                    container: "#" + timelineId
                }
            }
        ].filter(Boolean);
    }, [timelineId]);

    const handleWSMount = useCallback(
        (waveSurfer, wavesurferId, wavesurferInstances) => {

        const existingInstance = wavesurferInstances[wavesurferId];

        wavesurferRef.current = waveSurfer;

        const ws = wavesurferRef.current;

        if(!existingInstance){
            // Normal creation - 1st time creation 
        } else {
            setBackendType('MediaElement');

            const blobURL = URL.createObjectURL(existingInstance.file);
            const peaksObj = JSON.parse(existingInstance.peaks);
            ws.load(blobURL, peaksObj, existingInstance.duration);
            
            ws.on("region-created", regionCreatedHandler);

            ws.on("ready", () => {
                console.log("from preload - WaveSurfer is ready");
            });

            ws.on("region-removed", (region) => {
                console.log("region-removed --> ", region);
            });

            ws.on("loading", (data) => {
                console.log("from preload - loading --> ", data);
            });

            ws.on('error', (err) => {
                console.error("WaveSurfer Error:", err);
            });

            if (window) {
                window.surferidze = ws;
            }


        }
    }


    return (
        <div className="App relative">
            <>
                <WaveSurfer id={waveformId} plugins={plugins} onMount={(ws) => handleWSMount(ws, waveformId, wavesurferInstances)}>
                    <WaveForm
                        id={waveformId}
                        cursorColor="OrangeRed"
                        progressColor="#4786bd"
                        barWidth="3"
                        barRadius="3"
                        responsive="true"
                        partialRender="true"
                        backend={backendType}
                        preload="auto"
                    >
                        {regions.length > 0 ? regions.map((regionProps) => (
                            <Region
                                onUpdateEnd={handleRegionUpdate}
                                key={regionProps.id}
                                minLength={main_variables.minSec}
                                maxLength={main_variables.maxSec}
                                maxRegions={maxRegions}
                                {...regionProps}
                            />
                        )) : null}
                    </WaveForm>

                    <div className="timeline" id={timelineId} />

                </WaveSurfer>
            </>
        </div>
    )


}

Basically I create a new waveform with WebAudio backend, and I set a state wavesurferInstances to keep all info data of the waveform including the JSON data of the peaks so, if I have to change the order of my list, I don't have to recalculate all over again.

When I create a new element, the wavesurfer is correctly loaded as in your Codesandbox example.

However, if I change the order of the list using react-beautiful-dnd package, with the code above, the WaveSurfer will never be ready, the on ready event is never fired so, I can see only the waveform correctly drawn from JSON but plugins are not initialized.

If I click over the waveform, the on load event is fired and then the wavesurfer become ready, once ready it shows the plugins correctly in place.

I'm debugging this for 3 days and I don't know where to hit my head any more, could you please give me some help?
Thanks!

"react": "^18.2.0",
"next": "^13.0.6",
"wavesurfer-react": "^2.2.2",
"wavesurfer.js": "^6.4.0",

update to 2.X: plugin props change

I'm going to change a current way of passing plugins into component.

The problem of current version is: all plugins are pre-imported, thus increasing size of a bundle.

To resolve the problem, the most possible and comfortable solution would be the following...

This is how we currently should pass plugins config:

const waveSurferPlugins = [
  "minimap",
  { name: "regions", options: { dragSelection: true } }
];

You just tell enlist plugins you want to use, they're already imported inside WaveSurfer component.

This is how you will pass plugins after update (it is still my thoughts, not final realization):

import RegionsPlugin from "wavesurfer.js/dist/plugin/wavesurfer.regions.min";
import MinimapPlugin from "wavesurfer.js/dist/plugin/wavesurfer.minimap.min";
const waveSurferPlugins = [
  {
     plugin: MinimapPlugin
  },
  {
    plugin: RegionsPlugin,
    options: { dragSelection: true }
  }
];

This update will also have an impact on how special WaveForm and Timeline components will be treated. While WaveForm is a core feature, Timeline is a plugin.

After the update, unless you didn't specify TimelinePlugin in the plugins list, the Timeline component will be treated as a simple component with no special meaning.

ReferenceError: self is not defined

Hi
I'm trying to build my project in which wavesurfer-react 2.1.6 version is imported:

import {WaveSurfer, WaveForm} from 'wavesurfer-react';

and I'm getting an error

ReferenceError: self is not defined
    at Object.<anonymous> (/path-to-project/node_modules/wavesurfer.js/dist/webpack:/WaveSurfer/webpack/universalModuleDefinition:10:2)
    at Module._compile (node:internal/modules/cjs/loader:1103:14)
    at Module._compile (/path-to-project/node_modules/pirates/lib/index.js:136:24)
    at Module._extensions..js (node:internal/modules/cjs/loader:1157:10)
    at Object.newLoader [as .js] (/path-to-project/node_modules/pirates/lib/index.js:141:7)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (/path-to-project/node_modules/wavesurfer-react/dist/utils/createWavesurfer.js:1:1)

Do you have any suggestions, is this a problem with my build or somewhere inside the package? I would be glad of any help

Example of in use

Not sure how to use

Could the docs show a working example with a src value, options and even hosted on a demo site please?

Hiding the cursor/progressline

Hello,
it seems that I can't hide the little line that shows the progress. I tried it with the vanilla version and it is cursorColor = "transparent" or hideCursor = true. All other options work
Screenshot 2021-11-10 at 08 35 59
.

"attributes" property not updating on regions.

I'm using the attributes property in order to set text on a region. It works in the initial render, but then won't update when I pass in new props. I was able to hack it locally, but can't find the components folder in this repo to make a PR.

Before

  // TODO: may need some improvements
  useEffect(() => {
    if (regionRef) {
      let update = ["start", "end", "color", "data", "drag", "resize"].reduce(
        (result, prop) => {
          if (regionRef[prop] !== props[prop]) {
            return {
              ...result,
              [prop]: props[prop]
            };
          }

          return result;
        },
        {}
      );

      regionRef.update(update);
    }
  }, [
    props.start,
    props.end,
    props.color,
    props.data,
    props.resize,
    props.drag,
  ]);

After

  // TODO: may need some improvements
  useEffect(() => {
    if (regionRef) {
      let update = ["start", "end", "color", "data", "drag", "resize", "attributes"].reduce(
        (result, prop) => {
          if (regionRef[prop] !== props[prop]) {
            return {
              ...result,
              [prop]: props[prop]
            };
          }

          return result;
        },
        {}
      );

      regionRef.update(update);
    }
  }, [
    props.start,
    props.end,
    props.color,
    props.data,
    props.resize,
    props.drag,
    props.attributes,
  ]);

Error message on demo: Warning: Failed prop type: Invalid prop `plugins[0]` supplied to `WaveSurfer`, expected a ReactNode.

I'm getting this same error message locally...the plugin still works fine, but I'm trying to get 0 errors/warning and this is polluting the console. I'd love to know if there is something I'm doing wrong. I tried to follow the demo, but it has the same error.
This is the demo I'm referring to (linked on the ReadMe):
https://codesandbox.io/s/wavesurfer-react-20-gqvb6?from-embed

image

How to get the list of all regions?

I am trying to play a specific region given its start and end time. I am currently using const wsRegions = ws.plugins[0].regions; then I find the corresponding region using wsRegions.find().

I am implementing regions-heavy functionality, hence interacting with the regions list is very frequent. I am getting this TS error Property 'plugins' is private and only accessible within class 'WaveSurfer'.ts(2341).

Does this library include a more standard method to get the list of current regions?

"wavesurfer-react": "^3.0.2",
"wavesurfer.js": "^7.7.11",

Can not get zoom to work

Hi there, great package! Hope it is okay to raise an issue for this, because it is more a question:
Is it currently possible to zoom into the waveform?
I could not get it to work, I tried in the handler method of a slider:

wavesurferRef.current.zoom = value

or something like

<WaveSurfer  zoomLevel={valueFromState}>
<WaveSurfer  zoom={valueFromState}>

Sadly no luck so far. If it is possible, could you please nudge me in the right direction or even provide a working example? I am building on top of the live Demo https://codesandbox.io/s/wavesurfer-react-20-gqvb6 (which is currently not working, right?)

Thanks in advance!

generating new markers in component wrapped by <StrictMode> not rendering new markers

I used the sandbox example in which I made the following modification:

function AudioPlayer()... // previously was-> function App()
.
.
.
export default AudioPlayer; // previously was...
//const rootElement = document.getElementById("root");
//ReactDOM.render(, rootElement);

I then use the AudioPlayer Component as a child component which the parent component is wrapped by

simply put:



doesn't allow for newly generated markers to render to the screen. If I remove strictmode wrapping then the newly created markers render just fine.

Clearly I'm not understanding something about the rendering process under Strictmode.
Any thoughts on what I may need to change in order to still continue using strictmode and render newly created markers?

Thanks for any help!

recreate timeline if its id is changed

Issue #61 raised also the problem of rebuilding timeline (and also any other such plugin) when container query selector is changed, there is currently no watcher for that.

improve demo webpage

  • include title
  • include logo (wavesurfer.js logo + react logo), ask permission to use wavesurfer.js logo
  • include full featured demo
  • include version badge
  • include other information

I can use common wiki creation template for that

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.