Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D2nUMUMTsqm93PbQtipo6c
79 lines
3.0 KiB
TypeScript
79 lines
3.0 KiB
TypeScript
/* =============================================================================
|
|
* M02_DF_RoundRow.ts
|
|
* 끝수 고르기 줄 — 소수 몇 자리 · 반올림/올림/버림 · 단위 표준에서 자리 제안(적용 단추)
|
|
* 모양은 M02_DF_Model 의 CfRound · 칸 · 단추는 공용 작은 크기 · 글 [한, 영] 짝은 아래 TEXT
|
|
* ========================================================================== */
|
|
|
|
import { currentLanguageIndex } from "@ui/ui_template_locale";
|
|
import { createButton, el } from "@ui/ui_template_elements";
|
|
import type { CfRound } from "./M02_DF_Model";
|
|
|
|
const TEXT = {
|
|
Label: ["끝수", "Rounding"],
|
|
None: ["안 씀", "none"],
|
|
Places: ["소수 {n}자리", "{n} decimals"],
|
|
Suggest: ["표준 제안: 소수 {n}자리", "Standard suggests {n} decimals"],
|
|
Apply: ["적용", "Apply"],
|
|
PlacesAria: ["소수자리", "Decimal places"],
|
|
ModeAria: ["방법", "Method"],
|
|
} as const;
|
|
|
|
const METHODS: CfRound["method"][] = ["반올림", "올림", "버림"];
|
|
|
|
const tr = (key: keyof typeof TEXT, n?: number): string =>
|
|
TEXT[key][currentLanguageIndex === 1 ? 1 : 0].replace("{n}", String(n ?? ""));
|
|
|
|
export interface RoundRowOptions {
|
|
/** 지금 끝수 — 없으면 undefined */
|
|
round: CfRound | undefined;
|
|
/** 단위 표준이 제안한 소수자리 */
|
|
suggest: number | null;
|
|
readOnly?: boolean;
|
|
/** null = 끝수 벗김 */
|
|
onApply(round: CfRound | null): void;
|
|
}
|
|
|
|
export function createRoundRow(opts: RoundRowOptions): HTMLElement {
|
|
const now = opts.round ?? null;
|
|
const places = el("select", {
|
|
className: "ui-select ui-select--sm",
|
|
attrs: { "aria-label": tr("PlacesAria") },
|
|
});
|
|
places.append(el("option", { attrs: { value: "" }, text: tr("None") }));
|
|
for (let n = 0; n <= 6; n++) {
|
|
places.append(el("option", { attrs: { value: String(n) }, text: tr("Places", n) }));
|
|
}
|
|
places.value = now ? String(now.places) : "";
|
|
const method = el("select", {
|
|
className: "ui-select ui-select--sm",
|
|
attrs: { "aria-label": tr("ModeAria") },
|
|
});
|
|
for (const m of METHODS) method.append(el("option", { attrs: { value: m }, text: m }));
|
|
method.value = now?.method ?? "반올림";
|
|
if (opts.readOnly) places.disabled = method.disabled = true;
|
|
const emit = (): void =>
|
|
opts.onApply(
|
|
places.value === ""
|
|
? null
|
|
: { places: Number(places.value), method: method.value as CfRound["method"] },
|
|
);
|
|
places.addEventListener("change", emit);
|
|
method.addEventListener("change", () => places.value !== "" && emit());
|
|
const row = el("div", {
|
|
className: "m02-dfpanel-row",
|
|
children: [el("span", { className: "m02-dfpanel-label", text: tr("Label") }), places, method],
|
|
});
|
|
if (opts.suggest !== null && !now && !opts.readOnly) {
|
|
row.append(
|
|
el("span", { className: "m02-dfpanel-note", text: tr("Suggest", opts.suggest) }),
|
|
createButton({
|
|
label: tr("Apply"),
|
|
variant: "ghost",
|
|
size: "sm",
|
|
onClick: () => opts.onApply({ places: opts.suggest!, method: "반올림" }),
|
|
}),
|
|
);
|
|
}
|
|
return row;
|
|
}
|