# 컬럼 타입 및 컬럼 설정 (실전 상세)

data-grist는 다양한 컬럼 타입을 지원하며, grist-editor를 통해 고급 에디터를 사용할 수 있습니다. 아래는 실제 코드/스토리북/현업 패턴을 바탕으로 한 상세 매뉴얼입니다.

---

## 1. 컬럼 속성 표 (공통)

| 속성명      | 타입/예시                  | 설명/용도                                      |
| ----------- | -------------------------- | ---------------------------------------------- |
| type        | 'string'                   | 컬럼 데이터 타입 (필수)                        |
| name        | 'name'                     | 데이터 키 (필수, data.records의 필드명과 일치) |
| header      | '이름' 또는 {renderer: fn} | 컬럼 헤더명 또는 커스텀 렌더러                 |
| editor      | 'input', 'value-map' 등    | 셀 편집기 타입 (grist-editor 확장 포함)        |
| renderer    | fn 또는 'text' 등          | 셀 표시 방식 커스텀 함수/타입                  |
| sortable    | true/false                 | 정렬 가능 여부                                 |
| filter      | true/false/객체            | 필터링 지원/설정                               |
| validation  | fn                         | 값 검증 함수 (after, before, record, column)   |
| options     | 객체                       | editor/renderer에 전달할 추가 옵션             |
| hidden      | true/false                 | 컬럼 숨김 여부                                 |
| resizable   | true/false                 | 컬럼 너비 조절 가능 여부                       |
| width       | 120, '20%' 등              | 컬럼 너비(px, %, 함수)                         |
| align       | 'left'/'right'/'center'    | 셀 정렬                                        |
| accumulator | 'sum', 'avg' 등            | 집계 함수(합계/평균/카운트 등)                 |
| imex        | true/false/객체            | import/export 지원/설정                        |
| multiple    | true/false                 | 다중 선택 지원(예: select 타입)                |
| rowCount    | true/false                 | 행 번호 표시 여부                              |
| handlers    | { click, ... }             | 셀/컬럼 이벤트 핸들러                          |

---

## 2. 컬럼 타입별 상세 (editor/renderer/옵션/예시/확장)

### string

- **기본 editor**: input
- **기본 renderer**: text
- **추가 옵션**: maxLength, placeholder, defaultValue
- **예시**
  ```js
  { type: 'string', name: 'title', editor: 'input', options: { maxLength: 50, placeholder: '제목 입력' } }
  ```
- **custom editor/renderer**
  ```js
  { type: 'string', name: 'custom', editor: 'my-editor', renderer: v => v.toUpperCase() }
  // my-editor는 grist-editor에서 등록 필요
  ```
- **실수/문제/해결법**: editor 오타, options 구조 오류 주의

---

### number

- **기본 editor**: input[type=number]
- **기본 renderer**: text
- **추가 옵션**: min, max, step, defaultValue
- **예시**
  ```js
  { type: 'number', name: 'price', editor: 'input', options: { min: 0, max: 10000, step: 100 } }
  ```
- **custom editor/renderer**
  ```js
  { type: 'number', name: 'custom', editor: 'my-number-editor', renderer: v => v.toLocaleString() }
  ```
- **실수/문제/해결법**: min/max/step 누락 시 입력 제약 없음

---

### boolean

- **기본 editor**: checkbox
- **기본 renderer**: 체크박스/아이콘
- **예시**
  ```js
  { type: 'boolean', name: 'active', editor: 'checkbox' }
  ```
- **custom renderer**
  ```js
  { type: 'boolean', name: 'active', renderer: v => v ? '✅' : '❌' }
  ```

---

### select (실전 완전 정리)

- **기본 editor**: select
- **기본 renderer**: text/label
- **필수 옵션**: options (아래 다양한 방식 지원)
- **다중 선택**: multiple: true

#### 1. 문자열 배열

```js
{
  type: 'select',
  name: 'status',
  options: { options: ['진행중', '완료', '보류'] }
}
// label, value 모두 '진행중', '완료', '보류'
```

#### 2. 객체 배열

```js
{
  type: 'select',
  name: 'priority',
  options: {
    options: [
      { name: '긴급', value: 1 },
      { display: '보통', value: 2 },
      { name: '낮음', value: 3 }
    ]
  }
}
// label: name 또는 display, value: value
```

#### 3. 함수 반환 (동적 옵션)

```js
{
  type: 'select',
  name: 'category',
  options: {
    options: (value, column, record, rowIndex, field) => {
      // 예: record에 따라 옵션 다르게
      return record.type === 'A' ? ['X', 'Y'] : ['Z']
    }
  }
}
```

#### 4. Promise 반환 (비동기 옵션)

```js
{
  type: 'select',
  name: 'dynamic',
  options: {
    options: async () => {
      const result = await fetch('/api/options').then(res => res.json())
      return result // ['A', 'B'] 또는 [{name, value}]
    }
  }
}
```

#### 5. rowOptionField (행별 옵션)

```js
{
  type: 'select',
  name: 'category',
  editor: 'select',
  options: { options: ['A', 'B', 'C'] },
  rowOptionField: 'categoryOptions'
}
// → record.categoryOptions에서 옵션을 가져옴
```

#### 6. 다중 선택

```js
{
  type: 'select',
  name: 'tags',
  options: { options: ['A', 'B', 'C'] },
  multiple: true
}
// value는 배열로 전달됨
```

#### 7. custom renderer (label/value 매핑, 이모지 등)

```js
{
  type: 'select',
  name: 'priority',
  options: { options: [ { name: '긴급', value: 1 }, { name: '보통', value: 2 } ] },
  renderer: v => v === 1 ? '🔥 긴급' : v === 2 ? '⚡ 보통' : v
}
```

#### 8. 실전 팁/문제/해결법

- options는 **문자열 배열/객체 배열/함수/Promise** 모두 지원
- label은 name 또는 display, value는 value
- 동적/비동기 옵션 완벽 지원
- rowOptionField로 행별 옵션도 가능
- multiple 사용 시 value는 배열
- options 구조가 잘못되면 드롭다운이 비거나 렌더링 오류
- value와 label이 다르면 renderer로 표시값 커스텀 권장
- filter/sortable 옵션도 함께 사용 가능

#### 9. 예시 모음

```js
// 단일 선택, label/value 다름
{
  type: 'select',
  name: 'role',
  options: {
    options: [
      { name: '관리자', value: 'admin' },
      { name: '사용자', value: 'user' }
    ]
  },
  renderer: v => v === 'admin' ? '👑 관리자' : '👤 사용자'
}

// 다중 선택
{
  type: 'select',
  name: 'tags',
  options: { options: ['A', 'B', 'C'] },
  multiple: true
}

// 동적 옵션
{
  type: 'select',
  name: 'dynamic',
  options: { options: (v, c, r) => r.type === 'A' ? ['X', 'Y'] : ['Z'] }
}

// 비동기 옵션
{
  type: 'select',
  name: 'async',
  options: { options: async () => await fetch('/api/options').then(r => r.json()) }
}
```

---

### date

- **기본 editor**: date-picker
- **기본 renderer**: yyyy-MM-dd
- **추가 옵션**: min, max, format
- **예시**
  ```js
  { type: 'date', name: 'due', editor: 'date-picker', options: { min: '2023-01-01', max: '2024-12-31' } }
  ```

---

### text

- **기본 editor**: textarea
- **기본 renderer**: text
- **추가 옵션**: maxLength, rows, placeholder
- **예시**
  ```js
  { type: 'text', name: 'desc', editor: 'textarea', options: { rows: 3, maxLength: 200 } }
  ```

---

### object

- **기본 editor**: json-editor
- **기본 renderer**: JSON.stringify
- **예시**
  ```js
  { type: 'object', name: 'meta', editor: 'json-editor' }
  ```

---

### value-map (grist-editor 확장)

- **editor**: value-map
- **필수 옵션**: valuetype, defaultValue
- **예시**
  ```js
  { type: 'value-map', name: 'meta', editor: 'value-map', options: { valuetype: 'number', defaultValue: 0 } }
  ```
- **custom renderer**
  ```js
  { type: 'value-map', name: 'meta', renderer: v => Object.keys(v).length + '개' }
  ```

---

### parameters (grist-editor 확장)

- **editor**: parameters
- **필수 옵션**: spec, context
- **예시**
  ```js
  { type: 'parameters', name: 'params', editor: 'parameters', options: { spec: {...}, context: {...} } }
  ```

---

### i18n-label (grist-editor 확장)

- **editor**: i18n-label
- **필수 옵션**: languages
- **예시**
  ```js
  { type: 'i18n-label', name: 'label', editor: 'i18n-label', options: { languages: ['ko', 'en'] } }
  ```

---

### 기타(grist-editor 확장)

- **hashtags**: editor: hashtags, options: 없음/필수 없음
- **crontab**: editor: crontab, options: 없음/필수 없음
- **duration**: editor: duration, options: 없음/필수 없음
- **quantifier**: editor: quantifier, options: 없음/필수 없음
- **signature**: editor: signature, options: 없음/필수 없음
- **data**: editor: data, options: 없음/필수 없음

---

## 3. editor/renderer custom 등록/사용법

- **함수형 renderer**
  ```js
  { type: 'string', name: 'desc', renderer: v => v && v.length > 10 ? v.slice(0, 10) + '...' : v }
  ```
- **문자열 editor/renderer**
  ```js
  { type: 'string', name: 'desc', editor: 'input', renderer: 'text' }
  ```
- **커스텀 editor/renderer**
  ```js
  // grist-editor에서 'my-editor' 등록 후 사용
  { type: 'string', name: 'custom', editor: 'my-editor', renderer: 'my-renderer' }
  ```
- **등록 방법**
  - grist-editor 패키지에서 custom editor/renderer를 등록 후, 컬럼 editor/renderer에 타입명 지정
  - 예: `customElements.define('my-editor', class extends HTMLElement { ... })`

---

## 4. 실전 팁/문제/해결법

- editor/renderer 등록 시 타입 오타 주의
- 필수 옵션 누락 시 동작 오류(특히 select, value-map, parameters, i18n-label)
- options 구조는 editor마다 다르므로 반드시 공식 소스/스토리북 참고
- 커스텀 editor/renderer는 grist-editor에서 등록 후 사용
- data.records의 키와 columns의 name이 반드시 일치해야 함
- 컬럼 name/type/header/record/handlers 등 필수 속성 누락 주의

---

## 5. 참고/스토리북/데모

- 각 editor/renderer별 옵션/동작은 grist-editor 소스/스토리북에서 확인
- demo/스토리북에서 실전 config/패턴/문제 상황 예시 다수 제공

```js
const columns = [
  {
    type: 'string',
    name: 'name',
    header: '이름',
    sortable: true,
    filter: true,
    editor: 'input',
    renderer: v => v,
    width: 120,
    align: 'left',
    validation: (after, before) => !!after,
    options: {},
    handlers: { click: (columns, data, column, record) => console.log(record) }
  },
  {
    type: 'value-map',
    name: 'meta',
    header: '메타정보',
    editor: 'value-map',
    options: { valuetype: 'number', defaultValue: 0 }
  },
  {
    type: 'i18n-label',
    name: 'label',
    header: '다국어',
    editor: 'i18n-label'
  }
]
```

```html
<data-grist .columns="${columns}"></data-grist>
```
