- 부품 상자 CSS · 단추 기본 꼴을 CAD iframe 에 실음(integration/ui-kit.ts) · 자리 · 폭은 cad-* 그대로 - 상태막대 = ui-toggle--chip 22 · 특성/레이어 = ui-tabs 36 · ↶↷ · 리본 접기 · 탐색 막대 = ui-icon-btn 20 · 32 - 빠른 특성 · 블록 라이브러리 · 자리표 = ui-float-panel · 리본 넘침 · 스냅 · 명령 자동완성 = ui-ctx-menu - window.confirm · window.prompt → askConfirm · askText · 빈 안내 = ui-empty 작은 꼴 - 높이 단: 리본 칸 19→18 · 명령 칸 26→28 · 레이어 줄 40→42 · 문서 탭 25→24 · 도각 편집 단추 24 - 마우스 바탕 = --color-hover · 켜짐 = --color-accent-soft · 도면 그림 색(--draw-*) 안 건드림 - 안 쓰는 DropdownButton 지움(쓰는 곳 0 · grep) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
78 lines
2.7 KiB
TypeScript
78 lines
2.7 KiB
TypeScript
/**
|
|
* Shift+우클릭 한 번 스냅 메뉴(337 마 · 오토캐드) — 점 물음일 때만 · 고르면 그 이름을 친 것과 같은 길(`submitText`).
|
|
* 스냅 이름 · FROM · M2P 의 뜻은 친 글 사다리(`prompt-input.ts`) 몫 · 메뉴는 고르기만.
|
|
*/
|
|
import './snap-menu.css';
|
|
|
|
/** [친 글, 이름] — 오토캐드 객체 스냅 메뉴 차례 */
|
|
export const SNAP_MENU: readonly [string, string][] = [
|
|
['FROM', '시작점에서'],
|
|
['M2P', '두 점 사이의 중간'],
|
|
['END', '끝점'],
|
|
['MID', '중간점'],
|
|
['INT', '교차점'],
|
|
['CEN', '중심'],
|
|
['QUA', '사분점'],
|
|
['PER', '수직'],
|
|
['NOD', '노드'],
|
|
['NEA', '근처점'],
|
|
['NON', '없음'],
|
|
];
|
|
|
|
let current: { onPick: (name: string) => void; element: HTMLElement | null } | null = null;
|
|
|
|
const onKey = (evt: KeyboardEvent) => {
|
|
if (evt.key !== 'Escape') return;
|
|
evt.preventDefault();
|
|
evt.stopImmediatePropagation(); // Esc = 메뉴만 닫음(명령은 그대로)
|
|
closeSnapMenu();
|
|
};
|
|
const onOutside = (evt: MouseEvent) => {
|
|
if (!current?.element?.contains(evt.target as Node)) closeSnapMenu();
|
|
};
|
|
|
|
export const isSnapMenuOpen = (): boolean => current !== null;
|
|
|
|
export function closeSnapMenu(): void {
|
|
if (!current) return;
|
|
current.element?.remove();
|
|
current = null;
|
|
if (typeof window === 'undefined') return;
|
|
window.removeEventListener('keydown', onKey, true);
|
|
window.removeEventListener('mousedown', onOutside, true);
|
|
}
|
|
|
|
/** 메뉴에서 하나 고름 — 닫고 그 이름을 넘김 */
|
|
export function pickSnapMenu(name: string): void {
|
|
const picked = current;
|
|
closeSnapMenu();
|
|
picked?.onPick(name);
|
|
}
|
|
|
|
/** 화면 (x, y) 에 메뉴를 띄움 — DOM 없는 시험에선 상태만 */
|
|
export function openSnapMenu(x: number, y: number, onPick: (name: string) => void): void {
|
|
closeSnapMenu();
|
|
current = { onPick, element: null };
|
|
if (typeof document === 'undefined') return;
|
|
const menu = document.createElement('div');
|
|
menu.className = 'ui-ctx-menu cad-snap-menu controls'; // 꼴 = 메뉴 부품
|
|
menu.setAttribute('role', 'menu');
|
|
for (const [name, label] of SNAP_MENU) {
|
|
const item = document.createElement('button');
|
|
item.type = 'button';
|
|
item.className = 'ui-ctx-menu__item';
|
|
item.setAttribute('role', 'menuitem');
|
|
item.textContent = `${label} (${name})`;
|
|
item.addEventListener('click', () => pickSnapMenu(name));
|
|
menu.append(item);
|
|
}
|
|
document.body.append(menu);
|
|
// 화면 밖으로 안 나가게
|
|
const box = menu.getBoundingClientRect();
|
|
menu.style.left = `${Math.min(x, window.innerWidth - box.width - 4)}px`;
|
|
menu.style.top = `${Math.min(y, window.innerHeight - box.height - 4)}px`;
|
|
current.element = menu;
|
|
window.addEventListener('keydown', onKey, true);
|
|
window.addEventListener('mousedown', onOutside, true);
|
|
}
|