refactor(M01): 표 · 모달 · 띠 알림 · 배지 · 알약 · 보조 글 · 빈 상태를 부품으로 (PLAN 553-5)
- 표 둘 = 표 부품(m01-master__grid = 일반표 · m01-logic__grid = 데이터표) · 페이지 CSS 는 폭 · 머리 고정 · 칸 상태만 - 손 모달 다섯(조달 찾기 · 요소 고르기 · 표 바꾸기 · 복사 시트 · 표 고르기) = 모달 부품 openModal - 알림 띠 · 막힘 까닭 = 띠 알림 · 태그 = 배지 · 알약 · × · 삭제 · 로직 키 = 단추 부품 · muted 세 벌 = 보조 글 · 빈 줄 = 빈 상태 - M02 가 빌린 M01 클래스(표 · muted · 고르기 창)도 같은 부품으로 · 죽은 CSS 걷음 · 지킴 시험 test_553_5_m01_m02 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -31,6 +31,9 @@ import { fetchTables, type TableHead } from "./M01_MasterData_Api_Fetch";
|
||||
import { tx } from "./M01_MasterData_UI_Logic_Text";
|
||||
import { tl } from "./M01_MasterData_UI_LogicLab_Text";
|
||||
import "./M01_MasterData_UI_LogicLab_Style.css";
|
||||
import { createBadge } from "@ui/ui_template_badge";
|
||||
import { createText } from "@ui/ui_template_text";
|
||||
import { openModal } from "@ui/ui_template_modal";
|
||||
|
||||
const OWNERS = ["현장", "공용"] as const;
|
||||
const TABLE_GROUPS = ["소요량", "계수"] as const;
|
||||
@@ -78,29 +81,16 @@ function swapKey(raw: string, newKey: string): string {
|
||||
|
||||
/** 표 바꾸기 모달 — 소요량·계수 두 그룹을 함께 찾음 */
|
||||
function openTablePick(onPick: (table: TableHead) => void): void {
|
||||
const close = (): void => backdrop.remove();
|
||||
const search = createInputField({ type: "search", placeholder: tl("Copy_PickSearch") });
|
||||
const list = el("div", { className: "m01-logic__pick-list" });
|
||||
const dialog = el("div", {
|
||||
className: "m01-logic__pick ui-popup",
|
||||
attrs: { role: "dialog", "aria-label": tl("Copy_PickTitle") },
|
||||
children: [
|
||||
el("div", {
|
||||
className: "m01lab__modal-top",
|
||||
children: [
|
||||
el("h3", { text: tl("Copy_PickTitle") }),
|
||||
createButton({ label: tl("Modal_Close"), variant: "ghost", onClick: close }),
|
||||
],
|
||||
}),
|
||||
search.root,
|
||||
list,
|
||||
],
|
||||
// 모달 부품 — 제목줄 [닫기] · 바깥 누르기 · Esc · 위 고정 · 찾기 칸에 커서
|
||||
const { close } = openModal({
|
||||
title: tl("Copy_PickTitle"),
|
||||
closeLabel: tl("Modal_Close"),
|
||||
dialogClass: "m01-logic__pick",
|
||||
backdropClass: "m01-logic__backdrop",
|
||||
mount: (body) => body.append(search.root, list),
|
||||
});
|
||||
const backdrop = el("div", { className: "m01-logic__backdrop", children: [dialog] });
|
||||
backdrop.addEventListener("click", (ev) => ev.target === backdrop && close());
|
||||
backdrop.addEventListener("keydown", (ev) => ev.key === "Escape" && close());
|
||||
document.body.append(backdrop);
|
||||
search.input.focus();
|
||||
|
||||
let timer: number | undefined;
|
||||
const run = async (): Promise<void> => {
|
||||
@@ -113,11 +103,11 @@ function openTablePick(onPick: (table: TableHead) => void): void {
|
||||
...(hits.length
|
||||
? hits.map((t) => {
|
||||
const b = el("button", {
|
||||
className: "m01-logic__pick-row m01-logic__pick-row--button",
|
||||
attrs: { type: "button" },
|
||||
className: "m01-logic__pick-row ui-list-row ui-sidebar-row",
|
||||
attrs: { type: "button", "data-size": "32" },
|
||||
children: [
|
||||
el("span", { text: `${t.이름 || t.키} · ${t.원문번호 || ""}` }),
|
||||
el("span", { className: "m01-logic__muted", text: t.키 }),
|
||||
el("span", { className: "ui-text ui-text--muted", text: t.키 }),
|
||||
],
|
||||
});
|
||||
b.addEventListener("click", () => {
|
||||
@@ -126,7 +116,7 @@ function openTablePick(onPick: (table: TableHead) => void): void {
|
||||
});
|
||||
return b;
|
||||
})
|
||||
: [el("p", { className: "m01-logic__muted", text: tl("Copy_PickNone") })]),
|
||||
: [el("p", { className: "ui-text ui-text--muted", text: tl("Copy_PickNone") })]),
|
||||
);
|
||||
};
|
||||
search.input.addEventListener("input", () => {
|
||||
@@ -148,7 +138,7 @@ function aliasRow(a: FormulaAlias, onSwap: (raw: string) => void, sub: HTMLEleme
|
||||
className: "m01-logic__section-head",
|
||||
children: [
|
||||
el("strong", { text: a.이름 }),
|
||||
el("span", { className: "m01-logic__muted", text: about }),
|
||||
el("span", { className: "ui-text ui-text--muted", text: about }),
|
||||
],
|
||||
}),
|
||||
el("pre", { className: "m01lab__expr", text: a.원문 }),
|
||||
@@ -172,7 +162,7 @@ function logicAliasControls(
|
||||
): { root: HTMLElement } {
|
||||
let forked = false;
|
||||
const original = a.원문;
|
||||
const status = el("span", { className: "m01-logic__muted" });
|
||||
const status = el("span", { className: "ui-text ui-text--muted" });
|
||||
const refBtn = createButton({
|
||||
label: tl("Copy_Alias_Ref"),
|
||||
variant: "ghost",
|
||||
@@ -224,8 +214,10 @@ function lineBox(row: LogicRow, line: FormulaLine, onChange: () => void): HTMLEl
|
||||
className: "m01-logic__section-head",
|
||||
children: [
|
||||
el("strong", { text: line.이름 || line.자리 }),
|
||||
el("span", { className: "m01-logic__tag", text: tag }),
|
||||
...(line.단위 ? [el("span", { className: "m01-logic__muted", text: line.단위 })] : []),
|
||||
createBadge(tag, "accent"),
|
||||
...(line.단위
|
||||
? [el("span", { className: "ui-text ui-text--muted", text: line.단위 })]
|
||||
: []),
|
||||
],
|
||||
}),
|
||||
box,
|
||||
@@ -287,9 +279,7 @@ export async function openCopyScreen(opt: CopyOptions): Promise<void> {
|
||||
onLines: () => undefined,
|
||||
});
|
||||
} catch (error) {
|
||||
calcHost.replaceChildren(
|
||||
el("p", { className: "m01-logic__bad", text: error instanceof Error ? error.message : "" }),
|
||||
);
|
||||
calcHost.replaceChildren(createText(error instanceof Error ? error.message : "", "error"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -316,7 +306,7 @@ export async function openCopyScreen(opt: CopyOptions): Promise<void> {
|
||||
drawAliases();
|
||||
refreshCalc();
|
||||
|
||||
const close = (): void => backdrop.remove();
|
||||
let close = (): void => {};
|
||||
const onSave = async (): Promise<void> => {
|
||||
showLoadingOverlay();
|
||||
try {
|
||||
@@ -337,55 +327,48 @@ export async function openCopyScreen(opt: CopyOptions): Promise<void> {
|
||||
}
|
||||
};
|
||||
|
||||
const sheet = el("div", {
|
||||
className: "m01-logic__pick m01copy__sheet",
|
||||
attrs: { role: "dialog", "aria-label": tl("Copy_Title") },
|
||||
children: [
|
||||
el("div", {
|
||||
className: "m01lab__modal-top",
|
||||
children: [
|
||||
el("h3", { text: `${tl("Copy_Title")} — ${row.이름}(${opt.key})` }),
|
||||
createButton({ label: tl("Copy_Cancel"), variant: "ghost", onClick: close }),
|
||||
],
|
||||
}),
|
||||
el("div", {
|
||||
className: "m01copy__head",
|
||||
children: [nameField.root, ownerField.root],
|
||||
}),
|
||||
el("section", {
|
||||
className: "m01-logic__section",
|
||||
children: [el("h3", { text: tl("Copy_Aliases") }), aliasHost],
|
||||
}),
|
||||
el("section", {
|
||||
className: "m01-logic__section",
|
||||
children: [
|
||||
el("div", {
|
||||
className: "m01-logic__section-head",
|
||||
children: [
|
||||
el("h3", { text: tl("Copy_Lines") }),
|
||||
createButton({
|
||||
label: tl("Copy_AddExtra"),
|
||||
variant: "ghost",
|
||||
onClick: () => addExtra(row, refreshCalc, drawLines),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
linesHost,
|
||||
],
|
||||
}),
|
||||
el("section", { className: "m01-logic__section", children: [calcHost] }),
|
||||
el("div", {
|
||||
className: "m01-logic__pick-bar",
|
||||
children: [
|
||||
el("span", {}),
|
||||
el("span", {}),
|
||||
createButton({ label: tl("Copy_Save"), onClick: () => void onSave() }),
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
const backdrop = el("div", { className: "m01-logic__backdrop", children: [sheet] });
|
||||
backdrop.addEventListener("click", (ev) => ev.target === backdrop && close());
|
||||
backdrop.addEventListener("keydown", (ev) => ev.key === "Escape" && close());
|
||||
document.body.append(backdrop);
|
||||
// 모달 부품 — 제목줄 [취소] · 바깥 누르기 · Esc · 위 고정 · 폭만 복사 시트 곁값
|
||||
({ close } = openModal({
|
||||
title: `${tl("Copy_Title")} — ${row.이름}(${opt.key})`,
|
||||
closeLabel: tl("Copy_Cancel"),
|
||||
dialogClass: "m01-logic__pick m01copy__sheet",
|
||||
backdropClass: "m01-logic__backdrop",
|
||||
mount: (body) =>
|
||||
body.append(
|
||||
el("div", {
|
||||
className: "m01copy__head",
|
||||
children: [nameField.root, ownerField.root],
|
||||
}),
|
||||
el("section", {
|
||||
className: "m01-logic__section",
|
||||
children: [el("h3", { text: tl("Copy_Aliases") }), aliasHost],
|
||||
}),
|
||||
el("section", {
|
||||
className: "m01-logic__section",
|
||||
children: [
|
||||
el("div", {
|
||||
className: "m01-logic__section-head",
|
||||
children: [
|
||||
el("h3", { text: tl("Copy_Lines") }),
|
||||
createButton({
|
||||
label: tl("Copy_AddExtra"),
|
||||
variant: "ghost",
|
||||
onClick: () => addExtra(row, refreshCalc, drawLines),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
linesHost,
|
||||
],
|
||||
}),
|
||||
el("section", { className: "m01-logic__section", children: [calcHost] }),
|
||||
el("div", {
|
||||
className: "m01-logic__pick-bar",
|
||||
children: [
|
||||
el("span", {}),
|
||||
el("span", {}),
|
||||
createButton({ label: tl("Copy_Save"), onClick: () => void onSave() }),
|
||||
],
|
||||
}),
|
||||
),
|
||||
}));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user