feat(ui,api-client): B4/B5 추출 — @yakcloud/ui + @yakcloud/api-client

@yakcloud/ui (15 모듈, react peer, ds-sdk type-only):
- globals.css 3분할(tokens/components/sheet.css; 680px→--sheet-body-max-height)
- icons·primitives·controls·states, LineChart 6색 CSS 토큰화(+peakColorToken)
- CardSheet/PanelSheets: apiGet 디커플(콘텐츠 prop 주입)·lockPageScroll(container?) 폴백
- decorators(statusMeta 등, ds-sdk enum 소비), getServiceMeta(type, logoBase) 로고 URL-only
- 수정: tsconfig jsx:react-jsx, @types/react(-dom), CSS exports 서브패스

@yakcloud/api-client (3 모듈, react peer, ds-sdk type-only):
- apiGet/apiSend/apiDownload + ApiClientError, usePoll(SWR·LRU·gen guard·401/403)
- /api/v1 고정 훅 제외, 서버코드 유입 0(ApiCode만 ds-sdk에서)

검증: DAG PASS(ui↛api-client, api-client↛서버), 디커플 PASS, tsc --noEmit 통과(양 패키지).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-25 11:41:00 +09:00
parent 7d1c92a406
commit e34a325b52
21 changed files with 1144 additions and 9 deletions

View File

@ -0,0 +1,55 @@
// @yakcloud/ui — 상태 데코레이터(순수 UI 분류).
// ds-sdk enum(리터럴 유니온) → {kind:BadgeKind, label} 매핑. switch-case 만, I/O·로직 없음.
import type { ClusterStatus, DeploymentStatus, ServiceStatusDTO } from "@yakcloud/ds-sdk";
// Primitives.Badge 의 kind 분류.
export type BadgeKind = "active" | "prov" | "error" | "pending";
export function statusMeta(s: ClusterStatus): { kind: BadgeKind; label: string } {
switch (s) {
case "ACTIVE":
return { kind: "active", label: "Active" };
case "ERROR":
return { kind: "error", label: "오류" };
case "UPDATING":
return { kind: "prov", label: "업데이트 중" };
case "DELETING":
return { kind: "pending", label: "삭제 중" };
case "DELETED":
return { kind: "pending", label: "삭제됨" };
default:
return { kind: "prov", label: "Provisioning" };
}
}
export function deployStatusMeta(s: DeploymentStatus): { kind: BadgeKind; label: string } {
switch (s) {
case "RUNNING":
return { kind: "active", label: "Running" };
case "FAILED":
return { kind: "error", label: "Failed" };
case "STOPPED":
return { kind: "pending", label: "Stopped" };
case "QUEUED":
return { kind: "prov", label: "Queued" };
case "BUILDING":
return { kind: "prov", label: "Building" };
default:
return { kind: "prov", label: "Deploying" };
}
}
export function serviceStatusMeta(s: ServiceStatusDTO): { kind: BadgeKind; label: string } {
switch (s) {
case "READY":
return { kind: "active", label: "실행 중" };
case "ERROR":
return { kind: "error", label: "오류" };
case "DELETING":
return { kind: "pending", label: "삭제 중" };
case "DELETED":
return { kind: "pending", label: "삭제됨" };
default:
return { kind: "prov", label: "준비 중" }; // REQUESTED / PROVISIONING
}
}