feat(381-1 B05 평면): 되돌리기 · 다시하기 아이콘 곧은 꼬리 + 갈고리 · 절/성토선 테마 색 · 굵게
- 평면 도구줄 · 종단 도구줄 ↶ ↷ → HISTORY_ICON SVG(↩ ↪ 꼴 · 회전 반 바퀴 그림과 구분) - 절토 #e11d48/#ff6b6b · 성토 #0d9488/#2dd4bf · 도로 끝 1.8 · 비탈 끝 2.6 px - 시험 chrome_modal · 346_2 고쳐 씀 · 282 가짜 require 에 HISTORY_ICON Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013QyNXY2TUKXCFMwAca2APG
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
import type { StraightRun } from "./logic/B05_Profile_UI_Profile_Straighten";
|
||||
import { sameRun } from "./logic/B05_Profile_UI_Profile_Straighten";
|
||||
import { HISTORY_ICON } from "./B05_Profile_UI_RouteEdit_Chrome";
|
||||
import type { FreeChartGeom } from "../A00_Common/design/design_profile_free_view";
|
||||
|
||||
export type ProfileToolMode = "none" | "straighten" | "shift" | "free";
|
||||
@@ -174,6 +175,11 @@ export function createProfileTools(callbacks: ProfileToolsCallbacks): ProfileToo
|
||||
undo.disabled = !callbacks.canUndo();
|
||||
const redo = toolButton("↷", "다시하기 (Ctrl+Shift+Z)", callbacks.onRedo);
|
||||
redo.disabled = !callbacks.canRedo();
|
||||
// 평면 편집과 같은 그림(요구 241-9) — 글은 aria-label 로.
|
||||
undo.innerHTML = HISTORY_ICON.undo;
|
||||
undo.setAttribute("aria-label", "되돌리기");
|
||||
redo.innerHTML = HISTORY_ICON.redo;
|
||||
redo.setAttribute("aria-label", "다시하기");
|
||||
|
||||
const straighten = toolButton(
|
||||
"직선화",
|
||||
|
||||
@@ -31,6 +31,17 @@ export const HALF_TURN_ICON = {
|
||||
<path d="M3 8a5 5 0 0 1 10 0" /><path d="M13 8 14.8 5.6" /><path d="M13 8 10.6 6.6" /></svg>`,
|
||||
};
|
||||
|
||||
/** 되돌리기 · 다시하기 아이콘 — **곧은 꼬리 + 갈고리**(↩ ↪ · 요구 241-9). 둥근 화살표(`↶`·`↷`)는
|
||||
* 회전 단추와 헷갈렸다. 종단 도구줄도 같은 그림. */
|
||||
export const HISTORY_ICON = {
|
||||
undo: `<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true" fill="none"
|
||||
stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M3 6h7.5a3.5 3.5 0 0 1 0 7H7" /><path d="M6 3 3 6l3 3" /></svg>`,
|
||||
redo: `<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true" fill="none"
|
||||
stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M13 6H5.5a3.5 3.5 0 0 0 0 7H9" /><path d="M10 3l3 3-3 3" /></svg>`,
|
||||
};
|
||||
|
||||
export interface RouteEditChrome {
|
||||
overlay: HTMLElement;
|
||||
canvas: HTMLCanvasElement;
|
||||
@@ -65,9 +76,9 @@ export function createRouteEditChrome(
|
||||
data-act="hint-toggle" aria-expanded="false" title="조작 도움말 펼치기 · 접기">?</button>
|
||||
<i class="b05-route__view-separator" aria-hidden="true"></i>
|
||||
<button type="button" class="ui-btn ui-btn--glass" data-act="undo"
|
||||
title="되돌리기 (Ctrl+Z)" aria-label="되돌리기" disabled>↶</button>
|
||||
title="되돌리기 (Ctrl+Z)" aria-label="되돌리기" disabled>${HISTORY_ICON.undo}</button>
|
||||
<button type="button" class="ui-btn ui-btn--glass" data-act="redo"
|
||||
title="다시하기 (Ctrl+Y)" aria-label="다시하기" disabled>↷</button>
|
||||
title="다시하기 (Ctrl+Y)" aria-label="다시하기" disabled>${HISTORY_ICON.redo}</button>
|
||||
<i class="b05-route__view-separator" aria-hidden="true"></i>
|
||||
<span data-slot="tools"></span>
|
||||
<i class="b05-route__view-separator" aria-hidden="true"></i>
|
||||
@@ -79,7 +90,7 @@ export function createRouteEditChrome(
|
||||
aria-pressed="false" disabled
|
||||
title="1m 간격 등고선을 얇고 옅게 겹칩니다 (확대하면 보임)">1m 등고선</button>
|
||||
<button type="button" class="ui-btn ui-btn--glass" data-act="footprint"
|
||||
title="도로 끝 · 비탈 끝(깎기 붉음 · 쌓기 파랑)을 평면에 겹칩니다">절/성토선</button>
|
||||
title="도로 끝 · 비탈 끝(깎기 붉음 · 쌓기 청록)을 평면에 겹칩니다">절/성토선</button>
|
||||
<button type="button" class="ui-btn ui-btn--glass" data-act="measure"
|
||||
title="노선 위 두 점을 눌러 거리·기울기를 잽니다 (Shift+클릭도 같음)">거리 재기</button>
|
||||
<i class="b05-route__view-separator" aria-hidden="true"></i>
|
||||
|
||||
@@ -17,14 +17,13 @@ import {
|
||||
} from "./logic/B05_Profile_Footprint_Strokes";
|
||||
import "./B05_Profile_UI_Style_RouteEdit_Footprint.css";
|
||||
|
||||
/** 갈래 → 색 토큰 · 대체 색. */
|
||||
const STROKE_STYLE: Record<FootprintStrokeKind, [string, string]> = {
|
||||
road: ["--b05-footprint-road", "#475569"],
|
||||
cut: ["--b05-footprint-cut", "#dc2626"],
|
||||
fill: ["--b05-footprint-fill", "#2563eb"],
|
||||
slope: ["--b05-footprint-road", "#475569"],
|
||||
/** 갈래 → 색 토큰 · 대체 색 · 굵기(px · 비탈 끝이 더 굵음 · 요구 241-10). */
|
||||
const STROKE_STYLE: Record<FootprintStrokeKind, [string, string, number]> = {
|
||||
road: ["--b05-footprint-road", "#475569", 1.8],
|
||||
cut: ["--b05-footprint-cut", "#e11d48", 2.6],
|
||||
fill: ["--b05-footprint-fill", "#0d9488", 2.6],
|
||||
slope: ["--b05-footprint-road", "#475569", 2.6],
|
||||
};
|
||||
const STROKE_WIDTH = 1.4;
|
||||
|
||||
let shown = true;
|
||||
let redraw: (() => void) | null = null;
|
||||
@@ -77,9 +76,9 @@ export function drawFootprint(
|
||||
if (!strokes.length) return;
|
||||
context.save();
|
||||
context.setLineDash([]);
|
||||
context.lineWidth = STROKE_WIDTH;
|
||||
for (const { kind, points } of strokes) {
|
||||
const [token, fallback] = STROKE_STYLE[kind];
|
||||
const [token, fallback, width] = STROKE_STYLE[kind];
|
||||
context.lineWidth = width;
|
||||
context.strokeStyle = style.getPropertyValue(token).trim() || fallback;
|
||||
context.beginPath();
|
||||
points.forEach((vertex, index) => {
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/* 노선 편집 평면 발자국(PLAN 346-2) — 도로 끝 · 비탈 끝 깎기(붉음) · 쌓기(파랑) */
|
||||
/* 노선 편집 평면 발자국(PLAN 346-2) — 도로 끝 · 비탈 끝 깎기(붉음) · 쌓기(청록) */
|
||||
:root {
|
||||
--b05-footprint-road: #475569;
|
||||
--b05-footprint-cut: #dc2626;
|
||||
--b05-footprint-fill: #2563eb;
|
||||
--b05-footprint-cut: #e11d48;
|
||||
--b05-footprint-fill: #0d9488;
|
||||
}
|
||||
|
||||
:root[data-theme="dark"] {
|
||||
--b05-footprint-road: #cbd5e1;
|
||||
--b05-footprint-cut: #f87171;
|
||||
--b05-footprint-fill: #60a5fa;
|
||||
--b05-footprint-cut: #ff6b6b;
|
||||
--b05-footprint-fill: #2dd4bf;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root:not([data-theme="light"]) {
|
||||
--b05-footprint-road: #cbd5e1;
|
||||
--b05-footprint-cut: #f87171;
|
||||
--b05-footprint-fill: #60a5fa;
|
||||
--b05-footprint-cut: #ff6b6b;
|
||||
--b05-footprint-fill: #2dd4bf;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ const popup = {
|
||||
|
||||
// ---- 진짜 도구 묶음 ----
|
||||
const { createProfileTools } = load(read("B05_Profile", "B05_Profile_UI_Profile_Tools.ts"), {
|
||||
require: () => ({ sameRun: () => false }),
|
||||
require: () => ({ sameRun: () => false, HISTORY_ICON: { undo: "", redo: "" } }),
|
||||
document,
|
||||
});
|
||||
const tools = createProfileTools({
|
||||
|
||||
@@ -111,3 +111,8 @@ def test_편집기가_발자국을_그리고_단추로_켬끔() -> None:
|
||||
for token in ("--b05-footprint-road", "--b05-footprint-cut", "--b05-footprint-fill"):
|
||||
assert token in footprint
|
||||
assert css.count(f"{token}:") == 3 # 밝음 · 어두움 · 시스템 어두움
|
||||
# 381-1 — 절토 · 성토 테마 색 · 굵게(도로 끝 1.8 · 비탈 끝 2.6)
|
||||
for color in ("#e11d48", "#ff6b6b", "#0d9488", "#2dd4bf"):
|
||||
assert color in css
|
||||
assert '"#e11d48", 2.6]' in footprint and '"#0d9488", 2.6]' in footprint
|
||||
assert 'road: ["--b05-footprint-road", "#475569", 1.8]' in footprint
|
||||
|
||||
@@ -38,8 +38,13 @@ def test_겉틀은_본문_칸():
|
||||
assert ">저장 전으로</button>" not in chrome and "노선 반영</button>" not in chrome
|
||||
assert ">취소</button>" not in chrome and ">확인</button>" not in chrome
|
||||
# 352-2 — 되돌리기 · 다시하기 = 글 없이 기호 + aria-label · title(단축키)
|
||||
assert 'aria-label="되돌리기" disabled>↶</button>' in chrome
|
||||
assert 'aria-label="다시하기" disabled>↷</button>' in chrome
|
||||
# 381-1 — 곧은 꼬리 + 갈고리 SVG(회전 반 바퀴 그림과 헷갈리지 않게)
|
||||
assert 'aria-label="되돌리기" disabled>${HISTORY_ICON.undo}</button>' in chrome
|
||||
assert 'aria-label="다시하기" disabled>${HISTORY_ICON.redo}</button>' in chrome
|
||||
assert ">↶</button>" not in chrome and ">↷</button>" not in chrome
|
||||
tools = _read("B05_Profile_UI_Profile_Tools.ts")
|
||||
assert "undo.innerHTML = HISTORY_ICON.undo;" in tools
|
||||
assert "redo.innerHTML = HISTORY_ICON.redo;" in tools
|
||||
assert 'title="되돌리기 (Ctrl+Z)"' in chrome and 'title="다시하기 (Ctrl+Y)"' in chrome
|
||||
# 시험 · 배선이 집는 자리는 남김
|
||||
assert "b05-routeedit__measure-close" in chrome
|
||||
|
||||
Reference in New Issue
Block a user