# @ivtui/text-editor

A powerful and customizable text editor built with TipTap for React applications.

## Features

- ✅ **Text Formatting**: Bold, italic, underline, strikethrough, and more
- ✅ **Lists**: Bullet lists and ordered lists with custom styling
- ✅ **Text Alignment**: Left, center, right, and justify alignment
- ✅ **Links & Images**: Easy insertion of links and images
- ✅ **Resizable Editor**: Drag to resize the editor height
- ✅ **Word Count**: Built-in word counter display
- ✅ **Accessibility**: Full keyboard navigation and screen reader support
- ✅ **TypeScript**: Complete TypeScript support with proper types
- ✅ **Customizable**: Easily customizable styling and behavior

## Installation

```bash
npm install @ivtui/text-editor
```

## Dependencies

This package requires the following peer dependencies:

- `react` ^19.1.0
- `react-dom` ^19.1.0
- `@ivtui/base` (workspace package)
- `@iconify/react`
- `clsx`

## Basic Usage

```tsx
import { TextEditor } from "@ivtui/text-editor"
import { useState } from "react"

function MyComponent() {
  const [content, setContent] = useState("")

  return (
    <TextEditor
      value={content}
      onChange={setContent}
      placeholder="Start typing your content..."
      maxHeight={400}
    />
  )
}
```

## Props

### TextEditorProps

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `value` | `string` | `""` | HTML content of the editor |
| `onChange` | `(value: string) => void` | - | Callback fired when content changes |
| `placeholder` | `string` | `""` | Placeholder text when editor is empty |
| `className` | `string` | - | Additional CSS classes for the container |
| `disabled` | `boolean` | `false` | Whether the editor is disabled |
| `error` | `boolean` | `false` | Whether to show error styling |
| `maxHeight` | `number \| string` | `400` | Maximum height of the editor |

## Ref Interface

The `TextEditor` component exposes several methods through a ref:

```tsx
import { TextEditor, type TextEditorRef } from "@ivtui/text-editor"
import { useRef } from "react"

function MyComponent() {
  const editorRef = useRef<TextEditorRef>(null)

  const handleFocus = () => {
    editorRef.current?.focus()
  }

  const handleClear = () => {
    editorRef.current?.clear()
  }

  const getContent = () => {
    const html = editorRef.current?.getHTML()
    const text = editorRef.current?.getText()
    console.log({ html, text })
  }

  return (
    <TextEditor
      ref={editorRef}
      // ... other props
    />
  )
}
```

### TextEditorRef Methods

| Method | Type | Description |
|--------|------|-------------|
| `focus()` | `() => void` | Focus the editor |
| `getHTML()` | `() => string` | Get the HTML content |
| `getText()` | `() => string` | Get the plain text content |
| `setContent(content: string)` | `(content: string) => void` | Set the editor content |
| `clear()` | `() => void` | Clear the editor content |

## Advanced Usage

### With Form Libraries

```tsx
import { TextEditor } from "@ivtui/text-editor"
import { useForm } from "react-hook-form"

interface FormData {
  description: string
}

function MyForm() {
  const form = useForm<FormData>()

  return (
    <form onSubmit={form.handleSubmit(data => console.log(data))}>
      <TextEditor
        value={form.watch("description")}
        onChange={(value) => form.setValue("description", value)}
        error={!!form.formState.errors.description}
        placeholder="Enter description..."
      />

      <button type="submit">Submit</button>
    </form>
  )
}
```

### Custom Height Control

```tsx
import { TextEditor } from "@ivtui/text-editor"
import { useState } from "react"

function ResizableEditor() {
  const [content, setContent] = useState("")
  const [height, setHeight] = useState(300)

  return (
    <div>
      <div className="mb-4">
        <label>
          Height: {height}px
          <input
            type="range"
            min="200"
            max="800"
            value={height}
            onChange={(e) => setHeight(Number(e.target.value))}
          />
        </label>
      </div>

      <TextEditor
        value={content}
        onChange={setContent}
        maxHeight={height}
        placeholder="Resize me!"
      />
    </div>
  )
}
```

## Styling

The editor uses Tailwind CSS classes and can be customized by:

1. **Container styling**: Pass custom classes via the `className` prop
2. **Global CSS**: Override the CSS custom properties or classes
3. **Theme customization**: Modify the editor.css file

### Custom CSS

```css
/* Custom editor styling */
.my-custom-editor .tiptap {
  font-family: 'Custom Font', sans-serif;
  font-size: 16px;
  line-height: 1.6;
}

.my-custom-editor .tiptap h1 {
  color: #333;
  border-bottom: 2px solid #007bff;
}
```

## TipTap Extensions

The editor includes the following TipTap extensions:

- **StarterKit**: Basic functionality (headings, paragraphs, etc.)
- **Underline**: Text underline formatting
- **TextStyle**: Text styling support
- **Color**: Text color support
- **TextAlign**: Text alignment (left, center, right, justify)
- **Image**: Image insertion with base64 support
- **Link**: Link insertion and management
- **BulletList**: Bullet point lists
- **OrderedList**: Numbered lists
- **ListItem**: List item support
- **CharacterCount**: Character counting (10,000 limit)

## Development

To run the Storybook stories for development:

```bash
npm run storybook
```

## Contributing

Please read the main project's contributing guidelines before submitting PRs.

## License

Private - Investtal Design System
