Merge remote-tracking branch 'origin/sub_laptop_5' into main_laptop_1

This commit is contained in:
2026-11-04 11:48:02 +09:00
5 changed files with 86 additions and 0 deletions
+7
View File
@@ -72,6 +72,9 @@ export interface SpreadsheetOptions {
conditions?: ConditionOptions;
/** 그림 열쇠 → 주소(요구 347-5 · 시트 `그림`) — 없으면 이름 적힌 빈 상자 */
figureSrc?: FigureSrc;
/** 칸 칠(요구 621-5) — 시트 id · 행 · 열(0 부터) → 꼴 이름 `success|warning|info|danger|muted`(흐림) + `mine`(왼쪽 띠) ·
* 공백으로 여럿 · 칸 `data-tone` 으로 나감 · 보이는 칸만 부름 · 안 주면 화면 그대로 */
칠?: (시트: string, r: number, c: number) => string | null | undefined;
}
export interface SpreadsheetHandle {
@@ -93,6 +96,8 @@ export interface SpreadsheetHandle {
/** HTML 표를 지금 시트 고른 칸(왼위)부터 붙임(105-1 도면 → 면적) — 붙여넣기와 같은 길(병합 · 되돌리기 한 번) ·
* `check` = 덮을 자리의 값 칸 · 알약 칸 수 · 범위 → false 면 안 붙임 · 붙인 범위 A1 · 읽기만 · 못 하면 null */
pasteTable(html: string, check?: PasteCheck): Promise<string | null>;
/** 보이는 칸만 다시 그림(`칠` 결과가 바뀐 뒤) — 문서는 안 읽음 */
repaint(): void;
/** 범위 고름 · 보이게 굴림(329-2 엑셀 보기 창) — `시트` = id 나 이름(없으면 지금 시트 · 다르면 그 탭으로) ·
* 범위 여럿 = 여러 고름 · 시트가 없거나 주소가 틀리면 false(고름 그대로) */
select(범위: string | string[], 시트?: string): boolean;
@@ -138,6 +143,7 @@ export function createSpreadsheet(
root,
book,
readOnly,
fill: opts.칠,
engine: createCalcEngine(book),
history: createHistory(),
selection: selectCell(firstSheet(book), 0, 0),
@@ -369,6 +375,7 @@ export function createSpreadsheet(
return 이름;
},
pasteTable: (html, check) => pasteTableAt(ctx, html, check),
repaint: () => grid.render(),
select(range, sheetKey) {
const target = sheetKey
? ctx.book.시트.find((s) => s.id === sheetKey || s.이름 === sheetKey)
@@ -276,3 +276,40 @@ html[data-touch="on"] .aislo-grid__fill-handle {
touch-action: pan-x pan-y;
}
}
/* 칸 칠(옵션 `칠` · 요구 621-5) — 칸 원래 채움(인라인 background-color) 위에 겹침 · 어두움은 --color-* 가 따라감. */
.aislo-cell[data-tone~="success"] {
background-image: linear-gradient(
color-mix(in srgb, var(--color-success) 18%, transparent),
color-mix(in srgb, var(--color-success) 18%, transparent)
);
}
.aislo-cell[data-tone~="warning"] {
background-image: linear-gradient(
color-mix(in srgb, var(--color-warning) 18%, transparent),
color-mix(in srgb, var(--color-warning) 18%, transparent)
);
}
.aislo-cell[data-tone~="info"] {
background-image: linear-gradient(
color-mix(in srgb, var(--color-info) 18%, transparent),
color-mix(in srgb, var(--color-info) 18%, transparent)
);
}
.aislo-cell[data-tone~="danger"] {
background-image: linear-gradient(
color-mix(in srgb, var(--color-danger) 18%, transparent),
color-mix(in srgb, var(--color-danger) 18%, transparent)
);
}
.aislo-cell[data-tone~="muted"] {
color: var(--color-text-muted) !important;
}
.aislo-cell[data-tone~="mine"] {
box-shadow: inset 3px 0 0 var(--color-accent);
}
/* 읽기만 — 시트 탭 「+」 숨김 */
.ss--readonly .ss-tabs__add {
display: none;
}
@@ -319,6 +319,9 @@ export function renderCells(
if (need > w * 0.9) longs.push({ r: r0, c: c0, el: cellEl, own: w, need, align });
}
}
const tone = ctx.fill?.(sheet.id, r0, c0);
if (tone) cellEl.dataset.tone = tone;
else delete cellEl.dataset.tone; // 재사용 div — 앞 칸 꼴을 지움
cellEl.classList.toggle("is-error", display.isError);
cellEl.classList.toggle("has-comment", !!comment);
cellEl.classList.toggle(
@@ -94,6 +94,8 @@ export interface SpreadsheetContext {
/** 지금 문서 — 명령만이 바꿈(직접 고치지 말 것) */
book: Workbook;
readOnly: boolean;
/** 칸 칠(옵션 `칠`) — 시트 id · 행 · 열 → 꼴 이름(공백으로 여럿 · 없으면 칠 없음) · 보이는 칸만 부름 */
fill?: (시트: string, r: number, c: number) => string | null | undefined;
engine: CalcEngine;
history: History;
selection: Selection;
+37
View File
@@ -0,0 +1,37 @@
"""779-3 지킴 — 공용 격자 「칠」 옵션(요구 621-5): 안 주면 data-tone 없음 · 주면 보이는 칸만 · 색은 --color-* 만.
화면 수치 판정은 tmp 의 playwright 일회 검증 · 여기서는 길이 빠지지 않았는지만 지킴."""
import re
from pathlib import Path
SS = Path(__file__).parents[2] / "A00_Common/spreadsheet"
def read(name: str) -> str:
return (SS / name).read_text(encoding="utf-8")
def test_fill_option_flows_option_to_ctx_to_cell():
assert "칠?:" in read("spreadsheet.ts") and "fill: opts.칠" in read("spreadsheet.ts")
assert "fill?:" in read("spreadsheet_view_types.ts")
def test_tone_set_only_in_visible_cell_loop_and_cleared_when_absent():
cells = read("spreadsheet_grid_cells.ts")
assert cells.count("ctx.fill?.(") == 1 # 칸 그리는 반복(보이는 칸) 안 한 곳뿐
assert "cellEl.dataset.tone = tone" in cells
assert "delete cellEl.dataset.tone" in cells # 재사용 div — 안 주면 data-tone 없음
def test_repaint_handle_only_rerenders_grid():
assert re.search(r"repaint:\s*\(\)\s*=>\s*grid\.render\(\)", read("spreadsheet.ts"))
def test_css_tones_use_color_tokens_only_and_readonly_hides_add():
css = read("spreadsheet_grid.css")
tone = css[css.index('[data-tone~="success"]') :]
for name in ("success", "warning", "info", "danger"):
assert f"var(--color-{name}) 18%" in tone
assert "--draw-" not in tone
assert "var(--color-text-muted)" in tone and "var(--color-accent)" in tone
assert ".ss--readonly .ss-tabs__add" in css