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

cats-ui-lib

v2.2.8

Published

A comprehensive Angular UI component library built with Angular 19, providing a rich set of reusable, customizable components for modern web applications.

Readme

cats-ui-lib

A comprehensive Angular UI component library built with Angular 19, providing a rich set of reusable, customizable components for modern web applications.

npm version Angular


📦 Installation

npm install cats-ui-lib

⚙️ Setup

1. Configure angular.json

Add the following inside the build > options section of your angular.json:

"assets": [
  {
    "glob": "**/*",
    "input": "node_modules/cats-ui-lib/assets"
  }
],
"styles": [
  "node_modules/cats-ui-lib/styles/_index.scss"
]

🧩 Components


InputComponent<cats-ui-input>

Supports types: text · number · email · password

Template:

<cats-ui-input [inputConfig]="inputConfig" [(ngModel)]="name" required> </cats-ui-input>

<!-- Disabled state -->
<cats-ui-input [disabled]="true" [inputConfig]="inputConfig" [(ngModel)]="name"> </cats-ui-input>

TypeScript:

import { InputConfig } from "cats-ui-lib";

inputConfig: InputConfig = {
  type: "text",
  placeholder: "Enter value",
};

InputConfig options:

| Property | Type | Description | | ------------- | -------- | ------------------------------------------------- | | type | string | Input type: text, email, password, number | | placeholder | string | Placeholder text |


SingleSelectComponent<cats-ui-single-select>

Template:

<cats-ui-single-select [optionList]="options" [singleSelectConfig]="singleConfig" [parentNativeElement]="'parent'" (onSelection)="onSelection($event)"> </cats-ui-single-select>

TypeScript:

import { SingleSelectConfig } from 'cats-ui-lib';

options = [
  { id: 1, name: 'Option 1', disable: false },
  { id: 2, name: 'Option 2', disable: false },
];

singleConfig: SingleSelectConfig = {
  idField: 'id',
  textField: 'name',
  disabledField: 'disable',
  placeholder: 'Select Option',
};

onSelection(dt: any) {
  console.log('Selected:', dt);
}

SingleSelectConfig options:

| Property | Type | Description | | --------------- | -------- | ------------------------------ | | idField | string | Key for option ID | | textField | string | Key for display label | | disabledField | string | Key to mark option as disabled | | placeholder | string | Placeholder text |


MultiSelectComponent<cats-ui-multi-select>

Template:

<cats-ui-multi-select [optionList]="options" [multiSelectConfig]="multiSelectConfig" (onSelection)="onSelection($event)"> </cats-ui-multi-select>

TypeScript:

import { MultiSelectConfig } from "cats-ui-lib";

multiSelectConfig: MultiSelectConfig = {
  idField: "id",
  textField: "name",
  disabledField: "disable",
  placeholder: "Select Option",
  prefixLabel: "",
  enableSearch: true,
  chipLimit: 2,
  selectAll: true,
  required: false,
};

MultiSelectConfig options:

| Property | Type | Description | | --------------- | --------- | ---------------------------------------- | | idField | string | Key for option ID | | textField | string | Key for display label | | disabledField | string | Key to mark option as disabled | | placeholder | string | Placeholder text | | prefixLabel | string | Label prefix shown before selected chips | | enableSearch | boolean | Show search input inside dropdown | | chipLimit | number | Max chips to display before +N more | | selectAll | boolean | Show "Select All" option | | required | boolean | Mark field as required |


AutoComplete SingleSelect<cats-ui-input-single-select>

Template:

<cats-ui-input-single-select [optionsList]="options" [autoSingleSelectConfig]="autoSingleSelectConfig" (onItemSelection)="onSelection($event)"> </cats-ui-input-single-select>

TypeScript:

import { AutoCompleteSingleSelectConfig } from "cats-ui-lib";

autoSingleSelectConfig: AutoCompleteSingleSelectConfig = {
  idField: "id",
  textField: "name",
  disabledField: "",
  placeholder: "Enter or select",
  required: false,
  customInput: true,
};

AutoCompleteSingleSelectConfig options:

| Property | Type | Description | | --------------- | --------- | ---------------------------------------- | | idField | string | Key for option ID | | textField | string | Key for display label | | disabledField | string | Key to mark option as disabled | | placeholder | string | Placeholder text | | required | boolean | Mark field as required | | customInput | boolean | Allow free-text input not in option list |


AutoComplete MultiSelect<cats-ui-input-multi-select>

Template:

<cats-ui-input-multi-select [optionsList]="options" [autoCompleteMultiSelectConfig]="autoMultiSelectConfig" (onItemSelection)="onSelection($event)"> </cats-ui-input-multi-select>

TypeScript:

import { AutoCompleteMultiSelectConfig } from "cats-ui-lib";

autoMultiSelectConfig: AutoCompleteMultiSelectConfig = {
  idField: "id",
  textField: "name",
  disabledField: "disable",
  placeholder: "Type to Search",
  selectAll: false,
  chipLimit: 2,
  customInput: false,
  infoText: "Select any 8 KPIs",
  selectionLimit: 5,
};

AutoCompleteMultiSelectConfig options:

| Property | Type | Description | | ---------------- | --------- | ---------------------------------------- | | idField | string | Key for option ID | | textField | string | Key for display label | | disabledField | string | Key to mark option as disabled | | placeholder | string | Placeholder text (supports HTML) | | selectAll | boolean | Show "Select All" option | | chipLimit | number | Max chips shown before +N more | | customInput | boolean | Allow free-text input | | infoText | string | Helper text shown below the input | | selectionLimit | number | Max number of items that can be selected |


SearchBoxComponent<cats-ui-search-box>

Template:

<cats-ui-search-box [searchConfig]="searchConfig" (searchParamValue)="searchParamValue($event)"> </cats-ui-search-box>

TypeScript:

import { SearchConfig } from 'cats-ui-lib';

searchConfig: SearchConfig = {
  serachValue: '',
  placeholder: 'Search Here',
};

searchParamValue(data: any) {
  console.log('searchParamValue', data);
}

AccordionComponent<cats-ui-accordion>

Template:

<cats-ui-accordion>
  <cats-ui-accordion-item title="Panel 1" [index]="0">
    <ng-template>
      <p>Content for Panel 1.</p>
    </ng-template>
  </cats-ui-accordion-item>

  <cats-ui-accordion-item title="Panel 2" [index]="1">
    <ng-template>
      <p>Content for Panel 2.</p>
    </ng-template>
  </cats-ui-accordion-item>
</cats-ui-accordion>

RadioButtonComponent<cats-ui-radio-button>

Template:

<cats-ui-radio-button [config]="radioConfig" [optionList]="options" (selectionChange)="onRadio($event)"> </cats-ui-radio-button>

TypeScript:

import { RadioButtonConfig } from 'cats-ui-lib';

radioConfig: RadioButtonConfig = {
  valueField: 'id',
  textField: 'name',
  name: 'gender',
  disabled: 'disable',
};

options = [
  { id: 1, name: 'Option 1', disable: false },
  { id: 2, name: 'Option 2', disable: false },
];

onRadio(data: any) {
  console.log('radio', data);
}

RadioButtonConfig options:

| Property | Type | Description | | ------------ | -------- | --------------------------------- | | valueField | string | Key for option value | | textField | string | Key for display label | | name | string | HTML radio group name | | disabled | string | Key to mark an option as disabled |


CheckboxComponent<cats-ui-checkbox-button>

Template:

<cats-ui-checkbox-button [checkBoxConfig]="checkBoxConfig" [optionList]="taskOptions" (onCheckBoxSelection)="checkBox($event)"> </cats-ui-checkbox-button>

TypeScript:

import { CheckBoxConfig } from 'cats-ui-lib';

checkBoxConfig: CheckBoxConfig = {
  idField: 'id',
  textField: 'name',
  name: 'check23',
  disabledField: 'disable',
};

taskOptions = [
  { id: '101', name: 'Parent Task 1', disable: true },
  { id: '102', name: 'Parent Task 2', disable: false },
];

checkBox(data: any) {
  console.log('checkbox selection', data);
}

CheckBoxConfig options:

| Property | Type | Description | | --------------- | -------- | --------------------------------- | | idField | string | Key for option ID | | textField | string | Key for display label | | name | string | HTML checkbox group name | | disabledField | string | Key to mark an option as disabled |


ToggleComponent<cats-ui-toogle-button>

Template:

<cats-ui-toogle-button [toggleConfig]="toggleConfig" (onToggled)="onToggled($event)"> </cats-ui-toogle-button>

TypeScript:

import { ToggleConfig } from 'cats-ui-lib';

toggleConfig: ToggleConfig = {
  disabled: false,
  checked: false,
};

onToggled(data: any) {
  console.log('toggled', data);
}

ToggleConfig options:

| Property | Type | Description | | ---------- | --------- | --------------------- | | disabled | boolean | Disable the toggle | | checked | boolean | Initial checked state |


TabsetComponent<cats-ui-tabset>

An advanced tabset with add/close tab support, icons, badge counts, and a home tab.

Template:

<cats-ui-tabset [tabs]="tab1" [activeTab]="activeTab" [tabConfig]="tabConfig" (tabAdded)="onTabAdded($event)" (tabClosed)="onTabClosed($event)" (activeTabChange)="activeTabChange($event)">
  <!-- Tab ID 0 is the Home tab (requires homeTab: true in tabConfig) -->
  <cats-ui-tab-content [tabId]="0">Home Content</cats-ui-tab-content>
  <cats-ui-tab-content [tabId]="1">Tab 1 Content</cats-ui-tab-content>
  <cats-ui-tab-content [tabId]="2">Tab 2 Content</cats-ui-tab-content>
</cats-ui-tabset>

TypeScript:

tabConfig = {
  addTab:   true,   // Show "+" add tab button
  closeTab: true,   // Show close button on tabs
  homeTab:  true,   // Enable a fixed home tab at ID 0
  type:     'Stroke', // Tab style variant
};

tab1 = [
  { id: 1, title: 'Tab1' },
  {
    id: 2,
    title: 'Tab2',
    leadingIcon: 'images/command.svg',
    tralingIocn: 'images/x-circle.svg',
    count: 67,
  },
];

activeTab: 1;
tab = 6; // counter for dynamic tab IDs

onTabAdded(ev: any) {
  const newTab = {
    id: ++this.tab,
    title: `Dynamic Tab ${this.tab}`,
  };
  this.tab1 = [...this.tab1, newTab];
  this.activeTab = newTab.id;
}

onTabClosed(id: number) {
  console.log('Tab closed:', id);
}

activeTabChange(dt: any) {
  console.log('Active tab:', dt);
}

Tab item options:

| Property | Type | Description | | ------------- | -------- | -------------------------------- | | id | number | Unique tab ID | | title | string | Tab label | | leadingIcon | string | Icon path shown before the title | | tralingIocn | string | Icon path shown after the title | | count | number | Badge count shown on the tab |


WizardComponent<cats-ui-wizard>

A multi-step wizard modal with optional progress bar, step badge, and expandable layout. Steps are defined via ng-template using the wizardStep directive, and wizard state is managed through an injected WizardService.

Template:

<!-- Trigger button -->
<button (click)="openUserWizard()">Open User Wizard</button>

@if (wizard.isOpen('classification')()) {
<cats-ui-wizard wizardId="classification" title="Data Classification" [showProgressBar]="true" [showStepBadge]="true" (closed)="closeModal()">
  <ng-template wizardStep>
    <app-step-one></app-step-one>
  </ng-template>

  <ng-template wizardStep>
    <app-step-two></app-step-two>
  </ng-template>

  <ng-template wizardStep>
    <app-step-three></app-step-three>
  </ng-template>

  <ng-template wizardStep>
    <app-step-four></app-step-four>
  </ng-template>
</cats-ui-wizard>
}

TypeScript:

import { WizardService } from "cats-ui-lib";

export class ParentComponent {
  constructor(public wizard: WizardService) {}

  openUserWizard() {
    const wizardId = "classification";

    // Define the step titles and initial states
    this.wizard.stepConfig.update((config: any) => {
      config[wizardId] = [
        { title: "User Info", state: "active" },
        { title: "Details", state: "normal" },
        { title: "Review", state: "normal" },
        { title: "Confirm", state: "normal" },
      ];
      return config;
    });

    this.wizard.open(wizardId, { steps: [] });
  }

  closeModal() {
    this.wizard.close("classification");
  }
}

Component inputs:

| Input | Type | Description | | ----------------- | --------- | ----------------------------------------------------- | | wizardId | string | Unique identifier matching the ID used in the service | | title | string | Title displayed in the wizard header | | showProgressBar | boolean | Show a progress bar across the top of the wizard | | showStepBadge | boolean | Show a step counter badge (e.g. "Step 2 of 4") | | expandable | boolean | Allow the wizard to be expanded to full screen |

Component outputs:

| Output | Type | Description | | -------- | -------------------- | --------------------------------- | | closed | EventEmitter<void> | Emitted when the wizard is closed |

WizardService API:

| Method / Property | Signature | Description | | ----------------- | ------------------------------------------------ | ------------------------------------------------- | | open() | open(id: string, options: { steps: [] }): void | Opens the wizard with the given ID | | close() | close(id: string): void | Closes the wizard with the given ID | | isOpen() | isOpen(id: string): Signal<boolean> | Returns a signal indicating if the wizard is open | | stepConfig | WritableSignal<Record<string, StepConfig[]>> | Signal holding step definitions per wizard ID |

Step config object fields:

| Field | Type | Description | | ------- | -------- | ------------------------------------------------- | | title | string | Display label for the step in the progress bar | | state | string | Initial state: 'active' (current) or 'normal' |

Notes:

  • Each <ng-template wizardStep> maps to a step in the order it appears.
  • The number of <ng-template wizardStep> blocks should match the number of entries in stepConfig.
  • The wizard uses Angular Signals internally; use wizard.isOpen('id')() (note the call ()) to read the signal value in templates.

CustomDatePickerComponent<cats-ui-custom-date-picker>

Supports single, range, and dual modes with optional time selection.

| Mode | Description | | -------- | ---------------------------------- | | single | Single date picker (± time) | | range | Start and end date picker (± time) | | dual | Two-calendar view (± time) |

Template:

<!-- Single date + time -->
<cats-ui-custom-date-picker [config]="{ mode: 'single', time: true, parentDateFormat: 'MM/dd/yyyy' }" (applied)="displayData($event)"> </cats-ui-custom-date-picker>

<!-- Date range -->
<cats-ui-custom-date-picker [config]="{ mode: 'range', time: false, parentDateFormat: 'MM/dd/yyyy' }" (applied)="displayData($event)"> </cats-ui-custom-date-picker>

<!-- Date range + time -->
<cats-ui-custom-date-picker [config]="{ mode: 'range', time: true, parentDateFormat: 'MM/dd/yyyy' }" (applied)="displayData($event)"> </cats-ui-custom-date-picker>

<!-- Dual calendar -->
<cats-ui-custom-date-picker [config]="{ mode: 'dual', time: false, parentDateFormat: 'MM/dd/yyyy' }" (applied)="displayData($event)"> </cats-ui-custom-date-picker>

<!-- Dual calendar + time -->
<cats-ui-custom-date-picker [config]="{ mode: 'dual', time: true, parentDateFormat: 'MM/dd/yyyy' }" (applied)="displayData($event)"> </cats-ui-custom-date-picker>

Config options:

| Property | Type | Description | | ------------------ | --------- | --------------------------------------------- | | mode | string | 'single' | 'range' | 'dual' | | time | boolean | Show time picker alongside the date | | parentDateFormat | string | Output date format, e.g. 'MM/dd/yyyy' | | minDate | Date | Minimum selectable date | | maxDate | Date | Maximum selectable date | | placeholder | string | Placeholder for single-date mode | | fromPlaceholder | string | Placeholder for start date in range/dual mode | | toPlaceholder | string | Placeholder for end date in range/dual mode | | disabledDates | Date[] | Array of dates to disable | | disablePastDays | number | Number of past days to disable | | showDateLabel | boolean | Show label above date input | | showTimeLabel | boolean | Show label above time input |


TimestampFilterComponent<cats-ui-timestamp-filter>

A pre-built filter component with quick date presets, custom input, and date picker submenus.

Template:

<cats-ui-timestamp-filter [config]="timeFilterConfig" (selectionChange)="onFilterChange($event)"> </cats-ui-timestamp-filter>

TypeScript:

timeFilterConfig = {
  title: 'Timestamp Filter',
  showReset: true,
  options: [
    { label: 'Live',           value: 'live'  },
    { label: 'Today',          value: 'today', default: true },
    { label: 'This Week',      value: 'week'  },
    { label: 'This Month',     value: 'month' },
    { label: 'This Financial Year', value: 'fy' },
    { label: 'Last 24 Hours',  value: '24h'   },
    { label: 'Last 30 days',   value: '30d'   },

    // Custom number input (e.g. "Last N days")
    { label: 'Last', value: 'last', type: 'input', custom: true },

    // Date picker submenus
    {
      label: 'Custom Date',
      value: 'date',
      type: 'submenu',
      custom: true,
      pickerMode: 'single',
      parentDateFormat: 'MM/dd/yyyy',
    },
    {
      label: 'Custom Date and Time',
      value: 'datetime',
      type: 'submenu',
      custom: true,
      pickerMode: 'single',
      parentDateFormat: 'MM/dd/yyyy',
    },
    {
      label: 'Custom Date Range',
      value: 'range',
      type: 'submenu',
      custom: true,
      pickerMode: 'range',
    },
    {
      label: 'Custom Date and Time Range',
      value: 'datetimerange',
      type: 'submenu',
      custom: true,
    },
  ],
};

onFilterChange(dt: any) {
  console.log('timestamp filter', dt);
}

Config options:

| Property | Type | Description | | ----------- | --------- | ------------------------------ | | title | string | Label shown above the filter | | showReset | boolean | Show a reset button | | options | array | Array of filter option objects |

Option object fields:

| Field | Type | Description | | ------------------ | --------- | -------------------------------------------------------------- | | label | string | Display label for the option | | value | string | Emitted value on selection | | default | boolean | Pre-select this option on load | | type | string | 'input' for numeric entry, 'submenu' for date picker popup | | custom | boolean | Marks as a custom/user-defined option | | pickerMode | string | Date picker mode: 'single' | 'range' | | parentDateFormat | string | Output date format for picker submenus |


Tooltip DirectivecatsUiTooltip

Apply as an attribute on any HTML element.

<button catsUiTooltip="This is a tooltip">Hover me</button>

📁 Project Structure

cats-ui-lib/
├── accordion/
├── auto-complete-multi-select/
├── auto-complete-single-select/
├── checkbox-button/
├── custom-date-picker/
├── date-time-picker/
├── input/
├── multi-select/
├── radio-button/
├── search-box/
├── single-select/
├── tabs/
├── tabset/
├── timestamp-filter/
├── toogle-button/
└── wizard/

🔗 Links


🛠️ Development

Build the library

ng build cats-ui

Run unit tests

ng test

Publish to npm

ng build cats-ui
cd dist/cats-ui
npm publish

📋 Requirements

| Dependency | Version | | ---------- | ------- | | Angular | >= 19.x | | Node.js | >= 18.x |


📄 License

MIT © cats-ui-lib