feat(spreadsheet): 공개 손잡이 addSheet · 되돌리기 한 번 · 탭 없이 띄운 시트에 탭 줄 붙임 · 도면 표 → 면적 새 시트 검증(83-3)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015KYZ2HWWdUwZWYnn3tQz7X
This commit is contained in:
@@ -36,6 +36,7 @@ import type {
|
||||
CalcValues,
|
||||
Command,
|
||||
CommandEffect,
|
||||
Sheet,
|
||||
SheetCellAddress,
|
||||
Workbook,
|
||||
} from "./spreadsheet_types";
|
||||
@@ -81,6 +82,10 @@ export interface SpreadsheetHandle {
|
||||
/** 알약 키를 지금 시트 `칸`(A1)에 잇기 · 풀기(null) — 알약 누름과 같은 규칙 · 되돌리기 됨 ·
|
||||
* 그 칸 다른 알약은 함께 둠(`replace` 면 뺌) · 주소가 틀리거나 읽기만이면 false */
|
||||
setLink(key: string, cell: string | null, info?: LinkInfo, replace?: boolean): boolean;
|
||||
/** 시트 하나 덧붙임(끝 자리 · 83-3 도면 → 면적) — 되돌리기 한 번 · onChange · 이름 겹치면 「이름 (n)」 ·
|
||||
* `activate` 면 새 시트로 · 탭 줄 없이 띄운 시트면 탭 줄을 붙임(시트 1장으로 돌아가면 숨김) ·
|
||||
* 붙인 시트 이름 · 읽기만이면 null */
|
||||
addSheet(sheet: Sheet, opts?: { activate?: boolean }): string | null;
|
||||
destroy(): void;
|
||||
}
|
||||
|
||||
@@ -154,6 +159,8 @@ export function createSpreadsheet(
|
||||
others.push(...extras.parts);
|
||||
const detachKeys = attachKeys(ctx, ed, extras.keys);
|
||||
const detachMouse = attachMouse(ctx, ed, extras.mouse);
|
||||
/** `addSheet` 가 나중에 붙인 탭 줄(탭 없이 띄운 시트) */
|
||||
let lateTabs: PartHandle | null = null;
|
||||
const toast = el("div", { className: "ss-toast" });
|
||||
let toastTimer = 0;
|
||||
/** 알약 막대 · 연결 따라가기 — 선택이 있거나 문서에 연결이 있을 때만 불러옴(크기 예산) */
|
||||
@@ -303,6 +310,40 @@ export function createSpreadsheet(
|
||||
loadLinks(); // 처음 연결이면 알약 막대 · 칸 세모를 불러옴
|
||||
return true;
|
||||
},
|
||||
addSheet(sheet, add) {
|
||||
if (readOnly) return null;
|
||||
const taken = (name: string) =>
|
||||
ctx.book.시트.some((x) => x.이름.toLowerCase() === name.toLowerCase());
|
||||
let 이름 = sheet.이름;
|
||||
for (let n = 2; taken(이름); n += 1) 이름 = `${sheet.이름} (${n})`;
|
||||
let id = sheet.id;
|
||||
for (let n = ctx.book.시트.length + 1; ctx.book.시트.some((x) => x.id === id); n += 1)
|
||||
id = `s${n}`;
|
||||
const before = ctx.book.시트.length;
|
||||
dispatch({ 종류: "시트더하기", 시트: { ...sheet, id, 이름 }, 자리: ctx.book.시트.length });
|
||||
if (ctx.book.시트.length === before) return null; // 명령이 막힘(알림은 냄)
|
||||
if (noTabs && !lateTabs) {
|
||||
// 탭 줄 없이 띄운 시트 — 지금 붙이고 시트가 1장이면(되돌리기) 숨김
|
||||
const part = mountTabs(ctx);
|
||||
const bar = part.root;
|
||||
const sync = (): void => {
|
||||
const many = ctx.book.시트.length > 1;
|
||||
if (bar) bar.hidden = !many;
|
||||
root.classList.toggle("ss--notabs", !many);
|
||||
};
|
||||
lateTabs = {
|
||||
root: part.root,
|
||||
refresh: () => (part.refresh(), sync()),
|
||||
destroy: () => part.destroy(),
|
||||
};
|
||||
if (bar) status.root ? status.root.before(bar) : root.append(bar);
|
||||
others.push(lateTabs);
|
||||
sync();
|
||||
}
|
||||
if (add?.activate) showSheet(id);
|
||||
else for (const p of others) p.refresh();
|
||||
return 이름;
|
||||
},
|
||||
destroy() {
|
||||
clearTimeout(toastTimer);
|
||||
detachKeys();
|
||||
|
||||
Reference in New Issue
Block a user