Files
Aislo/B07_DesignDetail/openwebcad/src/components/PropertiesEditor.tsx
T
eomsangdonandClaude Opus 5 4cb9b15939 style: 저장소 전체 포맷터 일괄 적용 (prettier·biome·ruff)
파일마다 포맷 폭이 달라(≈80 대 100) 한 줄만 고쳐도 포맷터가 무관한 줄을 대량
재포맷했음. 사용자 지시로 전체를 한 번에 맞춤. 코드 동작 변경 없음 — 포맷만.

- 프론트엔드 `.ts/.css/.html` → 저장소 prettier (`.prettierrc`, printWidth 100)
- `B07_DesignDetail/openwebcad/**` → 자체 biome (tab 들여쓰기·single quote·lineWidth 100).
  `biome format` 만 사용 — `biome lint --write` 는 포맷 아닌 코드 수정까지 하므로 제외
- 파이썬 → `ruff format` (엔진 코드는 이미 정합, resources·scratch 스크립트 24개만 변경)

두 포맷터가 서로 되돌리지 않도록 `.prettierignore` 신규 — openwebcad 와 빌드·산출물
폴더를 prettier 대상에서 뺌. `.prettierrc` 에 `endOfLine: "auto"` 추가 — 기본값 `lf` 가
`core.autocrlf=true` 로 받은 CRLF 파일을 매번 전부 다시 써서 `--list-different` 가
실제 포맷 차이를 가리고 있었음.

검증: `tsc --noEmit` 통과(루트·openwebcad 둘 다), pytest 349 passed / 17 skipped /
0 failed, CAD vitest 87건 중 81 passed / 6 failed(laptop-sub 기준선과 동일, 회귀 없음).
포맷터 재실행 시 prettier·biome 모두 변경 0건.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-02 07:08:24 +09:00

148 lines
3.8 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 { getEntities, getLayers, getSelectedEntities, setEntities } from '../state';
import { dashToLineType, LINE_TYPES, LINE_WIDTHS } from './RibbonWidgets';
interface PropertiesEditorProps {
compact?: boolean;
}
function applyToSelection(mutate: (entity: Entity) => void): void {
const selected = getSelectedEntities();
if (!selected.length) return;
for (const entity of selected) mutate(entity);
setEntities([...getEntities()], true);
}
/** 여러 객체가 값이 다르면 '*가지각색' 대신 첫 객체 값을 보여 준다 (AutoCAD와 같은 관행) */
export const PropertiesEditor: FC<PropertiesEditorProps> = ({ compact = false }) => {
const selected = getSelectedEntities();
const layers = getLayers();
const first = selected[0];
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={first.lineColor}
onChange={(event) =>
applyToSelection((entity) => {
entity.lineColor = event.target.value;
})
}
/>
</label>
<label>
<span>선가중치</span>
<select
value={first.lineWidth}
onChange={(event) =>
applyToSelection((entity) => {
entity.lineWidth = Number(event.target.value);
})
}
>
{LINE_WIDTHS.map((width) => (
<option key={width} value={width}>
{width}px
</option>
))}
</select>
</label>
<label>
<span>선종류</span>
<select
value={dashToLineType(first.lineDash)}
onChange={(event) => {
const dash = LINE_TYPES.find((type) => type.value === event.target.value)?.dash;
applyToSelection((entity) => {
entity.lineDash = dash ? [...dash] : undefined;
});
}}
>
{LINE_TYPES.map((type) => (
<option key={type.value} value={type.value}>
{type.label}
</option>
))}
</select>
</label>
<label>
<span>도면층</span>
<select
value={first.layerId}
onChange={(event) =>
applyToSelection((entity) => {
entity.layerId = event.target.value;
})
}
>
{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>
);
};