npm package: @harshiniravikumar/react-footnote-system
Description: A fully featured, customizable, and accessible footnote management system for React applications with TypeScript support
Latest version: 1.0.0

# React Footnote System

A fully featured, customizable, and accessible footnote management system for React applications. Provides automatic numbering, context-based management, and flexible rendering with TypeScript support for modern web development.

## ✨ Core Features

- 🔢 **Automatic Numbering** – smart footnote numbering with context awareness
- 📝 **Context Management** – centralized footnote state across components
- 🎯 **Flexible Rendering** – customizable footnote references and lists
- ⚡ **TypeScript Support** – comprehensive type definitions included
- 🎨 **Customizable Styling** – complete visual customization options
- ♿ **Accessible** – ARIA support and semantic HTML structure
- 🔄 **Dynamic Registration** – footnotes register automatically when mounted
- 📱 **Responsive Design** – works seamlessly across all device sizes

## 📦 Installation

```bash
npm install "@harshiniravikumar/react-footnote-system"
```

## 🔧 Main Components

| Component | Type | Description |
|-----------|------|-------------|
| `FootnoteContext` | `Provider` | Context provider for footnote management |
| `FootnoteReference` | `Component` | Creates footnote references with automatic numbering |
| `FootnoteList` | `Component` | Renders all registered footnotes in list format |
| `Footnote` | `Component` | Standalone footnote component for advanced use cases |

## 🎯 Component Props

### FootnoteReference

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `id` | `string` | - | Unique identifier for the footnote (required) |
| `children` | `ReactNode` | - | The footnote content |
| `className` | `string` | `''` | Additional CSS classes for the reference |
| `onClick` | `() => void` | - | Custom click handler |
| `style` | `CSSProperties` | `{}` | Inline styles for the reference |
| `renderReference` | `(number: number) => ReactNode` | - | Custom reference renderer |

### FootnoteList

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `className` | `string` | `''` | CSS classes for the list container |
| `itemClassName` | `string` | `''` | CSS classes for footnote items |
| `title` | `string` | `"Footnotes"` | Title for the footnote section |
| `showTitle` | `boolean` | `true` | Whether to display the title |
| `orderBy` | `"appearance" \| "alphabetical"` | `"appearance"` | Footnote ordering method |
| `renderItem` | `(footnote: FootnoteData) => ReactNode` | - | Custom footnote item renderer |

### Footnote

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `id` | `string` | - | Unique identifier (required) |
| `content` | `string \| ReactNode` | - | Footnote content |
| `number` | `number` | - | Manual footnote number override |
| `autoRegister` | `boolean` | `true` | Automatically register with context |

## ⚙️ Footnote Context Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `startNumber` | `number` | `1` | Starting number for footnote numbering |
| `numberingStyle` | `"numeric" \| "roman" \| "alpha"` | `"numeric"` | Numbering style for footnotes |
| `allowDuplicates` | `boolean` | `false` | Allow duplicate footnote IDs |
| `resetOnUnmount` | `boolean` | `false` | Reset footnotes when context unmounts |
| `maxFootnotes` | `number` | `undefined` | Maximum number of footnotes allowed |

## 🎨 Theme Configuration

Customize the visual appearance of your footnotes:

```typescript
const footnoteTheme = {
  reference: {
    color: "#007bff",
    fontSize: "0.8em",
    verticalAlign: "super",
    textDecoration: "none",
    padding: "0 2px",
    borderRadius: "2px",
    backgroundColor: "transparent"
  },
  list: {
    borderTop: "1px solid #e0e0e0",
    marginTop: "2rem",
    paddingTop: "1rem",
    fontSize: "0.9em"
  },
  item: {
    marginBottom: "0.5rem",
    lineHeight: "1.4",
    color: "#666"
  },
  title: {
    fontSize: "1.1em",
    fontWeight: "bold",
    marginBottom: "1rem",
    color: "#333"
  }
};
```

## 🖼️ Basic Usage

```tsx
import React from 'react';
import { 
  FootnoteContext, 
  FootnoteReference, 
  FootnoteList 
} from "@your-username/react-footnote-system";

function BasicExample() {
  return (
    <FootnoteContext>
      <article>
        <h1>Article Title</h1>
        <p>
          This is some content with a footnote
          <FootnoteReference id="note1">
            This appears as footnote #1 at the bottom of the page.
          </FootnoteReference>
          and more text continues here.
        </p>
        
        <p>
          Another paragraph with another reference
          <FootnoteReference id="note2">
            This becomes footnote #2 with automatic numbering.
          </FootnoteReference>
          in the middle of the sentence.
        </p>

        <FootnoteList />
      </article>
    </FootnoteContext>
  );
}
```

## 🔮 Advanced Usage with All Features

```tsx
import React, { useRef, useContext } from 'react';
import { 
  FootnoteContext, 
  FootnoteReference, 
  FootnoteList,
  useFootnoteContext 
} from "@your-username/react-footnote-system";

function AdvancedExample() {
  const footnoteContext = useFootnoteContext();

  const handleFootnoteClick = (id: string) => {
    console.log('Footnote clicked:', id);
  };

  return (
    <FootnoteContext
      options={{
        startNumber: 1,
        numberingStyle: "numeric",
        allowDuplicates: false,
        resetOnUnmount: true,
        maxFootnotes: 50
      }}
      theme={{
        reference: {
          color: "#0066cc",
          backgroundColor: "#f0f8ff",
          borderRadius: "4px",
          padding: "2px 4px"
        },
        list: {
          borderTop: "2px solid #0066cc",
          backgroundColor: "#fafafa"
        }
      }}
    >
      <main>
        <section>
          <h1>Research Paper</h1>
          <p>
            Recent studies show significant findings
            <FootnoteReference 
              id="study-2024"
              onClick={() => handleFootnoteClick("study-2024")}
              className="custom-reference"
            >
              Smith, J., & Johnson, A. (2024). "Advanced Research Methods in Modern Science." 
              <em>Journal of Scientific Discovery</em>, 42(3), 123-145. 
              DOI: 10.1000/journal.2024.123
            </FootnoteReference>
            that support our hypothesis.
          </p>

          <p>
            The methodology employed
            <FootnoteReference id="methodology">
              Our research methodology followed the guidelines established by 
              the International Research Standards Committee (IRSC).
            </FootnoteReference>
            ensures reliable results across multiple scenarios.
          </p>
        </section>

        <footer>
          <FootnoteList 
            title="References & Notes"
            className="research-footnotes"
            itemClassName="footnote-item"
            showTitle={true}
            orderBy="appearance"
            renderItem={(footnote) => (
              <div className="custom-footnote">
                <span className="footnote-number">{footnote.number}.</span>
                <span className="footnote-content">{footnote.content}</span>
              </div>
            )}
          />
        </footer>
      </main>
    </FootnoteContext>
  );
}
```

## 📱 Multiple Contexts & Sections

```tsx
function MultiSectionDocument() {
  return (
    <div>
      {/* Chapter 1 with independent footnotes */}
      <FootnoteContext options={{ startNumber: 1 }}>
        <section>
          <h2>Chapter 1: Introduction</h2>
          <p>
            Content with footnotes
            <FootnoteReference id="ch1-intro">
              Introduction footnote content here.
            </FootnoteReference>
            specific to this chapter.
          </p>
          <FootnoteList title="Chapter 1 Notes" />
        </section>
      </FootnoteContext>

      <FootnoteContext options={{ startNumber: 1, numberingStyle: "roman" }}>
        <section>
          <h2>Chapter 2: Methodology</h2>
          <p>
            Different chapter content
            <FootnoteReference id="ch2-method">
              Methodology footnote with roman numerals.
            </FootnoteReference>
            with separate footnote numbering.
          </p>
          <FootnoteList title="Chapter 2 Notes" />
        </section>
      </FootnoteContext>
    </div>
  );
}
```

## 🎬 Custom Renderers & Animations

```tsx
function CustomFootnoteExample() {
  return (
    <FootnoteContext>
      <div>
        <p>
          Text with custom reference
          <FootnoteReference 
            id="custom"
            renderReference={(number) => (
              <span className="custom-ref">
                [{number}]
              </span>
            )}
          >
            Custom styled footnote content
          </FootnoteReference>
        </p>

        <FootnoteList 
          renderItem={(footnote) => (
            <div className="animated-footnote">
              <strong>{footnote.number}.</strong>
              <span>{footnote.content}</span>
            </div>
          )}
        />
      </div>
    </FootnoteContext>
  );
}
```

## 🔄 Callbacks & Events

| Callback | Type | Description |
|----------|------|-------------|
| `onFootnoteRegister` | `(id: string, content: ReactNode) => void` | Called when footnote is registered |
| `onFootnoteUnregister` | `(id: string) => void` | Called when footnote is unregistered |
| `onFootnoteClick` | `(id: string, number: number) => void` | Called when footnote reference is clicked |
| `onListRender` | `(footnotes: FootnoteData[]) => void` | Called when footnote list renders |
| `onMaxFootnotesReached` | `() => void` | Called when max footnotes limit is reached |

## 🛠️ Hook: useFootnoteContext

Access footnote context methods and state:

| Method/Property | Type | Description |
|-----------------|------|-------------|
| `footnotes` | `FootnoteData[]` | Array of all registered footnotes |
| `register` | `(id: string, content: ReactNode) => void` | Register a new footnote |
| `unregister` | `(id: string) => void` | Unregister a footnote |
| `getFootnote` | `(id: string) => FootnoteData \| undefined` | Get footnote by ID |
| `getFootnoteNumber` | `(id: string) => number \| undefined` | Get footnote number by ID |
| `reset` | `() => void` | Clear all footnotes |
| `count` | `number` | Total number of registered footnotes |

```tsx
import { useFootnoteContext } from "@your-username/react-footnote-system";

function FootnoteStats() {
  const { footnotes, count, reset } = useFootnoteContext();
  
  return (
    <div>
      <p>Total footnotes: {count}</p>
      <button onClick={reset}>Clear All Footnotes</button>
    </div>
  );
}
```

## 🎯 Real-World Examples

### Academic Paper
```tsx
<FootnoteContext options={{ numberingStyle: "numeric" }}>
  <article className="academic-paper">
    <h1>The Impact of Climate Change on Marine Ecosystems</h1>
    <p>
      Recent oceanographic studies
      <FootnoteReference id="ocean-study-2024">
        Martinez, C., et al. (2024). "Ocean Temperature Variations and Marine Biodiversity." 
        <em>Marine Biology Quarterly</em>, 78(2), 45-67.
      </FootnoteReference>
      indicate significant temperature variations in coastal waters.
    </p>
    
    <p>
      These findings corroborate earlier research
      <FootnoteReference id="previous-research">
        See Thompson, R. (2022) and Williams, S. (2023) for comprehensive 
        reviews of historical temperature data.
      </FootnoteReference>
      from the past decade.
    </p>

    <FootnoteList title="References" className="academic-references" />
  </article>
</FootnoteContext>
```

### Blog Post with Explanatory Notes
```tsx
<FootnoteContext options={{ numberingStyle: "alpha" }}>
  <article className="blog-post">
    <h1>Understanding React Hooks</h1>
    <p>
      React Hooks revolutionized functional components
      <FootnoteReference id="hooks-intro">
        Hooks were introduced in React 16.8 (February 2019) and allow you to 
        use state and other React features in functional components.
      </FootnoteReference>
      by enabling state management without classes.
    </p>

    <p>
      The useState hook
      <FootnoteReference id="usestate-example">
        <code>const [state, setState] = useState(initialValue)</code> is the 
        most commonly used hook for managing component state.
      </FootnoteReference>
      is fundamental to modern React development.
    </p>

    <FootnoteList 
      title="Additional Information" 
      className="blog-footnotes"
      showTitle={true}
    />
  </article>
</FootnoteContext>
```

### Legal Document with Roman Numerals
```tsx
<FootnoteContext options={{ numberingStyle: "roman" }}>
  <div className="legal-document">
    <h1>Terms of Service</h1>
    <section>
      <h2>Section 1: Definitions</h2>
      <p>
        "Service" refers to the platform
        <FootnoteReference id="service-definition">
          As defined under applicable consumer protection laws and regulations 
          in the jurisdiction where the service is provided.
        </FootnoteReference>
        provided by the Company.
      </p>
    </section>

    <FootnoteList 
      title="Legal References"
      className="legal-footnotes"
      itemClassName="legal-footnote-item"
    />
  </div>
</FootnoteContext>
```

## 🎨 Custom Styling Examples

### Modern Glass Effect
```css
.modern-footnotes .footnote-reference {
  background: rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 6px;
  padding: 2px 6px;
  color: #007bff;
  text-decoration: none;
  transition: all 0.2s ease;
}

.modern-footnotes .footnote-reference:hover {
  background: rgba(255, 255, 255, 0.2);
  transform: translateY(-1px);
}

.modern-footnotes .footnote-list {
  background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
  border-radius: 12px;
  padding: 1.5rem;
  margin-top: 2rem;
}
```

### Academic Style
```css
.academic-footnotes .footnote-reference {
  color: #d32f2f;
  font-weight: 500;
  vertical-align: super;
  font-size: 0.75em;
  text-decoration: none;
  border-bottom: 1px dotted #d32f2f;
}

.academic-footnotes .footnote-list {
  border-top: 2px solid #333;
  margin-top: 3rem;
  padding-top: 1rem;
  font-family: 'Times New Roman', serif;
}

.academic-footnotes .footnote-item {
  text-indent: -1em;
  padding-left: 1em;
  margin-bottom: 0.8rem;
}
```

## 📱 Responsive Behavior

```tsx
function ResponsiveFootnotes() {
  return (
    <FootnoteContext>
      <div className="responsive-content">
        <p>
          Mobile-optimized footnotes
          <FootnoteReference 
            id="mobile-note"
            className="responsive-reference"
          >
            On mobile devices, footnotes adapt to smaller screens with 
            optimized touch targets and readable font sizes.
          </FootnoteReference>
          work seamlessly across devices.
        </p>

        <FootnoteList className="responsive-footnote-list" />
      </div>
    </FootnoteContext>
  );
}
```

```css
@media (max-width: 768px) {
  .responsive-reference {
    font-size: 0.9em !important;
    padding: 4px 6px !important;
  }
  
  .responsive-footnote-list {
    font-size: 0.85em;
    padding: 1rem 0.5rem;
  }
}
```

## ♿ Accessibility Features

- **ARIA Labels**: Proper labeling for screen readers
- **Keyboard Navigation**: Tab and Enter key support
- **Semantic HTML**: Uses appropriate HTML elements
- **High Contrast**: Works with high contrast modes
- **Screen Reader Support**: Announces footnote numbers and content
- **Focus Management**: Proper focus indicators and management

```tsx
<FootnoteReference 
  id="accessible-note"
  aria-label="Footnote reference 1"
  role="doc-noteref"
>
  Accessible footnote content
</FootnoteReference>
```

## 🚀 Performance Features

- **Lazy Registration**: Footnotes register only when needed
- **Efficient Re-renders**: Optimized with React.memo and context optimization
- **Memory Management**: Automatic cleanup on unmount
- **Minimal Bundle Size**: Tree-shakeable components
- **No Dependencies**: Pure React implementation

## 📄 TypeScript Support

Comprehensive TypeScript definitions included:

```tsx
import type { 
  Footnotes,
  FootnoteProps,
  FootnoteContextType,
  FootnoteRefProps,
  FootnoteListProps,
  FootnoteData,
  FootnoteOptions,
  FootnoteTheme
} from "@your-username/react-footnote-system";

interface CustomFootnoteData {
  id: string;
  content: string;
  category: 'reference' | 'explanation' | 'source';
}

const MyComponent: React.FC = () => {
  const [footnotes, setFootnotes] = useState<CustomFootnoteData[]>([]);
  
  return (
    <FootnoteContext>
      {/* Your footnote implementation */}
    </FootnoteContext>
  );
};
```

## 🔧 Configuration Examples

### Numbered Footnotes (Default)
```tsx
<FootnoteContext options={{ numberingStyle: "numeric" }}>
  {/* Footnotes appear as: 1, 2, 3, ... */}
</FootnoteContext>
```

### Roman Numeral Footnotes
```tsx
<FootnoteContext options={{ numberingStyle: "roman" }}>
  {/* Footnotes appear as: i, ii, iii, ... */}
</FootnoteContext>
```

### Alphabetical Footnotes
```tsx
<FootnoteContext options={{ numberingStyle: "alpha" }}>
  {/* Footnotes appear as: a, b, c, ... */}
</FootnoteContext>
```

### Custom Starting Number
```tsx
<FootnoteContext options={{ startNumber: 10 }}>
  {/* Footnotes start from: 10, 11, 12, ... */}
</FootnoteContext>
```

## 🎪 Interactive Examples

### Footnotes with Custom Actions
```tsx
function InteractiveFootnotes() {
  const [selectedFootnote, setSelectedFootnote] = useState<string | null>(null);

  return (
    <FootnoteContext>
      <div>
        <p>
          Click this footnote
          <FootnoteReference 
            id="interactive"
            onClick={() => setSelectedFootnote("interactive")}
          >
            This footnote has custom click behavior and can trigger actions 
            in your application.
          </FootnoteReference>
          to see custom behavior.
        </p>

        {selectedFootnote && (
          <div className="footnote-popup">
            <p>You clicked footnote: {selectedFootnote}</p>
            <button onClick={() => setSelectedFootnote(null)}>Close</button>
          </div>
        )}

        <FootnoteList />
      </div>
    </FootnoteContext>
  );
}
```

### Dynamic Footnote Management
```tsx
function DynamicFootnotes() {
  const { register, unregister, footnotes, reset } = useFootnoteContext();

  const addDynamicFootnote = () => {
    const id = `dynamic-${Date.now()}`;
    register(id, `Dynamic footnote added at ${new Date().toLocaleTimeString()}`);
  };

  return (
    <div>
      <button onClick={addDynamicFootnote}>Add Footnote</button>
      <button onClick={reset}>Clear All</button>
      <p>Current footnotes: {footnotes.length}</p>
      <FootnoteList />
    </div>
  );
}
```

## 🔮 Integration with Other Libraries

### With Markdown Processors
```tsx
import ReactMarkdown from 'react-markdown';

function MarkdownWithFootnotes({ content }: { content: string }) {
  return (
    <FootnoteContext>
      <ReactMarkdown 
        components={{
          sup: ({ children }) => (
            <FootnoteReference id={`md-${children}`}>
              Markdown footnote content
            </FootnoteReference>
          )
        }}
      >
        {content}
      </ReactMarkdown>
      <FootnoteList />
    </FootnoteContext>
  );
}
```

### With Content Management Systems
```tsx
function CMSContent({ content }: { content: any[] }) {
  return (
    <FootnoteContext>
      {content.map((block, index) => {
        if (block.type === 'footnote') {
          return (
            <FootnoteReference key={index} id={block.id}>
              {block.content}
            </FootnoteReference>
          );
        }
        return <div key={index}>{block.content}</div>;
      })}
      <FootnoteList />
    </FootnoteContext>
  );
}
```

## 🧪 Testing Support

```tsx
import { render, screen } from '@testing-library/react';
import { FootnoteContext, FootnoteReference, FootnoteList } from 'your-library';

test('footnotes render correctly', () => {
  render(
    <FootnoteContext>
      <FootnoteReference id="test">Test footnote</FootnoteReference>
      <FootnoteList />
    </FootnoteContext>
  );
  
  expect(screen.getByText('1')).toBeInTheDocument();
  expect(screen.getByText('Test footnote')).toBeInTheDocument();
});
```

## 📄 License

MIT License - feel free to use in your projects!