# Angular 연동

이 디렉터리는 **TypeScript 소스로 배포**됩니다. 미리 컴파일한 Angular
라이브러리는 빌드에 쓰인 Angular 버전과 소비자 버전이 맞아야 하는데, 소스로
두면 소비자의 Angular 컴파일러가 직접 컴파일하므로 Angular 14 이상 어느
버전에서도 같은 파일이 동작합니다.

## 설정 (택 1)

### 방법 A — tsconfig 에 경로 추가 (권장)

`tsconfig.app.json` 의 `include` 에 한 줄 추가하면 Angular CLI 가 이 소스를
앱과 함께 컴파일합니다.

```jsonc
{
  "include": [
    "src/**/*.ts",
    "node_modules/@aeriz/wysiwyg/angular/*.ts" // ← 추가
  ]
}
```

### 방법 B — 파일 복사

`aeriz-editor.directive.ts` 를 앱 소스 안으로 복사합니다. 의존성은
`@angular/core`, `@angular/forms`, `@aeriz/wysiwyg` 뿐입니다.

## 스타일시트

`angular.json` 의 `styles` 배열에 추가합니다.

```jsonc
"styles": [
  "node_modules/@aeriz/wysiwyg/dist/aeriz-wysiwyg.min.css",
  "src/styles.css"
]
```

## 사용

### standalone 컴포넌트

```ts
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AerizEditorDirective } from '@aeriz/wysiwyg/angular';

@Component({
  standalone: true,
  imports: [FormsModule, AerizEditorDirective],
  template: `
    <div aerizEditor [(ngModel)]="html" theme="dark" placeholder="내용을 입력하세요"></div>
    <pre>{{ html }}</pre>
  `,
})
export class ComposeComponent {
  html = '<p>안녕하세요</p>';
}
```

### NgModule 앱

```ts
import { AerizWysiwygModule } from '@aeriz/wysiwyg/angular';

@NgModule({
  imports: [BrowserModule, FormsModule, AerizWysiwygModule],
})
export class AppModule {}
```

## 바인딩 방식

| 방식 | 템플릿 |
| --- | --- |
| 단방향 | `<div aerizEditor [value]="html" (valueChange)="html = $event"></div>` |
| 양방향 | `<div aerizEditor [(value)]="html"></div>` |
| ngModel | `<div aerizEditor [(ngModel)]="html"></div>` |
| Reactive Forms | `<div aerizEditor formControlName="body"></div>` |

## 입력 / 출력

| 이름 | 타입 | 설명 |
| --- | --- | --- |
| `value` | `string` | 본문 HTML |
| `placeholder` | `string` | 빈 본문 안내 문구 |
| `toolbar` | `ToolbarConfig \| false` | 툴바 구성. `false` 면 숨김 |
| `theme` | `'light' \| 'dark'` | 테마 |
| `locale` | `'en' \| 'ko' \| 'ja' \| 'zh'` | UI 언어 |
| `imageUploadUrl` | `string` | 이미지 업로드 API URL |
| `fileUploadUrl` | `string` | 파일 업로드 API URL |
| `imageUpload` | `(file: File) => Promise<string>` | 직접 업로드 핸들러 |
| `fileUpload` | `(file: File) => Promise<string>` | 직접 업로드 핸들러 |
| `(valueChange)` | `string` | 본문 변경 |
| `(stateChange)` | `EditorState` | 블록/선택 상태 변경 |
| `(ready)` | `AerizEditor` | 인스턴스 생성 완료 |

## 성능 메모

디렉티브는 에디터 인스턴스를 `NgZone` **밖에서** 생성합니다. 에디터는
`selectionchange` 등 고빈도 이벤트를 구독하므로, zone 안에서 만들면 캐럿을
움직일 때마다 변경 감지가 돌게 됩니다. 값이 실제로 바뀔 때만 zone 으로
복귀해 한 번 감지를 돌립니다.

## 뷰어

```html
<div aerizViewer [blocks]="blocks" theme="light"></div>
<!-- 블록 대신 HTML 문자열도 가능 -->
<div aerizViewer [html]="savedHtml"></div>
```
