npm package: @pecb-ui/components
Description: Professional Angular UI Components Library with TypeScript and SCSS by PECB
Author: PECB
Latest version: 1.2.0

# @pecb-ui/components

A professional Angular 17 UI components library built with TypeScript and SCSS. Features Storybook for component development and documentation, full accessibility compliance (WCAG 2.1 AA), and tree-shakeable, AOT-compatible builds.

[![npm version](https://img.shields.io/npm/v/@pecb-ui/components.svg)](https://www.npmjs.com/package/@pecb-ui/components)
[![Angular](https://img.shields.io/badge/Angular-17.3+-red.svg)](https://angular.io/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Features

- 🎯 **Angular 17.3+** - Built with the latest Angular features
- 📦 **APF Compliant** - Angular Package Format for maximum compatibility
- 🌳 **Tree-shakeable** - Only import what you use
- ⚡ **AOT Compatible** - Optimized for Ahead-of-Time compilation
- ♿ **WCAG 2.1 AA** - Full accessibility compliance
- 🎨 **SCSS Design System** - Professional variables, mixins, and utilities
- 📚 **Storybook** - Interactive component documentation
- 🔒 **Strict TypeScript** - Full type safety

## Installation

### From npm (recommended)

```bash
npm install @pecb-ui/components
```

### From local package

```bash
npm install /path/to/dist/ui-components/pecb-ui-components-1.0.0.tgz
```

## Peer Dependencies

This library requires the following peer dependencies:

```json
{
  "@angular/common": "^17.3.0",
  "@angular/core": "^17.3.0",
  "@angular/animations": "^17.3.0"
}
```

## Quick Start

### 1. Import the Module

```typescript
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { PecbComponentsModule } from '@pecb-ui/components';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    PecbComponentsModule  // Import the PECB UI components module
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }
```

### 2. Import Global Styles (Optional)

If you want to use the PECB design system variables in your application:

```scss
// styles.scss
@import '@pecb-ui/components/styles/main';
```

Or import specific abstracts:

```scss
// In your component SCSS
@import '@pecb-ui/components/styles/abstracts/variables';
@import '@pecb-ui/components/styles/abstracts/mixins';

.my-component {
  color: $primary-color;
  padding: $spacing-md;
  @include elevation(2);
}
```

### 3. Use Components

```html
<!-- app.component.html -->
<pecb-button variant="primary" size="medium" (clicked)="handleClick()">
  Click Me
</pecb-button>

<pecb-card elevation="md">
  <pecb-card-header>
    <h3>Welcome</h3>
  </pecb-card-header>
  <pecb-card-body>
    <p>Your content goes here</p>
  </pecb-card-body>
</pecb-card>
```

## Components

### Button Component

A versatile button component with multiple variants, sizes, and accessibility features.

```html
<!-- Basic button -->
<pecb-button variant="primary" (clicked)="onClick()">
  Submit
</pecb-button>

<!-- With loading state -->
<pecb-button variant="primary" [loading]="isLoading">
  Save
</pecb-button>

<!-- Disabled button -->
<pecb-button variant="danger" [disabled]="true">
  Delete
</pecb-button>

<!-- Full width button -->
<pecb-button variant="success" [fullWidth]="true">
  Continue
</pecb-button>

<!-- Icon button with accessibility label -->
<pecb-button variant="secondary" ariaLabel="Close dialog" iconLeft="✕">
</pecb-button>

<!-- Toggle button -->
<pecb-button variant="secondary" [ariaPressed]="isActive" (clicked)="toggle()">
  Toggle
</pecb-button>

<!-- Button that controls a dropdown -->
<pecb-button
  variant="primary"
  [ariaExpanded]="isOpen"
  ariaHasPopup="menu"
  ariaControls="dropdown-menu"
  (clicked)="toggleDropdown()">
  Menu
</pecb-button>
```

**Properties:**

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `variant` | `'primary' \| 'secondary' \| 'success' \| 'danger' \| 'warning' \| 'info' \| 'text'` | `'primary'` | Visual style variant |
| `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Button size |
| `disabled` | `boolean` | `false` | Disable the button |
| `loading` | `boolean` | `false` | Show loading spinner |
| `fullWidth` | `boolean` | `false` | Make button full width |
| `type` | `'button' \| 'submit' \| 'reset'` | `'button'` | HTML button type |
| `iconLeft` | `string` | - | Icon before text |
| `iconRight` | `string` | - | Icon after text |
| `ariaLabel` | `string` | - | Accessible label |
| `ariaExpanded` | `boolean` | - | ARIA expanded state |
| `ariaPressed` | `boolean` | - | ARIA pressed state (toggle buttons) |
| `ariaHasPopup` | `boolean \| 'menu' \| 'listbox' \| 'tree' \| 'grid' \| 'dialog'` | - | Popup type |
| `ariaControls` | `string` | - | ID of controlled element |

**Events:**

| Event | Type | Description |
|-------|------|-------------|
| `clicked` | `EventEmitter<MouseEvent>` | Emitted on button click |

### Card Component

A container component for displaying content with optional header, body, and footer sections.

```html
<!-- Basic card -->
<pecb-card elevation="md">
  <pecb-card-header>
    <h3>Card Title</h3>
  </pecb-card-header>
  <pecb-card-body>
    <p>Card content goes here</p>
  </pecb-card-body>
  <pecb-card-footer>
    <pecb-button variant="primary">Action</pecb-button>
  </pecb-card-footer>
</pecb-card>

<!-- Hoverable card -->
<pecb-card elevation="sm" [hoverable]="true">
  <pecb-card-body>
    <p>Hover over me!</p>
  </pecb-card-body>
</pecb-card>

<!-- Card as article (accessible) -->
<pecb-card role="article" ariaLabelledBy="article-title">
  <pecb-card-header>
    <h2 id="article-title">Article Headline</h2>
  </pecb-card-header>
  <pecb-card-body>
    <p>Article content...</p>
  </pecb-card-body>
</pecb-card>

<!-- Card as region -->
<pecb-card role="region" ariaLabel="Product Information">
  <pecb-card-body>
    <p>Product details...</p>
  </pecb-card-body>
</pecb-card>
```

**Properties:**

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `elevation` | `'none' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | Shadow depth |
| `hoverable` | `boolean` | `false` | Enable hover effect |
| `noPadding` | `boolean` | `false` | Remove default padding |
| `role` | `'article' \| 'region' \| 'group' \| 'listitem' \| 'none'` | `'none'` | Semantic role |
| `ariaLabel` | `string` | - | Accessible label |
| `ariaLabelledBy` | `string` | - | ID of labelling element |
| `ariaDescribedBy` | `string` | - | ID of describing element |

## Services

### NotificationService

A stateless, injectable service for displaying toast notifications.

```typescript
import { NotificationService } from '@pecb-ui/components';

@Component({...})
export class MyComponent {
  constructor(private notificationService: NotificationService) {}

  showSuccess(): void {
    this.notificationService.success('Operation completed successfully!');
  }

  showError(): void {
    this.notificationService.error('An error occurred', 'Error');
  }

  showWarning(): void {
    this.notificationService.warning('Please review your input', 'Warning');
  }

  showInfo(): void {
    this.notificationService.info('New updates available');
  }

  showCustom(): void {
    this.notificationService.show({
      message: 'Custom notification',
      type: 'info',
      duration: 10000,
      position: 'bottom-right',
      dismissible: true
    });
  }
}
```

### ThemeService

A stateless, injectable service for managing application themes.

```typescript
import { ThemeService } from '@pecb-ui/components';

@Component({...})
export class MyComponent {
  isDarkMode$ = this.themeService.theme$.pipe(
    map(config => config.resolvedTheme === 'dark')
  );

  constructor(private themeService: ThemeService) {}

  toggleTheme(): void {
    this.themeService.toggleTheme();
  }

  setDarkMode(): void {
    this.themeService.setTheme('dark');
  }

  useSystemPreference(): void {
    this.themeService.useSystemTheme();
  }

  setCustomColors(): void {
    this.themeService.setCustomVariables({
      primaryColor: '#007bff',
      backgroundColor: '#f8f9fa'
    });
  }
}
```

### LoadingService

A stateless, injectable service for managing loading states.

```typescript
import { LoadingService } from '@pecb-ui/components';

@Component({...})
export class MyComponent {
  isLoading$ = this.loadingService.isLoading$('data-fetch');

  constructor(private loadingService: LoadingService) {}

  async loadData(): Promise<void> {
    this.loadingService.start('data-fetch', 'Loading data...');
    try {
      const data = await this.fetchData();
      // Process data
    } finally {
      this.loadingService.stop('data-fetch');
    }
  }

  // Or use the helper method
  async loadDataAlt(): Promise<void> {
    const data = await this.loadingService.withLoading(
      'data-fetch',
      () => this.fetchData(),
      'Loading data...'
    );
  }
}
```

## Utilities

The library exports utility functions for common operations:

```typescript
import {
  // String utilities
  toKebabCase,
  toCamelCase,
  truncate,
  slugify,

  // DOM utilities
  generateUniqueId,
  getFocusableElements,
  trapFocus,
  copyToClipboard,

  // Accessibility utilities
  announceToScreenReader,
  getButtonAriaAttributes,
  prefersReducedMotion,

  // Error handling
  createError,
  wrapError,
  tryAsync
} from '@pecb-ui/components';
```

## Types & Interfaces

```typescript
import {
  // Common types
  Size,
  ComponentSize,
  ColorVariant,
  Position,

  // Component interfaces
  Disableable,
  Loadable,
  Focusable,
  SelectableItem,
  MenuItem,

  // Service interfaces
  NotificationConfig,
  ThemeConfig,
  LoadingState
} from '@pecb-ui/components';
```

## SCSS Design System

### Variables

```scss
// Colors
$primary-color: #1976d2;
$accent-color: #ff4081;
$success-color: #4caf50;
$warn-color: #f44336;
$info-color: #2196f3;

// Spacing (8px base unit)
$spacing-xs: 4px;
$spacing-sm: 8px;
$spacing-md: 16px;
$spacing-lg: 24px;
$spacing-xl: 32px;

// Typography
$font-family-base: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
$font-size-sm: 0.875rem;
$font-size-md: 1rem;
$font-size-lg: 1.125rem;

// Border radius
$border-radius-sm: 4px;
$border-radius-md: 8px;
$border-radius-lg: 12px;
```

### Mixins

```scss
// Responsive breakpoints
@include respond-to('md') {
  // Styles for medium screens and up
}

// Flexbox utilities
@include flex-center;
@include flex-between;

// Elevation (shadows)
@include elevation(2);

// Focus visible
@include focus-visible {
  outline: 2px solid $primary-color;
}

// Transitions
@include transition(background-color, color);
```

## Development

### Prerequisites

- Node.js 18+
- npm 9+
- Angular CLI 17.3+

### Setup

```bash
# Clone the repository
git clone https://github.com/pecb-ui/components.git
cd components

# Install dependencies
npm install

# Build the library
npm run build

# Run Storybook
npm run storybook

# Run tests
npm test
```

### Building

```bash
# Development build
npm run build

# Production build
npm run build:prod

# Create npm package
npm run publish:lib
```

### Testing

```bash
# Run tests in watch mode
npm test

# Run tests once with coverage
npm run test:ci
```

### Storybook

```bash
# Start Storybook dev server
npm run storybook

# Build Storybook for deployment
npm run build-storybook
```

## Browser Support

- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)

## Roadmap

Planned components:

- Input/Form controls
- Modal/Dialog
- Dropdown/Select
- Tabs
- Accordion
- Table
- Pagination
- Badge
- Avatar
- Tooltip
- Alert/Toast
- Progress indicators
- Date picker

## Contributing

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes using [Conventional Commits](https://www.conventionalcommits.org/)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## License

MIT License - see the [LICENSE](LICENSE) file for details.

## Support

For issues and questions, please use the [GitHub issue tracker](https://github.com/pecb-ui/components/issues).