Files
Aislo/B07_DesignDetail/openwebcad/src/components/PropertiesEditor.tsx
T
eomsangdonandClaude Opus 5.5 17e6500cf6 fix(506-3 B07 · CAD 작은 흠): 저장 길 · 죽은 길 걷음 · CAD 되돌리기 · B09 인쇄 미리보기 · M02 도움말
- 1-A 도면 GET · 저장 PUT 한도 60 s · 저장 중 미리받기 쉼 · 끊긴 저장 = 목록 confirmed 로 판정
- 2 CAD 자동백업 열쇠 = b07:{프로젝트}:{도면} · 도각 편집 = b07-frame:{프로젝트} · [초기화] 같은 열쇠
- 3-1 [초기화] 물음 글 = 프로젝트 도각 그대로 · [도각 편집] → [기본 도각 복원] 안내
- 3-2 풀린 장 저장본 json · 수량표 찌꺼기 걷음(_write_manifest 한 곳)
- 5-1 확정 풀기 · 배치 · 축척 = mark_stage(save)
- 7-3 start_stage 가 DEV_UNLOCK 표식 남김
- 6-a navigateDrawing · onNavigate · hasPrev · hasNext 걷음 · 6-b cad-host-save 토글 걷음 · 4-2 B08 안 쓰는 글 11 걷음
- 6-f 특성 판 색 끌기 = 되돌리기 한 칸(paintNowCommitLater 한 벌) · 6-g LAYMRG 사본 길
- 4-1 B09 [인쇄 미리보기] = 저장 뒤 이동 · 단계 그대로 · 6-e M02 카드 도움말 DWG 한 줄
- 시험 test_506_3_* 둘 · cad/undo-506-3 · test_298_2_b07_buttons 열쇠 맞춤

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 12:48:36 +09:00

161 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/** 특성 팔레트 본문 — 선택 객체의 값을 읽고 바로 고친다 (PROPERTIES) */
import type { FC } from 'react';
import type { Entity } from '../entities/Entity';
import { polylineLength, sampleEntityPoints } from '../helpers/geometry/sample-entity';
import {
commonValue,
LINE_TYPES,
LINE_WIDTHS,
paintNowCommitLater,
restyle,
selectionLineStyle,
styleTargets,
} from '../helpers/selection-style';
import { getLayers, getSelectedEntities } from '../state';
interface PropertiesEditorProps {
compact?: boolean;
}
/** 고른 것을 사본으로 바꿈 — 되돌리기 한 칸(488) · 선 특성은 글 뺌 */
const applyToSelection = (mutate: (entity: Entity) => void) => restyle(getSelectedEntities(), mutate);
const applyToLines = (mutate: (entity: Entity) => void) =>
restyle(styleTargets(getSelectedEntities()), mutate);
/** 여러 객체가 값이 다르면 빈 칸(488 · 리본과 같은 규칙 · 고르면 모두에 적용) */
export const PropertiesEditor: FC<PropertiesEditorProps> = ({ compact = false }) => {
const selected = getSelectedEntities();
const layers = getLayers();
const first = selected[0];
const view = selectionLineStyle();
if (!first) {
return <p className="cad-properties__empty">선택된 객체가 없습니다.</p>;
}
const points = sampleEntityPoints(first);
const box = first.getBoundingBox();
return (
<div className="cad-properties-editor" data-compact={compact}>
<div className="cad-properties-editor__title">
{selected.length === 1 ? first.getType() : `여러 객체 (${selected.length})`}
</div>
<label>
<span>색상</span>
<input
type="color"
value={view.color || '#000000'}
data-mixed={view.color ? undefined : 'true'}
onChange={(event) => {
// 끄는 동안 = 화면만 · 멎은 뒤 되돌리기 한 칸(리본 색 칸과 같은 길)
const color = event.target.value;
paintNowCommitLater(styleTargets(getSelectedEntities()), (entity) => {
entity.lineColor = color;
});
}}
/>
</label>
<label>
<span>선 두께</span>
<select
value={view.width}
onChange={(event) =>
applyToLines((entity) => {
entity.lineWidth = Number(event.target.value);
})
}
>
<option value="" hidden />
{LINE_WIDTHS.map((width) => (
<option key={width} value={width}>
{width}px
</option>
))}
</select>
</label>
<label>
<span>선종류</span>
<select
value={view.lineType}
onChange={(event) => {
const dash = LINE_TYPES.find((type) => type.value === event.target.value)?.dash;
applyToLines((entity) => {
entity.lineDash = dash ? [...dash] : undefined;
});
}}
>
<option value="" hidden />
{LINE_TYPES.map((type) => (
<option key={type.value} value={type.value}>
{type.label}
</option>
))}
</select>
</label>
<label>
<span>레이어</span>
<select
value={commonValue(selected, (entity) => entity.layerId)}
onChange={(event) =>
applyToSelection((entity) => {
entity.layerId = event.target.value;
})
}
>
<option value="" hidden />
{layers.map((layer) => (
<option key={layer.id} value={layer.id}>
{layer.name}
</option>
))}
</select>
</label>
<label>
<span>투명도</span>
<input
type="number"
min={0}
max={90}
step={5}
value={Math.round((1 - (first.opacity ?? 1)) * 100)}
onChange={(event) => {
const percent = Math.min(90, Math.max(0, Number(event.target.value)));
applyToSelection((entity) => {
entity.opacity = 1 - percent / 100;
});
}}
/>
</label>
{!compact && (
<dl className="cad-properties-editor__readout">
<div>
<dt>길이</dt>
<dd>{polylineLength(points).toFixed(3)}</dd>
</div>
<div>
<dt>크기</dt>
<dd>
{(box.xmax - box.xmin).toFixed(3)} × {(box.ymax - box.ymin).toFixed(3)}
</dd>
</div>
<div>
<dt>시작점</dt>
<dd>{points[0] ? `${points[0].x.toFixed(2)}, ${points[0].y.toFixed(2)}` : '-'}</dd>
</div>
<div>
<dt>그룹</dt>
<dd>{first.groupId ? '있음' : '없음'}</dd>
</div>
</dl>
)}
</div>
);
};