npm package: @ng-shangjc/textarea
Description: Textarea component source package for ng-shangjc angular components
Author: jc-develop
Latest version: 1.0.3-beta

<p align="center">
<a href="https://juliancallejas.github.io/ng-shangjc-docs">
  <img src="https://res.cloudinary.com/dphleqb5t/image/upload/v1772819746/shangjc/shangjc-64-bg-dark_kwzs81.svg" width="307" alt="Shangjc"  /> 
</a>
</p>

# Textarea Component

A flexible and feature-rich textarea component with auto-resize functionality, character counting, form integration, and comprehensive accessibility support. Perfect for collecting multi-line user input with advanced validation and customization options.

## Official Documentation

<a href="https://juliancallejas.github.io/ng-shangjc-docs/?path=/docs/components-textarea">
    ng-Shangjc docs
</a>

## Features

- 📏 **Auto-resize**: Automatically adjusts height based on content with min/max row constraints
- 🔢 **Character Count**: Optional character counter with limit warnings and visual feedback
- 📝 **Form Integration**: Implements ControlValueAccessor for seamless reactive forms support
- 🎨 **Multiple Sizes**: Small, default, and large variants for different use cases
- 🚫 **Max Length**: Built-in character limit enforcement with keyboard prevention
- ⌨️ **Keyboard Support**: Full keyboard navigation including shortcuts and special keys
- ♿ **Accessibility**: Complete ARIA support with proper labels, roles, and screen reader compatibility
- 🎯 **Type-Safe**: Full TypeScript support with strict type checking and autocomplete
- 🎨 **Customizable**: Extensive styling options with custom CSS classes
- ⚡ **Performance**: Optimized with signals and OnPush change detection
- 🔄 **Two-way Binding**: Support for both signal and traditional two-way data binding
- 🎮 **Control Button**: Optional clear button for easy content removal
- 📱 **Responsive**: Works seamlessly across all screen sizes and devices

## Installation

### Step 1: Install the CLI

First, install the ng-shangjc CLI globally or use npx:

```bash
# Install globally
npm install -g @ng-shangjc/cli

# or with yarn
yarn global add @ng-shangjc/cli

# or with pnpm
pnpm install -g @ng-shangjc/cli

# Or use npx without installation
npx @ng-shangjc/cli <command>
```

### Step 2: Initialize your project

If you haven't already, initialize your Angular project for ng-shangjc components:

```bash
ng-shangjc init
```

This will create a `shangjc.config.json` file and set up your project for component installations.

### Step 3: Install the component

Install the textarea component into your project:

```bash
ng-shangjc install textarea
```

The component will be installed in the configured path (default: `src/ui/shangjc`). Adjust the import path in your components based on your project structure and the configured installation path.

## Import

After installation, import the components from your configured installation path. The examples below use the default path `src/ui/shangjc` - adjust the path according to your project structure and configuration.

### Standalone Components (Recommended)

Import and use the individual components directly in your standalone components:

```typescript
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TextareaComponent } from './ui/shangjc/textarea';

@Component({
  selector: 'app-example',
  standalone: true,
  imports: [
    CommonModule,
    TextareaComponent
  ],
  template: `
    <ng-shangjc-textarea
      placeholder="Enter your message..."
      label="Message"
      (valueChange)="onValueChange($event)">
    </ng-shangjc-textarea>
  `
})
export class ExampleComponent { 
  onValueChange(value: string) {
    console.log('Textarea value:', value);
  }
}
```

### Using NgModule (Legacy)

If you're using NgModules, import the `TextareaModule`:

```typescript
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TextareaModule } from './ui/shangjc/textarea';

@NgModule({
  declarations: [YourComponent],
  imports: [
    CommonModule,
    TextareaModule
  ]
})
export class YourModule { }
```

Then use the components in your templates:

```html
<ng-shangjc-textarea placeholder="Enter your message..."></ng-shangjc-textarea>
```

## Basic Usage

### Default Example

```typescript
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TextareaComponent } from './ui/shangjc/textarea';

@Component({
  selector: 'app-example',
  standalone: true,
  imports: [CommonModule, TextareaComponent],
  template: `
    <div class="w-80">
      <ng-shangjc-textarea
        placeholder="Enter your message..."
        label="Message"
        (valueChange)="onMessageChange($event)">
      </ng-shangjc-textarea>
    </div>
  `,
})
export class ExampleComponent {
  onMessageChange(value: string) {
    console.log('Message changed:', value);
  }
}
```

### With Auto-resize

```typescript
<ng-shangjc-textarea
  placeholder="This textarea will grow as you type..."
  label="Auto-resize Textarea"
  [autoResize]="true"
  [minRows]="3"
  [maxRows]="10">
</ng-shangjc-textarea>
```

### With Character Count

```typescript
<ng-shangjc-textarea
  placeholder="Enter up to 500 characters..."
  label="Limited Input"
  [maxLength]="500"
  [showCharacterCount]="true">
</ng-shangjc-textarea>
```

### With Reactive Forms

```typescript
import { Component } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { TextareaComponent } from './ui/shangjc/textarea';

@Component({
  selector: 'app-contact',
  standalone: true,
  imports: [ReactiveFormsModule, TextareaComponent],
  template: `
    <form [formGroup]="contactForm" class="space-y-4 w-80">
      <ng-shangjc-textarea
        formControlName="message"
        label="Message"
        placeholder="Enter your message"
        [maxLength]="1000"
        [showCharacterCount]="true"
        [autoResize]="true"
        [error]="messageError">
      </ng-shangjc-textarea>
    </form>
  `
})
export class ContactComponent {
  contactForm = new FormGroup({
    message: new FormControl('', { validators: [Validators.required, Validators.maxLength(1000)] })
  });

  get messageError() {
    const control = this.contactForm.get('message');
    if (control?.hasError('required')) return 'Message is required';
    if (control?.hasError('maxlength')) return 'Message must be less than 1000 characters';
    return '';
  }
}
```

## Advanced Usage

### Controlled Component

```typescript
import { Component, signal } from '@angular/core';
import { TextareaComponent } from './ui/shangjc/textarea';

@Component({
  selector: 'app-controlled-example',
  standalone: true,
  imports: [TextareaComponent],
  template: `
    <div class="space-y-4 w-80">
      <ng-shangjc-textarea
        placeholder="Controlled textarea..."
        label="Controlled Input"
        [(value)]="message"
        [maxLength]="200"
        [showCharacterCount]="true">
      </ng-shangjc-textarea>
      
      <div class="p-4 bg-gray-100 rounded">
        <p class="text-sm">Current value: {{ message() }}</p>
        <button (click)="clearMessage()" class="mt-2 px-3 py-1 bg-blue-500 text-white rounded">
          Clear
        </button>
      </div>
    </div>
  `
})
export class ControlledExampleComponent {
  message = signal('');

  clearMessage() {
    this.message.set('');
  }
}
```

### Custom Styling

```typescript
<ng-shangjc-textarea
  placeholder="Custom styled textarea..."
  label="Custom Styling"
  [class]="'border-blue-300 bg-blue-50 focus:ring-blue-500'"
  [labelClass]="'text-blue-600 font-semibold'"
  [errorClass]="'text-red-600 italic'">
</ng-shangjc-textarea>
```

## API Reference

### TextareaComponent

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `placeholder` | `string` | `''` | Placeholder text for the textarea |
| `label` | `string` | `''` | Label text displayed above the textarea |
| `error` | `string` | `''` | Error message displayed below the textarea |
| `disabled` | `boolean` | `false` | Whether the textarea is disabled |
| `readonly` | `boolean` | `false` | Whether the textarea is readonly |
| `required` | `boolean` | `false` | Whether the textarea is required |
| `autoResize` | `boolean` | `false` | Enable automatic height adjustment |
| `maxLength` | `number` | `undefined` | Maximum character limit |
| `showCharacterCount` | `boolean` | `false` | Show character counter |
| `rows` | `number` | `3` | Number of visible rows (when not auto-resizing) |
| `maxRows` | `number` | `undefined` | Maximum rows when auto-resizing |
| `minRows` | `number` | `undefined` | Minimum rows when auto-resizing |
| `size` | `'default' \| 'sm' \| 'lg'` | `'default'` | Size variant |
| `controlButton` | `boolean` | `true` | Whether to show the clear button |
| `class` | `string` | `''` | Additional CSS classes for textarea |
| `labelClass` | `string` | `''` | Additional CSS classes for label |
| `errorClass` | `string` | `''` | Additional CSS classes for error message |
| `ariaLabel` | `string` | `undefined` | ARIA label for accessibility |
| `ariaDescribedby` | `string` | `undefined` | ARIA described-by for accessibility |
| `ariaInvalid` | `boolean` | `undefined` | ARIA invalid state |
| `name` | `string` | `undefined` | Name attribute for form submission |
| `autocomplete` | `boolean` | `false` | HTML autocomplete attribute |
| `autofocus` | `boolean` | `false` | Whether textarea should be focused on page load |
| `title` | `string` | `undefined` | Title attribute for accessibility |
| `role` | `string` | `undefined` | ARIA role attribute |
| `id` | `string` | `auto-generated` | ID of textarea element |
| `value` | `string` | `''` | The value of the textarea field (two-way binding supported) |

### Events

| Event | Type | Description |
|-------|------|-------------|
| `valueChange` | `EventEmitter<string>` | Emitted when textarea value changes |
| `focused` | `EventEmitter<void>` | Emitted when textarea receives focus |
| `blurred` | `EventEmitter<void>` | Emitted when textarea loses focus |

### Public Methods

| Method | Parameters | Description |
|--------|------------|-------------|
| `focus()` | - | Programmatically focus the textarea |
| `blur()` | - | Programmatically blur the textarea |
| `select()` | - | Select all text in the textarea |
| `setSelectionRange()` | `start: number, end: number` | Set text selection range |

## Accessibility

- **Keyboard Navigation**: Full support for Tab, Shift+Tab, Enter, Space, Arrow keys, and standard textarea shortcuts
- **ARIA Attributes**: Proper ARIA labels, roles, and states for screen readers
- **Focus Management**: Visible focus indicators and proper focus handling
- **Screen Reader**: Compatible with screen readers with proper announcements
- **Semantic Structure**: Uses proper HTML semantic elements and attributes

### ARIA Features

- `aria-label` for custom accessibility labels
- `aria-describedby` for additional context
- `aria-invalid` for validation states
- Character count announcements for screen readers
- Proper focus management and keyboard navigation

## Browser Support

- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+

## Contributing

See the main project [CONTRIBUTING.md](../../CONTRIBUTING.md) for guidelines.

---

**Part of ng-shangjc component library** • [Documentation](https://juliancallejas.github.io/ng-shangjc-docs/)

<p align="center">
<a href="https://github.com/JulianCallejas">
  <img src="https://res.cloudinary.com/dphleqb5t/image/upload/v1740784502/github-jc-develop/JC-LOGO-Horizontal-170-50-thin-github_uu3b5n.svg" width="170" alt="{ jc - develop }"  /> 
</a>
</p>