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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@rubixscript/react-native-pdf-report

v2.0.0

Published

A versatile React Native PDF report generation library for any tracking app - pomodoro, expenses, skills, reading, habits, and more

Downloads

193

Readme

React Native PDF Report Library

npm version License: MIT

A versatile and customizable React Native PDF report generation library for any tracking app - pomodoro, expenses, skills, reading, habits, fitness, and more!

Features

  • 📊 Universal Tracking: Works with any type of tracking app
  • 🎨 Fully Customizable: Custom labels, colors, and terminology
  • 📱 Beautiful UI: Modern, responsive modal with smooth animations
  • 🌓 Dark Mode: Full dark mode support
  • 📈 Multiple Report Types: Summary, monthly, yearly, custom range, and item-specific reports
  • Type-Safe: Written in TypeScript with comprehensive type definitions
  • 🎯 Flexible Data Model: Generic data structures that adapt to your app's needs
  • 🧩 Modular Architecture: Clean, maintainable code with reusable components
  • 🎣 Custom Hooks: Powerful hooks for form management and logic
  • 🛠️ Utility Functions: Built-in formatters, validators, and helpers
  • 💪 Production Ready: Battle-tested and optimized for performance

Installation

npm install @rubixscript/react-native-pdf-report

Peer Dependencies

npm install expo-linear-gradient @expo/vector-icons @react-native-community/datetimepicker

Quick Start

import React, { useState } from 'react';
import { View, Button } from 'react-native';
import { PDFReportModal, DataItem, ActivitySession, ReportLabels } from '@rubixscript/react-native-pdf-report';

export default function App() {
  const [showModal, setShowModal] = useState(false);

  // Your tracking data
  const data: DataItem[] = [
    {
      id: '1',
      title: 'My Item',
      subtitle: 'Category or Author',
      progress: 75,
      total: 100,
      current: 75,
      startDate: new Date(),
    },
  ];

  const sessions: ActivitySession[] = [
    {
      id: 's1',
      itemId: '1',
      date: new Date(),
      duration: 60,
      value: 10,
    },
  ];

  // Customize labels for your app
  const labels: ReportLabels = {
    itemLabel: 'Task',
    itemLabelPlural: 'Tasks',
    sessionLabel: 'Session',
    sessionLabelPlural: 'Sessions',
    reportTitle: 'Activity Report',
  };

  const handleGenerateReport = (options) => {
    console.log('Generate PDF with options:', options);
    // Implement your PDF generation logic here
  };

  return (
    <View>
      <Button title="Generate Report" onPress={() => setShowModal(true)} />

      <PDFReportModal
        visible={showModal}
        onClose={() => setShowModal(false)}
        darkMode={false}
        data={data}
        sessions={sessions}
        onGenerateReport={handleGenerateReport}
        labels={labels}
        primaryColor="#007AFF"
      />
    </View>
  );
}

Use Cases

This library is perfect for:

  • 📚 Reading Trackers - Track books, pages read, reading sessions
  • 🍅 Pomodoro Apps - Track work sessions, focus time, productivity
  • 💰 Expense Trackers - Track spending, budgets, transactions
  • 🎯 Skill Trackers - Track learning progress, practice sessions
  • 🏃 Fitness Apps - Track workouts, exercises, progress
  • Habit Trackers - Track daily habits, streaks, consistency
  • Time Trackers - Track time spent on projects, tasks
  • 📝 Journal Apps - Track entries, moods, reflections
  • And many more!

Examples

Pomodoro / Productivity Tracker

const pomodoroLabels: ReportLabels = {
  itemLabel: 'Task',
  itemLabelPlural: 'Tasks',
  sessionLabel: 'Pomodoro Session',
  sessionLabelPlural: 'Pomodoro Sessions',
  reportTitle: 'Productivity Report',
  summaryLabel: 'Productivity Summary',
  progressLabel: 'Pomodoros Completed',
  durationLabel: 'Focus Time',
  totalLabel: 'Total Tasks',
};

const tasks: DataItem[] = [
  {
    id: '1',
    title: 'Complete Project Proposal',
    subtitle: 'Work Project',
    progress: 60,
    total: 10, // total pomodoros
    current: 6, // completed pomodoros
    category: 'Work',
    color: '#E74C3C',
  },
];

<PDFReportModal
  labels={pomodoroLabels}
  data={tasks}
  sessions={pomodoroSessions}
  primaryColor="#E74C3C"
  {...otherProps}
/>

Expense Tracker

const expenseLabels: ReportLabels = {
  itemLabel: 'Category',
  itemLabelPlural: 'Categories',
  sessionLabel: 'Transaction',
  sessionLabelPlural: 'Transactions',
  reportTitle: 'Expense Report',
  summaryLabel: 'Financial Summary',
  progressLabel: 'Amount Spent',
};

const categories: DataItem[] = [
  {
    id: '1',
    title: 'Groceries',
    subtitle: 'Food & Beverages',
    progress: 75, // % of budget used
    total: 500, // budget
    current: 375, // spent
    category: 'Food',
    color: '#2ECC71',
  },
];

const expenses: ActivitySession[] = [
  {
    id: 'e1',
    itemId: '1',
    date: new Date(),
    value: 85.50, // expense amount
    notes: 'Weekly grocery shopping',
  },
];

<PDFReportModal
  labels={expenseLabels}
  data={categories}
  sessions={expenses}
  primaryColor="#2ECC71"
  {...otherProps}
/>

Skill Tracker

const skillLabels: ReportLabels = {
  itemLabel: 'Skill',
  itemLabelPlural: 'Skills',
  sessionLabel: 'Practice Session',
  sessionLabelPlural: 'Practice Sessions',
  reportTitle: 'Skill Development Report',
  progressLabel: 'Skill Points Earned',
  durationLabel: 'Practice Time',
};

const skills: DataItem[] = [
  {
    id: '1',
    title: 'JavaScript',
    subtitle: 'Programming Language',
    progress: 75,
    total: 100,
    current: 75,
    category: 'Programming',
    metadata: {
      level: 'Advanced',
      hoursInvested: 250,
    },
  },
];

<PDFReportModal
  labels={skillLabels}
  data={skills}
  sessions={practiceSessions}
  primaryColor="#8B5CF6"
  {...otherProps}
/>

Reading Tracker (Legacy Support)

const readingLabels: ReportLabels = {
  itemLabel: 'Book',
  itemLabelPlural: 'Books',
  sessionLabel: 'Reading Session',
  sessionLabelPlural: 'Reading Sessions',
  reportTitle: 'Reading Report',
  progressLabel: 'Pages Read',
  durationLabel: 'Reading Time',
};

// You can also use the legacy Book and ReadingSession types
// They are aliases for DataItem and ActivitySession

API Reference

PDFReportModal Props

| Prop | Type | Required | Default | Description | |------|------|----------|---------|-------------| | visible | boolean | Yes | - | Controls modal visibility | | onClose | () => void | Yes | - | Callback when modal is closed | | darkMode | boolean | Yes | - | Enable dark mode | | data | DataItem[] | Yes | - | Array of items to track | | sessions | ActivitySession[] | Yes | - | Array of activity sessions | | onGenerateReport | (options: ReportOptions) => void | Yes | - | Callback with report configuration | | labels | ReportLabels | No | Default labels | Custom text labels | | reportTypes | ReportTypeConfig[] | No | Default types | Custom report type configs | | userName | string | No | - | User name for personalization | | primaryColor | string | No | #007AFF | Primary theme color | | accentColor | string | No | - | Accent theme color |

DataItem Type

interface DataItem {
  id: string;                    // Unique identifier
  title: string;                 // Main title (book title, task name, etc.)
  subtitle?: string;             // Subtitle (author, category, etc.)
  imageUri?: string;             // Optional image URL
  progress?: number;             // Progress percentage (0-100)
  total?: number;                // Total units (pages, hours, etc.)
  current?: number;              // Current units completed
  startDate?: Date | string;     // Start date
  completedDate?: Date | string; // Completion date
  notes?: string[];              // Notes array
  category?: string;             // Category
  color?: string;                // Color for UI
  metadata?: Record<string, any>; // Custom metadata
  isPinned?: boolean;            // Pinned status
  [key: string]: any;            // Additional custom fields
}

ActivitySession Type

interface ActivitySession {
  id: string;                    // Unique identifier
  itemId: string;                // Reference to DataItem
  date: Date | string;           // Session date
  startValue?: number;           // Start value (page, time, etc.)
  endValue?: number;             // End value
  duration?: number;             // Duration in minutes
  value?: number;                // Numeric value (amount, points, etc.)
  notes?: string;                // Session notes
  imageUrl?: string;             // Optional image
  metadata?: Record<string, any>; // Custom metadata
  [key: string]: any;            // Additional custom fields
}

ReportLabels Type

interface ReportLabels {
  itemLabel?: string;            // e.g., "Book", "Task", "Expense"
  itemLabelPlural?: string;      // e.g., "Books", "Tasks"
  sessionLabel?: string;         // e.g., "Session", "Transaction"
  sessionLabelPlural?: string;   // e.g., "Sessions", "Transactions"
  reportTitle?: string;          // e.g., "Reading Report"
  summaryLabel?: string;         // e.g., "Summary"
  progressLabel?: string;        // e.g., "Pages Read"
  durationLabel?: string;        // e.g., "Reading Time"
  totalLabel?: string;           // e.g., "Total Books"
}

ReportOptions Type

interface ReportOptions {
  type: ReportType;              // 'summary' | 'monthly' | 'yearly' | 'custom' | 'item-details'
  startDate?: Date;              // For custom reports
  endDate?: Date;                // For custom reports
  includeCharts?: boolean;       // Include charts in report
  includeSessionDetails?: boolean; // Include session details
  includeItemDetails?: boolean;  // Include item details
  includeAchievements?: boolean; // Include achievements
  itemId?: string;               // For item-specific reports
  customTitle?: string;          // Custom report title
  labels?: ReportLabels;         // Labels for the report
}

Customization

Custom Report Types

You can define custom report types with your own icons and descriptions:

const customReportTypes: ReportTypeConfig[] = [
  {
    type: 'summary',
    title: '🎯 My Custom Summary',
    description: 'All-time statistics',
    icon: '🎯',
  },
  {
    type: 'monthly',
    title: '📅 Monthly Review',
    description: 'This month\'s progress',
    icon: '📅',
  },
  // ... more custom types
];

<PDFReportModal
  reportTypes={customReportTypes}
  {...otherProps}
/>

Custom Colors

<PDFReportModal
  primaryColor="#FF6B6B"
  accentColor="#4ECDC4"
  {...otherProps}
/>

Flexible Data Model

The library uses a flexible data model that can store any custom fields:

const customData: DataItem[] = [
  {
    id: '1',
    title: 'My Item',
    subtitle: 'Subtitle',
    // Add any custom fields
    customField: 'custom value',
    rating: 5,
    tags: ['tag1', 'tag2'],
    metadata: {
      // Store complex custom data
      anyData: 'you need',
    },
  },
];

UI Features

  • Modern Design: Beautiful card-based UI with smooth animations
  • 🎨 Customizable Colors: Change primary and accent colors to match your brand
  • 🌓 Dark Mode: Full dark mode support throughout
  • 📱 Responsive: Works perfectly on all screen sizes
  • ⌨️ Accessibility: Touch-friendly with proper accessibility labels
  • 🔄 Smooth Transitions: Animated modal with slide transitions
  • 📅 Date Pickers: Native date pickers for custom date ranges
  • Smart Validation: Form validation with helpful error messages

Fixed Issues (v2.0.0)

  • Modal Overlay Issue: Fixed modal not opening properly due to overlay blocking interaction
  • Generic Library: Transformed from reading-specific to universal tracking library
  • Improved Aesthetics: Enhanced UI with better spacing, colors, and typography
  • Better Accessibility: Improved touch targets and visual feedback
  • Type Safety: Comprehensive TypeScript types for better DX

Migrating from v1.x

If you're upgrading from v1.x (reading-specific version):

// OLD (v1.x)
import { Book, ReadingSession } from '@rubixscript/react-native-pdf-report';

const books: Book[] = [...];
const sessions: ReadingSession[] = [...];

<PDFReportModal books={books} readingSessions={sessions} />

// NEW (v2.x) - Backward compatible
import { Book, ReadingSession } from '@rubixscript/react-native-pdf-report';

const books: Book[] = [...]; // Still works!
const sessions: ReadingSession[] = [...]; // Still works!

<PDFReportModal data={books} sessions={sessions} />

// OR use new generic types
import { DataItem, ActivitySession } from '@rubixscript/react-native-pdf-report';

const data: DataItem[] = [...];
const sessions: ActivitySession[] = [...];

<PDFReportModal data={data} sessions={sessions} labels={customLabels} />

The Book and ReadingSession types are still available as aliases for backward compatibility.

Examples Directory

Check out the examples/ directory for complete working examples:

  • reading-tracker.tsx - Reading tracking app
  • pomodoro-tracker.tsx - Productivity/pomodoro app
  • expense-tracker.tsx - Expense tracking app
  • skill-tracker.tsx - Skill development app

Architecture

This library follows a modular architecture for maintainability and extensibility:

  • 8 Modular Components: Each with a single responsibility
  • 2 Custom Hooks: useReportForm and useReportTypes
  • Utility Functions: Formatters, validators, and constants
  • Type-Safe: Comprehensive TypeScript definitions

The main PDFReportModal component has been reduced from 795 lines to just 272 lines through modularization!

For detailed architecture documentation, see ARCHITECTURE.md.

Component Structure

PDFReportModal (Main Orchestrator)
├── ModalHeader
├── ScrollView
│   ├── ReportTypeSelector
│   ├── DateRangeSelector (conditional)
│   ├── ItemSelector (conditional)
│   ├── CustomTitleInput
│   └── ReportOptionsToggles
└── ModalFooter

Using Individual Components

All components are exported and can be used independently:

import {
  ReportTypeSelector,
  DateRangeSelector,
  ItemSelector,
  CustomTitleInput,
  ReportOptionsToggles,
  ModalHeader,
  ModalFooter,
} from '@rubixscript/react-native-pdf-report';

Using Custom Hooks

import { useReportForm, useReportTypes } from '@rubixscript/react-native-pdf-report';

// In your component
const { selectedReportType, handleGenerateReport, ... } = useReportForm({
  visible,
  labels,
  onGenerateReport,
  onClose,
});

Using Utilities

import {
  formatDate,
  formatDuration,
  formatCurrency,
  validateDateRange,
  DEFAULT_LABELS,
} from '@rubixscript/react-native-pdf-report';

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

When contributing, please:

  • Follow the modular architecture patterns
  • Keep components small and focused (< 150 lines)
  • Add TypeScript types for all props
  • Write tests for new functionality
  • Update documentation

License

MIT © RubixScript Team

Links

Support

If you find this library helpful, please give it a ⭐ on GitHub!

For questions and support, please open an issue on GitHub.