feat(spreadsheet): C 격자 — 행·열 묶어 접기(윤곽 +/- 단추, 계약 더함)
RowInfo·ColumnInfo.묶음{층,접힘} · Command「묶음설정」더함(계약 더함) — 접힘 상태 저장 ·
접으면 숨김처럼 그리되 머리 이중선 표시는 숨김·걸러짐과 갈라 안 보임(따로 표시).
commands.ts 는 기존 setAxis 틀에 「묶음」prop·case 만 최소로 얹음(exhaustive switch 깨짐 막음).
ORCA 시험 틀에서 접기·펴기 dispatch·저장·머리 이동·표시 구분 수치로 확인.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVM3xZ1aUPcUTuW2WZSnwg
This commit is contained in:
@@ -105,7 +105,7 @@ export function buildColGeometry(book: Workbook, sheet: Sheet): LineGeometry {
|
||||
for (const [key, info] of Object.entries(sheet.열 ?? {})) {
|
||||
const c = colIndex(key);
|
||||
if (c < 0) continue;
|
||||
if (info.숨김) overrides.set(c, 0);
|
||||
if (info.숨김 || info.묶음?.접힘) overrides.set(c, 0);
|
||||
else if (info.폭 !== undefined) overrides.set(c, colCharsToPx(info.폭));
|
||||
}
|
||||
return new SparseGeometry(base, overrides);
|
||||
@@ -117,12 +117,41 @@ export function buildRowGeometry(book: Workbook, sheet: Sheet): LineGeometry {
|
||||
for (const [key, info] of Object.entries(sheet.행 ?? {}) as [string, RowInfo][]) {
|
||||
const r = Number(key) - 1;
|
||||
if (!Number.isInteger(r) || r < 0) continue;
|
||||
if (info.숨김) overrides.set(r, 0);
|
||||
if (info.숨김 || info.걸러짐 || info.묶음?.접힘) overrides.set(r, 0);
|
||||
else if (info.높이 !== undefined) overrides.set(r, ptToPx(info.높이));
|
||||
}
|
||||
return new SparseGeometry(base, overrides);
|
||||
}
|
||||
|
||||
/** 접힌 윤곽 묶음(연속 자리) — 묶음 있는 자리를 모아 붙은 것끼리 한 덩이로(같은 접힘 값끼리만). */
|
||||
export interface OutlineRun {
|
||||
from: number;
|
||||
to: number;
|
||||
collapsed: boolean;
|
||||
}
|
||||
|
||||
export function buildOutlineRuns<T extends { 묶음?: { 층: number; 접힘?: boolean } }>(
|
||||
records: Record<string, T> | undefined,
|
||||
indexOf: (key: string) => number,
|
||||
): OutlineRun[] {
|
||||
const items = Object.entries(records ?? {})
|
||||
.map(([key, info]) => ({ i: indexOf(key), collapsed: !!info.묶음?.접힘, has: !!info.묶음 }))
|
||||
.filter((x) => x.has && x.i >= 0)
|
||||
.sort((a, b) => a.i - b.i);
|
||||
const runs: OutlineRun[] = [];
|
||||
for (const it of items) {
|
||||
const last = runs[runs.length - 1];
|
||||
if (last && last.to === it.i - 1 && last.collapsed === it.collapsed) last.to = it.i;
|
||||
else runs.push({ from: it.i, to: it.i, collapsed: it.collapsed });
|
||||
}
|
||||
return runs;
|
||||
}
|
||||
|
||||
/** 그 자리가 숨김 · 걸러짐(사용자 · 필터) 인가 — 묶음 접힘은 빼고(화면 표시가 다름). */
|
||||
export function isExplicitHidden(info: { 숨김?: boolean; 걸러짐?: boolean } | undefined): boolean {
|
||||
return !!info?.숨김 || !!info?.걸러짐;
|
||||
}
|
||||
|
||||
/** `from..to` 안에서 숨기지 않은 자리만. */
|
||||
export function visibleIndices(geo: LineGeometry, from: number, to: number): number[] {
|
||||
const list: number[] = [];
|
||||
|
||||
Reference in New Issue
Block a user