sellmate-design-system-react 9.0.0-beta.21 → 9.0.0-beta.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -1153,6 +1153,25 @@ const columns: STableColumn[] = [
1153
1153
 
1154
1154
  `SSplitter` 의 구분선은 평소 자리만 잡고 칠해지지 않다가, 경계에 커서를 올리거나 포커스를 주면 그때 드러난다 — 조절 가능한 자리라는 신호다. **항상 보이는 선이 필요하면 `SDivider` 를 쓴다.** 선 색·두께·주변 여백은 토큰이 정하므로 직접 주지 않는다.
1155
1155
 
1156
+ **세로 구분선의 길이는 `height` prop 으로 준다 — `className` 의 `h-*` 로 주지 않는다.**
1157
+
1158
+ ```tsx
1159
+ // 줄 높이를 그대로 채운다 (기본)
1160
+ <div className="flex items-center gap-sd-8">
1161
+ <span>총 주문 3건</span>
1162
+ <SDivider vertical />
1163
+ <span>총 품목 12건</span>
1164
+ </div>
1165
+
1166
+ // 양옆 글자보다 짧은 선이 필요할 때만 길이를 정한다
1167
+ <SDivider vertical height={20} />
1168
+
1169
+ // 하지 말 것 — 선이 줄 맨 위에 붙는다
1170
+ <SDivider vertical className="h-sd-20" />
1171
+ ```
1172
+
1173
+ 길이를 주지 않으면 `align-self: stretch` 로 부모 줄 높이를 채우는데, `stretch` 는 높이가 `auto` 일 때만 늘린다. `className` 으로 높이를 정하면 `stretch` 가 조용히 무효가 되어 선이 위로 솟는다. `height` 는 길이와 교차축 가운데 정렬을 함께 적용하므로 이 함정이 없다 — 위·아래 정렬이 필요하면 `className="self-start"` 처럼 명시한다. (`sellmate/divider-vertical-height` 규칙이 잡는다.)
1174
+
1156
1175
  ```tsx
1157
1176
  <SSplitter defaultValue={30} limits={[20, 60]}>
1158
1177
  <SSplitter.Before>내비게이션</SSplitter.Before>
@@ -1198,9 +1217,19 @@ const columns: STableColumn[] = [
1198
1217
 
1199
1218
  `SEditor` 는 **서식이 값의 일부일 때만** 쓴다. 값을 HTML 문자열로 주고받으므로 저장·검색·비교가 평문보다 비싸고, 화면에 다시 보여줄 때도 HTML 로 렌더해야 한다. 서식이 필요 없는 메모·사유는 `STextarea` 다 — "입력창이 커 보여서" 고르는 컴포넌트가 아니다. 반대로 공지·안내문·상품 상세처럼 **작성자가 정한 강조와 목록이 그대로 보여야 하는 글**이면 `STextarea` 로는 표현할 수 없다.
1200
1219
 
1201
- `SEditor` 도 `SInput`·`STextarea` 와 같은 폼 필드다 — `label`·`hint`·`rules`·`errorMessage` 를 자기 prop 으로 받고 `SForm` 제출 검증에도 들어간다. 빈 문서는 빈 문자열로 나오므로 `required` 규칙이 그대로 걸린다. 툴바 구성은 `toolbar` 줄이거나 늘릴 수 있고, 서식 입력이 필요 없는 자리에 굳이 놓아야 한다면 `toolbar={false}` 가 아니라 `STextarea` 를 고른다.
1220
+ `SEditor` 도 `SInput`·`STextarea` 와 같은 폼 필드다 — `label`·`hint`·`rules`·`errorMessage` 를 자기 prop 으로 받고 `SForm` 제출 검증에도 들어간다. 빈 문서는 빈 문자열로 나오므로 `required` 규칙이 그대로 걸린다. **툴바를 끄는 길은 없다** 서식 입력이 필요 없는 자리라면 서식 없는 `SEditor` 가 아니라 `STextarea` 를 고른다.
1221
+
1222
+ 툴바는 **프리셋 둘 중 하나뿐이다.** 기본은 쓸 수 있는 것을 모두 보이고, **`simple` 을 켜면 글자에 거는 서식만 남는다** — 목록·정렬·인용·코드·링크·이미지·구분선이 빠지고 선택했을 때 뜨는 판도 같은 범위로 줄어든다. 받은 글의 **문단 구조까지 작성자를 따라가면 곤란한 자리**(좁은 칸의 메모·사유·짧은 안내문)가 `simple` 이다. 항목을 직접 조합하는 prop 은 없다 — 화면마다 다른 툴바가 서면 그 자체가 학습 비용이 된다.
1223
+
1224
+ 본문에서 따옴표·하이픈·화살표는 **자동으로 치환된다**(`"` → `“”`, `--` → `—`, `->` → `→`). 끌 수 없으므로, 상품 코드·규격 문자열처럼 **입력한 그대로 남아야 하는 값**은 `SEditor` 본문이 아니라 `SInput` 으로 따로 받는다.
1225
+
1226
+ 툴바는 **자리를 지킨다**(고정). 긴 글을 쓰는 동안 막대가 화면 밖으로 나가지 않으므로, 툴바를 따로 감싸거나 위치를 주지 않는다.
1202
1227
 
1203
- 글을 선택하면 **그 위에 서식 판이 뜬다**(버블 메뉴). 툴바까지 커서를 옮기지 않고 바로 굵게·색·링크를 걸기 위한 것이라 기본으로 켜져 있고, 읽기 전용·비활성일 때는 뜨지 않는다. 판은 줄이라 줄바꿈하지 않으므로 **좁은 칸에 놓인 에디터라면 `bubbleMenu` 항목을 줄이거나 `false` 끈다**그대로 두면 필드 밖으로 넘친다. 뜨는 자리는 DS 잡는다, 직접 감싸거나 위치를 주지 않는다.
1228
+ 툴바에는 **글자 크기 드롭다운**과 **글자색 팔레트**가 들어 있다 — 작성자가 문단마다 크기·색을 직접 지정할 수 있고, 크기 목록 맨 위 `기본` 은 지정을 떼는 자리다. 크기 눈금은 화면 타이포(§2-1) 아니라 워드프로세서의 눈금이라 본문보다 훨씬 단계까지 있다. **눈금도 팔레트도 좁히는 prop 없다** 화면마다 고를 있는 것이 다르면 같은 글이 어디에 붙느냐에 따라 다르게 보이기 때문이다. 그래서 **작성자가 화면 리듬을 벗어나면 곤란한 자리(상품 상세 설명·반복 노출되는 안내문 등)라면 `SEditor` 맞는 자리인지 먼저 본다** 서식이 값의 일부가 아니라면 `STextarea` 다. 고른 크기·색은 저장되는 HTML 그대로 남아 나중에 되돌릴 수 없다.
1229
+
1230
+ 본문에는 **표**도 들어간다 — 툴바의 `표` 드롭다운에서 격자를 끌어 크기를 고르고(최대 8행 × 10열), 행·열을 늘리고, 칸을 병합한다. **열 너비는 균등 고정이고 바꿀 수 없다**: 너비를 저장하면 그 값이 px 로 박혀 작성한 화면보다 좁은 곳에서 표가 넘친다. 대신 어떤 폭에서도 표가 상자 안에 들어오도록 열을 고르게 나눈다 — 열이 많은 표는 좁은 칸에서 글자가 잘게 접히므로, **열이 넷을 넘어가는 표라면 `SEditor` 본문이 아니라 `STable` 이 맞는 자리인지 본다.** 표는 작성자가 쓰는 글의 일부일 때만 여기에 있고, 데이터를 줄 세워 보여 주는 것은 `STable` 이다.
1231
+
1232
+ 글을 선택하면 **그 위에 서식 판이 뜬다**(버블 메뉴). 툴바까지 커서를 옮기지 않고 바로 굵게·색·링크를 거는 길이다. **끄고 켜는 prop 은 없다** — 편집할 수 있으면 언제나 뜨고, 읽기 전용·비활성일 때는 뜨지 않는다. 화면마다 있고 없고가 달라지면 그 자체가 학습 비용이 되기 때문이다. 판의 구성은 `simple` 이 막대와 함께 정한다. 뜨는 자리는 DS 가 잡는다, 직접 감싸거나 위치를 주지 않는다.
1204
1233
 
1205
1234
  `SEditor` 는 화면에 처음 놓일 때 **에디터 엔진을 따로 불러온다** — 앱 초기 번들에는 들어가지 않는다. 그동안은 같은 크기의 빈 편집 영역이 자리를 지키므로 레이아웃은 흔들리지 않지만, **마운트하자마자 `ref.current.getHTML()` 로 값을 읽거나 툴바를 누를 수는 없다.** 열자마자 커서를 놓고 싶으면 `ref.current.focus()` 를 그냥 부르면 된다 — 준비되는 순간 대신 실행된다.
1206
1235
 
@@ -1661,24 +1690,28 @@ export default function ProductListPage() {
1661
1690
 
1662
1691
  행 높이를 줄이는 것은 `dense` 다. 세로 여백만 줄고 좌우 패딩은 그대로라, 값이 잘리지 않으면서 한 화면에 들어가는 행 수가 늘어난다.
1663
1692
 
1664
- **어느 쪽이 편한지는 화면이 아니라 사용자가 안다.** 그래서 목록 페이지는 밀도를 고정하지 말고 `useDensityToggle` 고를 있게 둔다페이지네이션 바 우측(rows per page 셀렉트 왼쪽)에 `좁게 보기` · `넓게 보기` 링크가 붙는다.
1693
+ **어느 쪽이 편한지는 화면이 아니라 사용자가 안다.** 그래서 `dense` 밀도를 고정하는 스위치가 아니라 **시작 밀도이자 밀도 토글의 스위치**다켜면 하단 바 우측(rows per page 셀렉트 왼쪽)에 `좁게 보기` · `넓게 보기` 링크가 붙는다. 켜고 끄는 별도 prop 은 없다.
1665
1694
 
1666
1695
  ```tsx
1667
- // 사용자가 고른 밀도는 다음 방문에도 남는 것이 자연스럽다 — 저장은 페이지 몫이다
1668
- const [dense, setDense] = useState(() => loadPref('list.dense', true));
1696
+ // 좁게 시작하고, 사용자가 바꾸는 밀도는 표가 알아서 들고 간다
1697
+ <STable dense useRowsPerPageSelect pagination={{ currentPage, lastPage }} />;
1698
+
1699
+ // 사용자가 고른 밀도를 다음 방문에도 남기려는 화면만 받아서 저장한다.
1700
+ // 저장한 값은 시작 밀도로만 돌려준다 — 되돌려 넣지 않는다
1701
+ const [initialDense] = useState(() => loadPref('list.dense', true));
1669
1702
 
1670
1703
  <STable
1671
- dense={dense}
1672
- onDenseChange={next => { setDense(next); savePref('list.dense', next); }}
1673
- useDensityToggle
1704
+ dense={initialDense}
1705
+ onDenseChange={next => savePref('list.dense', next)}
1674
1706
  useRowsPerPageSelect
1675
1707
  pagination={{ currentPage, lastPage }}
1676
1708
  />;
1677
1709
  ```
1678
1710
 
1679
- - **밀도는 `STable` 이 갖지 않는다.** `dense` 곧 현재 상태이고, `onDenseChange` 없이 `useDensityToggle` 켜면 눌러도 아무 일도 일어나지 않는다.
1680
- - **토글은 페이지네이션이 있을 때만 나타난다** 사는 곳이 바이기 때문이다. 페이지네이션 없는 표에서 밀도를 고르게 하려면 `STableBar` 쪽에 직접 둔다.
1681
- - 라벨과 아이콘은 현재 상태가 아니라 **누르면 되는 상태**를 가리킨다. `dense` `넓게 보기` 다.
1711
+ - **누른 뒤의 밀도는 `STable` 이 내부 상태로 들고 간다.** `onDenseChange` 없이도 토글은 동작한다. 저장이 필요한 화면만 받아서 저장하면 된다.
1712
+ - **`dense` `onDenseChange` 값을 되돌려 넣지 않는다.** 토글을 붙일지는 prop 정하므로, 넓게 순간 `dense` `false` 되면 토글이 사라져 다시 좁힐 길이 없다. prop 값을 바꿔 넘기는 것은 외부 버튼 등으로 밀도를 **되돌릴 때**만 쓴다 — 내부 밀도가 그 값으로 맞춰진다.
1713
+ - **`dense` 페이지네이션이 없어도 토글이 나온다** 하단 바를 토글만 담아 그린다. `dense` 아니면 토글도 없다.
1714
+ - 라벨과 아이콘은 현재 상태가 아니라 **누르면 되는 상태**를 가리킨다. 좁게 보고 있으면 `넓게 보기` 다.
1682
1715
 
1683
1716
  ### 4-3. 폼 페이지 (등록/수정)
1684
1717
 
@@ -1894,7 +1927,7 @@ export default function ProductDetailPage() {
1894
1927
  - [ ] 필터·폼·상세 정보를 `SKeyValueTable` 로 만들었는가 (컨트롤을 `div` 로 나열하지 않았는가). 필터를 `SChipFilter` 로 했다면 §3-7-11 의 판정을 거쳤는가
1895
1928
  - [ ] 섹션 구분에 `SSectionHeaderCard` 를 썼는가 (직접 만든 카드가 아니라)
1896
1929
  - [ ] 목록의 주요 액션이 `STableBar` 의 `rightActions` 에 있는가 (페이지 제목 줄이 아니라)
1897
- - [ ] 목록 페이지 표에 `useDensityToggle` 로 밀도를 고를 있게 뒀는가, `onDenseChange` 함께 줬는가 (§4-2 — 핸들러 없이 켜면 눌러도 아무 일도 없다)
1930
+ - [ ] 목록 페이지 표에 `dense` 로 밀도 토글을 띄웠는가, 값을 `onDenseChange` 결과로 되돌려 넣지는 않았는가 (§4-2 — 되돌려 넣으면 넓게 순간 토글이 사라진다)
1898
1931
  - [ ] 상태 표시에 `STag size="sm"` 을 썼는가
1899
1932
  - [ ] 테이블에서 양을 나타내는 컬럼(금액·수량·개수 등)이 전부 `align: 'right'` 인가
1900
1933
  - [ ] 번호·코드·전화번호·일자 컬럼에 `align: 'center'` 를 **명시**했는가 (생략하면 좌측이 된다)
package/README.md CHANGED
@@ -178,17 +178,18 @@ export default [
178
178
 
179
179
  **`error` 는 "지키지 않으면 깨지는 것" 에만 씁니다.** 앱 화면을 Tailwind 로 자유롭게 만드는 것은 정상이고, 디자인 시스템이 그 자유까지 막지 않습니다. 나머지는 권고(`warn`)입니다.
180
180
 
181
- | 규칙 | 기본 | 검출 대상 |
182
- | -------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
183
- | `sellmate/no-off-scale-spacing` | **error** | 스케일 밖 디자인 시스템 간격 (`gap-sd-13`) — Tailwind v4 에서 **조용히 무시되어** 스타일이 사라진다 |
184
- | `sellmate/no-raw-html-control` | **error** | 대응 컴포넌트가 있는 생 HTML (`<button>` `<input>` `<select>` `<textarea>` `<table>` `<form>` `<dialog>` `<hr>` `<details>` `<progress>`), `alert()`/`confirm()` — 디자인 시스템을 통째로 우회하는 경우 |
185
- | `sellmate/prefer-typo-preset` | warn | `text-14 font-bold` 같은 낱개 조합 `typo-*` 프리셋 |
186
- | `sellmate/component-group-gap` | warn | 같은 컴포넌트를 나열할 때의 그룹 간격 배열 방향에 따라 값이 다르다(체크박스 가로 24 / 세로 8) |
187
- | `sellmate/table-numeric-align` | warn | 수량 컬럼(금액·수량 등)에 `align: 'right'` 누락**`--fix` 자동 교정** |
188
- | `sellmate/require-locale-number` | warn | 수량 컬럼의 `toLocaleString()` 누락 — 자리 콤마 |
189
- | `sellmate/field-width-grade` | warn | 필드 폭이 `maxLength`(스키마 상한) 어긋남등급 미지정 · 등급 밖 폭 · 상한 대비 과부족 · 등급 px 직접 지정(**`--fix` 로 등급 이름 치환**) |
190
- | `sellmate/table-column-width` | warn | 컬럼 미지정(기본 120px 조용히 들어감) · px 아닌(`%` `clamp()`) · 값을 그리는 열의 `autoWidth` 오용 |
191
- | `sellmate/no-arbitrary-class` | **off** | 토큰이 있는 속성(색·타이포·간격·모서리) 임의 `text-[14px]`, `bg-[#eee]`. 고유 화면에는 정당한 사용이 많아 기본값은 끕니다 |
181
+ | 규칙 | 기본 | 검출 대상 |
182
+ | ---------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
183
+ | `sellmate/no-off-scale-spacing` | **error** | 스케일 밖 디자인 시스템 간격 (`gap-sd-13`) — Tailwind v4 에서 **조용히 무시되어** 스타일이 사라진다 |
184
+ | `sellmate/no-raw-html-control` | **error** | 대응 컴포넌트가 있는 생 HTML (`<button>` `<input>` `<select>` `<textarea>` `<table>` `<form>` `<dialog>` `<hr>` `<details>` `<progress>`), `alert()`/`confirm()` — 디자인 시스템을 통째로 우회하는 경우 |
185
+ | `sellmate/divider-vertical-height` | **error** | 세로 `SDivider` 의 높이를 `className="h-*"` 로 준 경우 — `align-self: stretch` 무효가 되어 선이 줄 맨 위에 붙는다. `height` prop 으로 준다(**`--fix` 로 치환**) |
186
+ | `sellmate/prefer-typo-preset` | warn | `text-14 font-bold` 같은 낱개 조합 `typo-*` 프리셋 |
187
+ | `sellmate/component-group-gap` | warn | 같은 컴포넌트를 나열할 때의 그룹 간격배열 방향에 따라 값이 다르다(체크박스 가로 24 / 세로 8) |
188
+ | `sellmate/table-numeric-align` | warn | 수량 컬럼(금액·수량 )`align: 'right'` 누락 — **`--fix` 자동 교정** |
189
+ | `sellmate/require-locale-number` | warn | 수량 컬럼의 `toLocaleString()` 누락 자리 콤마 |
190
+ | `sellmate/field-width-grade` | warn | 필드 폭이 `maxLength`(스키마 상한)와 어긋남 등급 미지정 · 등급 · 상한 대비 과부족 · 등급 px 직접 지정(**`--fix` 로 등급 이름 치환**) |
191
+ | `sellmate/table-column-width` | warn | 컬럼 미지정(기본 120px 이 조용히 들어감) · px 아닌 폭(`%` `clamp()`) · 값을 그리는 열의 `autoWidth` 오용 |
192
+ | `sellmate/no-arbitrary-class` | **off** | 토큰이 있는 속성(색·타이포·간격·모서리)의 임의 값 — `text-[14px]`, `bg-[#eee]`. 앱 고유 화면에는 정당한 사용이 많아 기본값은 끕니다 |
192
193
 
193
194
  `className` 뿐 아니라 `cn()`/`clsx()` 인자, 템플릿 리터럴, 객체 키 안까지 검사합니다.
194
195
 
@@ -286,9 +287,9 @@ export default [
286
287
  한글은 전각이라 영숫자의 약 두 배를 먹으므로 **두 기준 사이에는 아무것도 보고하지 않습니다** —
287
288
  영숫자로 채워도 넘칠 때만 "좁다", 한글로 채워도 남을 때만 "넓다" 로 판정합니다.
288
289
 
289
- | 등급 | `SInput` (sm) | `SInput` (md) | `SNumberInput` (sm) | `SNumberInput` (sm, `useButton`) |
290
- | ---- | ------------- | ------------- | ------------------- | -------------------------------- |
291
- | `xs` | — | — | 영숫자 8 | 영숫자 2 |
290
+ | 등급 | `SInput` (sm) | `SInput` (md) | `SNumberInput` (sm) | `SNumberInput` (sm, `useButton`) |
291
+ | ---- | ------------------- | ------------------- | ------------------- | -------------------------------- |
292
+ | `xs` | — | — | 영숫자 8 | 영숫자 2 |
292
293
  | `sm` | 영숫자 14 / 한글 7 | 영숫자 11 / 한글 6 | 영숫자 14 | 영숫자 8 |
293
294
  | `md` | 영숫자 20 / 한글 11 | 영숫자 16 / 한글 9 | 영숫자 20 | 영숫자 14 |
294
295
  | `lg` | 영숫자 32 / 한글 17 | 영숫자 26 / 한글 14 | 영숫자 32 | 영숫자 26 |
@@ -77,14 +77,15 @@ export interface SChipFilterChangeDetail {
77
77
 
78
78
  ```ts
79
79
  /** 필터 하나의 정의. type에 따라 쓸 수 있는 속성이 달라진다 —
80
- * options는 single·multi·keyword, presets·selectable·maxRange는 date·period,
81
- * render는 custom 에만 있다 */
80
+ * options는 select·select-multi·keyword, presets·maxRange·radioButton은
81
+ * datepicker-range·datepicker-statistics, render는 custom 에만 있다 */
82
82
  export type SChipFilterField =
83
- | SChipFilterSingleField
84
- | SChipFilterMultiField
83
+ | SChipFilterSelectField
84
+ | SChipFilterSelectMultiField
85
+ | SChipFilterDatePickerDayField
86
+ | SChipFilterDatePickerRangeField
87
+ | SChipFilterDatePickerStatisticsField
85
88
  | SChipFilterKeywordField
86
- | SChipFilterDateField
87
- | SChipFilterPeriodField
88
89
  | SChipFilterCustomField;
89
90
  ```
90
91
 
@@ -112,21 +113,57 @@ export type SChipFilterValue =
112
113
  | undefined;
113
114
  ```
114
115
 
115
- ### SChipFilterSingleField
116
+ ### SChipFilterSelectField
116
117
 
117
118
  ```ts
118
119
  /** 후보 하나를 고른다 */
119
- export interface SChipFilterSingleField extends SChipFilterOptionsField {
120
- type: 'single';
120
+ export interface SChipFilterSelectField extends SChipFilterOptionsField {
121
+ type: 'select';
121
122
  }
122
123
  ```
123
124
 
124
- ### SChipFilterMultiField
125
+ ### SChipFilterSelectMultiField
125
126
 
126
127
  ```ts
127
128
  /** 후보 여럿을 고른다 */
128
- export interface SChipFilterMultiField extends SChipFilterOptionsField {
129
- type: 'multi';
129
+ export interface SChipFilterSelectMultiField extends SChipFilterOptionsField {
130
+ type: 'select-multi';
131
+ }
132
+ ```
133
+
134
+ ### SChipFilterDatePickerDayField
135
+
136
+ ```ts
137
+ /** 날짜 하나를 고른다 — 캘린더 트리거 하나만 놓인다. 프리셋으로 고르게 하거나 시작~종료를
138
+ * 받아야 하면 datepicker-range 다 */
139
+ export interface SChipFilterDatePickerDayField extends SChipFilterFieldBase {
140
+ type: 'datepicker-day';
141
+ /** 캘린더 트리거의 placeholder */
142
+ placeholder?: string;
143
+ /** 선택 가능 범위 */
144
+ selectable?: [string, string];
145
+ }
146
+ ```
147
+
148
+ ### SChipFilterDatePickerRangeField
149
+
150
+ ```ts
151
+ /** 기간(시작~종료)을 고른다. presets를 주면 프리셋 라디오 목록으로 고르고,
152
+ * 주지 않으면 기간 피커 하나만 놓인다 */
153
+ export interface SChipFilterDatePickerRangeField extends SChipFilterPresetsField {
154
+ type: 'datepicker-range';
155
+ /** presets를 필터 바에 세그먼트 라디오로 펼쳐 놓는다(팝오버 없음).
156
+ * 기본 false — 칩 클릭 시 팝오버 안에 세로 라디오 목록(+사용자 지정 선택 시 기간 피커) */
157
+ radioButton?: boolean;
158
+ }
159
+ ```
160
+
161
+ ### SChipFilterDatePickerStatisticsField
162
+
163
+ ```ts
164
+ /** 집계 단위(일·월·분기·반기·연)와 그 단위의 값을 함께 고른다 */
165
+ export interface SChipFilterDatePickerStatisticsField extends SChipFilterPresetsField {
166
+ type: 'datepicker-statistics';
130
167
  }
131
168
  ```
132
169
 
@@ -151,29 +188,6 @@ export interface SChipFilterKeywordField extends SChipFilterOptionsField {
151
188
  }
152
189
  ```
153
190
 
154
- ### SChipFilterDateField
155
-
156
- ```ts
157
- /** 날짜 하나 또는 기간을 고른다 */
158
- export interface SChipFilterDateField extends SChipFilterPresetsField {
159
- type: 'date';
160
- /** presets 없이 단일 캘린더 트리거로 동작할 때의 placeholder */
161
- placeholder?: string;
162
- /** presets를 필터 바에 세그먼트 라디오로 펼쳐 놓는다(팝오버 없음).
163
- * 기본 false — 칩 클릭 시 팝오버 안에 세로 라디오 목록(+사용자 지정 선택 시 기간 피커) */
164
- radioButton?: boolean;
165
- }
166
- ```
167
-
168
- ### SChipFilterPeriodField
169
-
170
- ```ts
171
- /** 집계 단위(일·월·분기·반기·연)와 그 단위의 값을 함께 고른다 */
172
- export interface SChipFilterPeriodField extends SChipFilterPresetsField {
173
- type: 'period';
174
- }
175
- ```
176
-
177
191
  ### SChipFilterCustomField
178
192
 
179
193
  ```ts
@@ -211,7 +225,7 @@ export interface SChipFilterKeywordValue {
211
225
  ### SChipFilterPeriodValue
212
226
 
213
227
  ```ts
214
- /** period 필드 값 — 선택 단위(unit)와 그 단위의 입력값(value)을 함께 보관한다 */
228
+ /** datepicker-statistics 필드 값 — 선택 단위(unit)와 그 단위의 입력값(value)을 함께 보관한다 */
215
229
  export interface SChipFilterPeriodValue {
216
230
  unit: SChipFilterPeriodUnit;
217
231
  value?: string | number | SDateRangeValue | null;
@@ -228,35 +242,13 @@ export type SChipFilterCustomValue = Record<string, unknown>;
228
242
  ### SChipFilterOptionsField
229
243
 
230
244
  ```ts
231
- /** 후보 목록에서 고르는 필터 — single·multi·keyword */
245
+ /** 후보 목록에서 고르는 필터 — select·select-multi·keyword */
232
246
  export interface SChipFilterOptionsField extends SChipFilterFieldBase {
233
247
  /** 고를 수 있는 후보 목록 */
234
248
  options?: SChipFilterOption[];
235
249
  }
236
250
  ```
237
251
 
238
- ### SChipFilterKeywordInput
239
-
240
- ```ts
241
- /** keyword 필드의 입력 방식 — 무엇을 키워드 하나의 끝으로 볼지 */
242
- export type SChipFilterKeywordInput = 'tag' | 'csv';
243
- ```
244
-
245
- ### SChipFilterPresetsField
246
-
247
- ```ts
248
- /** 프리셋으로 기간을 고르는 필터 — date·period */
249
- export interface SChipFilterPresetsField extends SChipFilterFieldBase {
250
- /** 프리셋 라디오 목록. date에서 지정하지 않으면 단일 캘린더 트리거로 동작하고,
251
- * period에서 지정하지 않으면 일별·월별·분기별·반기별·연도별·사용자 지정 기본 목록을 쓴다 */
252
- presets?: SChipFilterDatePreset[];
253
- /** 선택 가능 범위 */
254
- selectable?: [string, string];
255
- /** "사용자 지정" 프리셋으로 기간을 고를 때의 최대 선택 일수 */
256
- maxRange?: number;
257
- }
258
- ```
259
-
260
252
  ### SChipFilterFieldBase
261
253
 
262
254
  ```ts
@@ -273,9 +265,17 @@ export interface SChipFilterFieldBase {
273
265
  * required도 같은 효과를 낸다 — 처음부터 바에 보이는 것은 fixed이거나 required인 필드뿐이고,
274
266
  * 나머지는 전부 "필터 추가"에서 골라야 나타난다 */
275
267
  fixed?: boolean;
276
- /** 초기값 및 clearable 클릭 시 되돌아갈 값. required 여부와 무관하게 적용된다 — 값이 비어 있으면
277
- * 마운트(또는 "필터 추가"로 활성화) 시 이 값이 자동으로 채워진다. required인데 지정하지 않으면
278
- * 타입별 내장 기본값(single: 번째 옵션, date: 오늘 날짜)을 대신 쓴다 */
268
+ /** 초기값 및 clearable 클릭 시 되돌아갈 값.
269
+ *
270
+ * **`fixed` 또는 `required` 필드에서만 쓴다.** 필드에 지정하면 무시하고 콘솔에 알린다 —
271
+ * 뺄 수 있는 필터는 처음에 바에 없는데, 값 맵에는 기본값이 채워져 **보이지도 지울 수도 없는
272
+ * 조건이 검색에 걸린다.** 칩을 지워 값을 비워도 "검색 초기화"가 그 값을 되돌려 놓아 필터가
273
+ * 조용히 되살아난다. 처음부터 값이 정해져 있어야 하는 필터라면 그것이 `fixed`·`required` 다.
274
+ *
275
+ * required인데 지정하지 않으면 타입별 내장 기본값(select: 첫 번째 옵션,
276
+ * datepicker-day·datepicker-range: 오늘 날짜)을 대신 쓴다. 인라인(radioButton) datepicker-range
277
+ * 필드는 팝오버 없이 바에 바로 노출되어 빈 상태로 둘 수 없으므로, 이 규칙과 무관하게 언제나
278
+ * 오늘이 채워진다 */
279
279
  defaultValue?: SChipFilterValue;
280
280
  /** 이 필터만 비활성. 바에 남아 있되 팝오버가 열리지 않고 clearable도 눌리지 않는다.
281
281
  * 바 전체를 잠그려면 SChipFilterProps.disabled를 쓴다 — 둘은 OR로 합쳐진다 */
@@ -283,6 +283,28 @@ export interface SChipFilterFieldBase {
283
283
  }
284
284
  ```
285
285
 
286
+ ### SChipFilterPresetsField
287
+
288
+ ```ts
289
+ /** 프리셋으로 기간을 고르는 필터 — datepicker-range·datepicker-statistics */
290
+ export interface SChipFilterPresetsField extends SChipFilterFieldBase {
291
+ /** 프리셋 라디오 목록. datepicker-range에서 지정하지 않으면 프리셋 없이 기간 피커 하나만 놓이고,
292
+ * datepicker-statistics에서 지정하지 않으면 일별·월별·분기별·반기별·연도별·사용자 지정 기본 목록을 쓴다 */
293
+ presets?: SChipFilterDatePreset[];
294
+ /** 선택 가능 범위 */
295
+ selectable?: [string, string];
296
+ /** "사용자 지정" 프리셋으로 기간을 고를 때의 최대 선택 일수 */
297
+ maxRange?: number;
298
+ }
299
+ ```
300
+
301
+ ### SChipFilterKeywordInput
302
+
303
+ ```ts
304
+ /** keyword 필드의 입력 방식 — 무엇을 키워드 하나의 끝으로 볼지 */
305
+ export type SChipFilterKeywordInput = 'tag' | 'csv';
306
+ ```
307
+
286
308
  ### SChipFilterMatchMode
287
309
 
288
310
  ```ts
@@ -308,7 +330,7 @@ export interface SChipFilterOption {
308
330
  ### SChipFilterDatePreset
309
331
 
310
332
  ```ts
311
- /** date/period 필드의 프리셋 라디오 항목 (오늘/지난 7일/일별/월별/사용자 지정 등) */
333
+ /** datepicker-range·datepicker-statistics 필드의 프리셋 라디오 항목 (오늘/지난 7일/일별/월별/사용자 지정 등) */
312
334
  export interface SChipFilterDatePreset {
313
335
  /** 프리셋 식별자 */
314
336
  value: string;
@@ -316,7 +338,8 @@ export interface SChipFilterDatePreset {
316
338
  label: string;
317
339
  /** true면 "사용자 지정" — 선택 시 날짜/기간 피커가 추가로 노출된다. resolve는 무시된다. */
318
340
  custom?: boolean;
319
- /** custom이 아닐 때 실제 값을 계산한다. 단일 날짜(string) 또는 기간([start,end]) 모두 가능 */
341
+ /** custom이 아닐 때 실제 값을 계산한다. 단일 날짜(string) 또는 기간([start,end]) 모두 가능
342
+ * datepicker-range 에서는 'd' 를 그 하루짜리 기간 ['d', 'd'] 와 같은 값으로 본다 */
320
343
  resolve?: () => string | SDateRangeValue;
321
344
  }
322
345
  ```
@@ -1,8 +1,9 @@
1
1
  import { type CSSProperties, type ReactNode } from 'react';
2
2
  import { type SDateRangeValue } from '../SDateRangePicker';
3
3
  /** 필터가 값을 받는 방식. 각 값에 대응하는 필드 인터페이스가 따로 있다 —
4
- * SChipFilterSingleField·SChipFilterMultiField·SChipFilterKeywordField·
5
- * SChipFilterDateField·SChipFilterPeriodField·SChipFilterCustomField */
4
+ * SChipFilterSelectField·SChipFilterSelectMultiField·SChipFilterKeywordField·
5
+ * SChipFilterDatePickerDayField·SChipFilterDatePickerRangeField·
6
+ * SChipFilterDatePickerStatisticsField·SChipFilterCustomField */
6
7
  export type SChipFilterType = SChipFilterField['type'];
7
8
  export type SChipFilterOptionValue = string | number;
8
9
  export type SChipFilterMatchMode = 'contains' | 'exact' | 'excludes';
@@ -12,7 +13,7 @@ export interface SChipFilterOption {
12
13
  label: string;
13
14
  disabled?: boolean;
14
15
  }
15
- /** date/period 필드의 프리셋 라디오 항목 (오늘/지난 7일/일별/월별/사용자 지정 등) */
16
+ /** datepicker-range·datepicker-statistics 필드의 프리셋 라디오 항목 (오늘/지난 7일/일별/월별/사용자 지정 등) */
16
17
  export interface SChipFilterDatePreset {
17
18
  /** 프리셋 식별자 */
18
19
  value: string;
@@ -20,7 +21,8 @@ export interface SChipFilterDatePreset {
20
21
  label: string;
21
22
  /** true면 "사용자 지정" — 선택 시 날짜/기간 피커가 추가로 노출된다. resolve는 무시된다. */
22
23
  custom?: boolean;
23
- /** custom이 아닐 때 실제 값을 계산한다. 단일 날짜(string) 또는 기간([start,end]) 모두 가능 */
24
+ /** custom이 아닐 때 실제 값을 계산한다. 단일 날짜(string) 또는 기간([start,end]) 모두 가능
25
+ * datepicker-range 에서는 'd' 를 그 하루짜리 기간 ['d', 'd'] 와 같은 값으로 본다 */
24
26
  resolve?: () => string | SDateRangeValue;
25
27
  }
26
28
  /** keyword 필드에서 matchModes 활성 시 사용하는 값 형태 — 입력해 추가한 키워드 목록 */
@@ -28,7 +30,7 @@ export interface SChipFilterKeywordValue {
28
30
  keywords: string[];
29
31
  mode: SChipFilterMatchMode;
30
32
  }
31
- /** period 필드 값 — 선택 단위(unit)와 그 단위의 입력값(value)을 함께 보관한다 */
33
+ /** datepicker-statistics 필드 값 — 선택 단위(unit)와 그 단위의 입력값(value)을 함께 보관한다 */
32
34
  export interface SChipFilterPeriodValue {
33
35
  unit: SChipFilterPeriodUnit;
34
36
  value?: string | number | SDateRangeValue | null;
@@ -50,23 +52,31 @@ export interface SChipFilterFieldBase {
50
52
  * required도 같은 효과를 낸다 — 처음부터 바에 보이는 것은 fixed이거나 required인 필드뿐이고,
51
53
  * 나머지는 전부 "필터 추가"에서 골라야 나타난다 */
52
54
  fixed?: boolean;
53
- /** 초기값 및 clearable 클릭 시 되돌아갈 값. required 여부와 무관하게 적용된다 — 값이 비어 있으면
54
- * 마운트(또는 "필터 추가"로 활성화) 시 이 값이 자동으로 채워진다. required인데 지정하지 않으면
55
- * 타입별 내장 기본값(single: 번째 옵션, date: 오늘 날짜)을 대신 쓴다 */
55
+ /** 초기값 및 clearable 클릭 시 되돌아갈 값.
56
+ *
57
+ * **`fixed` 또는 `required` 필드에서만 쓴다.** 필드에 지정하면 무시하고 콘솔에 알린다 —
58
+ * 뺄 수 있는 필터는 처음에 바에 없는데, 값 맵에는 기본값이 채워져 **보이지도 지울 수도 없는
59
+ * 조건이 검색에 걸린다.** 칩을 지워 값을 비워도 "검색 초기화"가 그 값을 되돌려 놓아 필터가
60
+ * 조용히 되살아난다. 처음부터 값이 정해져 있어야 하는 필터라면 그것이 `fixed`·`required` 다.
61
+ *
62
+ * required인데 지정하지 않으면 타입별 내장 기본값(select: 첫 번째 옵션,
63
+ * datepicker-day·datepicker-range: 오늘 날짜)을 대신 쓴다. 인라인(radioButton) datepicker-range
64
+ * 필드는 팝오버 없이 바에 바로 노출되어 빈 상태로 둘 수 없으므로, 이 규칙과 무관하게 언제나
65
+ * 오늘이 채워진다 */
56
66
  defaultValue?: SChipFilterValue;
57
67
  /** 이 필터만 비활성. 바에 남아 있되 팝오버가 열리지 않고 clearable도 눌리지 않는다.
58
68
  * 바 전체를 잠그려면 SChipFilterProps.disabled를 쓴다 — 둘은 OR로 합쳐진다 */
59
69
  disabled?: boolean;
60
70
  }
61
- /** 후보 목록에서 고르는 필터 — single·multi·keyword */
71
+ /** 후보 목록에서 고르는 필터 — select·select-multi·keyword */
62
72
  export interface SChipFilterOptionsField extends SChipFilterFieldBase {
63
73
  /** 고를 수 있는 후보 목록 */
64
74
  options?: SChipFilterOption[];
65
75
  }
66
- /** 프리셋으로 기간을 고르는 필터 — date·period */
76
+ /** 프리셋으로 기간을 고르는 필터 — datepicker-range·datepicker-statistics */
67
77
  export interface SChipFilterPresetsField extends SChipFilterFieldBase {
68
- /** 프리셋 라디오 목록. date에서 지정하지 않으면 단일 캘린더 트리거로 동작하고,
69
- * period에서 지정하지 않으면 일별·월별·분기별·반기별·연도별·사용자 지정 기본 목록을 쓴다 */
78
+ /** 프리셋 라디오 목록. datepicker-range에서 지정하지 않으면 프리셋 없이 기간 피커 하나만 놓이고,
79
+ * datepicker-statistics에서 지정하지 않으면 일별·월별·분기별·반기별·연도별·사용자 지정 기본 목록을 쓴다 */
70
80
  presets?: SChipFilterDatePreset[];
71
81
  /** 선택 가능 범위 */
72
82
  selectable?: [string, string];
@@ -74,12 +84,12 @@ export interface SChipFilterPresetsField extends SChipFilterFieldBase {
74
84
  maxRange?: number;
75
85
  }
76
86
  /** 후보 하나를 고른다 */
77
- export interface SChipFilterSingleField extends SChipFilterOptionsField {
78
- type: 'single';
87
+ export interface SChipFilterSelectField extends SChipFilterOptionsField {
88
+ type: 'select';
79
89
  }
80
90
  /** 후보 여럿을 고른다 */
81
- export interface SChipFilterMultiField extends SChipFilterOptionsField {
82
- type: 'multi';
91
+ export interface SChipFilterSelectMultiField extends SChipFilterOptionsField {
92
+ type: 'select-multi';
83
93
  }
84
94
  /** keyword 필드의 입력 방식 — 무엇을 키워드 하나의 끝으로 볼지 */
85
95
  export type SChipFilterKeywordInput = 'tag' | 'csv';
@@ -99,18 +109,26 @@ export interface SChipFilterKeywordField extends SChipFilterOptionsField {
99
109
  * 기본 false — 2개(포함/일치)만 */
100
110
  excludeMode?: boolean;
101
111
  }
102
- /** 날짜 하나 또는 기간을 고른다 */
103
- export interface SChipFilterDateField extends SChipFilterPresetsField {
104
- type: 'date';
105
- /** presets 없이 단일 캘린더 트리거로 동작할 때의 placeholder */
112
+ /** 날짜 하나를 고른다 캘린더 트리거 하나만 놓인다. 프리셋으로 고르게 하거나 시작~종료를
113
+ * 받아야 하면 datepicker-range */
114
+ export interface SChipFilterDatePickerDayField extends SChipFilterFieldBase {
115
+ type: 'datepicker-day';
116
+ /** 캘린더 트리거의 placeholder */
106
117
  placeholder?: string;
118
+ /** 선택 가능 범위 */
119
+ selectable?: [string, string];
120
+ }
121
+ /** 기간(시작~종료)을 고른다. presets를 주면 프리셋 라디오 목록으로 고르고,
122
+ * 주지 않으면 기간 피커 하나만 놓인다 */
123
+ export interface SChipFilterDatePickerRangeField extends SChipFilterPresetsField {
124
+ type: 'datepicker-range';
107
125
  /** presets를 필터 바에 세그먼트 라디오로 펼쳐 놓는다(팝오버 없음).
108
126
  * 기본 false — 칩 클릭 시 팝오버 안에 세로 라디오 목록(+사용자 지정 선택 시 기간 피커) */
109
127
  radioButton?: boolean;
110
128
  }
111
129
  /** 집계 단위(일·월·분기·반기·연)와 그 단위의 값을 함께 고른다 */
112
- export interface SChipFilterPeriodField extends SChipFilterPresetsField {
113
- type: 'period';
130
+ export interface SChipFilterDatePickerStatisticsField extends SChipFilterPresetsField {
131
+ type: 'datepicker-statistics';
114
132
  }
115
133
  /** 칩+팝오버를 거치지 않고 바에 놓을 노드를 앱이 직접 그린다 */
116
134
  export interface SChipFilterCustomField extends SChipFilterFieldBase {
@@ -126,9 +144,9 @@ export interface SChipFilterCustomField extends SChipFilterFieldBase {
126
144
  }) => ReactNode;
127
145
  }
128
146
  /** 필터 하나의 정의. type에 따라 쓸 수 있는 속성이 달라진다 —
129
- * options는 single·multi·keyword, presets·selectable·maxRange는 date·period,
130
- * render는 custom 에만 있다 */
131
- export type SChipFilterField = SChipFilterSingleField | SChipFilterMultiField | SChipFilterKeywordField | SChipFilterDateField | SChipFilterPeriodField | SChipFilterCustomField;
147
+ * options는 select·select-multi·keyword, presets·maxRange·radioButton은
148
+ * datepicker-range·datepicker-statistics, render는 custom 에만 있다 */
149
+ export type SChipFilterField = SChipFilterSelectField | SChipFilterSelectMultiField | SChipFilterDatePickerDayField | SChipFilterDatePickerRangeField | SChipFilterDatePickerStatisticsField | SChipFilterKeywordField | SChipFilterCustomField;
132
150
  export interface SChipFilterChangeDetail {
133
151
  key: string;
134
152
  value: SChipFilterValue;
@@ -1 +1 @@
1
- export { SChipFilter, type SChipFilterChangeDetail, type SChipFilterCustomField, type SChipFilterDateField, type SChipFilterDatePreset, type SChipFilterField, type SChipFilterFieldBase, type SChipFilterGroup, type SChipFilterGroupRule, type SChipFilterHandle, type SChipFilterKeywordField, type SChipFilterKeywordInput, type SChipFilterKeywordValue, type SChipFilterMatchMode, type SChipFilterMultiField, type SChipFilterOption, type SChipFilterOptionValue, type SChipFilterOptionsField, type SChipFilterPeriodField, type SChipFilterPresetsField, type SChipFilterProps, type SChipFilterSingleField, type SChipFilterType, type SChipFilterValue, type SChipFilterValueMap, } from './SChipFilter';
1
+ export { SChipFilter, type SChipFilterChangeDetail, type SChipFilterCustomField, type SChipFilterDatePickerDayField, type SChipFilterDatePickerRangeField, type SChipFilterDatePickerStatisticsField, type SChipFilterDatePreset, type SChipFilterField, type SChipFilterFieldBase, type SChipFilterGroup, type SChipFilterGroupRule, type SChipFilterHandle, type SChipFilterKeywordField, type SChipFilterKeywordInput, type SChipFilterKeywordValue, type SChipFilterMatchMode, type SChipFilterOption, type SChipFilterOptionValue, type SChipFilterOptionsField, type SChipFilterPresetsField, type SChipFilterProps, type SChipFilterSelectField, type SChipFilterSelectMultiField, type SChipFilterType, type SChipFilterValue, type SChipFilterValueMap, } from './SChipFilter';
@@ -9,6 +9,7 @@
9
9
  | Prop | Type | Default | Description |
10
10
  |------|------|---------|-------------|
11
11
  | `vertical?` | `boolean` | `false` | true면 수직 분할선, false면 수평 분할선 |
12
+ | `height?` | `number \| string` | — | 수직 분할선의 길이. 숫자는 px, 문자열은 CSS 값(토큰 var 참조 등)으로 쓴다. 주지 않으면 `align-self: stretch` 로 부모 줄 높이를 그대로 채운다. 값을 주면 그 높이로 고정하고 교차축 가운데(`self-center`)에 맞춘다 — `align-self: stretch` 는 높이가 auto 일 때만 늘리므로, 높이를 정하는 순간 정렬을 함께 정해야 한다. 그래서 높이는 `className="h-*"` 가 아니라 이 prop 으로 준다. 수평 분할선에는 적용되지 않는다 (두께는 1px 로 고정). |
12
13
 
13
14
  ## Dependencies
14
15
 
@@ -2,6 +2,17 @@ import { type HTMLAttributes } from 'react';
2
2
  export interface SDividerProps extends HTMLAttributes<HTMLHRElement> {
3
3
  /** true면 수직 분할선, false면 수평 분할선 */
4
4
  vertical?: boolean;
5
+ /**
6
+ * 수직 분할선의 길이. 숫자는 px, 문자열은 CSS 값(토큰 var 참조 등)으로 쓴다.
7
+ *
8
+ * 주지 않으면 `align-self: stretch` 로 부모 줄 높이를 그대로 채운다. 값을 주면
9
+ * 그 높이로 고정하고 교차축 가운데(`self-center`)에 맞춘다 — `align-self: stretch`
10
+ * 는 높이가 auto 일 때만 늘리므로, 높이를 정하는 순간 정렬을 함께 정해야 한다.
11
+ * 그래서 높이는 `className="h-*"` 가 아니라 이 prop 으로 준다.
12
+ *
13
+ * 수평 분할선에는 적용되지 않는다 (두께는 1px 로 고정).
14
+ */
15
+ height?: number | string;
5
16
  }
6
17
  /** SDivider — sd-divider 포팅. 색상은 `--sys-color-divider-default`. */
7
18
  export declare const SDivider: import("react").ForwardRefExoticComponent<SDividerProps & import("react").RefAttributes<HTMLHRElement>>;
@@ -71,6 +71,7 @@ export interface SDraggableGroupMoveEvent {
71
71
  export interface SDraggableListRenderState {
72
72
  onDragHandleMouseDown: (event: MouseEvent<HTMLDivElement>) => void;
73
73
  selected: boolean;
74
+ disabled: boolean;
74
75
  depth: number;
75
76
  }
76
77
  ```
@@ -3,6 +3,7 @@ import { type SListProps } from '../SList';
3
3
  export interface SDraggableListRenderState {
4
4
  onDragHandleMouseDown: (event: MouseEvent<HTMLDivElement>) => void;
5
5
  selected: boolean;
6
+ disabled: boolean;
6
7
  depth: number;
7
8
  }
8
9
  export type SDraggableListDropIntent = 'before' | 'inside' | 'after';
@@ -1,5 +1,5 @@
1
1
  import { type CSSProperties, type RefObject } from 'react';
2
- import { type SEditorColorOption, type SEditorToolbarItem } from './editor.config';
2
+ import { type SEditorToolbarItem } from './editor.config';
3
3
  import type { SEditorHandle } from './SEditor';
4
4
  import type { TiptapApi } from './tiptap-api';
5
5
  export interface EditorBodyProps {
@@ -15,17 +15,13 @@ export interface EditorBodyProps {
15
15
  /** 에디터 인스턴스가 생겼다 — 껍데기가 밀린 focus() 를 흘려보낸다 */
16
16
  onReady: () => void;
17
17
  placeholder: string;
18
- typography: boolean;
19
18
  editable: boolean;
20
19
  disabled: boolean;
21
20
  minHeight?: number | string;
22
21
  maxHeight?: number | string;
23
- toolbar: SEditorToolbarItem[] | false;
24
- /** 선택 영역 위에 뜨는 서식 판. `false` 그리지 않는다 */
25
- bubbleMenu: SEditorToolbarItem[] | false;
26
- fontSizes: number[];
27
- colors: SEditorColorOption[];
28
- highlights: SEditorColorOption[];
22
+ toolbar: SEditorToolbarItem[];
23
+ /** 선택 영역 위에 뜨는 서식 편집할 있으면 언제나 뜬다 (SEditor 주석 참고) */
24
+ bubbleMenu: SEditorToolbarItem[];
29
25
  onImageUpload?: (file: File) => Promise<string>;
30
26
  editorClass?: string;
31
27
  editorStyle?: CSSProperties;