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

@mikael_tenshio/form-rescue

v1.0.14

Published

An intelligent, zero-dependency auto-saver for HTML forms.

Readme

Form Rescue

npm version CI Status License: MIT

An intelligent, zero-dependency auto-saver for HTML forms.

Form Rescue acts as a safety net for your users. It automatically and efficiently persists form data to localStorage in the background as the user types. If the user accidentally closes the tab, navigates away, or experiences a browser crash, Form Rescue will seamlessly restore their typed data upon returning to the page.

Features

  • Zero Dependencies: Lightweight and built with modern vanilla JavaScript/TypeScript.
  • Debounced Auto-saving: Ensures high performance by waiting for the user to pause typing before writing to storage.
  • Cross-Tab Synchronization: Automatically syncs form state across multiple open tabs.
  • Smart Expiration: Supports configurable Time-To-Live (TTL) to automatically discard stale drafts.
  • AJAX Support: Built-in support for intercepting and handling custom asynchronous form submissions.
  • Custom Element Support: Can save and restore content from custom contenteditable elements.

Installation

Install via npm:

npm install @mikael_tenshio/form-rescue

Basic Usage

The easiest way to use Form Rescue is by calling the static watch method and passing a CSS selector for your form.

import Rescue from '@mikael_tenshio/form-rescue';

// Initializes auto-saving on the form with the ID "checkout-form"
Rescue.watch('#checkout-form');

Alternatively, you can instantiate it directly with an HTML element:

const myForm = document.getElementById('checkout-form');
const rescueInstance = new Rescue(myForm);

Browser Script Tag

If you prefer to load Form Rescue directly in the browser, use the bundled browser build:

<script src="https://unpkg.com/@mikael_tenshio/form-rescue/dist/rescue.min.js"></script>
<script>
  const form = document.getElementById('checkout-form');
  new window.Rescue(form);
</script>

Configuration Options

You can pass an optional configuration object as the second argument to customize the behavior of Form Rescue.

Rescue.watch('#checkout-form', {
  ttl: '48h',
  debounce: 500,
  clearOnSubmit: true,
});

Available Options

| Option | Type | Default | Description | | --------------- | ---------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | ttl | string | '24h' | Time-to-live for the saved draft. Supports minutes (m), hours (h), and days (d). Examples: '30m', '12h', '7d'. | | debounce | number | 300 | Delay in milliseconds to wait after the last input event before saving the draft. | | storageKey | string | auto-generated | Custom key used for localStorage. Defaults to a unique key based on the URL path and form ID/name. | | clearOnSubmit | boolean | true | Automatically clears the draft from storage when the native submit event fires. | | onDraftFound | function | undefined | Callback triggered when an existing draft is found on initialization. Passes the draft data and a manual restore function. | | onSave | function | undefined | Callback triggered immediately after a draft is successfully saved to storage. | | onAjaxSubmit | function | undefined | Callback for asynchronous form submissions. Prevents default behavior, awaits the returned Promise, and clears the draft only upon success. |

API Reference

Instance Methods

Once instantiated, you have access to several methods for manual control over the form's draft state.

save()

Manually triggers an immediate save of the current form state, bypassing the standard debounce delay.

rescueInstance.save();

clear()

Manually deletes the saved draft from localStorage.

rescueInstance.clear();

destroy()

Removes all event listeners and cleans up the instance. This is highly recommended for Single Page Applications (SPAs) to prevent memory leaks when a form component is unmounted.

rescueInstance.destroy();

Static Methods

Rescue.watch(selectorOrElement, options?)

A utility method to easily find a form in the DOM and initialize Form Rescue. Returns the created Rescue instance, or undefined if the form cannot be found.

HTML Attributes

Form Rescue respects specific HTML attributes to grant you granular control over what gets saved.

Excluding Specific Fields

By default, Form Rescue ignores disabled fields, type="file" inputs, and fields without a name attribute.

To explicitly prevent a specific input from being saved, add the data-no-rescue attribute:

<input type="password" name="userPassword" data-no-rescue />

Custom Content Elements

If you are using custom text editors or contenteditable elements, you can instruct Form Rescue to save their innerHTML by using the data-rescue-content attribute. The value provided will be used as the internal property key.

<div contenteditable="true" data-rescue-content="documentNotes">User notes go here...</div>

Advanced Usage

Handling AJAX Submissions

If your form submits data asynchronously, the default submit listener might clear the draft before the server confirms a successful operation. Use onAjaxSubmit to handle this safely:

Rescue.watch('#ajax-form', {
  onAjaxSubmit: async (event) => {
    // event.preventDefault() is automatically called by Form Rescue

    const response = await fetch('/api/submit', {
      method: 'POST',
      body: new FormData(event.target),
    });

    if (!response.ok) {
      throw new Error('Server error'); // Draft is retained
    }

    // Promise resolves successfully; Draft is automatically cleared
    return response.json();
  },
});

Prompting Before Restore

If you want to ask the user before overwriting their form with a saved draft, use the onDraftFound callback.

Rescue.watch('#ticket-form', {
  onDraftFound: (draft, restore) => {
    const dateStr = new Date(draft.timestamp).toLocaleString();
    if (confirm(`We found an unsaved draft from ${dateStr}. Would you like to restore it?`)) {
      restore();
    }
  },
});

License

MIT