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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@virtueer/emblor

v1.1.1

Published

A full featured, unstyled tag input component for React

Downloads

43

Readme

https://github.com/JaleelB/shadcn-tag-input/assets/78449846/7f678789-ef5e-4913-b26c-9317003d6dbc

Emblor is a fully-featured tag input component designed for seamless integration into any project — styled your way or ready to adopt the sleek aesthetics of Shadcn's design system

Features

  • Customizable: Emblor is unstyled by default, allowing you to easily style it to fit your design system.
  • Accessible: Emblor is built with accessibility in mind, ensuring that it is usable by everyone.
  • Easy to use: Emblor provides a simple and easy to use API that allows you to quickly integrate a tag input component into your project.

Installation

To install Emblor, run the command:

pnpm add emblor

Usage

Here's a sample implementation that initializes the component with a list of initial tags and suggestions list. Apart from this, there are multiple events, handlers for which need to be set.

The example below uses tailwindcss @shadcn/ui tailwind-merge clsx:

import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form';
import { Tag, TagInput } from '@/components/tag-input';
import Link from 'next/link';
import { Button, buttonVariants } from '@/components/ui/button';
import { z } from 'zod';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import React from 'react';
import { toast } from '@/components/ui/use-toast';

const FormSchema = z.object({
  topics: z.array(
    z.object({
      id: z.string(),
      text: z.string(),
    }),
  ),
});

export default function Hero() {
  const form = useForm<z.infer<typeof FormSchema>>({
    resolver: zodResolver(FormSchema),
  });

  const [tags, setTags] = React.useState<Tag[]>([]);

  const { setValue } = form;

  function onSubmit(data: z.infer<typeof FormSchema>) {
    toast({
      title: 'You submitted the following values:',
      description: (
        <pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
          <code className="text-white">{JSON.stringify(data, null, 2)}</code>
        </pre>
      ),
    });
  }

  return (
    <section className="z-10 max-w-5xl w-full flex flex-col items-center text-center gap-5">
      <div className="z-10 w-full flex flex-col items-center text-center gap-5">
        <h1 className="scroll-m-20 text-4xl font-bold tracking-tight">Shadcn Tag Input</h1>
        <p className="text-muted-foreground max-w-[450px]">
          An implementation of a Tag Input component built on top of Shadcn UI&apos;s input component.
        </p>
        <div className="flex gap-2 mt-1">
          <Link href="#try" className={`${buttonVariants({ variant: 'default', size: 'lg' })} min-w-[150px] shadow-sm`}>
            Try it out
          </Link>
          <Link
            href="https://github.com/JaleelB/shadcn-tag-input"
            className={`${buttonVariants({ variant: 'secondary', size: 'lg' })} shadow-sm`}
          >
            Github
          </Link>
        </div>
      </div>

      <div id="try" className="w-full py-8">
        <div className="w-full relative my-4 flex flex-col space-y-2">
          <div className="preview flex min-h-[350px] w-full justify-center p-10 items-center mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 relative rounded-md border">
            <Form {...form}>
              <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8 flex flex-col items-start">
                <FormField
                  control={form.control}
                  name="topics"
                  render={({ field }) => (
                    <FormItem className="flex flex-col items-start">
                      <FormLabel className="text-left">Topics</FormLabel>
                      <FormControl>
                        <TagInput
                          {...field}
                          placeholder="Enter a topic"
                          tags={tags}
                          // using Shadcn input styling
                          className="sm:min-w-[450px] flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
                          setTags={(newTags) => {
                            setTags(newTags);
                            setValue('topics', newTags as [Tag, ...Tag[]]);
                          }}
                        />
                      </FormControl>
                      <FormDescription>These are the topics that you&apos;re interested in.</FormDescription>
                      <FormMessage />
                    </FormItem>
                  )}
                />
                <Button type="submit">Submit</Button>
              </form>
            </Form>
          </div>
        </div>
      </div>
    </section>
  );
}

To create a detailed API Reference section in your README for the Emblor tag input component, you can structure it similarly to the OTPInput example you provided. Here's a structured API reference that incorporates the properties and options of the Emblor tag input:


API Reference

TagInput

The primary component for user interaction. Configure the tag input behavior and appearance using these props, and manage tag data dynamically.

Props

type TagInputProps = {
  // Placeholder text for the input.
  placeholder?: string; // default: ""

  // Array of tags displayed as pre-selected.
  tags: Array<{ id: string; text: string }>; // default: []

  // Function to set the state of tags.
  setTags: React.Dispatch<React.SetStateAction<{ id: string; text: string }[]>>;

  // Enable or disable the autocomplete feature.
  enableAutocomplete?: boolean; // default: false

  // List of autocomplete options.
  autocompleteOptions?: Array<{ id: string; text: string }>; // default: []

  // Maximum number of tags allowed.
  maxTags?: number; // default: null

  // Minimum number of tags required.
  minTags?: number; // default: null

  // Make the input read-only.
  readOnly?: boolean; // default: false

  // Disable the input.
  disabled?: boolean; // default: false

  // Callback function when a tag is added.
  onTagAdd?: (tag: string) => void; // default: null

  // Callback function when a tag is removed.
  onTagRemove?: (tag: string) => void; // default: null

  // Allow duplicate tags.
  allowDuplicates?: boolean; // default: false

  // Maximum length of a tag.
  maxLength?: number; // default: null

  // Minimum length of a tag.
  minLength?: number; // default: null

  // Function to validate a tag.
  validateTag?: (tag: string) => boolean; // default: null

  // Character used to separate tags.
  delimiter?: Delimiter; // default: null

  // Show the count of tags.
  showCount?: boolean; // default: false

  // Placeholder text when tag limit is reached.
  placeholderWhenFull?: string; // default: ""

  // Sort tags alphabetically.
  sortTags?: boolean; // default: false

  // List of characters that can be used as delimiters.
  delimiterList?: string[]; // default: []

  // Truncate tag text to a certain length.
  truncate?: number; // default: null

  // Function to filter autocomplete options.
  autocompleteFilter?: (option: string) => boolean; // default: null

  // Layout direction of the tag inputs.
  direction?: 'row' | 'column'; // default: 'row'

  // A callback function that is called whenever the input value changes.
  onInputChange?: (value: string) => void; // default: null

  // A callback function that is used to render custom tag elements.
  customTagRenderer?: (tag: { id: string; text: string }) => React.ReactElement; // default: null

  // Function to be called when the input field gains focus.
  onFocus?: React.FocusEventHandler<HTMLInputElement>; // default: null

  // Function to be called when the input field loses focus.
  onBlur?: React.FocusEventHandler<HTMLInputElement>; // default: null

  // Only allow tags that are present in the autocomplete options.
  restrictTagsToAutocompleteOptions?: boolean; // default: false

  // A callback function to be called when a tag is clicked.
  onTagClick?: (tag: { id: string; text: string }) => void; // default: null

  // Enable drag and drop functionality.
  draggable?: boolean; // default: false

  // Position of the input field in relation to the tags.
  inputFieldPosition?: 'bottom' | 'top' | 'inline'; // default: 'bottom'

  // Show a button to clear all tags.
  clearAll?: boolean; // default: false

  // A callback function to be called when the clear all button is clicked.
  onClearAll?: () => void; // default: null

  // Additional props to be passed to the input field.
  inputProps?: React.InputHTMLAttributes<HTMLInputElement>; // default: {}

  // Use a popover to display tags instead of inline.
  usePopoverForTags?: boolean; // default: false
};

Delimiter

Define the delimiters that can be used to separate tags within the input.

enum Delimiter {
  Comma = ',',
  Enter = 'Enter',
}

Documentation

You can find out more about the API and implementation in the Documentation.