aboutsummaryrefslogtreecommitdiffstats
path: root/docs/design/001-first-component.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/design/001-first-component.md')
-rw-r--r--docs/design/001-first-component.md26
1 files changed, 25 insertions, 1 deletions
diff --git a/docs/design/001-first-component.md b/docs/design/001-first-component.md
index fcfa3df..df462e5 100644
--- a/docs/design/001-first-component.md
+++ b/docs/design/001-first-component.md
@@ -38,6 +38,7 @@ view tasks_list_focus = at.position
| TUI | `vega tui app.pmod` | 대체 화면, 원시 입력. 제목·필드·목록·표·키 목록·입력 줄. 포커스 행을 최소 스크롤로 화면에 두고 **보이는 행의 칸만** 계산한다. 터미널에 보이는 격자를 기억해 **바뀐 칸만** 보낸다. 크기 변경(SIGWINCH), frame 핸들러가 있으면 60 Hz |
| CLI | `vega cli app.pmod < script` | 파이프용 평문. 목록은 `> ` 표시와 `[badge]`, 표는 표시 폭으로 정렬한 열. 터미널이고 `NO_COLOR`가 없을 때만 색 |
| NUI | `vega say app.pmod < script` | 문장. 이벤트마다 포커스 항목을 말하고(`Item 2 of 3: danger, milk, urgent.`), 실패하면 `Could not toggle.`, `show`에서 화면 전체 |
+| GUI | `vega web app.pmod [--listen 주소] [--port N]` | 웹 페이지. 제목·필드·목록(`listbox`)·표·키 목록·입력 칸. 키, 행 클릭, 휠, 입력을 받고 열린 페이지마다 변경을 알린다. 보이는 행만 계산한다 |
포커스는 표면에서도 옮긴다. TUI에서 목록·표의 행을 클릭하면 그 행이 포커스가 되고, 휠은 포커스를 한 행씩 옮긴다
(SGR 마우스 보고). 스크립트는 `point 보기 행`(0부터)과 `click 줄 칸`(마지막으로 보인 프레임, 1부터)으로 같은 일을 한다.
@@ -52,6 +53,29 @@ Tab이 키 모드로 바꾸면 글자·숫자·Space가 `KeyA`·`Digit0`·`Space
표시 폭은 Vega가 맡는다. 한글·CJK·그림 이모지는 두 칸, 결합 문자·변이 선택자·ZWJ는 0칸, 제어 문자는
제어 그림(U+2400대)으로 보인다. grapheme 단위 자르기는 아직 없어 ZWJ 이모지 묶음은 근사다.
+## 웹 (GUI)
+
+`vega web app.pmod`는 같은 명세를 브라우저에 보인다. 기본은 이 기기(127.0.0.1)에서만 받는다. 다른 기기에서 열려면
+`--listen 0.0.0.0`처럼 주소를 준다. 앱이 곧 서버의 상태이므로 여러 탭이 한 앱을 함께 본다.
+
+| 요청 | 하는 일 |
+|---|---|
+| `GET /` | 페이지 하나(HTML·CSS·JS, 의존성 없음, 5 KB). 밝은·어두운 모드, 톤은 색, 포커스는 강조 |
+| `GET /screen?rows=R&first=F,…` | 화면 JSON. 목록·표마다 마지막 첫 행 F에서 R행만, TUI와 같은 최소 스크롤로 포커스를 창 안에 둔다 |
+| `POST /key` `/text` `/point` | 키 누름·뗌, 확정된 글, 행 가리키기(`파트 행`) |
+| `GET /events` | 서버 전송 이벤트. 앱이 바뀔 때마다 열린 페이지 모두에 한 번 |
+
+페이지의 키는 브라우저의 `KeyboardEvent.code`를 그대로 보낸다. Pure의 키 이름(`ArrowUp`, `KeyA`, `Space`, `Digit1`)이 같은
+이름 체계라 변환표가 없다. 입력 칸에서는 글이 칸으로 가고 Enter가 확정한다. 위아래 화살표와 PageUp·PageDown은 앱으로 간다.
+행을 클릭하면 그 행이, 휠을 굴리면 포커스가 한 행씩 옮겨 간다(`pure_app_point`). 목록은 `listbox`와 `aria-selected`로
+그려 화면 낭독기가 포커스를 읽는다.
+
+검증: 무작위 키·글·행 가리키기 1,200단계에서 화면 JSON(제목, 필드, 행 수, 포커스, 창의 행과 배지·톤)이 모델과 같고,
+열린 이벤트 스트림이 변경을 듣고, 저장소가 다음 실행으로 이어진다. 헤드리스 Chromium을 DevTools 프로토콜로 움직여
+페이지 자체도 확인한다(`tests/browser.mjs`). ArrowUp이 포커스를 옮기고, 행 클릭이 그 행을 고르고, Space가 완료(흐린 톤,
+배지)를 표시하고, 한글을 입력하고 Enter를 치면 새 항목이 생겨 포커스를 받는다. 모든 예제에 무작위 요청을 보내도 응답이
+올바르다.
+
## 셀 단위 갱신
TUI는 매 변경마다 격자를 앱에서 다시 그리지만(보이는 칸만 계산), 터미널에는 지금 보이는 것과 다른 칸만 보낸다.
@@ -111,5 +135,5 @@ CLI나 문장 표면이 그대로 이어받는다. Vega에도 앱에도 저장 �
## 남은 것
-- GUI 표면, 음성 합성으로 가는 NUI.
+- 음성 합성으로 가는 NUI, 창이 있는 데스크톱 GUI(지금 GUI는 브라우저다).
- 문장의 언어. 지금 NUI의 틀 문장은 영어이고 값은 앱의 text 그대로다.