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

@form-guardian/react

v1.0.5

Published

React hooks for form autosave functionality. Provides useFormAutosave hook for easy integration with React forms and useDraftStatus hook for real-time draft status monitoring. Works seamlessly with React Hook Form, Formik, and plain React forms.

Readme

@form-guardian/react

React hooks for form autosave functionality. Provides useFormAutosave hook for easy integration with React forms and useDraftStatus hook for real-time draft status monitoring. Works seamlessly with React Hook Form, Formik, and plain React forms.

⚠️ Warning: useFormAutosave is currently unstable and may have issues with certain use cases. For production applications, consider using attachFormAutosave from @form-guardian/dom directly, which is more stable and reliable.

Overview

@form-guardian/react provides React-specific hooks that wrap the universal @form-guardian/dom functionality. It offers a more React-idiomatic API with hooks, automatic cleanup, and type-safe integration with React form libraries.

Installation

npm install @form-guardian/react

Peer Dependencies:

  • React >= 16.8.0 (hooks support required)

Features

  • React Hooks API - useFormAutosave and useDraftStatus hooks
  • TypeScript Support - Full type inference for form data
  • Automatic Cleanup - Handles cleanup on unmount
  • React Hook Form Integration - Works seamlessly with RHF
  • Formik Integration - Compatible with Formik forms
  • Plain React Forms - Works with controlled components
  • Draft Status Monitoring - Real-time draft status with useDraftStatus

Quick Start

Basic Usage

import { useFormAutosave } from '@form-guardian/react';

function ContactForm() {
  const { formRef, hasDraft, restoreDraft, clearDraft } = useFormAutosave('contact-form', {
    autoRestore: true,
    onAfterSave: (values) => {
      console.log('Draft saved:', values);
    }
  });

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    // ... submit logic
    await clearDraft(); // Clear draft on successful submit
  };

  return (
    <form ref={formRef} onSubmit={handleSubmit}>
      <input name="name" />
      <input name="email" />
      <button type="submit">Submit</button>
      {hasDraft && (
        <button type="button" onClick={restoreDraft}>
          Restore Draft
        </button>
      )}
    </form>
  );
}

With React Hook Form

import { useForm } from 'react-hook-form';
import { useFormAutosave } from '@form-guardian/react';

interface FormData {
  name: string;
  email: string;
  message: string;
}

function MyForm() {
  const { register, handleSubmit, setValue } = useForm<FormData>();
  
  const { formRef, restoreValues } = useFormAutosave<FormData>('my-form', {
    autoRestore: false, // We'll restore manually
  });

  // Restore draft values into React Hook Form
  useEffect(() => {
    restoreValues(setValue);
  }, [restoreValues, setValue]);

  return (
    <form ref={formRef} onSubmit={handleSubmit(onSubmit)}>
      <input {...register('name')} />
      <input {...register('email')} />
      <textarea {...register('message')} />
      <button type="submit">Submit</button>
    </form>
  );
}

With Draft Status

import { useFormAutosave, useDraftStatus } from '@form-guardian/react';

function FormWithStatus() {
  const { formRef } = useFormAutosave('my-form');
  
  const { hasDraft, updatedAt, isExpired, isChecking } = useDraftStatus('my-form');

  return (
    <div>
      <form ref={formRef}>
        {/* form fields */}
      </form>
      
      {hasDraft && updatedAt && (
        <div>
          <p>Draft saved: {new Date(updatedAt).toLocaleString()}</p>
          {isExpired && <p>⚠️ Draft has expired</p>}
          {isChecking && <p>Checking draft...</p>}
        </div>
      )}
    </div>
  );
}

API

useFormAutosave<T>(formId, options?)

React hook for form autosave functionality.

⚠️ Warning: This hook is currently unstable. For production use, consider using attachFormAutosave from @form-guardian/dom directly.

Parameters

  • formId - Unique identifier for the form
  • options - Configuration options (same as attachFormAutosave)

Returns

  • formRef - Ref to attach to form element
  • hasDraft - Boolean indicating if draft exists
  • draftTimestamp - Timestamp of draft (or null)
  • restoreDraft() - Function to manually restore draft
  • getDraftValues() - Get draft values as object
  • restoreValues(setValue, getDefaultValues?) - Restore values for controlled components
  • clearDraft() - Clear the draft
  • saveValues(values?) - Manually save values

useDraftStatus<T>(formId, options?)

Lightweight hook for checking draft status without touching the DOM.

Parameters

  • formId - Unique identifier for the form
  • options - Configuration options:
    • includeOrigin - Include origin in draft ID (default: true)
    • storagePrefix - Storage prefix (default: 'fg')
    • ttl - Time to live for drafts

Returns

  • hasDraft - Boolean indicating if draft exists
  • isExpired - Boolean indicating if draft has expired
  • updatedAt - Timestamp of last update (or null)
  • isChecking - Boolean indicating if status is being checked
  • refresh() - Function to manually refresh status
  • clear() - Function to clear the draft

Examples

With Analytics Events

const { formRef } = useFormAutosave<FormData>('checkout-form', {
  onBeforeSave: async (values) => {
    analytics.track('draft_save_started');
  },
  onAfterSave: async (values) => {
    analytics.track('draft_saved', { fieldCount: Object.keys(values).length });
  },
  onBeforeRestore: async (values) => {
    analytics.track('draft_restore_started');
  },
  onAfterRestore: async (values) => {
    analytics.track('draft_restored');
  },
  onDraftExpired: async (draftId) => {
    analytics.track('draft_expired', { draftId });
  }
});

With Batching

const { formRef } = useFormAutosave('large-form', {
  batchSaveInterval: 5000, // Save every 5 seconds
  onAfterSave: (values) => {
    console.log('Batch saved');
  }
});

TypeScript with Custom Types

interface ContactFormData {
  name: string;
  email: string;
  phone: string;
  message: string;
}

function ContactForm() {
  const { formRef, getDraftValues } = useFormAutosave<ContactFormData>('contact-form', {
    onAfterSave: (values) => {
      // values is typed as ContactFormData
      console.log(values.name); // TypeScript knows this exists
    }
  });

  const handleLoadDraft = async () => {
    const draft = await getDraftValues();
    if (draft) {
      // draft is typed as ContactFormData | null
      console.log(draft.email);
    }
  };

  return <form ref={formRef}>...</form>;
}

Draft Status Banner

function DraftBanner({ formId }: { formId: string }) {
  const { hasDraft, updatedAt, isExpired, clear } = useDraftStatus(formId, {
    ttl: { days: 7 }
  });

  if (!hasDraft) return null;

  return (
    <div className="draft-banner">
      {isExpired ? (
        <p>⚠️ Your draft has expired.</p>
      ) : (
        <p>📝 You have a draft from {new Date(updatedAt!).toLocaleString()}</p>
      )}
      <button onClick={() => clear()}>Discard</button>
    </div>
  );
}

When to Use

Use @form-guardian/react if you:

  • Are building a React application
  • Want a React-idiomatic API with hooks
  • Need type-safe integration with React form libraries
  • Want automatic cleanup and lifecycle management
  • Need real-time draft status monitoring

For non-React applications or custom integrations, use @form-guardian/dom instead.