From b79793ea31293eb0ea915cdd2b5786fccd89e84d Mon Sep 17 00:00:00 2001 From: umsangdon Date: Mon, 28 Sep 2026 09:59:08 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat(spreadsheet):=20D=20=EC=8B=9C=ED=8A=B8?= =?UTF-8?q?=20=ED=83=AD=20=EC=97=86=EC=95=B0=20=EC=84=A0=ED=83=9D=20?= =?UTF-8?q?=E2=80=94=20createSpreadsheet({tabs:=20false})?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 탭 줄을 안 그림 · Ctrl+PageDown/PageUp · Shift+F11 을 받지 않음(브라우저 몫) · [데이터 ▾] 의 시트 숨기기 · 탭 색 빠짐 - 산출근거(시트 하나)용 · 크기 화면 28,199 B(예산 28,672) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01L6KXAabDTenEU7hrDQmCKY --- A00_Common/spreadsheet/spreadsheet.ts | 11 ++++++++--- A00_Common/spreadsheet/spreadsheet_actions.ts | 8 ++++++-- A00_Common/spreadsheet/spreadsheet_data_menu.ts | 9 ++++++++- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/A00_Common/spreadsheet/spreadsheet.ts b/A00_Common/spreadsheet/spreadsheet.ts index 341a9fc5..38951196 100644 --- a/A00_Common/spreadsheet/spreadsheet.ts +++ b/A00_Common/spreadsheet/spreadsheet.ts @@ -51,6 +51,8 @@ export interface SpreadsheetOptions { onChange?: (book: Workbook) => void; /** 고름이 바뀜 — 시트 id · 활성 칸 A1 · 범위 A1 */ onSelect?: (selection: { 시트: string; 칸: string; 범위: string }) => void; + /** 아래 시트 탭 줄 — false 면 안 그림(산출근거 = 시트 하나) · 시트 오가기 · 새 시트 단축키 · 시트 메뉴도 끔 */ + tabs?: boolean; } export interface SpreadsheetHandle { @@ -88,7 +90,10 @@ export function createSpreadsheet( opts: SpreadsheetOptions = {}, ): SpreadsheetHandle { const readOnly = !!opts.readOnly; - const root = el("div", { className: readOnly ? "ss ss--readonly" : "ss" }); + const noTabs = opts.tabs === false; + const root = el("div", { + className: `ss${readOnly ? " ss--readonly" : ""}${noTabs ? " ss--notabs" : ""}`, + }); host.append(root); const firstSheet = (b: Workbook) => b.시트.find((s) => s.id === b.활성) ?? b.시트[0]; /** 시트마다 마지막 고름(탭을 오가도 그대로) */ @@ -116,14 +121,14 @@ export function createSpreadsheet( const ed = createEditor(ctx); ctx.editor = ed; const toolbar: PartHandle | null = readOnly ? null : mountToolbar(ctx); - const tabs = mountTabs(ctx); + const tabs: PartHandle | null = noTabs ? null : mountTabs(ctx); const menu: PartHandle | null = readOnly ? null : attachMenu(ctx); const clip = attachClipboard(ctx); const status = createStatusBar(ctx); const others = [toolbar, tabs, menu, clip, status].filter((p): p is PartHandle => !!p); grid.root.classList.add("ss-grid-host"); - for (const node of [toolbar?.root, ed.bar, grid.root, tabs.root, status.root]) + for (const node of [toolbar?.root, ed.bar, grid.root, tabs?.root, status.root]) if (node) root.append(node); const extras = attachExtras(ctx, ed, toolbar?.root ?? null); others.push(...extras.parts); diff --git a/A00_Common/spreadsheet/spreadsheet_actions.ts b/A00_Common/spreadsheet/spreadsheet_actions.ts index 4c8fa631..9fae231f 100644 --- a/A00_Common/spreadsheet/spreadsheet_actions.ts +++ b/A00_Common/spreadsheet/spreadsheet_actions.ts @@ -81,6 +81,8 @@ const CTRL_SHIFT: Record = { PageUp: "prev", }; +const SHEET_ACTS = new Set(["next", "prev", "newSheet"]); + /** body 에 뜬 창(.ui-confirm)이 다 닫히면 초점을 격자로 — 창을 연 바로 뒤에 부름 */ export function watchClose(back: () => void): void { const w = new MutationObserver(() => { @@ -114,8 +116,10 @@ export function mountActions(ctx: SpreadsheetContext, back: () => void): Actions return { key(e) { const act = pick(e); - if (act) go(act); - return !!act; + // 시트 탭이 없으면(산출근거) 시트 오가기 · 새 시트를 받지 않음 — 브라우저 몫으로 둠 + if (!act || (SHEET_ACTS.has(act) && ctx.root.classList.contains("ss--notabs"))) return false; + go(act); + return true; }, items: [ item(TEXT.goTo, "goTo"), diff --git a/A00_Common/spreadsheet/spreadsheet_data_menu.ts b/A00_Common/spreadsheet/spreadsheet_data_menu.ts index 3339afae..307c2293 100644 --- a/A00_Common/spreadsheet/spreadsheet_data_menu.ts +++ b/A00_Common/spreadsheet/spreadsheet_data_menu.ts @@ -181,7 +181,14 @@ export function mountDataMenu(ctx: SpreadsheetContext, back: () => void): DataMe async () => (await import("./spreadsheet_names")).createNameManagerPanel, ), ], - [TEXT.sheets, () => void openPanel(TEXT.sheets, async () => createSheetExtraPanel)], + ...(ctx.root.classList.contains("ss--notabs") // 시트 탭 없음(산출근거) — 시트 창도 없음 + ? [] + : [ + [ + TEXT.sheets, + () => void openPanel(TEXT.sheets, async () => createSheetExtraPanel), + ] as MapContextMenuItem, + ]), [TEXT.grid, () => (toggleGridlines(), back())], ...act.items, { From 86ae6db5a095bd60617828d191be333652e14c63 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Mon, 28 Sep 2026 09:59:09 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat(M02):=20=EC=82=B0=EC=B6=9C=EA=B7=BC?= =?UTF-8?q?=EA=B1=B0=20=EC=B9=B4=EB=93=9C=20=C2=B7=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=ED=8E=B8=EC=A7=91=20=E2=80=94=20=EC=8B=9C=ED=8A=B8=20=ED=83=AD?= =?UTF-8?q?=20=EC=97=86=EC=9D=B4(tabs:=20false)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01L6KXAabDTenEU7hrDQmCKY --- M02_MasterTemplete/M02_MasterTemplete_Structure.ts | 2 +- M02_MasterTemplete/M02_MasterTemplete_UI_Main.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/M02_MasterTemplete/M02_MasterTemplete_Structure.ts b/M02_MasterTemplete/M02_MasterTemplete_Structure.ts index 84b123e5..45fbc284 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Structure.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_Structure.ts @@ -153,7 +153,7 @@ export function createStructurePanel(opts: StructurePanelOptions): StructurePane try { const { createSpreadsheet } = await loadSpreadsheet(); if (mine !== seq || !basisDoc) return; - basis = createSpreadsheet(basisHost, basisDoc, { readOnly: true }); + basis = createSpreadsheet(basisHost, basisDoc, { readOnly: true, tabs: false }); } catch (error) { if (mine === seq) basisHost.replaceChildren(note(fill(TEXT.noSheet, why(error)))); } diff --git a/M02_MasterTemplete/M02_MasterTemplete_UI_Main.ts b/M02_MasterTemplete/M02_MasterTemplete_UI_Main.ts index 53f66bbd..56112e6c 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_UI_Main.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_UI_Main.ts @@ -186,6 +186,7 @@ export function createMain(isAdmin: boolean, onSaved?: () => void): MainHandle { const { createSpreadsheet } = await import("../A00_Common/spreadsheet/spreadsheet"); editor = createSpreadsheet(host, doc as Parameters[1], { readOnly, + tabs: false, // 산출근거 = 시트 하나 · 탭 줄 없음 onChange: () => (dirty = !readOnly), }); } catch {