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

@youngsonf2/halo-widgets

v1.0.0

Published

Feature-rich, framework-agnostic widgets library with 12+ input components. Works with React, Vue, Angular, and Svelte.

Downloads

6

Readme

Halo Widgets

A feature-rich, framework-agnostic widgets library built with vanilla HTML, CSS, and TypeScript. Fully compatible with React, Vue, Angular, and Svelte.

Installation

npm install @halo-widgets/core

Framework Support

React

import { TextInput, PasswordInput, SliderInput } from "@halo-widgets/react";

<TextInput placeholder="Enter text" maxLength={100} />

Vue

<script setup>
import { TextInput } from "@halo-widgets/vue";
</script>

<template>
  <TextInput placeholder="Enter text" :maxLength="100" />
</template>

Angular

import { TextInputComponent } from "@halo-widgets/angular";

@Component({
  imports: [TextInputComponent],
  template: '<halo-text-input [config]="{ placeholder: 'Enter text' }" />'
})

Svelte

<script>
  import { TextInput } from "@halo-widgets/svelte";
</script>

<TextInput placeholder="Enter text" maxLength={100} />

Widgets

1. Text Input

A powerful text input with validation, suggestions, character counter, and more.

import { TextInput } from "@halo-widgets/react";

<TextInput
  // Basic props
  id="username"
  name="username"
  label="Username"
  placeholder="Enter your username"
  helperText="Choose a unique username"
  
  // Value
  value="john_doe"
  defaultValue=""
  
  // Validation
  required={true}
  minLength={3}
  maxLength={20}
  pattern="^[a-zA-Z0-9_]+$"
  
  // Character handling
  allowSpaces={false}  // Set to true for full names/addresses
  lowercase={true}     // Auto convert to lowercase
  uppercase={false}    // Auto convert to uppercase
  trim={true}          // Remove leading/trailing spaces
  
  // UI Features
  showCounter={true}         // Show character count
  clearable={true}           // Show clear button
  showSuggestions={true}     // Enable suggestions dropdown
  suggestionsApi="https://api.datamuse.com/sug?s="  // API for suggestions
  debounceMs={300}           // Debounce delay for API calls
  
  // State
  disabled={false}
  readOnly={false}
  
  // Callbacks
  onChange={(value) => console.log(value)}
  onValidate={(isValid, error) => console.log(isValid, error)}
  
  // Styling
  className="custom-class"
/>

Props:

  • id, name, label, placeholder, helperText - Standard form field props
  • value, defaultValue - Controlled/uncontrolled value
  • required, minLength, maxLength, pattern - Validation rules
  • allowSpaces - Allow spaces in input (default: true)
  • lowercase, uppercase, trim - Text transformation
  • showCounter - Display character counter
  • clearable - Show clear button
  • showSuggestions - Enable suggestions dropdown
  • suggestionsApi - API endpoint for suggestions (query appended to URL)
  • debounceMs - Debounce delay for onChange and API calls (default: 300)
  • disabled, readOnly - Input state
  • onChange(value) - Fired on value change
  • onValidate(isValid, error?) - Fired on validation

2. Password Input

Password input with strength meter, requirements checker, generator, visibility toggle, and breach detection.

import { PasswordInput } from "@halo-widgets/react";

<PasswordInput
  // Basic props
  label="Password"
  placeholder="Enter a strong password"
  helperText="Must be at least 10 characters"
  
  // Visibility toggle
  showVisibilityToggle={true}  // Eye icon to show/hide password
  
  // Strength meter
  showStrength={true}          // Show password strength bar
  strengthConfig={{
    minLength: 10,
    requireLowercase: true,
    requireUppercase: true,
    requireNumber: true,
    requireSymbol: true,
  }}
  
  // Requirements checklist
  showRequirements={true}      // Show requirements list
  
  // Password generator
  showGenerator={true}         // Show "Generate" button
  generatorConfig={{
    length: 16,
    lowercase: true,
    uppercase: true,
    numbers: true,
    symbols: true,
  }}
  
  // Copy to clipboard
  showCopyButton={true}        // Show copy button
  
  // Breach detection (HaveIBeenPwned API)
  checkPwned={true}            // Check if password is compromised
  pwnedDebounceMs={1000}       // Delay before checking
  
  // Validation
  required={true}
  minLength={10}
  maxLength={128}
  
  // Callbacks
  onChange={(value) => console.log(value)}
  onStrengthChange={(score, feedback) => console.log(score, feedback)}
  onValidate={(isValid, error) => console.log(isValid, error)}
/>

Props:

  • showVisibilityToggle - Show eye icon to toggle visibility
  • showStrength - Display strength meter (Weak/Fair/Good/Strong)
  • strengthConfig - Customize strength requirements
  • showRequirements - Display requirements checklist
  • showGenerator - Show password generator button
  • generatorConfig - Customize generated password format
  • showCopyButton - Show copy to clipboard button
  • checkPwned - Check against HaveIBeenPwned API
  • pwnedDebounceMs - Debounce delay for breach check
  • onStrengthChange(score, feedback) - Fired when strength changes

3. Email Input

Email input with validation, multiple emails (chips), domain suggestions, and Gravatar integration.

import { EmailInput } from "@halo-widgets/react";

<EmailInput
  // Basic props
  label="Email Address"
  placeholder="Enter your email"
  
  // Multiple emails
  multiple={false}             // Allow multiple emails as chips
  maxEmails={5}                // Max number of emails (if multiple)
  
  // Validation
  required={true}
  validateFormat={true}        // Basic regex validation
  validateDomain={true}        // Check for valid TLD
  allowedDomains={["gmail.com", "company.com"]}  // Whitelist domains
  blockedDomains={["tempmail.com"]}              // Blacklist domains
  
  // Plus addressing
  allowPlusAddressing={true}   // Allow [email protected]
  normalizePlusAddressing={false}  // Strip +tag when normalizing
  
  // Domain suggestions
  showDomainSuggestions={true} // Suggest common domains
  commonDomains={["gmail.com", "yahoo.com", "outlook.com"]}
  
  // Gravatar
  showGravatar={true}          // Show user avatar from Gravatar
  gravatarSize={40}            // Avatar size in pixels
  
  // UI
  lowercase={true}             // Auto convert to lowercase
  trim={true}                  // Auto trim spaces
  
  // Callbacks
  onChange={(value) => console.log(value)}  // string or string[]
  onValidate={(isValid, error) => console.log(isValid, error)}
/>

Props:

  • multiple - Enable multiple email input with chips
  • maxEmails - Maximum number of emails (for multiple mode)
  • validateFormat - Email regex validation
  • validateDomain - Check for valid domain and TLD
  • allowedDomains - Only allow specific domains
  • blockedDomains - Block specific domains
  • allowPlusAddressing - Allow plus addressing ([email protected])
  • normalizePlusAddressing - Strip +tag portion
  • showDomainSuggestions - Show common domain suggestions
  • commonDomains - List of domains to suggest
  • showGravatar - Display user avatar from Gravatar
  • gravatarSize - Avatar image size

4. Phone Input

International phone input with country selection, formatting, and validation.

import { PhoneInput } from "@halo-widgets/react";

<PhoneInput
  // Basic props
  label="Phone Number"
  placeholder="Enter phone number"
  
  // Country selection
  allowCountrySelect={true}    // Show country dropdown
  defaultCountry="US"          // Default country code (ISO 3166-1 alpha-2)
  preferredCountries={["US", "GB", "CA"]}  // Show these first
  onlyCountries={["US", "CA", "MX"]}       // Restrict to these
  
  // Dial code
  separateDialCode={true}      // Show dial code separately (+1)
  
  // Formatting
  format="national"            // "national" | "international" | "e164"
  autoFormat={true}            // Auto-format as user types
  
  // Validation
  required={true}
  validateOnChange={true}      // Validate while typing
  strictValidation={false}     // Strict digit count validation
  minDigits={10}
  maxDigits={15}
  
  // Callbacks
  onChange={(value, country, formatted) => console.log(value, country, formatted)}
  onCountryChange={(country) => console.log(country)}
  onValidate={(isValid, error) => console.log(isValid, error)}
/>

Props:

  • allowCountrySelect - Show country picker dropdown
  • defaultCountry - Initial country (ISO 3166-1 alpha-2 code)
  • preferredCountries - Countries shown at top of dropdown
  • onlyCountries - Restrict to specific countries
  • separateDialCode - Display dial code separately (e.g., +1)
  • format - Output format: "national", "international", or "e164"
  • autoFormat - Auto-format number as user types
  • validateOnChange - Validate in real-time
  • strictValidation - Enforce exact digit count per country
  • minDigits, maxDigits - Digit count validation
  • onCountryChange(country) - Fired when country changes

5. Location Input

Location input with Google Places Autocomplete, coordinate parsing, and custom dropdown.

import { LocationInput } from "@halo-widgets/react";

<LocationInput
  // Google Maps API
  apiKey="YOUR_GOOGLE_MAPS_API_KEY"  // Required
  
  // Basic props
  label="Location"
  placeholder="Search for a location"
  
  // Search configuration
  countryCodes={[]}            // Restrict to countries (ISO 3166-1 alpha-2)
  types={["geocode"]}          // Place types: geocode, address, establishment, etc.
  
  // Features
  allowCoordinates={true}      // Allow direct coordinate input (lat,lng)
  showCurrentLocation={false}  // Show "Use current location" button
  
  // UI
  debounceMs={300}             // Debounce search requests
  
  // Callbacks
  onChange={(value) => console.log(value)}
  onPlaceSelect={(place) => console.log(place)}  // Full place details
  onValidate={(isValid, error) => console.log(isValid, error)}
/>

Props:

  • apiKey - Google Maps API key (required)
  • countryCodes - Restrict search to specific countries (e.g., ["US", "GB"])
  • types - Place types to search (geocode, address, establishment, etc.)
  • allowCoordinates - Allow direct coordinate input (e.g., "40.7128, -74.0060")
  • showCurrentLocation - Show button to get user's current location
  • debounceMs - Delay before sending search requests
  • onPlaceSelect(place) - Returns full place details (address components, geometry, etc.)

6. Date Input

Date picker with single date, range, and month-only modes.

import { DateInput } from "@halo-widgets/react";

<DateInput
  // Basic props
  label="Select Date"
  placeholder="Pick a date"
  
  // Mode
  mode="single"                // "single" | "range" | "month"
  
  // Date constraints
  min="2020-01-01"             // Minimum selectable date
  max="2030-12-31"             // Maximum selectable date
  
  // Value (format: YYYY-MM-DD)
  value="2024-03-15"           // For single mode
  value={["2024-03-01", "2024-03-31"]}  // For range mode
  
  // Formatting
  format="MM/DD/YYYY"          // Display format for single/range
  monthFormat="MMM YYYY"       // Display format for month mode (e.g., "Mar 2024")
  
  // Calendar configuration
  weekStartsOn={0}             // 0=Sunday, 1=Monday
  showShortcuts={true}         // Show Today/Clear buttons
  
  // Callbacks
  onChange={(value) => console.log(value)}  // string or [string, string]
  onValidate={(isValid, error) => console.log(isValid, error)}
/>

Props:

  • mode - Selection mode: "single", "range", or "month"
  • min, max - Date range constraints (YYYY-MM-DD format)
  • value - Current value (string for single/month, tuple for range)
  • format - Display format (e.g., "MM/DD/YYYY", "DD-MM-YYYY")
  • monthFormat - Format for month-only mode (e.g., "MMM YYYY")
  • weekStartsOn - First day of week (0=Sunday, 1=Monday)
  • showShortcuts - Show Today/Clear action buttons

7. Number Input

Number input with formatting, validation, steppers, and special formats (currency, percentage).

import { NumberInput } from "@halo-widgets/react";

<NumberInput
  // Basic props
  label="Amount"
  placeholder="0"
  
  // Value
  value={42}
  defaultValue={0}
  
  // Range
  min={0}
  max={1000}
  step={1}                     // Increment/decrement step
  
  // Precision
  precision={2}                // Decimal places (e.g., 2 for currency)
  
  // Formatting
  thousandSeparator={true}     // Show thousands separator (1,000)
  locale="en-US"               // Number formatting locale
  prefix="$"                   // Prefix (e.g., "$" for currency)
  suffix="%"                   // Suffix (e.g., "%" for percentage)
  
  // Validation
  required={true}
  allowNegative={true}         // Allow negative numbers
  
  // UI Features
  showSteppers={false}         // Show +/- buttons
  
  // Callbacks
  onChange={(value) => console.log(value)}
  onValidate={(isValid, error) => console.log(isValid, error)}
/>

Props:

  • value, defaultValue - Number value
  • min, max - Range constraints
  • step - Increment/decrement amount
  • precision - Decimal places (0 for integers)
  • thousandSeparator - Show comma separators (e.g., 1,000)
  • locale - Locale for number formatting
  • prefix, suffix - Add symbols (e.g., "$", "%", "kg")
  • allowNegative - Allow negative numbers
  • showSteppers - Display increment/decrement buttons

Common use cases:

// Currency
<NumberInput prefix="$" precision={2} min={0} />

// Percentage
<NumberInput suffix="%" min={0} max={100} />

// Age
<NumberInput min={0} max={120} precision={0} />

8. Textarea Input

Multi-line text input with auto-grow, character counter, and suggestions.

import { TextareaInput } from "@halo-widgets/react";

<TextareaInput
  // Basic props
  label="Description"
  placeholder="Enter description"
  helperText="Describe your project"
  
  // Size
  rows={4}                     // Initial visible rows
  autoGrow={true}              // Expand as user types
  maxHeight={300}              // Max height in pixels (if autoGrow)
  
  // Length constraints
  minLength={10}
  maxLength={500}
  showCounter={true}           // Show character counter
  
  // UI Features
  clearable={true}             // Show clear button
  
  // Behavior
  debounceMs={300}             // Debounce onChange calls
  onEnter="newline"            // "newline" | "submit"
  
  // Validation
  required={true}
  
  // Callbacks
  onChange={(value) => console.log(value)}
  onValidate={(isValid, error) => console.log(isValid, error)}
/>

Props:

  • rows - Initial number of visible rows
  • autoGrow - Automatically expand height as content grows
  • maxHeight - Maximum height in pixels (when autoGrow enabled)
  • minLength, maxLength - Character length validation
  • showCounter - Display character counter
  • clearable - Show clear button
  • debounceMs - Delay before firing onChange
  • onEnter - Behavior when Enter is pressed: "newline" or "submit"

9. Dropdown Input

Searchable dropdown with local/API options, single/multi-select, and chips.

import { DropdownInput } from "@halo-widgets/react";

<DropdownInput
  // Basic props
  label="Select Country"
  placeholder="Choose..."
  
  // Options (local)
  options={[
    { label: "United States", value: "us" },
    { label: "Canada", value: "ca" },
    { label: "Mexico", value: "mx" },
  ]}
  
  // Options (API)
  optionsApi="https://api.example.com/search?q="
  optionsMap={{                // Map API response to { label, value }
    label: "name",
    value: "id",
  }}
  
  // Search
  searchable={true}            // Enable search
  minCharsForSearch={1}        // Min characters before searching API
  debounceMs={300}             // Debounce API requests
  
  // Selection
  multiple={false}             // Allow multiple selection
  maxSelected={3}              // Max items (if multiple)
  
  // Value
  value="us"                   // For single select
  value={["us", "ca"]}         // For multi-select
  
  // Validation
  required={true}
  
  // Callbacks
  onChange={(value) => console.log(value)}  // string or string[]
  onValidate={(isValid, error) => console.log(isValid, error)}
/>

Props:

  • options - Local options array: { label: string, value: string }[]
  • optionsApi - API endpoint for dynamic options (query appended to URL)
  • optionsMap - Map API response fields to label/value
  • searchable - Enable search/filter functionality
  • minCharsForSearch - Minimum characters before triggering API search
  • debounceMs - Delay before API requests
  • multiple - Allow multiple selection with chips
  • maxSelected - Maximum number of selections (multi-select only)
  • value - Current value (string for single, array for multi)

API Response Format:

{
  "results": [
    { "name": "Option 1", "id": "opt1" },
    { "name": "Option 2", "id": "opt2" }
  ]
}

With optionsMap: { label: "name", value: "id" }, the dropdown will display "Option 1" and use "opt1" as the value.


10. Checkbox Input

Checkbox group with select-all, single/multi-select, and validation.

import { CheckboxInput } from "@halo-widgets/react";

<CheckboxInput
  // Basic props
  label="Select your interests"
  helperText="Choose at least one"
  
  // Options
  options={[
    { label: "AI", value: "ai" },
    { label: "Web Development", value: "web" },
    { label: "Mobile Apps", value: "mobile" },
    { label: "Data Science", value: "data", disabled: true },
  ]}
  
  // Mode
  single={false}               // Single-select mode (like radio)
  
  // Value
  value={["ai", "web"]}        // For multi-select
  defaultValue={["ai"]}        // Default value
  
  singleValue="web"            // For single mode
  
  // Validation
  required={true}
  minSelected={1}              // Min selections (multi-select)
  maxSelected={3}              // Max selections (multi-select)
  
  // UI Features
  selectAll={true}             // Show "Select all" option
  
  // Styling
  boxBackground="#fff"         // Checkbox background color
  checkColor="#6366f1"         // Checkmark color
  
  // State
  disabled={false}
  readOnly={false}
  
  // Callbacks
  onChange={(values) => console.log(values)}          // For multi-select
  onChangeSingle={(value) => console.log(value)}      // For single mode
  onValidate={(isValid, error) => console.log(isValid, error)}
/>

Props:

  • options - Array of options: { label: string, value: string, disabled?: boolean }[]
  • single - Single-select mode (behaves like radio but styled as checkbox)
  • value, defaultValue - Selected values (array for multi, string for single)
  • singleValue - Current value in single mode
  • required - At least one must be selected
  • minSelected, maxSelected - Selection count validation (multi-select)
  • selectAll - Show "Select all" checkbox at top
  • boxBackground - Checkbox box background color
  • checkColor - Checkmark/tick color
  • disabled, readOnly - Disable interaction
  • onChangeSingle(value) - Callback for single mode

11. Radio Input

Radio button group with validation and custom styling.

import { RadioInput } from "@halo-widgets/react";

<RadioInput
  // Basic props
  label="Choose a plan"
  helperText="Select your subscription tier"
  
  // Options
  options={[
    { label: "Basic", value: "basic" },
    { label: "Pro", value: "pro" },
    { label: "Enterprise", value: "ent", disabled: true },
  ]}
  
  // Value
  value="pro"
  defaultValue="basic"
  
  // Validation
  required={true}
  
  // Styling
  boxBackground="#fff"         // Circle background color
  dotColor="#10b981"           // Selected dot color
  
  // State
  disabled={false}
  readOnly={false}
  
  // Callbacks
  onChange={(value) => console.log(value)}
  onValidate={(isValid, error) => console.log(isValid, error)}
/>

Props:

  • options - Array of options: { label: string, value: string, disabled?: boolean }[]
  • value, defaultValue - Selected value (string)
  • required - Must select one option
  • boxBackground - Radio circle background color
  • dotColor - Selected dot color
  • disabled, readOnly - Disable interaction
  • onChange(value) - Fired when selection changes (returns selected value or null)

12. Slider Input

Range slider with single or dual handles, formatting, and value bubble.

import { SliderInput } from "@halo-widgets/react";

<SliderInput
  // Basic props
  label="Volume"
  helperText="Adjust volume level"
  
  // Mode
  mode="single"                // "single" | "range"
  
  // Range
  min={0}
  max={100}
  step={1}                     // Increment step
  precision={0}                // Decimal places
  
  // Value
  value={50}                   // For single mode
  value={[20, 80]}             // For range mode
  
  // Formatting
  prefix="$"                   // Prefix for display
  suffix="%"                   // Suffix for display
  showValueBubble={true}       // Show value above slider
  
  // State
  disabled={false}
  readOnly={false}
  
  // Callbacks
  onChange={(value) => console.log(value)}  // number or [number, number]
/>

Props:

  • mode - "single" (one handle) or "range" (two handles)
  • min, max - Slider range
  • step - Increment amount per move
  • precision - Decimal places for value
  • value - Current value (number for single, tuple for range)
  • prefix, suffix - Display formatting (e.g., "$", "%", "kg")
  • showValueBubble - Display current value above slider
  • disabled, readOnly - Disable interaction
  • onChange(value) - Returns number (single) or [min, max] (range)

Common use cases:

// Volume
<SliderInput min={0} max={100} suffix="%" />

// Price range
<SliderInput mode="range" min={0} max={1000} prefix="$" />

// Temperature
<SliderInput min={-20} max={40} suffix="°C" step={0.5} precision={1} />

Styling

All widgets use CSS variables for theming. Override these in your global CSS:

:root {
  --halo-color-primary: #6366f1;
  --halo-color-border: #e5e7eb;
  --halo-color-text: #111827;
  --halo-color-error: #ef4444;
  --halo-color-success: #10b981;
}

You can also apply custom classes via the className prop on any widget.


License

MIT


Support

For issues and feature requests, visit our GitHub repository.