Files
Aislo/A00_Common/spreadsheet/spreadsheet_sheet_extra.ts
T
eomsangdonandClaude Sonnet 5 4aca316ace feat(spreadsheet): 3단계 — 시트 숨김·보이기·탭 색(계약 더함)
spreadsheet_sheet_extra.ts 새로 만듦 — 시트 관리 창(숨김 토글·탭 색 고르기), 마지막 보이는 시트는 숨김 거절, 활성 시트를 숨기면 다른 시트로 옮김.
계약(spreadsheet_types.ts)에 Sheet.숨김·탭색 최소로 더함(git-sync 뒤 더함) · 파일 목록 표에 이번 셋(상태 표시줄·자동 합계·시트 여분) 적음 · css(spreadsheet_stage3.css)에 세 파일 스타일 얹음.
엔진 A·격자 C 안 건드림 — 탭 줄(spreadsheet_tabs.ts) 이음은 sub7 몫(머리 주석에 적음).
시험 resources/tester/spreadsheet/test_stage3_sheet_extra.ts 9개 통과.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EUypcnp5d1gU2aeKh9F2H7
2026-09-27 21:14:21 +09:00

114 lines
4.7 KiB
TypeScript

/* =============================================================================
* spreadsheet_sheet_extra.ts (3단계 · 주인 sub_laptop_4)
* 시트 숨기기 · 보이기 · 시트 탭 색. 저장 자리 `Sheet.숨김` · `Sheet.탭색`(0 계약에 방금 더함).
* 이 파일은 관리 창(전체 시트 목록 + 숨김 · 색 조작)만 그림 — 실제 탭 줄(`spreadsheet_tabs.ts`,
* E 파일)을 안 건드림.
*
* 잇는 법(E `spreadsheet_tabs.ts` · sub7 — 지금은 하나도 안 이어짐):
* 1) `mountTabs` 의 `render()` 가 `ctx.book.시트` 를 돌 때 `숨김` 인 시트는 탭을 안 그림.
* 2) 탭 엘리먼트에 `sheet.탭색` 이 있으면 밑줄 · 배경을 그 색으로(엑셀처럼).
* 3) 숨은 시트를 다시 보이려면 탭 우클릭 메뉴에 [숨긴 시트 보이기] 항목을 두고 이 파일의
* `createSheetExtraPanel(ctx)` 를 열거나, `showSheet(ctx, id)` 를 바로 부름.
* ========================================================================== */
import { createButton, el } from "@ui/ui_template_elements";
import type { Sheet } from "./spreadsheet_types";
import type { PartHandle, SpreadsheetContext } from "./spreadsheet_view_types";
// css 는 stage3.css 에 얹음(잇는 법 머리 참고) — 실제로 붙일 때 `import "./spreadsheet_stage3.css";` 더함.
function applySheet(ctx: SpreadsheetContext, sheetId: string, next: Sheet): void {
ctx.dispatch({ 종류: "시트통째", 시트: { ...next, id: sheetId } });
}
/** 시트를 숨김 — 마지막 보이는 시트는 못 숨김(까닭 글 돌려줌 · 되면 null). 활성 시트를 숨기면
* 다른 보이는 시트로 활성을 옮김. */
export function hideSheet(ctx: SpreadsheetContext, id: string): string | null {
const others = ctx.book.시트.filter((s) => s.id !== id && !s.숨김);
if (!others.length) return "마지막 보이는 시트는 못 숨김";
const sheet = ctx.book.시트.find((s) => s.id === id);
if (!sheet || sheet.숨김) return null;
applySheet(ctx, id, { ...sheet, 숨김: true });
if (ctx.book.활성 === id) ctx.showSheet(others[0].id);
return null;
}
/** 숨긴 시트를 다시 보임. */
export function unhideSheet(ctx: SpreadsheetContext, id: string): void {
const sheet = ctx.book.시트.find((s) => s.id === id);
if (!sheet || !sheet.숨김) return;
applySheet(ctx, id, { ...sheet, 숨김: false });
}
/** 탭 색 — `color` 가 null 이면 색을 지움(기본 탭 색으로). */
export function setSheetTabColor(ctx: SpreadsheetContext, id: string, color: string | null): void {
const sheet = ctx.book.시트.find((s) => s.id === id);
if (!sheet) return;
const next: Sheet = { ...sheet };
if (color) next.탭색 = color;
else delete next.탭색;
applySheet(ctx, id, next);
}
/** 시트 관리 창 — 전체 시트 목록 + 숨김 토글 · 탭 색 고르기. */
export function createSheetExtraPanel(ctx: SpreadsheetContext): PartHandle {
const root = el("div", { className: "ss-sheetextra" });
const list = el("ul", { className: "ss-sheetextra__list" });
let error: HTMLElement | null = null;
const showError = (msg: string | null): void => {
error?.remove();
error = null;
if (!msg) return;
error = el("p", { text: msg });
error.style.color = "var(--color-danger, red)";
root.append(error);
};
function render(): void {
list.replaceChildren(
...ctx.book.시트.map((sheet) => {
const li = el("li", { className: "ss-sheetextra__row" });
const label = el("span", { text: sheet.이름 + (sheet.숨김 ? "(숨김)" : "") });
const colorInput = el("input", {
attrs: { type: "color", value: sheet.탭색 ?? "#ffffff" },
}) as HTMLInputElement;
colorInput.addEventListener("change", () =>
setSheetTabColor(ctx, sheet.id, colorInput.value),
);
const colorClear = createButton({ label: "색 지움", variant: "ghost" });
colorClear.addEventListener("click", () => {
setSheetTabColor(ctx, sheet.id, null);
render();
});
const toggle = createButton({
label: sheet.숨김 ? "보이기" : "숨기기",
variant: "ghost",
});
toggle.addEventListener("click", () => {
if (sheet.숨김) {
unhideSheet(ctx, sheet.id);
showError(null);
} else {
showError(hideSheet(ctx, sheet.id));
}
render();
});
li.append(label, colorInput, colorClear, toggle);
return li;
}),
);
}
root.append(el("h4", { text: "시트 관리" }), list);
render();
return {
root,
refresh: render,
destroy(): void {
root.remove();
},
};
}