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

@metadiv-studio/select-remote

v0.1.7

Published

A powerful, customizable remote data select component for React applications. This component provides a searchable dropdown that fetches options from remote APIs with built-in search functionality, custom rendering, and seamless integration with your exis

Downloads

77

Readme

@metadiv-studio/select-remote

A powerful, customizable remote data select component for React applications. This component provides a searchable dropdown that fetches options from remote APIs with built-in search functionality, custom rendering, and seamless integration with your existing UI components.

🚀 Installation

npm i @metadiv-studio/select-remote

📖 Description

SelectRemote is a React component that creates a searchable dropdown select input that fetches data from remote APIs. It's designed to handle large datasets efficiently by implementing debounced search, remote data fetching, and customizable rendering options.

Key Features

  • 🔍 Debounced Search: Built-in 500ms debouncing for optimal API performance
  • 🌐 Remote Data Fetching: Fetch options from any API endpoint
  • 🎨 Customizable Rendering: Custom render functions for labels and selected items
  • Accessibility: Proper keyboard navigation and screen reader support
  • 🎯 Portal-based Dropdown: Dropdown renders in a portal to avoid layout issues
  • 🔄 Real-time Updates: Automatic refresh when dependencies change
  • 🎭 Action Buttons: Optional action buttons for additional functionality
  • 🌙 Dark Mode Support: Built-in dark mode styling with Tailwind CSS

🛠️ Usage

Basic Usage

import SelectRemote from '@metadiv-studio/select-remote';

function MyComponent() {
  const [selectedValue, setSelectedValue] = useState('');

  const fetchUsers = async (keyword: string) => {
    const response = await fetch(`/api/users?search=${keyword}`);
    return response.json();
  };

  const handleChange = (value: string, item?: User) => {
    setSelectedValue(value);
    console.log('Selected user:', item);
  };

  return (
    <SelectRemote
      value={selectedValue}
      onChange={handleChange}
      onList={fetchUsers}
      renderLabel={(user) => user.name}
      valueKey="id"
      placeholder="Select a user"
    />
  );
}

Advanced Usage with Custom Rendering

import SelectRemote from '@metadiv-studio/select-remote';

function AdvancedSelect() {
  const [selectedProduct, setSelectedProduct] = useState('');

  const fetchProducts = async (keyword: string) => {
    const response = await fetch(`/api/products?search=${keyword}`);
    return response.json();
  };

  const getProduct = async (id: string) => {
    const response = await fetch(`/api/products/${id}`);
    return response.json();
  };

  const renderProductLabel = (product: Product) => (
    <div className="flex items-center gap-2">
      <img src={product.image} alt={product.name} className="w-6 h-6 rounded" />
      <span>{product.name}</span>
      <span className="text-gray-500">${product.price}</span>
    </div>
  );

  const renderSelectedProduct = (product: Product) => (
    <div className="flex items-center gap-2">
      <img src={product.image} alt={product.name} className="w-4 h-4 rounded" />
      <span className="font-medium">{product.name}</span>
    </div>
  );

  return (
    <SelectRemote
      value={selectedProduct}
      onChange={(value, product) => setSelectedProduct(value)}
      onList={fetchProducts}
      onGet={getProduct}
      renderLabel={renderProductLabel}
      renderSelectedItem={renderSelectedProduct}
      valueKey="id"
      placeholder="Choose a product"
      className="w-80"
    />
  );
}

With Action Buttons

import SelectRemote from '@metadiv-studio/select-remote';

function SelectWithActions() {
  const [selectedCategory, setSelectedCategory] = useState('');

  const fetchCategories = async (keyword: string) => {
    const response = await fetch(`/api/categories?search=${keyword}`);
    return response.json();
  };

  const actionButtons = [
    {
      icon: 'plus',
      onClick: () => console.log('Add new category'),
      tooltip: 'Add Category'
    },
    {
      icon: 'refresh',
      onClick: () => console.log('Refresh categories'),
      tooltip: 'Refresh'
    }
  ];

  return (
    <SelectRemote
      value={selectedCategory}
      onChange={(value) => setSelectedCategory(value)}
      onList={fetchCategories}
      renderLabel={(category) => category.name}
      valueKey="id"
      placeholder="Select category"
      actionButtons={actionButtons}
    />
  );
}

🔧 API Reference

Props

| Prop | Type | Required | Description | |------|------|----------|-------------| | value | string | ✅ | Current selected value | | onChange | (value: string, item?: T) => void | ✅ | Callback when selection changes | | onList | (keyword: string) => Promise<AxiosResponse<Response<T[]>>> | ✅ | Function to fetch options list | | onGet | (id: string, item?: T) => Promise<AxiosResponse<Response<T>>> | ❌ | Function to fetch single item | | onListRef | any[] | ❌ | Dependencies array for refreshing options | | renderSelectedItem | (item: T) => React.ReactNode | ❌ | Custom render for selected item | | renderLabel | (item: T) => React.ReactNode | ✅ | Custom render for option labels | | valueKey | keyof T | ✅ | Key to use as value from item object | | placeholder | string | ❌ | Placeholder text when nothing is selected | | disabled | boolean | ❌ | Whether the select is disabled | | className | string | ❌ | Additional CSS classes | | actionButtons | ActionButtonProps[] | ❌ | Optional action buttons |

Generic Type

The component is generic and accepts a type parameter T for your data structure:

interface User {
  id: string;
  name: string;
  email: string;
}

<SelectRemote<User>
  // ... props
/>

🎨 Styling

The component uses Tailwind CSS classes and follows a consistent design system. Key styling features:

  • Responsive Design: Adapts to container width
  • Dark Mode: Automatic dark mode support
  • Hover States: Interactive hover effects
  • Focus States: Accessible focus indicators
  • Custom Classes: Extensible via className prop

Custom Styling

<SelectRemote
  // ... other props
  className="w-96 border-2 border-blue-500 rounded-lg"
/>

🔄 Data Flow

  1. Initial Load: Component fetches initial options based on current value
  2. Search Input: User types in search box (debounced by 500ms)
  3. API Call: onList function is called with search keyword
  4. Options Update: Dropdown options are updated with API response
  5. Selection: User selects an option, triggering onChange callback
  6. State Update: Component updates internal state and closes dropdown

🚨 Error Handling

The component includes built-in error handling:

  • API errors are logged to console
  • Graceful fallbacks for failed requests
  • Empty state handling with user-friendly messages

🔌 Dependencies

This package has the following peer dependencies:

  • react ^18
  • react-dom ^18

And includes these internal dependencies:

  • @metadiv-studio/action-buttons
  • @metadiv-studio/axios-configurator
  • @metadiv-studio/button
  • @metadiv-studio/input
  • @metadiv-studio/translation

📱 Browser Support

  • Modern browsers with ES6+ support
  • React 18+
  • TypeScript support included

🤝 Contributing

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

📄 License

This project is licensed under the UNLICENSED license.

🆘 Support

If you encounter any issues or have questions, please open an issue on the GitHub repository.