fix(B09): 설계내역서 폴더 줄 글꼴 한 벌 · 들여쓰기 넓힘 · 끌기 놓을 자리 표시 · 데이터 점검 틈 (240 · 121 · 122)
- 레벨 고쳐 생긴 폴더 줄도 처음 폴더 줄과 같은 꼴(is-title · 크기 = 레벨) - 들여쓰기 한 단 22px · 끌기 좌우 한 단 = 들여쓰기 폭 - 끌기 미리 보기 = 레벨 시작 점 · 「○○ 안 · 레벨 N」 · 들어갈 폴더 줄 테두리 · 끄는 줄 흐림 - 데이터 점검 [업데이트] 위 틈 = 카드 왼쪽 여유 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LLCk2y5xE8YGVgjbTntWsY
This commit is contained in:
@@ -66,11 +66,6 @@
|
||||
font-size: var(--text-caption);
|
||||
}
|
||||
|
||||
/* 182 설계내역서 묶음 줄 굵게 · 레벨 들여쓰기 = 공용 표 level 옵션(201-1) */
|
||||
.b09-estimation .ui-data-table__table tbody tr.is-group td {
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
|
||||
/* 166-2 설계내역서 손 줄 — 사용자가 더한 줄 표시(왼쪽 띠) */
|
||||
.b09-estimation .ui-data-table__table tbody tr.is-hand td:first-child {
|
||||
background-image: linear-gradient(to right, var(--color-primary) 3px, transparent 3px);
|
||||
@@ -163,6 +158,11 @@
|
||||
background: var(--color-warning);
|
||||
}
|
||||
|
||||
/* 122 데이터 점검 [업데이트] — 제목 아래 틈 = 카드 왼쪽 여유와 같게 */
|
||||
.b09-options [data-b09-refresh] {
|
||||
margin-top: calc(var(--spacing-8) + var(--spacing-4));
|
||||
}
|
||||
|
||||
/* 연결 점검 목록 — 이름 · 탭(작게) · 알림 글 */
|
||||
.b09-check__head,
|
||||
.b09-check__note {
|
||||
@@ -179,13 +179,51 @@
|
||||
|
||||
/* 줄 끌기(204-1) — 놓을 자리 · 레벨 미리 보기 선 · 못 놓는 자리 = 빨간 점선 */
|
||||
.b09-estimation__drop {
|
||||
--drop-c: var(--color-primary);
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
height: 0;
|
||||
border-top: 2px solid var(--color-primary);
|
||||
border-top: 2px solid var(--drop-c);
|
||||
color: var(--drop-c);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.b09-estimation__drop.is-bad {
|
||||
border-top: 2px dashed var(--color-danger);
|
||||
--drop-c: var(--color-danger);
|
||||
border-top-style: dashed;
|
||||
}
|
||||
|
||||
/* 121 선 머리 = 레벨 시작 점 + 「어디 안 · 몇 레벨」 · 들어갈 폴더 줄 = 테두리 · 끄는 줄 = 흐리게 */
|
||||
.b09-estimation__drop::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
left: -5px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border: 2px solid;
|
||||
border-radius: 50%;
|
||||
background: var(--color-canvas);
|
||||
}
|
||||
|
||||
.b09-estimation__drop-tag {
|
||||
position: absolute;
|
||||
top: -11px;
|
||||
padding: 1px var(--spacing-8);
|
||||
border: 1px solid;
|
||||
border-radius: var(--radius-pills);
|
||||
background: var(--color-surface-raised);
|
||||
font-size: var(--text-caption);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.b09-estimation [data-b09-table="bill"] tbody tr.is-drop-into td {
|
||||
box-shadow:
|
||||
inset 0 2px 0 var(--color-primary),
|
||||
inset 0 -2px 0 var(--color-primary);
|
||||
background-color: color-mix(in srgb, var(--color-primary) 14%, transparent);
|
||||
}
|
||||
|
||||
.b09-estimation [data-b09-table="bill"] tbody tr.is-drag-src td {
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
@@ -99,7 +99,8 @@ export const buildBill: TabBuild = (ctx): BillTable => {
|
||||
rowClass: (i) => {
|
||||
const r = rows[i];
|
||||
if (!r) return null;
|
||||
const title = r.kind === "title" ? "is-title" : r.kind === "group" ? "is-group" : "";
|
||||
// 240 폴더 줄 = 처음 · 레벨 고쳐 생긴 것 모두 같은 줄 꼴(글자 크기 = 레벨 · 공용 is-lvN)
|
||||
const title = r.kind === "item" ? "" : "is-title";
|
||||
return [title, r.auto ? "" : "is-hand"].filter((c) => c).join(" ") || null;
|
||||
},
|
||||
// 228-1 레벨 = 셈 나무 깊이(들여 · 내어쓰기 · 끌기 = 다시 셈 · 다시 그림) · 글꼴 = 레벨 · 묶음(빈 공종도)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* 놓을 자리 = 줄 사이 틈(포인터가 줄 가운데 위 = 그 줄 앞) · 끄는 줄 자손 = 함께 감 · 자기 자손 안 = 못 놓음
|
||||
* 레벨 = 위 줄 + 1(위 줄 아래로 · 항목이면 저절로 묶음) ~ 아래 줄 레벨 · 맨 위(1) = 맨 위 줄만
|
||||
* 놓기 = 표 drop(`…_Bill_Edit` dropMove — 메뉴와 같은 지킬 것) · 미리 보기 선(못 놓음 = is-bad · 커서 not-allowed)
|
||||
* 미리 보기(121) = 선 머리 글 「○○ 안 · 레벨 N」 + 들어갈 폴더 줄 테두리 + 끄는 줄 흐리게 · 좌우 한 단 = 들여쓰기 폭(--dt-indent)
|
||||
* 잡기 = 글 칸 · 단추 밖 아무 칸 · 6px 넘게 움직여야 끌기(그냥 누름 = 줄 고름)
|
||||
* ========================================================================== */
|
||||
|
||||
@@ -64,9 +65,15 @@ export function attachDrag(root: HTMLElement, table: BillTable, done: (key: stri
|
||||
const tr = target.closest<HTMLElement>("tr[data-i]");
|
||||
if (!tr || !root.contains(tr)) return;
|
||||
const from = Number(tr.dataset.i);
|
||||
const step = parseFloat(getComputedStyle(tr).fontSize) || 14;
|
||||
const step = parseFloat(getComputedStyle(tr).getPropertyValue("--dt-indent")) || 14;
|
||||
const line = document.createElement("div");
|
||||
line.className = "b09-estimation__drop";
|
||||
const tag = document.createElement("span");
|
||||
tag.className = "b09-estimation__drop-tag";
|
||||
line.append(tag);
|
||||
const rowEl = (i: number): HTMLElement | null => root.querySelector(`tr[data-i="${i}"]`);
|
||||
let into: HTMLElement | null = null;
|
||||
let lifted: HTMLElement[] = [];
|
||||
let on = false;
|
||||
let run: (() => void) | null = null;
|
||||
let seen = "";
|
||||
@@ -76,6 +83,13 @@ export function attachDrag(root: HTMLElement, table: BillTable, done: (key: stri
|
||||
if (!on) {
|
||||
on = true;
|
||||
document.body.append(line);
|
||||
const lv = Number(table.rows[from]?.level ?? 1);
|
||||
for (let i = from; i === from || Number(table.rows[i]?.level ?? 1) > lv; i++) {
|
||||
const el = rowEl(i);
|
||||
if (!el) break;
|
||||
el.classList.add("is-drag-src");
|
||||
lifted.push(el);
|
||||
}
|
||||
document.body.style.userSelect = "none";
|
||||
window.getSelection()?.removeAllRanges();
|
||||
}
|
||||
@@ -95,14 +109,24 @@ export function attachDrag(root: HTMLElement, table: BillTable, done: (key: stri
|
||||
if (key !== seen) {
|
||||
seen = key;
|
||||
run = at ? table.drop!(from, at.parent, at.before) : null;
|
||||
const p = at?.parent ? table.rows.findIndex((r) => String(r.key) === at.parent) : -1;
|
||||
into?.classList.remove("is-drop-into");
|
||||
into = p >= 0 ? rowEl(p) : null;
|
||||
into?.classList.add("is-drop-into");
|
||||
tag.textContent = !run
|
||||
? "못 놓음"
|
||||
: `${p >= 0 ? `「${String(table.rows[p].name ?? "").trim()}」 안` : "맨 위"} · 레벨 ${at!.level}`;
|
||||
}
|
||||
const cell = tr.querySelector("td.ui-data-table__lv") ?? tr;
|
||||
const box = root.getBoundingClientRect();
|
||||
const left = box.left + ((at?.level ?? want) - 1) * step + 8;
|
||||
const left = cell.getBoundingClientRect().left + ((at?.level ?? want) - 1) * step + 8;
|
||||
Object.assign(line.style, {
|
||||
top: `${y - 1}px`,
|
||||
left: `${left}px`,
|
||||
width: `${Math.max(box.right - left, 40)}px`,
|
||||
});
|
||||
// 머리 글 = 명칭 칸 바로 오른쪽 · 선 위에 걸침(줄 이름을 덮지 않게)
|
||||
tag.style.left = `${Math.max(12, cell.getBoundingClientRect().right - left + 8)}px`;
|
||||
line.classList.toggle("is-bad", !run);
|
||||
document.body.style.cursor = run ? "grabbing" : "not-allowed";
|
||||
};
|
||||
@@ -111,6 +135,9 @@ export function attachDrag(root: HTMLElement, table: BillTable, done: (key: stri
|
||||
window.removeEventListener("pointerup", stop);
|
||||
window.removeEventListener("pointercancel", stop);
|
||||
line.remove();
|
||||
into?.classList.remove("is-drop-into");
|
||||
for (const el of lifted) el.classList.remove("is-drag-src");
|
||||
lifted = [];
|
||||
document.body.style.userSelect = "";
|
||||
document.body.style.cursor = "";
|
||||
if (!on) return;
|
||||
|
||||
@@ -311,7 +311,7 @@ def test_연결_단추_칸_메뉴_고르기_창_TS():
|
||||
assert out["link"] == [None, {"tab": "dg", "key": "DG:a"}] # 단추 칸 = 이동 안 함
|
||||
assert out["cls"] == [
|
||||
"is-title",
|
||||
"is-group is-hand",
|
||||
"is-title is-hand",
|
||||
"is-hand",
|
||||
None,
|
||||
] # fmt: skip 201-1 레벨 = 공용 표 level
|
||||
|
||||
@@ -88,7 +88,7 @@ def test_CSS_레벨_글꼴_규칙():
|
||||
css = (ROOT / "ui_template" / "ui_template_data_table.css").read_text("utf-8")
|
||||
tokens = dict(re.findall(r"(--dt-(?:lv\d-size|indent)): ([^;]+);", css))
|
||||
assert tokens == {
|
||||
"--dt-indent": "var(--text-body-sm)",
|
||||
"--dt-indent": "22px",
|
||||
"--dt-lv1-size": "var(--text-body)",
|
||||
"--dt-lv2-size": "15px",
|
||||
"--dt-lv4-size": "13px",
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
"""PLAN 240 · 121 · 122 — B09 설계내역서 폴더 줄 글꼴 한 벌 · 들여쓰기 폭 · 끌기 미리 보기 · 데이터 점검 틈."""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
B09 = ROOT / "B09_Estimation"
|
||||
|
||||
|
||||
def _read(p: Path) -> str:
|
||||
return p.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_폴더_줄은_처음이든_레벨_고쳐_생겼든_같은_줄_꼴():
|
||||
src = _read(B09 / "B09_Estimation_UI_Tabs_Bill.ts")
|
||||
assert 'const title = r.kind === "item" ? "" : "is-title";' in src
|
||||
assert '"is-group"' not in src
|
||||
css = _read(B09 / "B09_Estimation_UI_Page.css")
|
||||
assert "tr.is-group" not in css # 옛 묶음 줄 꼴(색 다름) 없음
|
||||
|
||||
|
||||
def test_들여쓰기_한_단_넓힘_끌기_한_단과_같음():
|
||||
css = _read(ROOT / "ui_template" / "ui_template_data_table.css")
|
||||
assert re.search(r"--dt-indent: 22px;", css)
|
||||
drag = _read(B09 / "B09_Estimation_UI_Tabs_Bill_Drag.ts")
|
||||
assert 'getPropertyValue("--dt-indent")' in drag
|
||||
|
||||
|
||||
def test_끌기_미리_보기_어디_안_몇_레벨_폴더_테두리_끄는_줄_흐림():
|
||||
drag = _read(B09 / "B09_Estimation_UI_Tabs_Bill_Drag.ts")
|
||||
for part in (
|
||||
"b09-estimation__drop-tag",
|
||||
"is-drop-into",
|
||||
"is-drag-src",
|
||||
"못 놓음",
|
||||
"안",
|
||||
"맨 위",
|
||||
):
|
||||
assert part in drag, part
|
||||
css = _read(B09 / "B09_Estimation_UI_Page.css")
|
||||
for sel in (".b09-estimation__drop-tag", "tr.is-drop-into td", "tr.is-drag-src td"):
|
||||
assert sel in css, sel
|
||||
# 끝나면 표시를 모두 걷음
|
||||
assert 'into?.classList.remove("is-drop-into")' in drag
|
||||
assert 'el.classList.remove("is-drag-src")' in drag
|
||||
|
||||
|
||||
def test_데이터_점검_업데이트_위_틈_카드_왼쪽_여유와_같음():
|
||||
css = _read(B09 / "B09_Estimation_UI_Page.css")
|
||||
m = re.search(r"\.b09-options \[data-b09-refresh\] \{\s*margin-top: ([^;]+);", css)
|
||||
assert m and m.group(1) == "calc(var(--spacing-8) + var(--spacing-4))"
|
||||
card = _read(ROOT / "ui_template" / "ui_template_overlay.css")
|
||||
assert re.search(
|
||||
r"\.ui-sidebar-card \{\s*padding: calc\(var\(--spacing-8\) \+ var\(--spacing-4\)\);", card
|
||||
)
|
||||
@@ -10,8 +10,8 @@
|
||||
--dt-head: color-mix(in srgb, var(--color-accent) 6%, var(--color-surface));
|
||||
--dt-line: var(--color-border);
|
||||
--dt-edge: color-mix(in srgb, var(--color-text-secondary) 45%, var(--color-border));
|
||||
/* 들여쓰기 한 단 = 표 기본 글자 1em(레벨 글자 크기와 무관 · 끌기 한 단과 같음) */
|
||||
--dt-indent: var(--text-body-sm);
|
||||
/* 들여쓰기 한 단(레벨 글자 크기와 무관 · 끌기 한 단과 같음 · 121 넓힘) */
|
||||
--dt-indent: 22px;
|
||||
/* 레벨 글자 크기(PLAN 228-1) — 줄 높이 28px 안 · Lv3 = 표 기본(14px) */
|
||||
--dt-lv1-size: var(--text-body);
|
||||
--dt-lv2-size: 15px;
|
||||
|
||||
Reference in New Issue
Block a user