npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@waiverforever/waiver-widget

v1.4.1

Published

embed waiver widget for your site

Readme

WaiverForever Waiver Widget

Adding a waiver widget to your website to allow participants to sign without leaving the page.

npm version

Steps

  1. Choose the preferred waiver templates from your templates.
  2. Go to Template Settings page -> Waiver Widget tab.
  3. Enable the widgets and configure them.
  4. Keep the templateIds for the next steps.
  5. There are multiple ways of embedding our waiver widget into your website:

Want to add it to your WordPress website? Click here to see our tutorial

Easy route: reference the widget script from CDN

We can load the widget automatically or manually.

For automatically loading, append the following HTML snippet into the body tag of your website:

<script src="https://cdn.waiverforever.com/qs3/ew.js?templateId=${templateId1,templateId2}"></script>
  1. Widget with its trigger button will be mounted as soon as the script is loaded. It exposes the widget instance as a global JavaScript variable named waiverWidget (note: its initial letter is lowercase) and WF_EMBED_WAIVER (for backward compatibility).
  2. If you need multiple waivers be signed one by one, you can set multiple template IDs by join them with comma. e.g. templateId=t123,t456
  3. If you you want to enable the prefill feature for the waiver, you can set the prefill_id query parameter to the value of the prefill data. e.g. templateId=t123&prefill_id=p456
  4. The widget instance has a hook method .onReady, which you can use to perform extra operations if needed.
  5. If you don't like the default triggering button and want to create your own way to trigger the waiver modal, simply adding a query sdkMode=yes to disable it:
<script src="https://cdn.waiverforever.com/qs3/ew.js?templateId=${templateId1,templateId2}&sdkMode=yes"></script>

For manually loading, append the following HTML snippet into the body tag of your website:

<script src="https://cdn.waiverforever.com/qs3/ew.js"></script>
  1. If the script's src doesn't contain a specified templateId, the script exposes the widget constructor as a global JavaScript variable named WaiverWidget (note: its initial letter is uppercase).
  2. You could manually initialize the widget instance on demand. Please make sure performing any extra operations after the .onReady hook is triggered.

You could also load the widget script dynamically, e.g. The AMD way:

require(['https://cdn.waiverforever.com/qs3/ew.js'], function (WaiverWidget) {
  const widget = new WaiverWidget({
    templateId: `${templateId}`, // You can also pass multiple template ids as an array, they will be displayed one after signing one.
    sdkMode: true
  })

  widget.onReady(function(){
    myCustomButton.addEventListener('click', function () {
      widget.toggle()
    })
  })
})

Importing the widget into the module system

Install the widget by npm or yarn:

# npm
npm i --save @waiverforever/waiver-widget
# yarn
yarn add @waiverforever/waiver-widget
// app.js
import WaiverWidget from '@waiverforever/waiver-widget'

const widget = new WaiverWidget({
  templateId: `${templateId}`, // You can also pass multiple template ids as an array, they will be displayed one after signing one.
  sdkMode: true
})

widget.onReady(function () {
  myCustomButton.addEventListener('click', function () {
    widget.toggle()
  })
})
  1. TypeScript is fully supported.
  2. Definitions bring TS/JS users the better developing experience.
  3. Could be used in ES modules or CommonJS standards systems.
  4. Could be dynamically loaded by third-party bundler's code splitting feature.

Reference

Terms

  • widget constructor: In manually loading or dynamically loading scenarios, the script exposes a constructor named WaiverWidget as a global variable. In a module system, we could require or import it directly.
  • widget instance: Instance of widget constructor. We could register events to its hooks and manipulate the instance through its methods.
  • SDK mode: Widget without the default triggering button, you need to programmatically trigger the waiver modal.
  • window mode: When enabled, instead of showing waiver modal, a new waiver page will be opened. If you passed multiple waiver template ID the window mode will be turn off.
  • embed mode: When enabled, the waiver modal will be embedded into the current page and mounted to the target element.

API

WaiverWidget constructor

interface WidgetOption {
    templateId: string | string[]; // required, template id, or pass multiple ids
    sdkMode?: boolean; // by default it is false
    windowMode?: boolean; // by default it depends on the useragent (true for mobile devices, false for desktops)
    stylesheetURL?: string; // specify the stylesheet URL of the embedded waiver
    embed?: boolean; // by default it is false
    embedTargetId?: string; // specify the target element id for the embedded waiver, by default it is 'wf-embed-waiver-target'
}

type WaiverWidgetConstructor = new (option?: WidgetOption): IWidget;

WaiverWidget instance

interface IWidget {
    closeEmbedWaiverModal: () => void;  // Legacy API, for backward compatibility
    show: () => void; // Show widget modal and hide trigger button(in non-sdk mode)
    close: () => void; // Opposite operation of show()
    toggle: () => void; // Toggle between show and close methods
    destroy: () => void; // Destroy the current widget instance. After ensuring previous widget instance is destroyed, we can re-initialize another widget instance.
    onShowed: (callback: () => void) => void; // Event registry for modal showed hook
    onReady: (callback: (widget: IWidget) => void) => void; // Event registry for widget instance ready hook, an interactive widget instance will be passed to the registered hook
    onLoad: (callback: (signedCount: number) => void) => void; // Event registry for waiver page loading in the SDK mode
    onSigned: (callback: (signedCount: number) => void) => void; // Event registry for waiver signing success hook
    onClosed: (callback: (signedCount: number) => void) => void; // Event registry for modal close hook, the registered callback will receives a boolean type argument presents whether the user signed or not
    onDestroyed: (callback: () => void) => void; // Event registry for widget destroyed hook
    onAction: (callback: (action: Action) => void) => void; // Added from v1.3.0, Event registry for waiver action hook, the registered callback will receives a string type argument presents the action of the widget
}

type Action =
| {
    type: 'SHOW', // widget modal showed event, it doesn't trigger when the widget is in the embed mode
}
| {
    type: 'READY' // widget ready event
    payload: {
      widget: IWidget, // widget instance
    }
}
| {
    type: 'LOAD' // waiver loaded event
    payload: {
      signedCount: number, // Signed count
    }
}
| {
  type: 'SIGNED', // Waiver signed event
  payload: {
    templateId: string, // Template ID
    referenceNumber: string, // Reference Number
    waiverId: string, // Waiver ID
    waiverQRLink: string, // Waiver QR Link
    signedCount: number, // Signed count
  }
}
| {
    type: 'CLOSE' // Waiver modal closed event, it doesn't trigger when the widget is in the embed mode
    payload: {
      signedCount: number, // Signed count
    }
}
| {
    type: 'DESTROY' // widget destroyed event
}

Usage

const widget = new WaiverWidget({
    templateId: `${templateId}`,
})

widget.onReady(function () {
  console.log('widget ready')
})
widget.onSigned(function () {
  console.log('signed!')
})
widget.onClosed(function(signed){
  console.log('close modal, signed:', signed)
})
widget.onShowed(function () {
  console.log('onShowed')
})
widget.onDestroyed(function () {
  console.log('onDestroyed')
})
widget.onAction(function (action) {
  console.log('waiver action:', action)

  switch (action.type) {
    case 'SHOW':
      console.log('waiver showed')
      break
    case 'READY':
      console.log('waiver ready', action.payload.widget)
      break
    case 'LOAD':
      console.log('waiver loaded')
      console.log('signed count:', action.payload.signedCount)
      break
    case 'SIGNED':
      console.log('waiver signed')
      console.log('signed count:', action.payload.signedCount)
      console.log('template id:', action.payload.templateId)
      console.log('reference number:', action.payload.referenceNumber)
      console.log('waiver id:', action.payload.waiverId)
      console.log('waiver qr link:', action.payload.waiverQRLink)
      break
    case 'CLOSE':
      console.log('waiver closed')
      console.log('signed count:', action.payload.signedCount)
      break
    case 'DESTROY':
      console.log('waiver destroyed')
      break
  }
})

Protips

If you get bored of using the callback style .onReady hook and others, and the async/await syntax is available in your runtime, here are some tips for you.

All of the widget APIs are thenable/awaitable! It means you can use the widget instance, instance methods and event hooks in a synchronous-like way.

Thenable/awaitable instance

Awaiting the response of the widget instance, we get a ready state (fully-interactive) instance.

// note: use in async function, or some `top-level await` syntax implemented environment
async function appDidMount () {
  const widget = await new WaiverWidget({
    templateId: `${templateId}`, // You can also pass multiple template ids  as an array, they will be displayed one after signing one.
  })

  widget.show() // widget is in ready state
}

Thenable/awaitable instance methods

Awaiting a response of a widget method, we receive the callback payload of the method's corresponding event hook.

async function appShowWaiverInstruction () {
  // `.onShowed` event has no return value
  await widget.show()
  sendLog('waiver showed')
}
async function appCloseWaiverInstruction () {
  // We get the signed count, which is the `.onClosed` event's callback payload
  const signedCount = await widget.close()
  sendLog('waiver closed, with signed count: ' + signedCount)
}

Thenable/awaitable event hooks

A registered event handler will be triggered whenever the event occurs. An awaited event hook will only respond to the event payload for once.

async function appDidMount () {
  // ... initialize widget instance ...
  widget.onSigned(async function () {
    // signedCount presents the number you signed successfully
    const signedCount = await widget.onClosed
    // Log will be sent under the condition that waiver is signed and then the modal is closed
    sendLog('waiver closed, with signed count: ' + signedCount)
  })
}

Actually, awaiting a response of a event hook is rarely used.