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

@refinelyai/feedback-widget

v0.0.4

Published

A highly customizable feedback widget library with star ratings and text input - works on web and React Native

Readme

@refinelyai/feedback-widget

A highly customizable feedback widget library with star ratings and text input that works seamlessly across web and React Native platforms.

Features

  • 🌐 Cross-Platform: Works on web browsers and React Native
  • Star Rating System: Customizable star ratings with labels
  • 📝 Text Input: Multi-line text input with character counting
  • 🎨 Highly Customizable: Extensive styling and behavior options
  • 🔄 React Hooks: Built-in React hooks for easy integration
  • 📦 Multiple Entry Points: Choose the right bundle for your platform
  • 🚀 TypeScript Support: Full TypeScript support with type definitions

Installation

npm install @refinelyai/feedback-widget

Quick Start

Web Usage

import { FeedbackWidget } from '@refinelyai/feedback-widget';

const widget = new FeedbackWidget('#feedback-container', {
  apiKey: 'your-api-key',
  apiUrl: 'get-your-api-on-https://refinelyai.netlify.app',
  customization: {
    title: 'Rate your experience',
    layout: 'vertical'
  }
});

React Usage

import { FeedbackWidget } from '@refinelyai/feedback-widget/react';

function App() {
  return (
    <FeedbackWidget
      apiKey="your-api-key"
      apiUrl="get-your-api-on-https://refinelyai.netlify.app"
      customization={{
        title: 'Rate your experience',
        layout: 'vertical'
      }}
      onSuccess={(response) => console.log('Success:', response)}
      onError={(error) => console.error('Error:', error)}
    />
  );
}

React Native Usage

import { FeedbackWidget } from '@refinelyai/feedback-widget/react-native';

function App() {
  return (
    <FeedbackWidget
      apiKey="your-api-key"
      apiUrl="https://your-api.com/feedback"
      customization={{
        title: 'Rate your experience',
        layout: 'vertical'
      }}
      onSuccess={(response) => console.log('Success:', response)}
      onError={(error) => console.error('Error:', error)}
    />
  );
}

Entry Points

The library provides multiple entry points for different use cases:

  • Main: @refinelyai/feedback-widget - Web version (backward compatibility)
  • Web: @refinelyai/feedback-widget/web - Web-specific implementation
  • React: @refinelyai/feedback-widget/react - React components and hooks
  • React Native: @refinelyai/feedback-widget/react-native - React Native components

Configuration

FeedbackConfig

interface FeedbackConfig {
  apiKey: string;
  apiUrl: string;
  customization?: FeedbackCustomization;
}

FeedbackCustomization

interface FeedbackCustomization {
  // Container styling
  containerStyle?: Record<string, any>;
  containerClassName?: string;

  // Title/Header
  title?: string;
  titleStyle?: Record<string, any>;
  titleClassName?: string;

  // Star rating customization
  starRating?: {
    maxStars?: number;
    starSize?: string | number;
    starColor?: string;
    starActiveColor?: string;
    starHoverColor?: string;
    showLabels?: boolean;
    labels?: string[];
    labelStyle?: Record<string, any>;
    labelClassName?: string;
  };

  // Text input customization
  textInput?: {
    placeholder?: string;
    maxLength?: number;
    rows?: number;
    style?: Record<string, any>;
    className?: string;
    label?: string;
    labelStyle?: Record<string, any>;
    labelClassName?: string;
  };

  // Submit button customization
  submitButton?: {
    text?: string;
    style?: Record<string, any>;
    className?: string;
    loadingText?: string;
    successText?: string;
    errorText?: string;
  };

  // Layout options
  layout?: 'vertical' | 'horizontal';
  spacing?: string | number;

  // Callbacks
  onSubmit?: (data: FeedbackData) => void;
  onSuccess?: (response: any) => void;
  onError?: (error: Error) => void;
}

React Hooks

useFeedbackWidget

import { useFeedbackWidget } from '@refinelyai/feedback-widget/react';

function MyComponent() {
  const {
    rating,
    setRating,
    text,
    setText,
    isSubmitting,
    submitFeedback,
    reset
  } = useFeedbackWidget({
    apiKey: 'your-api-key',
    apiUrl: 'https://your-api.com/feedback'
  });

  const handleSubmit = async () => {
    try {
      const response = await submitFeedback();
      console.log('Success:', response);
    } catch (error) {
      console.error('Error:', error);
    }
  };

  return (
    <div>
      {/* Your custom UI */}
      <button onClick={handleSubmit} disabled={isSubmitting}>
        Submit
      </button>
    </div>
  );
}

Examples

Basic Web Widget

<!DOCTYPE html>
<html>
<head>
    <title>Feedback Widget Demo</title>
</head>
<body>
    <div id="feedback-container"></div>
    
    <script type="module">
        import { FeedbackWidget } from '@refinelyai/feedback-widget';
        
        const widget = new FeedbackWidget('#feedback-container', {
            apiKey: 'your-api-key',
            apiUrl: 'https://your-api.com/feedback',
            customization: {
                title: 'How was your experience?',
                layout: 'vertical',
                starRating: {
                    maxStars: 5,
                    labels: ['Terrible', 'Poor', 'Okay', 'Good', 'Excellent']
                },
                textInput: {
                    placeholder: 'Tell us more about your experience...',
                    maxLength: 500
                }
            }
        });
    </script>
</body>
</html>

React Component with Custom Styling

import { FeedbackWidget } from '@refinelyai/feedback-widget/dist/react';

function CustomFeedbackWidget() {
  return (
    <FeedbackWidget
      apiKey="your-api-key"
      apiUrl="https://your-api.com/feedback"
      customization={{
        title: 'We value your feedback!',
        titleStyle: {
          color: '#2c3e50',
          fontSize: '20px'
        },
        starRating: {
          starSize: 28,
          starColor: '#ecf0f1',
          starActiveColor: '#f39c12',
          labels: ['Not satisfied', 'Could be better', 'Okay', 'Good', 'Excellent!']
        },
        textInput: {
          placeholder: 'Share your thoughts with us...',
          style: {
            borderColor: '#3498db',
            borderRadius: '8px'
          }
        },
        submitButton: {
          text: 'Send Feedback',
          style: {
            backgroundColor: '#3498db',
            borderRadius: '8px'
          }
        }
      }}
      onSuccess={(response) => {
        alert('Thank you for your feedback!');
      }}
      onError={(error) => {
        alert('Sorry, something went wrong. Please try again.');
      }}
    />
  );
}

React Native with Custom Theme

import { FeedbackWidget } from '@refinelyai/feedback-widget/dist/react-native';

function MobileFeedbackWidget() {
  return (
    <FeedbackWidget
      apiKey="your-api-key"
      apiUrl="https://your-api.com/feedback"
      customization={{
        title: 'Rate our app!',
        starRating: {
          starSize: 32,
          starColor: '#e0e0e0',
          starActiveColor: '#ffd700',
          labels: ['Poor', 'Fair', 'Good', 'Very Good', 'Excellent']
        },
        textInput: {
          placeholder: 'What can we improve?',
          maxLength: 300
        },
        submitButton: {
          text: 'Submit Review',
          loadingText: 'Sending...',
          successText: 'Thanks!'
        }
      }}
      style={{
        margin: 20,
        borderRadius: 12,
        shadowColor: '#000',
        shadowOffset: { width: 0, height: 2 },
        shadowOpacity: 0.1,
        shadowRadius: 4,
        elevation: 3
      }}
    />
  );
}

API Reference

FeedbackWidget Class (Web)

class FeedbackWidget {
  constructor(container: HTMLElement | string, config: FeedbackConfig, events?: FeedbackEvents);
  
  reset(): void;
  setRating(rating: number): void;
  setText(text: string): void;
  getRating(): number;
  getText(): string;
}

FeedbackWidget Component (React/React Native)

interface FeedbackWidgetProps extends FeedbackConfig {
  onRatingChange?: (rating: number) => void;
  onTextChange?: (text: string) => void;
  onSubmit?: (data: FeedbackData) => void;
  onSuccess?: (response: FeedbackResponse) => void;
  onError?: (error: Error) => void;
  onReset?: () => void;
  style?: any;
}

useFeedbackWidget Hook

function useFeedbackWidget(config: FeedbackConfig): {
  rating: number;
  setRating: (rating: number) => void;
  text: string;
  setText: (text: string) => void;
  isSubmitting: boolean;
  submitFeedback: () => Promise<FeedbackResponse | null>;
  reset: () => void;
}

Browser Support

  • Chrome 60+
  • Firefox 55+
  • Safari 12+
  • Edge 79+

React Native Support

  • React Native 0.60+
  • Expo SDK 36+

License

MIT

Contributing

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