- ui_template_input.ts · .css 새로 — createInputField · createSelectField 를 옮김(ui_template_elements 가 다시 내보냄 · 부르는 길 그대로) · size(data-size 단 높이) · unit(칸 안 단위) · multiline · createSlider(이름 | 막대 | 값 글 3열) - 옛 compact 는 단을 안 붙임 — 옛 작은 칸 30 그대로(32 로 맞추면 페이지 칸이 바뀜 · 553 에서 단으로 옮김) - 입력 · 고르기 상태 = 마우스 선 짙게 · 막힘 흐림 · 오류 빨강(aria-invalid 같이) · 고르기 화살표 = 보라 → 보조 글 색(밝음 · 어두움 따로) - 체크 = 라디오 · 칩 꼴 더함(createCheckbox 부름 그대로) · 켜기(스위치 · 색 점 칩) · 분할 고르기(대시보드 .b01-sys-seg 꼴) · 탭(밑줄 · 보조 알약 = 옛 .ui-subtabs · 수 배지) - 배지(알약 · 수 · 램프 ✓ ✗ · 점 · 옛 .ui-tag 같이) · 툴팁 제자리 상자(tooltipBox) · 보조 글(흐린 · 안내 · 오류 ✗ · 경고 ! · 성공 ✓) - 부품 모음 기본 묶음 13 줄 모두 새 부품 견본 · 상태 다섯 칸 · 여덟 단 한 줄 - 시험 test_552_2_parts 새로(머리 · 옛 이름 · 크기 단 · 상태 · 날 색 없음 · 부품 모음 13) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
73 lines
2.7 KiB
TypeScript
73 lines
2.7 KiB
TypeScript
/* =============================================================================
|
|
* ui_template_segment.ts
|
|
* 부품 「분할 고르기」(552-2 · 부품 모음 `#/b01-account?view=ui-kit`) — 붙은 칸 둘 ~ 다섯 중 하나
|
|
*
|
|
* 꼴 = 글 · 아이콘(+ title) · 글 + 아이콘
|
|
* 크기 = data-size 20 · 24 · 28 · 32(기본 28)
|
|
* 상태 = 마우스 `:hover` · 눌림 `:active` · 막힘 `disabled` · 고름 = aria-checked — CSS 는 `[data-state]` 로도 받음
|
|
* 쓰기 = `createSegment({ options: [{ value: "list", label: "목록" }, { value: "card", label: "카드" }], value: "list", onChange })`
|
|
* 대신 = B01 `.b01-sys-seg` · `.b01-home__seg` · `.b01-proj-seg` · B04 `b04-surface__sheet-method` · B05 `b05-routerec__pills` ·
|
|
* B06 `b06-design__btn(--active)` · CAD `.cad-inspector-tabs` · E04 · E06 · E07 `*-toggle` · M02 `m02-dfip__chips`
|
|
* ========================================================================== */
|
|
|
|
import { setUiSize, type UiSize } from "./ui_template_button";
|
|
import { icon, type IconName } from "./ui_template_icons";
|
|
import "./ui_template_segment.css";
|
|
|
|
export interface SegmentOption {
|
|
value: string;
|
|
label?: string;
|
|
icon?: IconName;
|
|
/** 아이콘만이면 필수 */
|
|
title?: string;
|
|
disabled?: boolean;
|
|
}
|
|
|
|
export interface SegmentHandle {
|
|
root: HTMLDivElement;
|
|
get: () => string;
|
|
/** 고름을 바꿈(onChange 는 안 부름) */
|
|
set: (value: string) => void;
|
|
}
|
|
|
|
export function createSegment(opts: {
|
|
options: SegmentOption[];
|
|
value: string;
|
|
onChange?: (value: string) => void;
|
|
/** 20 · 24 · 28 · 32 권함 */
|
|
size?: UiSize;
|
|
ariaLabel?: string;
|
|
}): SegmentHandle {
|
|
const root = document.createElement("div");
|
|
root.className = "ui-segment";
|
|
root.setAttribute("role", "radiogroup");
|
|
if (opts.ariaLabel) root.setAttribute("aria-label", opts.ariaLabel);
|
|
setUiSize(root, opts.size ?? 28);
|
|
let current = opts.value;
|
|
const items = opts.options.map((o) => {
|
|
const b = document.createElement("button");
|
|
b.type = "button";
|
|
b.className = "ui-segment__item";
|
|
b.setAttribute("role", "radio");
|
|
b.dataset.value = o.value;
|
|
if (o.icon) b.append(icon(o.icon, 16));
|
|
if (o.label) b.append(o.label);
|
|
if (o.title) b.title = o.title;
|
|
if (o.title && !o.label) b.setAttribute("aria-label", o.title);
|
|
b.disabled = o.disabled ?? false;
|
|
b.addEventListener("click", () => {
|
|
if (current === o.value) return;
|
|
set(o.value);
|
|
opts.onChange?.(o.value);
|
|
});
|
|
return b;
|
|
});
|
|
const set = (value: string): void => {
|
|
current = value;
|
|
for (const b of items) b.setAttribute("aria-checked", String(b.dataset.value === value));
|
|
};
|
|
set(current);
|
|
root.append(...items);
|
|
return { root, get: () => current, set };
|
|
}
|