JSPM

sgh-select-lib

0.0.5
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 7
  • Score
    100M100P100Q35685F
  • License MIT

Advanced Angular select component library with search, multi-select, and Bootstrap styling support

Package Exports

  • sgh-select-lib
  • sgh-select-lib/package.json

Readme

SGH Select Library

npm version License: MIT Angular Bootstrap

A comprehensive, feature-rich Angular select component library with advanced search, multi-select capabilities, and Bootstrap styling support.

✨ Features

  • 🔍 Advanced Search - Built-in search/filter with debounced input
  • 🎯 Single & Multiple Selection - Configurable selection modes
  • 🎨 Bootstrap Integration - Full Bootstrap 5+ styling with CSS custom properties
  • 🔧 Flexible Data Binding - Support for various data formats and custom property mapping
  • 📱 Responsive Design - Mobile-friendly with Bootstrap responsive utilities
  • Accessibility - WCAG compliant with ARIA support and keyboard navigation
  • 🚀 Performance - Optimized rendering with virtual scrolling support
  • 🎭 Customizable - Template slots for custom option rendering
  • 🌙 Dark Theme Support - Bootstrap dark mode compatible
  • 📦 Tree-shakable - Optimized bundle size with no Material dependencies

📦 Installation

npm install sgh-select-lib

Peer Dependencies

Make sure you have the following peer dependencies installed:

npm install @angular/core @angular/common @angular/forms bootstrap rxjs

Bootstrap Setup

Add Bootstrap CSS to your project. You can either:

Option 1: Install Bootstrap via npm

npm install bootstrap

Then add to your angular.json styles array:

"styles": [
  "node_modules/bootstrap/dist/css/bootstrap.min.css",
  "src/styles.scss"
]

Option 2: Use Bootstrap CDN Add to your src/index.html:

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">

🚀 Quick Start

1. Import the Module

import { SghSelectLibModule } from 'sgh-select-lib';

@NgModule({
  imports: [
    SghSelectLibModule,
    // ... other imports
  ],
  // ...
})
export class AppModule { }

2. Basic Usage

<!-- Advanced select with Bootstrap styling -->
<sgh-select
  [options]="['Option 1', 'Option 2', 'Option 3']"
  placeholder="Choose an option"
  (selectionChange)="onSelectionChange($event)">
</sgh-select>

<!-- Simple native select (for basic use cases) -->
<sgh-select-simple
  [options]="['Option 1', 'Option 2', 'Option 3']"
  placeholder="Choose an option"
  (selectionChange)="onSelectionChange($event)">
</sgh-select-simple>

3. Advanced Usage

<!-- Object array with custom mapping -->
<sgh-select
  [options]="workQueueList"
  [multiple]="false"
  [searchable]="true"
  labelKey="workQueueName"
  valueKey="workQueueId"
  placeholder="Select work queue"
  searchPlaceholder="Search queues..."
  [clearable]="true"
  (selectionChange)="onWorkQueueChange($event)"
  (searchChange)="onSearchChange($event)">
</sgh-select>

📚 API Reference

Component Properties

Input Properties

Property Type Default Description
options any[] [] Array of options to display
multiple boolean false Enable multiple selection mode
searchable boolean true Enable search/filter functionality
labelKey string 'label' Property name for display text
valueKey string 'value' Property name for option value
disabledKey string 'disabled' Property name for disabled state
groupKey string undefined Property name for option grouping
placeholder string 'Select...' Placeholder text
searchPlaceholder string 'Search...' Search input placeholder
disabled boolean false Disable the component
required boolean false Mark as required field
clearable boolean true Show clear button
maxSelections number undefined Maximum selections (multiple mode)
noOptionsText string 'No options found' Text when no options available
loadingText string 'Loading...' Loading state text
loading boolean false Show loading state
compareWith function undefined Custom comparison function

Output Events

Event Type Description
selectionChange SelectChangeEvent Fired when selection changes
searchChange SelectSearchEvent Fired when search term changes
opened void Fired when dropdown opens
closed void Fired when dropdown closes
focus void Fired when component receives focus
blur void Fired when component loses focus

Data Formats

The component supports various data formats:

Simple Arrays

const options = ['Apple', 'Banana', 'Orange'];

Object Arrays

const options = [
  { id: 1, name: 'Apple', category: 'Fruit' },
  { id: 2, name: 'Banana', category: 'Fruit' },
  { id: 3, name: 'Carrot', category: 'Vegetable' }
];

Complex Nested Objects

const options = [
  {
    workQueueId: "1",
    workQueueName: "Processing Queue",
    assignedVisits: 5,
    details: { priority: 'high', department: 'IT' }
  }
];

💡 Usage Examples

<sgh-select
  [options]="countries"
  labelKey="name"
  valueKey="code"
  placeholder="Select country"
  [searchable]="true"
  (selectionChange)="onCountrySelect($event)">
</sgh-select>
export class ExampleComponent {
  countries = [
    { code: 'US', name: 'United States' },
    { code: 'CA', name: 'Canada' },
    { code: 'UK', name: 'United Kingdom' }
  ];

  onCountrySelect(event: SelectChangeEvent) {
    console.log('Selected:', event.value);
    console.log('Option data:', event.option);
  }
}

Multiple Select with Max Selections

<sgh-select
  [options]="skills"
  [multiple]="true"
  [maxSelections]="3"
  labelKey="name"
  valueKey="id"
  placeholder="Select up to 3 skills"
  (selectionChange)="onSkillsChange($event)">
</sgh-select>

Grouped Options

<sgh-select
  [options]="employees"
  labelKey="name"
  valueKey="id"
  groupKey="department"
  placeholder="Select employee">
</sgh-select>
employees = [
  { id: 1, name: 'John Doe', department: 'Engineering' },
  { id: 2, name: 'Jane Smith', department: 'Engineering' },
  { id: 3, name: 'Bob Wilson', department: 'Marketing' }
];

Custom Templates

<sgh-select [options]="users" labelKey="name" valueKey="id">
  <!-- Custom option template -->
  <ng-template #optionTemplate let-option let-data="data">
    <div class="custom-option">
      <img [src]="data.avatar" alt="Avatar" class="avatar">
      <div class="user-info">
        <div class="name">{{ option.label }}</div>
        <div class="email">{{ data.email }}</div>
      </div>
    </div>
  </ng-template>

  <!-- Custom selected value template -->
  <ng-template #selectedTemplate let-options>
    <span>{{ options.length }} users selected</span>
  </ng-template>
</sgh-select>

Reactive Forms Integration

<form [formGroup]="myForm">
  <sgh-select
    formControlName="selectedOption"
    [options]="options"
    labelKey="label"
    valueKey="value"
    placeholder="Select option">
  </sgh-select>
</form>
export class FormComponent implements OnInit {
  myForm: FormGroup;

  ngOnInit() {
    this.myForm = this.fb.group({
      selectedOption: ['', Validators.required]
    });
  }
}

Loading State with Async Data

<sgh-select
  [options]="options$ | async"
  [loading]="loading"
  loadingText="Fetching options..."
  placeholder="Select option">
</sgh-select>
export class AsyncComponent implements OnInit {
  options$: Observable<any[]>;
  loading = false;

  ngOnInit() {
    this.loading = true;
    this.options$ = this.service.getOptions().pipe(
      finalize(() => this.loading = false)
    );
  }
}

🎨 Styling and Theming

CSS Custom Properties

The component uses CSS custom properties for easy theming with Bootstrap-compatible values:

:root {
  /* Primary Colors (Bootstrap-compatible) */
  --sgh-select-primary-color: #0d6efd;
  --sgh-select-secondary-color: #6c757d;
  --sgh-select-success-color: #198754;
  --sgh-select-danger-color: #dc3545;
  
  /* Background Colors */
  --sgh-select-bg-color: #ffffff;
  --sgh-select-hover-color: #e9ecef;
  
  /* Text Colors */
  --sgh-select-text-color: #212529;
  --sgh-select-text-muted: #6c757d;
  
  /* Border and Spacing */
  --sgh-select-border-color: #ced4da;
  --sgh-select-border-radius: 0.375rem;
  --sgh-select-padding-x: 0.75rem;
  --sgh-select-padding-y: 0.375rem;
}

Bootstrap Dark Mode Support

The component automatically supports Bootstrap's dark mode:

<html data-bs-theme="dark">
  <body>
    <sgh-select [options]="options"></sgh-select>
  </body>
</html>

Custom Bootstrap Themes

// Custom Bootstrap theme
:root {
  --sgh-select-primary-color: #e91e63;
  --sgh-select-border-radius: 0.5rem;
}

// Size variants
.sgh-select-lg {
  --sgh-select-font-size: 1.25rem;
  --sgh-select-padding-y: 0.5rem;
  --sgh-select-padding-x: 1rem;
}

.sgh-select-sm {
  --sgh-select-font-size: 0.875rem;
  --sgh-select-padding-y: 0.25rem;
  --sgh-select-padding-x: 0.5rem;
}

Custom Styling with Bootstrap Classes

<!-- Apply custom Bootstrap classes -->
<div class="my-custom-select">
  <sgh-select 
    [options]="options"
    class="sgh-select-primary">
  </sgh-select>
</div>
.my-custom-select {
  .sgh-select-trigger {
    @extend .btn-outline-success;
  }
  
  .sgh-dropdown-menu {
    @extend .shadow-lg;
  }
}

🔧 Service Utilities

The library includes a service with helpful utilities:

import { SghSelectLibService } from 'sgh-select-lib';

export class MyComponent {
  constructor(private selectService: SghSelectLibService) {}

  ngOnInit() {
    // Transform data to select options
    const options = this.selectService.transformToSelectOptions(
      this.rawData,
      'displayName',
      'id'
    );

    // Filter options
    const filtered = this.selectService.filterOptions(
      options,
      'search term',
      ['description', 'category']
    );

    // Sort options
    const sorted = this.selectService.sortOptions(options, 'label', 'asc');
  }
}

♿ Accessibility

The component follows WCAG guidelines and includes:

  • Full keyboard navigation support
  • Screen reader compatibility
  • ARIA labels and descriptions
  • Focus management
  • High contrast mode support

Keyboard Shortcuts

Key Action
Space/Enter Open dropdown
Arrow Up/Down Navigate options
Escape Close dropdown
Tab Move focus
Home/End First/last option

🌐 Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)
  • Mobile browsers (iOS Safari, Chrome Mobile)

📝 Development

Building the Library

ng build sgh-select-lib

Running Tests

ng test sgh-select-lib

Publishing

cd dist/sgh-select-lib
npm publish

🤝 Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🏷️ Changelog

v0.0.3

  • BREAKING CHANGE: Migrated from Angular Material to Bootstrap 5+
  • Removed all Material Design dependencies
  • Added Bootstrap 5+ styling and theming support
  • Improved CSS custom properties system
  • Enhanced accessibility with Bootstrap ARIA patterns
  • Maintained all existing functionality with Bootstrap UI
  • Added Bootstrap dark mode compatibility
  • Reduced bundle size by removing Material dependencies

v0.0.2

  • Previous Material Design version
  • Single and multiple selection support
  • Advanced search functionality
  • Material Design integration
  • Accessibility features
  • Custom templates
  • Dark theme support

🔄 Migration from Material Design (v0.0.2 to v0.0.3)

If you're upgrading from the Material Design version, please note:

Required Changes:

  1. Remove Angular Material dependencies:

    npm uninstall @angular/material @angular/cdk
  2. Install Bootstrap:

    npm install bootstrap
  3. Update styles: Replace Material theme with Bootstrap CSS (see Bootstrap Setup section above)

What's Changed:

  • UI now uses Bootstrap styling instead of Material Design
  • All functionality remains the same
  • CSS custom properties have been updated with Bootstrap-compatible values
  • Icons now use Font Awesome instead of Material Icons

What's Not Changed:

  • All component APIs remain identical
  • Event handlers work the same way
  • Template slots and custom templates work the same way
  • All input/output properties are unchanged

📞 Support

For issues and questions:


Made with ❤️ by SGH Development Team