feat(b09): 좌측 하단 고정 줄 — [박스보기|호표보기] 한 설정(묶음 탭 셋 · 옛 탭별 값 하나로 · 탭 줄 토글 걷음) · [하이퍼링크|팝업] 스위치(pref global · 기본 팝업) · DRAFT.actions 자리 · [?][저장][내역 초기화] 그대로 (303-1 · 304-1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ji4nuyLVHcxrXWHTdb5nRD
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
/* =============================================================================
|
||||
* B09_Estimation_UI_Dock.ts
|
||||
* B09 좌측 하단 고정 줄(PLAN 303-1 · 304-1) — 위에서부터
|
||||
* ① [박스보기|호표보기] 묶음 탭 셋 보기(304-1 · 한 값)
|
||||
* ② [하이퍼링크|팝업] 행 누름(303 · 기본 팝업)
|
||||
* ③ `DRAFT.actions` 단추(초안 · 비면 줄 없음)
|
||||
* ④ [?][저장][내역 초기화](도움말 줄 `data-help-row`)
|
||||
*
|
||||
* 스위치 값 = pref global(계정 공용 · [저장] 필요 없음) · 바닥 고정 = 공용 `.ui-sidebar-actions` 한 벌
|
||||
* ========================================================================== */
|
||||
|
||||
import { createButton } from "@ui/ui_template_elements";
|
||||
import { readState, writeState } from "../A00_Common/b_page_state";
|
||||
import { DRAFT } from "./B09_Estimation_UI_Tabs";
|
||||
import {
|
||||
chooseGroupView,
|
||||
groupView,
|
||||
viewLabel,
|
||||
type GroupView,
|
||||
} from "./B09_Estimation_UI_Tabs_Groups";
|
||||
|
||||
export type LinkMode = "popup" | "link";
|
||||
|
||||
const LINK_LABEL: Record<LinkMode, string> = { link: "하이퍼링크", popup: "팝업" };
|
||||
|
||||
/** 행 누름 길 — 모르는 값 · 못 읽음 = 팝업 */
|
||||
export function linkMode(): LinkMode {
|
||||
try {
|
||||
return readState<unknown>("b09-link-mode") === "link" ? "link" : "popup";
|
||||
} catch {
|
||||
return "popup";
|
||||
}
|
||||
}
|
||||
|
||||
function setLinkMode(mode: LinkMode): void {
|
||||
try {
|
||||
writeState("b09-link-mode", mode);
|
||||
} catch {
|
||||
// 기억 못 하면 기본(팝업)으로 돌아감
|
||||
}
|
||||
}
|
||||
|
||||
/** 단추 둘 스위치 — 켜진 쪽 filled · aria-pressed */
|
||||
function switchRow<T extends string>(
|
||||
name: string,
|
||||
values: T[],
|
||||
label: (value: T) => string,
|
||||
current: () => T,
|
||||
pick: (value: T) => void,
|
||||
): HTMLElement {
|
||||
const row = document.createElement("div");
|
||||
row.className = "ui-btn-group b09-dock__row";
|
||||
row.dataset.b09Switch = name;
|
||||
const buttons = values.map((value) => {
|
||||
const button = createButton({
|
||||
label: label(value),
|
||||
variant: "ghost",
|
||||
onClick: () => {
|
||||
if (value === current()) return;
|
||||
pick(value);
|
||||
sync();
|
||||
},
|
||||
});
|
||||
button.dataset.value = value;
|
||||
return button;
|
||||
});
|
||||
const sync = (): void =>
|
||||
buttons.forEach((button, k) => {
|
||||
const on = values[k] === current();
|
||||
button.classList.toggle("ui-btn--filled", on);
|
||||
button.classList.toggle("ui-btn--ghost", !on);
|
||||
button.setAttribute("aria-pressed", String(on));
|
||||
});
|
||||
sync();
|
||||
row.append(...buttons);
|
||||
return row;
|
||||
}
|
||||
|
||||
/** 하단 고정 줄 — onView = 보기 바뀜(묶음 탭이면 다시 그림) */
|
||||
export function createDock(buttons: HTMLElement[], onView: () => void): HTMLElement {
|
||||
const views: GroupView[] = ["cards", "table"];
|
||||
const view = switchRow("view", views, viewLabel, groupView, (value) => {
|
||||
chooseGroupView(value);
|
||||
onView();
|
||||
});
|
||||
const link = switchRow<LinkMode>(
|
||||
"link",
|
||||
["link", "popup"],
|
||||
(mode) => LINK_LABEL[mode],
|
||||
linkMode,
|
||||
setLinkMode,
|
||||
);
|
||||
const extra = DRAFT.actions.map((make) => make());
|
||||
const draft = document.createElement("div");
|
||||
draft.className = "b09-dock__row";
|
||||
draft.dataset.b09DraftActions = "";
|
||||
draft.append(...extra);
|
||||
const main = document.createElement("div");
|
||||
main.className = "b09-dock__row";
|
||||
main.dataset.helpRow = "";
|
||||
main.append(...buttons);
|
||||
const dock = document.createElement("div");
|
||||
dock.className = "ui-sidebar-actions b09-dock";
|
||||
dock.append(view, link, ...(extra.length ? [draft] : []), main);
|
||||
return dock;
|
||||
}
|
||||
Reference in New Issue
Block a user