feat(spreadsheet): 상태 표시줄 확대 비율 — sub6 zoom() 이음

sub6 격자 확대 커밋(origin/sub_laptop_6 7b294adc) 받아 GridHandle.zoom() 으로 처음 값 · 격자 root 「aislo-grid-zoom」 사건으로 바뀔 때마다 「확대 N%」 다시 씀.
가짜 SpreadsheetContext(test_stage2_helpers.ts) 격자에 zoom() 스텁 더함(0 계약 필수 자리라 안 채우면 모양 안 맞음).
ORCA(포트 5179) — 실제 createSpreadsheet 를 띄워 Ctrl+휠(WheelEvent ctrlKey) 로 확인: 「확대 100%」→「확대 332%」로 실시간 바뀜.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EUypcnp5d1gU2aeKh9F2H7
This commit is contained in:
2026-09-27 23:12:57 +09:00
co-authored by Claude Sonnet 5
parent 7b294adca2
commit ede12fbc0e
2 changed files with 19 additions and 8 deletions
@@ -2,13 +2,9 @@
* spreadsheet_statusbar.ts (3단계 · 주인 sub_laptop_4)
* 아래 상태 표시줄 — 고른 범위의 합계 · 평균 · 개수(COUNTA) · 숫자 개수(COUNT) · 최소 · 최대.
* 엑셀처럼 우클릭으로 보일 줄 고름(이 표시줄만의 취향 — 문서에는 안 남음 · 계약 손 안 댐).
* 확대 비율 자리는 칸만 둠 — 실제 격자 확대와는 아직 안 이어짐(아래 「잇는 법」 2).
*
* 잇는 법(D · C · sub7 — 지금은 하나도 안 이어짐):
* 1) `spreadsheet.ts` 가 `createStatusBar(ctx)` 를 한 번 부르고 `root` 를 화면 맨 아래 붙임.
* `ctx.select()` 뒤(그리고 `dispatch` 로 값이 바뀐 뒤) `refresh()` 를 부름 — 스스로 구독 안 함.
* 2) 확대 비율을 실제로 쓰려면 `GridHandle` 에 `zoom()` · `setZoom()` 을 계약(0)에 더하고(격자 C 몫),
* 이 파일의 확대 자리를 그 값으로 채우고 바꾸면 `setZoom` 을 부르게 이음.
* 확대 비율 — `ctx.grid.zoom()` 으로 처음 값 · 격자 root 의 `aislo-grid-zoom` 사건(sub6, 2026-09-27)을
* 들어 Ctrl+휠로 바뀔 때마다 다시 씀. `setZoom` 은 아직 계약에 없음(격자만 바꿈 · 상태줄은 읽기만).
* 화면 붙이기는 `spreadsheet.ts`(D)가 `createStatusBar(ctx)` 로 이미 함(root 를 격자 아래).
* ========================================================================== */
import { el } from "@ui/ui_template_elements";
@@ -76,14 +72,27 @@ function formatNumber(n: number): string {
: n.toLocaleString(undefined, { maximumFractionDigits: 4 });
}
function zoomText(ratio: number): string {
return `확대 ${Math.round(ratio * 100)}%`;
}
/** 아래 상태 표시줄 — 우클릭 메뉴로 보일 줄 고름. */
export function createStatusBar(ctx: SpreadsheetContext): PartHandle {
const root = el("div", { className: "ss-statusbar" });
const stats = el("div", { className: "ss-statusbar__stats" });
const zoom = el("span", { className: "ss-statusbar__zoom", text: "확대 100%" });
const zoom = el("span", {
className: "ss-statusbar__zoom",
text: zoomText(ctx.grid.zoom()),
});
const menu = createMapContextMenu("ss-statusbar");
root.append(stats, zoom, menu.element);
const onZoom = (ev: Event): void => {
const ratio = (ev as CustomEvent<{ zoom: number }>).detail?.zoom;
if (typeof ratio === "number") zoom.textContent = zoomText(ratio);
};
ctx.grid.root.addEventListener("aislo-grid-zoom", onZoom);
let visible = new Set<StatKey>(STAT_KEYS);
function render(): void {
@@ -115,6 +124,7 @@ export function createStatusBar(ctx: SpreadsheetContext): PartHandle {
root,
refresh: render,
destroy(): void {
ctx.grid.root.removeEventListener("aislo-grid-zoom", onZoom);
menu.close();
root.remove();
},
@@ -142,6 +142,7 @@ export function makeCtx(
hitTest: () => null,
reveal: () => {},
visibleRange: () => ({ r0: 0, c0: 0, r1: 0, c1: 0 }),
zoom: () => 1,
editorSlot: () => ({ layer: {} as HTMLElement, box: { x: 0, y: 0, w: 0, h: 0 } }),
destroy: () => {},
},