cats-ui-lib
v2.2.30
Published
Standalone Angular UI component library for inputs, selects, filters, navigation, dialogs, wizards, file upload, header, and sidebar.
Readme
cats-ui-lib
Angular UI component library for inputs, selects, filters, navigation, dialogs, wizards, file upload, and shared CATS application chrome.
Install
npm install cats-ui-libPeer dependencies: Angular >=18 <22.
Setup
Add library styles and image assets in angular.json:
{
"projects": {
"your-app": {
"architect": {
"build": {
"options": {
"assets": [
{
"glob": "**/*",
"input": "node_modules/cats-ui-lib/assets",
"output": "images"
}
],
"styles": ["node_modules/cats-ui-lib/styles/_index.scss", "src/styles.scss"]
}
}
}
}
}
}All components are standalone. Import only the components/directives you use:
import { Component } from "@angular/core";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { InputComponent, SingleSelectComponent, MultiSelectComponent, SearchBoxComponent } from "cats-ui-lib";
@Component({
selector: "app-example",
standalone: true,
imports: [FormsModule, ReactiveFormsModule, InputComponent, SingleSelectComponent, MultiSelectComponent, SearchBoxComponent],
templateUrl: "./example.component.html",
})
export class ExampleComponent {}Components
Input
Selector: <cats-ui-input>
Use for text, email, password, number, validation messages, and optional leading/trailing dropdowns.
<cats-ui-input
[inputConfig]="nameInput"
[(ngModel)]="name"
(onInput)="handleInput($event)"
(onChange)="handleChange($event)"
(onFocus)="handleFocus($event)"
(onBlur)="handleBlur($event)"
(onKeyDown)="handleKeyDown($event)"
(onKeyUp)="handleKeyUp($event)"
></cats-ui-input>
<cats-ui-input [inputConfig]="phoneInput" [(ngModel)]="phone" (onDropdownSelection)="onDialCodeChange($event)"></cats-ui-input>import { InputConfig } from 'cats-ui-lib';
name = '';
phone = '';
nameInput: InputConfig = {
type: 'text',
label: 'Name',
placeholder: 'Enter name',
showErrorMessage: false,
errorMessage: 'Name is required',
};
phoneInput: InputConfig = {
type: 'number',
label: 'Phone',
placeholder: 'Enter phone number',
leadingDropdown: {
options: [
{ id: 'in', name: '+91' },
{ id: 'us', name: '+1' },
],
selected: 'in',
idField: 'id',
textField: 'name',
},
};
handleInput(value: string) {
console.log(value);
}
handleChange(value: string) {
console.log(value);
}
handleFocus(value: string) {
console.log(value);
}
handleBlur(value: string) {
console.log(value);
}
handleKeyDown(value: string) {
console.log(value);
}
handleKeyUp(value: string) {
console.log(value);
}
onDialCodeChange(item: any) {
console.log(item);
}Important config fields: type, placeholder, label, showDropdown, dropdownPosition, dropdownOptions, dropdownSelected, leadingDropdown, trailingDropdown, errorMessage, showErrorMessage.
Available outputs: onInput, onChange, onFocus, onBlur, onKeyDown, onKeyUp, onDropdownSelection.
Single Select
Selector: <cats-ui-single-select>
<cats-ui-single-select [optionList]="statusOptions" [singleSelectConfig]="singleSelectConfig" [selectedOption]="selectedStatus" [valueField]="'id'" (onSelection)="onStatusChange($event)" (onScroll)="loadMoreStatuses()"></cats-ui-single-select>import { SingleSelectConfig } from 'cats-ui-lib';
statusOptions = [
{ id: 1, name: 'Open', color: '#0f766e', icon: 'images/check-circle.svg' },
{ id: 2, name: 'Closed', disabled: true },
];
selectedStatus = 1;
singleSelectConfig: SingleSelectConfig = {
idField: 'id',
textField: 'name',
disabledField: 'disabled',
colorField: 'color',
iconField: 'icon',
placeholder: 'Select status',
enableSearch: true,
searchPlaceholder: 'Search status',
required: true,
};
onStatusChange(item: any) {
console.log(item);
}Multi Select
Selector: <cats-ui-multi-select>
<cats-ui-multi-select [optionList]="teamOptions" [multiSelectConfig]="multiSelectConfig" [selectedOptions]="selectedTeams" (onSelection)="onTeamsChange($event)"></cats-ui-multi-select>import { MultiSelectConfig } from 'cats-ui-lib';
teamOptions = [
{ id: 'qa', name: 'QA' },
{ id: 'dev', name: 'Development' },
{ id: 'ops', name: 'Operations', disabled: true },
];
selectedTeams = [teamOptions[0]];
multiSelectConfig: MultiSelectConfig = {
idField: 'id',
textField: 'name',
disabledField: 'disabled',
placeholder: 'Select teams',
prefixLabel: 'Teams',
enableSearch: true,
chipLimit: 2,
selectAll: true,
required: false,
};
onTeamsChange(items: any[]) {
console.log(items);
}Auto Complete Single Select
Selector: <cats-ui-input-single-select>
<cats-ui-input-single-select [optionsList]="users" [autoSingleSelectConfig]="autoSingleConfig" [selectedItem]="selectedUser" (onItemSelection)="onUserChange($event)" (onScroll)="loadMoreUsers()"></cats-ui-input-single-select>import { AutoCompleteSingleSelectConfig } from 'cats-ui-lib';
users = [
{ id: 1, name: 'Aarav Shah' },
{ id: 2, name: 'Maya Rao', disabled: true },
];
selectedUser = users[0];
autoSingleConfig: AutoCompleteSingleSelectConfig = {
idField: 'id',
textField: 'name',
disabledField: 'disabled',
placeholder: 'Enter or select user',
customInput: true,
required: true,
};
onUserChange(value: any) {
console.log(value);
}Auto Complete Multi Select
Selector: <cats-ui-input-multi-select>
<cats-ui-input-multi-select [optionsList]="kpiOptions" [autoCompleteMultiSelectConfig]="autoMultiConfig" [selectedItem]="selectedKpis" (onItemSelection)="onKpisChange($event)" (onScroll)="loadMoreKpis()"></cats-ui-input-multi-select>import { AutoCompleteMultiSelectConfig } from 'cats-ui-lib';
kpiOptions = [
{ id: 'aht', name: 'Average Handle Time' },
{ id: 'csat', name: 'CSAT' },
];
selectedKpis = [];
autoMultiConfig: AutoCompleteMultiSelectConfig = {
idField: 'id',
textField: 'name',
placeholder: 'Type to search',
selectAll: false,
chipLimit: 2,
customInput: false,
pattern: '',
infoText: 'Select up to 5 KPIs',
selectionLimit: 5,
};
onKpisChange(items: any[]) {
console.log(items);
}Search Box
Selector: <cats-ui-search-box>
<cats-ui-search-box [searchConfig]="searchConfig" [(ngModel)]="searchText" (searchParamValue)="onSearch($event)" (onClose)="clearSearch()"></cats-ui-search-box>import { SearchConfig } from 'cats-ui-lib';
searchText = '';
searchConfig: SearchConfig = {
serachValue: '',
placeholder: 'Search here',
};
onSearch(value: string) {
console.log(value);
}
clearSearch() {
this.searchText = '';
}Checkbox Button
Selector: <cats-ui-checkbox-button>
<cats-ui-checkbox-button [checkBoxConfig]="checkboxConfig" [optionList]="taskOptions" [selectedOptions]="selectedTasks" (onCheckBoxSelection)="onTaskSelection($event)"></cats-ui-checkbox-button>import { CheckBoxConfig } from 'cats-ui-lib';
taskOptions = [
{ id: 101, name: 'Parent Task 1', disabled: false },
{ id: 102, name: 'Parent Task 2', disabled: true },
];
selectedTasks = [taskOptions[0]];
checkboxConfig: CheckBoxConfig = {
idField: 'id',
textField: 'name',
disabledField: 'disabled',
name: 'tasks',
type: 'checkbox',
};
onTaskSelection(items: any[]) {
console.log(items);
}Radio Button
Selector: <cats-ui-radio-button>
<cats-ui-radio-button [config]="radioConfig" [optionList]="priorityOptions" [selectedRadio]="selectedPriority" (selectionChange)="onPriorityChange($event)"></cats-ui-radio-button>import { RadioButtonConfig } from 'cats-ui-lib';
priorityOptions = [
{ id: 'low', name: 'Low' },
{ id: 'high', name: 'High', disabled: true },
];
selectedPriority = 'low';
radioConfig: RadioButtonConfig = {
label: 'Priority',
valueField: 'id',
textField: 'name',
disabled: 'disabled',
name: 'priority',
layout: 'horizontal',
};
onPriorityChange(item: any) {
console.log(item);
}Toggle Button
Selector: <cats-ui-toogle-button>
<cats-ui-toogle-button [toggleConfig]="toggleConfig" (onToggled)="onToggle($event)"></cats-ui-toogle-button>import { ToggleConfig } from 'cats-ui-lib';
toggleConfig: ToggleConfig = {
checked: true,
disabled: false,
type: 'primary',
};
onToggle(checked: boolean) {
console.log(checked);
}File Upload
Selector: <cats-ui-file-upload>
Supports drag/drop, file picker, single or multiple files, accept filtering, min/max size validation, and Angular forms.
<cats-ui-file-upload [(ngModel)]="files" placeholder="Drop invoices here" helperText="PDF, PNG, or JPG. Max 5 MB." accept=".pdf,.png,.jpg,.jpeg" [multiple]="true" [maxSize]="5 * 1024 * 1024" buttonPosition="right" (onfileChange)="onFilesChange($event)" (onfileRemove)="onFilesRemove($event)"></cats-ui-file-upload>files: File[] = [];
onFilesChange(files: File[]) {
console.log(files);
}
onFilesRemove(files: File[]) {
console.log(files);
}Custom Date Picker
Selector: <cats-ui-custom-date-picker>
Modes: single, range, and dual. It can emit a formatted date string, a date-time object, or a date range object.
<cats-ui-custom-date-picker [(ngModel)]="singleDate" [config]="singleDateConfig" (applied)="onDateApply($event)" (cancelled)="onDateCancel()"></cats-ui-custom-date-picker>
<cats-ui-custom-date-picker [(ngModel)]="dateRange" [config]="rangeConfig" (applied)="onRangeApply($event)"></cats-ui-custom-date-picker>import { DatePickerConfig } from 'cats-ui-lib';
singleDate = null;
dateRange = null;
singleDateConfig: DatePickerConfig = {
mode: 'single',
time: true,
parentDateFormat: 'MM/dd/yyyy',
placeholder: 'Select date',
minDate: new Date(2026, 0, 1),
maxDate: new Date(2026, 11, 31),
showDateLabel: true,
showTimeLabel: true,
};
rangeConfig: DatePickerConfig = {
mode: 'dual',
time: false,
parentDateFormat: 'yyyy-MM-dd',
fromPlaceholder: 'From',
toPlaceholder: 'To',
disabledDates: [new Date(2026, 7, 15)],
};
onDateApply(value: any) {
console.log(value);
}
onRangeApply(value: any) {
console.log(value);
}
onDateCancel() {}Timestamp Filter
Selector: <cats-ui-timestamp-filter>
Use quick presets, "last N" input, and custom date picker submenus.
<cats-ui-timestamp-filter [config]="timeFilterConfig" [selectedValue]="selectedTimeFilter" (selectionChange)="onTimeFilterChange($event)"></cats-ui-timestamp-filter>import { TimeFilterConfig, TimeFilterValue } from 'cats-ui-lib';
selectedTimeFilter: TimeFilterValue = {
type: 'today',
};
timeFilterConfig: TimeFilterConfig = {
title: 'Timestamp',
showReset: true,
options: [
{ label: 'Live', value: 'live' },
{ label: 'Today', value: 'today', default: true, parentDateFormat: 'MM/dd/yyyy' },
{ label: 'This Week', value: 'week', parentDateFormat: 'MM/dd/yyyy' },
{ label: 'This Month', value: 'month', parentDateFormat: 'MM/dd/yyyy' },
{ label: 'This Financial Year', value: 'fy', parentDateFormat: 'MM/dd/yyyy' },
{ label: 'Last 24 Hours', value: '24h', parentDateFormat: 'MM/dd/yyyy' },
{ label: 'Last 7 Days', value: '7d', parentDateFormat: 'MM/dd/yyyy' },
{ label: 'Last 30 Days', value: '30d', parentDateFormat: 'MM/dd/yyyy' },
{ label: 'Last', value: 'last', type: 'input', custom: true },
{
label: 'Custom Date',
value: 'customDate',
type: 'submenu',
custom: true,
pickerMode: 'single',
parentDateFormat: 'MM/dd/yyyy',
},
{
label: 'Custom Date Range',
value: 'customRange',
type: 'submenu',
custom: true,
pickerMode: 'dual',
parentDateFormat: 'MM/dd/yyyy',
},
],
};
onTimeFilterChange(value: any) {
console.log(value);
}Accordion
Selectors: <cats-ui-accordion>, <cats-ui-accordion-item>
<cats-ui-accordion [closeOthers]="true">
<cats-ui-accordion-item title="General" [index]="0">
<ng-template>
<p>General settings content.</p>
</ng-template>
</cats-ui-accordion-item>
<cats-ui-accordion-item title="Advanced" [index]="1">
<ng-template>
<p>Advanced settings content.</p>
</ng-template>
</cats-ui-accordion-item>
</cats-ui-accordion>Tabset
Selectors: <cats-ui-tabset>, <cats-ui-tab-content>
<cats-ui-tabset [tabs]="tabs" [(activeTab)]="activeTab" [tabConfig]="tabConfig" (tabAdded)="addTab()" (tabClosed)="closeTab($event)">
<cats-ui-tab-content [tabId]="0">Home content</cats-ui-tab-content>
<cats-ui-tab-content [tabId]="1">Overview content</cats-ui-tab-content>
<cats-ui-tab-content [tabId]="2">Audit content</cats-ui-tab-content>
</cats-ui-tabset>import { TabConfig, TabItem } from 'cats-ui-lib';
activeTab: number | null = 1;
tabConfig: TabConfig = {
type: 'Stroke',
addTab: true,
closeTab: true,
homeTab: true,
homeTabName: 'Home',
};
tabs: TabItem[] = [
{ id: 1, title: 'Overview', leadingIcon: 'images/home.svg' },
{ id: 2, title: 'Audit', count: 4, tralingIocn: 'images/x-circle.svg' },
];
addTab() {
const id = Math.max(...this.tabs.map((tab) => tab.id)) + 1;
this.tabs = [...this.tabs, { id, title: `Tab ${id}` }];
this.activeTab = id;
}
closeTab(id: number) {
console.log(id);
}Wizard
Selector: <cats-ui-wizard> with wizardStep directive.
<button type="button" (click)="openWizard()">Open wizard</button>
@if (wizard.isOpen('userSetup')()) {
<cats-ui-wizard wizardId="userSetup" title="User Setup" [showProgressBar]="true" [showStepBadge]="true" (closed)="closeWizard()">
<ng-template wizardStep>
<app-user-details></app-user-details>
</ng-template>
<ng-template wizardStep>
<app-user-permissions></app-user-permissions>
</ng-template>
</cats-ui-wizard>
}import { WizardService, WizardStepDirective } from 'cats-ui-lib';
constructor(public wizard: WizardService) {}
openWizard() {
const wizardId = 'userSetup';
this.wizard.stepConfig.update((config: any) => ({
...config,
[wizardId]: [
{ title: 'Details', state: 'active' },
{ title: 'Permissions', state: 'normal' },
],
}));
this.wizard.activeStep.update((active: any) => ({
...active,
[wizardId]: 1,
}));
this.wizard.open(wizardId, { steps: [] });
}
next() {
this.wizard.nextStep('userSetup');
}
previous() {
this.wizard.previousStep('userSetup');
}
closeWizard() {
this.wizard.close('userSetup');
}Dialog Box
Service: DialogBoxService
Open any component or TemplateRef in a dialog. The returned DialogRef exposes close(result?) and afterClosed().
<button type="button" (click)="openConfirm(confirmTpl)">Open dialog</button>
<ng-template #confirmTpl let-dialogRef="dialogRef">
<p>Archive this record?</p>
<button type="button" (click)="dialogRef.close('cancel')">Cancel</button>
<button type="button" (click)="dialogRef.close('archive')">Archive</button>
</ng-template>import { TemplateRef } from '@angular/core';
import { DialogBoxService, DialogConfig } from 'cats-ui-lib';
constructor(private dialog: DialogBoxService) {}
openConfirm(template: TemplateRef<any>) {
const config: DialogConfig = {
id: 'archive-dialog',
title: 'Confirm archive',
showHeader: true,
showBackdrop: true,
closeOnBackdropClick: false,
class: 'archive-dialog',
};
this.dialog.open(template, config).afterClosed().subscribe((result) => {
console.log(result);
});
}
closeAllDialogs() {
this.dialog.closeAll();
}Header
Selector: <cats-ui-header>
<cats-ui-header [headerConfig]="headerConfig" [dropdownItems]="environments" [selectedDropdownItem]="selectedEnvironment" (onDropdownSelection)="onEnvironmentChange($event)"></cats-ui-header>import { HeaderConfig } from 'cats-ui-lib';
headerConfig: HeaderConfig = {
brandLogo: 'images/brand-Logo.svg',
productLogo: 'images/product-logo.svg',
showDropdown: true,
showGlobalIcon: true,
showAiAgent: true,
};
environments = [
{ id: 'dev', label: 'Development' },
{ id: 'prod', label: 'Production' },
];
selectedEnvironment = this.environments[0];
onEnvironmentChange(item: any) {
console.log(item);
}Sidebar
Selector: <cats-ui-sidebar>
Supports collapsible menus, sectional mode, module/feature/attribute navigation, active item restore, and optional router navigation via url.
<cats-ui-sidebar [appMenus]="menus" [sidebarConfig]="sidebarConfig" [activeItem]="activeItem" (activeSidebar)="onSidebarChange($event)"></cats-ui-sidebar>import { SidebarConfig, SidebarModule } from 'cats-ui-lib';
sidebarConfig: SidebarConfig = {
sidebarType: 'default',
switchOrganiser: true,
};
activeItem = {
moduleIndex: 0,
featureIndex: 0,
attrIndex: 0,
};
menus: SidebarModule[] = [
{
moduleName: 'Dashboard',
icon: 'images/home.svg',
activeIcon: 'images/home.svg',
isEnable: true,
url: '/dashboard',
},
{
moduleName: 'Admin',
icon: 'images/settings.svg',
activeIcon: 'images/settings-04.svg',
isEnable: true,
features: [
{
featuresName: 'Users',
icon: 'images/user.svg',
activeIcon: 'images/user-active.svg',
isEnable: true,
attributes: [
{
attributeName: 'All Users',
icon: 'images/users.svg',
activeIcon: 'images/users-01.svg',
url: '/admin/users',
},
],
},
],
},
];
onSidebarChange(event: any) {
console.log(event.module, event.feature, event.attribute, event.activeItem);
}Outside Click Directive
Directive: catsOutsideClick
<div catsOutsideClick (clickOutSide)="isOpen = false">Dropdown content</div>Development
npm install
npm run buildBuild only the library:
npx ng build cats-uiRun tests:
npm testPublic API
Exports include:
- Components: input, single-select, multi-select, search-box, auto-complete single/multi select, toggle, checkbox, radio, date picker, accordion, tabset, timestamp filter, wizard, file upload, header, dialog box, sidebar.
- Directives:
catsUiTooltip,catsOutsideClick. - Services:
CatsUiService,WizardService,DialogBoxService. - Config models:
InputConfig,SingleSelectConfig,MultiSelectConfig,SearchConfig,AutoCompleteSingleSelectConfig,AutoCompleteMultiSelectConfig,ToggleConfig,CheckBoxConfig,RadioButtonConfig,DialogConfig, plus component-specific interfaces.
License
MIT
