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

finsignal-feed-explore

v2.18.1

Published

News feed explorer components for React web applications

Readme

finsignal-feed-explore

News feed explorer components for React web applications. A comprehensive library for displaying and interacting with financial news feeds.

Version 2.4.0 - FilterButton Component 🎯

New in this version:

  • FilterButton - Self-contained filter button component with three states
  • 🔄 Seamless integration with FeedList for filter management
  • 🎨 Customizable colors for icons and badge
  • 📦 Fully typed with TypeScript

Previous Updates (2.0.0) - Major Design Update 🎨

Version 2.0.0 included a complete redesign to match the native app UI:

  • ✨ Larger, bolder titles (20px, 700 weight) for better readability
  • 🎯 Improved source display with circular logos positioned after title
  • 📐 Better content hierarchy and spacing matching native design
  • 🎭 Professional action bar with left/right icon grouping
  • 🔍 Larger icons (24px) with proper colors and opacity
  • 💡 AI Insight styling with gradient background and sparkle icon
  • 🖱️ Enhanced drag'n'drop visual feedback

Installation

npm install finsignal-feed-explore
# or
yarn add finsignal-feed-explore

Quick Start

import { FeedList } from 'finsignal-feed-explore';
import 'finsignal-feed-explore/dist/newsfeed.css';

function App() {
  return (
    <FeedList
      onNewsClick={(news) => console.log('Clicked:', news)}
      onFiltersApply={(filters) => console.log('Filters:', filters)}
    />
  );
}

Note:

  • apiUrl is optional. If not provided, the component will use the default API URL: https://explore-gateway.changesandbox.ru/
  • Russian localization is enabled by default. All filter labels and categories will be displayed in Russian.

Main Components

FeedList

The main component for displaying a news feed with filtering, infinite scroll, and interactive actions.

import { FeedList } from 'finsignal-feed-explore';
import 'finsignal-feed-explore/dist/newsfeed.css';

<FeedList
  onNewsClick={(news) => handleNewsClick(news)}
  onShowFilter={() => console.log('Filter button clicked')}
  initialFilters={['earnings', 'ipo']}
  enableInfiniteScroll={true}
  enableDragDrop={true}
  onDragStart={(news, e) => console.log('Drag started:', news.title)}
/>

NewsSnippet

Individual news item component that can be used standalone.

import { NewsSnippet } from 'finsignal-feed-explore';

<NewsSnippet
  news={newsItem}
  onShareClick={() => {}}
  onBookmarkClick={() => {}}
  showShareIcon={true}
  showBookmarkIcon={true}
/>

FiltersOverlay

Filter overlay component for market events selection.

import { FiltersOverlay } from 'finsignal-feed-explore';

<FiltersOverlay
  isOpen={isOpen}
  selectedFilters={filters}
  onClose={() => setIsOpen(false)}
  onApply={(filters) => handleFiltersApply(filters)}
/>

FilterButton

Self-contained filter button with three visual states that works seamlessly with FeedList.

import { FeedList, FilterButton } from 'finsignal-feed-explore';
import { useState } from 'react';

function NewsSidebar() {
  const [isFiltersOpen, setIsFiltersOpen] = useState(false);
  const [filterCount, setFilterCount] = useState(0);

  return (
    <div>
      {/* Header with FilterButton */}
      <header>
        <FilterButton
          isFiltersOpen={isFiltersOpen}
          filterCount={filterCount}
          onClick={() => setIsFiltersOpen(!isFiltersOpen)}
        />
        <h2>Explore</h2>
      </header>

      {/* FeedList synced with FilterButton */}
      <FeedList
        isFiltersOpen={isFiltersOpen}
        onFiltersOpenChange={setIsFiltersOpen}
        onFiltersChange={(data) => setFilterCount(data.count)}
        onNewsClick={(news) => console.log('Clicked:', news)}
      />
    </div>
  );
}

Visual States:

  1. Normal - Filter icon (no active filters)
  2. With Badge - Filter icon + count badge (has active filters)
  3. Close - X icon (filters overlay is open)

Props:

| Prop | Type | Required | Description | |------|------|----------|-------------| | isFiltersOpen | boolean | Yes | Whether filters overlay is open | | filterCount | number | Yes | Number of active filters to show in badge | | onClick | () => void | Yes | Click handler | | className | string | No | Additional CSS class | | closeIconColor | string | No | Color for close icon (default: #7863F6) | | filterIconColor | string | No | Color for filter icon (default: #242429) | | badgeBackgroundColor | string | No | Badge background color (default: #2d3339) | | badgeTextColor | string | No | Badge text color (default: #ffffff) |

Features

  • ✅ Beautiful news snippets based on modern design system
  • ✅ Filter news by market events (earnings, IPO, M&A, etc.)
  • ✅ Configurable action buttons (share, bookmark, like, dislike, AI)
  • ✅ Callbacks for all user interactions
  • ✅ API integration with /api/v1/content/search endpoint
  • Mock data fallback - Shows 3 example news items when API is unavailable
  • ✅ Infinite scroll support
  • ✅ Light theme (web optimized)
  • ✅ Responsive design
  • ✅ TypeScript support
  • ✅ React Native Web compatible

API Reference

FeedList Props

| Prop | Type | Required | Description | |------|------|----------|-------------| | apiUrl | string | No | Base API URL for fetching news (default: https://explore-gateway.changesandbox.ru/) | | onNewsClick | (news: NewsItem) => void | No | Called when news item is clicked | | onShareClick | (news: NewsItem) => void | No | Called when share button is clicked | | onBookmarkClick | (news: NewsItem) => void | No | Called when bookmark button is clicked | | onLikeClick | (news: NewsItem) => void | No | Called when like button is clicked | | onDislikeClick | (news: NewsItem) => void | No | Called when dislike button is clicked | | onAIClick | (news: NewsItem) => void | No | Called when AI button is clicked | | onFiltersOpen | () => void | No | Called when filters overlay opens | | onFiltersClose | () => void | No | Called when filters overlay closes | | onFiltersApply | (filters: string[]) => void | No | Called when filters are applied | | onShowFilter | () => void | No | Called when filter button is clicked (before opening internal overlay) | | showShareIcon | boolean | No | Show/hide share button (default: true) | | showBookmarkIcon | boolean | No | Show/hide bookmark button (default: true) | | showLikeIcon | boolean | No | Show/hide like button (default: false) | | showDislikeIcon | boolean | No | Show/hide dislike button (default: false) | | showAIIcon | boolean | No | Show/hide AI button (default: true) | | showFilterIcon | boolean | No | Show/hide filter button (default: true) | | initialFilters | string[] | No | Initial market events filters | | enableInfiniteScroll | boolean | No | Enable/disable infinite scroll (default: true) | | marketEventsTaxonomy | MarketEventTaxonomyItem[] | No | Custom market events taxonomy | | enableDragDrop | boolean | No | Enable drag'n'drop for news items (default: false). Data is automatically set in dataTransfer with key 'application/news-data' | | onDragStart | (news: NewsItem, e: DragEvent) => void | No | Called when drag starts on a news item (after data is set in dataTransfer) | | onDragEnd | (news: NewsItem, e: DragEvent) => void | No | Called when drag ends on a news item | | feedType | 'trending' \| 'personal' \| 'hot' | No | Deprecated (v1.7.0 compat) - Feed type parameter (ignored in current version) | | useMockData | boolean | No | Deprecated (v1.7.0 compat) - Use mock data flag (ignored in current version) |

Types

NewsItem

interface NewsItem {
  id: string;
  title: string;
  content: string;
  source?: string;
  sourceUrl?: string;
  sources?: Array<{
    name: string;
    url?: string;
    logo?: string;
  }>;
  timestamp?: string;
  cover?: string;
  recommendation?: {
    text: string;
    priceRange?: string;
  };
  stocks?: Array<{
    symbol: string;
    price: string;
    change: string;
    changeType: 'positive' | 'negative';
    logo?: string;
  }>;
  summary?: string;
  tags?: string[];
  personalizedKeyPoints?: string[];
  market_events?: string[];
}

Hooks

useFeedData

Hook for fetching and managing feed data.

import { useFeedData } from 'finsignal-feed-explore';

const { items, isLoading, hasMore, loadMore, refresh } = useFeedData({
  filters: ['earnings'],
  limit: 20
});

useFilters

Hook for managing filter state.

import { useFilters } from 'finsignal-feed-explore';

const {
  selectedMarketEvents,
  isOpen,
  toggleFilter,
  clearFilters,
  setFilters,
  openFilters,
  closeFilters
} = useFilters(['earnings']);

Constants

MARKET_EVENT_TAXONOMY

Default market events taxonomy with categories like earnings, IPO, M&A, etc.

Russian localization is enabled by default - all filter labels and categories are automatically displayed in Russian.

import { MARKET_EVENT_TAXONOMY, MarketEventTaxonomyItem } from 'finsignal-feed-explore';

// Each item includes:
// - key: unique identifier (used for API communication)
// - name: English name
// - nameRu: Russian name (displayed in UI by default)
// - category: English category
// - categoryRu: Russian category (displayed in UI by default)

// No need to pass marketEventsTaxonomy prop - it's used internally by default
<FeedList />

// Or customize if needed:
<FeedList marketEventsTaxonomy={customTaxonomy} />

MarketEventTaxonomyItem Structure:

interface MarketEventTaxonomyItem {
  key: string;           // e.g., 'earnings_quarterly_results'
  name: string;          // e.g., 'Quarterly earnings report'
  nameRu: string;        // e.g., 'Квартальные результаты'
  category: string;      // e.g., 'Earnings'
  categoryRu: string;    // e.g., 'Финансовые результаты'
}

Categories included:

  • Mergers & Acquisitions (Слияния и поглощения)
  • Earnings (Финансовые результаты)
  • Dividends & Capital Returns (Дивиденды и выплаты)
  • Corporate Actions & Structure (Корпоративные действия)
  • Management & Leadership Changes (Изменения в руководстве)

MOCK_NEWS

Mock news data for development and fallback scenarios.

import { MOCK_NEWS } from 'finsignal-feed-explore';

// Array of 3 example news items
console.log(MOCK_NEWS);

DEFAULT_API_URL

Default API URL used when apiUrl is not provided.

import { DEFAULT_API_URL } from 'finsignal-feed-explore';

console.log(DEFAULT_API_URL); // 'https://explore-gateway.changesandbox.ru/'

Utilities

formatTimestamp

Utility function for formatting timestamps.

import { formatTimestamp } from 'finsignal-feed-explore';

const formatted = formatTimestamp('2024-01-15T10:30:00Z');

theme

Theme configuration object.

import { theme } from 'finsignal-feed-explore';

// Access theme colors, spacing, etc.
console.log(theme.colors);

API Integration

The component expects the API to follow this structure:

Default API URL: https://explore-gateway.changesandbox.ru/

Endpoint: POST {apiUrl}/api/v1/content/search

Request:

{
  "limit": 20,
  "offset": 0,
  "market_events": ["earnings", "ipo"]
}

Response:

{
  "items": [...],
  "next_offset": 20,
  "total": 100,
  "offset": 0,
  "limit": 20
}

Drag & Drop Integration

Enable drag'n'drop to allow users to drag news items onto other components (e.g., a board or canvas).

How it works

  1. Enable drag'n'drop in FeedList:
<FeedList
  enableDragDrop={true}
  onDragStart={(news, e) => {
    console.log('Started dragging:', news.title);
  }}
/>
  1. Handle drop in your target component:
const handleDrop = (event: React.DragEvent) => {
  event.preventDefault();
  
  // Get news data from dataTransfer
  const newsDataStr = event.dataTransfer.getData('application/news-data');
  
  if (newsDataStr) {
    const newsData = JSON.parse(newsDataStr);
    // newsData contains: { id, title, content, recommendation, stocks }
    
    // Create a card or handle the news as needed
    createNewsCard(newsData);
  }
};

<div
  onDrop={handleDrop}
  onDragOver={(e) => e.preventDefault()}
>
  {/* Your drop target */}
</div>

Data Format

When dragging, the following data is automatically set in dataTransfer with key 'application/news-data':

{
  id: string;
  title: string;
  content: string;
  recommendation?: {
    text: string;
    priceRange?: string;
  };
  stocks?: Array<{
    symbol: string;
    price: string;
    change: string;
    changeType: 'positive' | 'negative';
  }>;
}

Mock Data

The widget automatically displays 3 example news items when:

  • API is unavailable or returns an error
  • No real news data is loaded yet

This ensures users always see content, even during development or API downtime.

Development

Building the package

# Install dependencies
npm install

# Build the package
npm run build

The build process:

  1. Compiles TypeScript files to JavaScript
  2. Generates type definitions (.d.ts files)
  3. Copies all CSS files to dist directory

Testing locally

Before publishing, test the package locally:

# In the package directory
npm link

# In your test project (e.g., trading-diary-master/frontend)
npm link finsignal-feed-explore

Publishing

# Update version in package.json (e.g., 2.4.0 -> 2.4.1)
# Update CHANGELOG.md with new changes

# Build and publish (build runs automatically before publish)
npm publish

Note: The prepublishOnly script automatically runs npm run build before publishing.

Peer Dependencies

  • react: >=18.0.0

Dependencies

  • lucide-react: ^0.544.0 (for icons)
  • react-native-web: ^0.20.0 (for cross-platform compatibility)

License

MIT

Repository

GitHub Repository