Files
Aislo/A00_Common/spreadsheet/spreadsheet_spill.ts
T
eomsangdonandClaude Opus 5.5 cd2690450e feat(spreadsheet): 긴 글이 옆 빈 칸으로 넘쳐 보이게(엑셀)
- 왼쪽 · 일반 맞춤 글은 오른쪽으로 · 오른쪽 맞춤은 왼쪽으로 · 가운데는 양쪽으로 — 옆 칸이 빌 때만
- 비지 않은 칸 · 병합 칸 · 틀 고정 경계에서 멈춤 · 가운데 맞춤이 한쪽만 막히면 그쪽을 잘라 냄
- 줄 바꿈 켠 칸 · 숫자(####) · 오류는 안 넘침 · 덮은 칸 사이 눈금선 감춤 · 고치는 중에는 활성 칸 넘침 감춤
- 폭 계산은 새 파일 spreadsheet_spill.ts(격자 파일이 이미 700 줄 넘어 따로) · 정확한 글 폭은 글 요소
  scrollWidth 를 판마다 한 번에 읽음
- ORCA(M02 면적산출 편집 창) 수치 확인 — 왼 · 오른 · 가운데 넘침 글 잘림 0 · 막힘 · 병합 · 틀 고정 멈춤 ·
  스크롤 · 확대 뒤 칸에 붙어 있음 · 비지 않은 칸과 겹침 0 · 실제 문서 새 그림 겹침 0 · 크기 시험 통과

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BYN9gMie8e6pXzSxJNb6Xt
2026-09-28 22:33:55 +09:00

62 lines
2.3 KiB
TypeScript

/* =============================================================================
* spreadsheet_spill.ts
* 긴 글 넘침(엑셀) — 칸보다 긴 글을 옆 빈 칸 위로 보임. 왼쪽 · 일반 맞춤은 오른쪽으로 · 오른쪽 맞춤은
* 왼쪽으로 · 가운데는 양쪽으로. 비지 않은 칸 · 병합 칸 · 판 끝(틀 고정 경계 · 그린 범위 밖)에서 멈춤.
* 격자(`spreadsheet_grid.ts`)가 판 하나를 그릴 때 줄마다 칸 자리(`slots`)를 모아 부름 — 계산만 여기.
* ========================================================================== */
/** 같은 판 · 같은 줄 · 병합 아닌 칸 하나(병합 칸 · 안 그린 칸은 넣지 않음 → 거기서 멈춤) */
export interface SpillSlot {
w: number;
empty: boolean;
}
/** 넘침 — 왼 · 오른쪽으로 더 쓸 폭(px) · 덮은 칸 열 범위 · 가운데 맞춤이 한쪽만 막혀 잘라 낼 폭 */
export interface Spill {
left: number;
right: number;
from: number;
to: number;
/** 가운데 맞춤 — 글 상자는 양쪽 반씩 늘리고 막힌 쪽은 이만큼 잘라 냄(글은 칸 가운데 그대로) */
clipLeft: number;
clipRight: number;
}
export type SpillAlign = "left" | "right" | "center";
/** 칸 c(폭 own)의 글 폭 need 가 넘치면 정렬 쪽 빈 칸으로 늘린 결과 · 안 넘치거나 못 늘리면 null */
export function spillOf(
slots: Map<number, SpillSlot>,
c: number,
own: number,
need: number,
align: SpillAlign,
): Spill | null {
if (need <= own) return null;
let from = c;
let to = c;
const grow = (dir: -1 | 1, want: number): number => {
let got = 0;
for (let k = c + dir; got < want; k += dir) {
const s = slots.get(k);
if (!s || !s.empty) break;
got += s.w;
if (dir < 0) from = k;
else to = k;
}
return got;
};
if (align === "center") {
const half = (need - own) / 2;
const l = Math.min(grow(-1, half), half);
const r = Math.min(grow(1, half), half);
if (!l && !r) return null;
return { left: half, right: half, from, to, clipLeft: half - l, clipRight: half - r };
}
const got = grow(align === "right" ? -1 : 1, need - own);
if (!got) return null;
return align === "right"
? { left: got, right: 0, from, to, clipLeft: 0, clipRight: 0 }
: { left: 0, right: got, from, to, clipLeft: 0, clipRight: 0 };
}