feat(V2-1c): packages/ui 추출 — DS 컴포넌트 + theme + theme-vars 분리
packages/ui (@d3ro/ui) 신규: - src/theme.ts (d3roPalette/d3roTypo/d3roShadow/d3roRadius SSOT) - src/theme-vars.ts (팝업/main 프로세스용 CSS 변수 맵) - src/components/ds/ (CrtDisplay, InstrumentPanel, Led, MetalCard, MetalDial, PhosphorText, PhysicalButton, ScreenPanel, ButtonGroup) - src/index.ts barrel - subpath exports: ./theme, ./theme-vars, ./components/ds - React/MUI/Emotion은 peerDependencies로 선언 - @d3ro/core만 직접 의존성 apps/desktop/src/shared/ 디렉토리 완전 제거: - theme-vars가 마지막 남은 파일이었음 - tsconfig include에서 src/shared/**/* 제거 일괄 치환 (renderer 전역): - ../theme, ../../theme, ./theme → @d3ro/ui/theme - ../components/ds, ../../components/ds, ./ds, ../ds → @d3ro/ui/components/ds - ../ds/<Component>, ../../ds/<Component> → @d3ro/ui/components/ds (세부 파일 import는 barrel로 통합) - @shared/theme-vars → @d3ro/ui/theme-vars (WindowManager) apps/desktop 설정: - package.json: @d3ro/ui: '*' dep 추가 - tsconfig.node/web.json: @shared/* paths 완전 제거, @d3ro/ui, @d3ro/ui/* paths 추가 - electron.vite.config.ts: @shared alias 제거, @d3ro/ui alias 추가, externalize exclude에 @d3ro/ui 추가 - vitest.config.ts: alias 교체 DS 컴포넌트 내부의 '../../theme' 상대 경로는 packages/ui 구조에서 동일하게 해결되어 그대로 유효. 검증: typecheck + build + dev 런타임 모두 통과.
This commit is contained in:
parent
3b0eb3393b
commit
a041f1b6a9
56 changed files with 191 additions and 76 deletions
|
|
@ -1,199 +0,0 @@
|
|||
// src/shared/theme-vars.ts
|
||||
// 팝업 윈도우용 CSS 변수 맵.
|
||||
// main process (WindowManager)에서 insertCSS로 팝업에 테마를 주입할 때 사용.
|
||||
// renderer의 theme.ts RAW와 동기화 유지 필요.
|
||||
// Node.js/Electron main 환경에서 import 가능 (DOM API 없음).
|
||||
|
||||
export type PopupThemeKey = 'dark' | 'light' | 'nord' | 'solarized' | 'catppuccin' | 'dracula'
|
||||
|
||||
interface PopupThemeVars {
|
||||
/** 카드 배경 (팝업 본체) */
|
||||
'--d3-bg-card': string
|
||||
/** 앱 배경 (recording-tip 반투명 배경) */
|
||||
'--d3-bg-tip': string
|
||||
/** 주요 텍스트 */
|
||||
'--d3-text-primary': string
|
||||
/** 보조 텍스트 */
|
||||
'--d3-text-secondary': string
|
||||
/** 비활성 텍스트 (번호, 시간 등) */
|
||||
'--d3-text-inactive': string
|
||||
/** 힌트/최약 텍스트 */
|
||||
'--d3-text-muted': string
|
||||
/** dimLabel 텍스트 (command-popup 제목) */
|
||||
'--d3-text-dimLabel': string
|
||||
/** 기본 테두리 */
|
||||
'--d3-border-default': string
|
||||
/** 미묘한 테두리 (구분선, hover) */
|
||||
'--d3-border-subtle': string
|
||||
/** 강한 테두리 (progress background) */
|
||||
'--d3-border-strong': string
|
||||
/** 악센트 색상 (웨이브바, 선택 바) */
|
||||
'--d3-accent-main': string
|
||||
/** 악센트 dim (active 배경) */
|
||||
'--d3-accent-dim': string
|
||||
/** 팝업 박스 섀도 */
|
||||
'--d3-shadow-popup': string
|
||||
/** 결과 팝업 배경 (불투명) */
|
||||
'--d3-bg-result': string
|
||||
/** 결과 팝업 테두리 */
|
||||
'--d3-border-result': string
|
||||
/** 결과 팝업 텍스트 */
|
||||
'--d3-text-result': string
|
||||
/** 결과 팝업 버튼 색상 */
|
||||
'--d3-action-btn': string
|
||||
/** 결과 팝업 버튼 hover 배경 */
|
||||
'--d3-action-btn-hover-bg': string
|
||||
/** 결과 팝업 버튼 hover 색상 */
|
||||
'--d3-action-btn-hover': string
|
||||
}
|
||||
|
||||
const POPUP_THEME_VARS: Record<PopupThemeKey, PopupThemeVars> = {
|
||||
dark: {
|
||||
'--d3-bg-card': '#242427',
|
||||
'--d3-bg-tip': 'rgba(0,0,0,0.85)',
|
||||
'--d3-text-primary': 'rgba(255,255,255,0.87)',
|
||||
'--d3-text-secondary': 'rgba(255,255,255,0.6)',
|
||||
'--d3-text-inactive': 'rgba(255,255,255,0.3)',
|
||||
'--d3-text-muted': 'rgba(255,255,255,0.25)',
|
||||
'--d3-text-dimLabel': '#5c2615',
|
||||
'--d3-border-default': 'rgba(255,255,255,0.08)',
|
||||
'--d3-border-subtle': 'rgba(255,255,255,0.06)',
|
||||
'--d3-border-strong': 'rgba(255,255,255,0.15)',
|
||||
'--d3-accent-main': '#f25b29',
|
||||
'--d3-accent-dim': 'rgba(242,91,41,0.08)',
|
||||
'--d3-shadow-popup': '0 8px 32px rgba(0,0,0,0.5)',
|
||||
'--d3-bg-result': '#1e1e1e',
|
||||
'--d3-border-result': 'rgba(255,255,255,0.08)',
|
||||
'--d3-text-result': 'rgba(255,255,255,0.87)',
|
||||
'--d3-action-btn': 'rgba(255,255,255,0.4)',
|
||||
'--d3-action-btn-hover-bg': 'rgba(255,255,255,0.08)',
|
||||
'--d3-action-btn-hover': 'rgba(255,255,255,0.7)',
|
||||
},
|
||||
light: {
|
||||
'--d3-bg-card': '#ffffff',
|
||||
'--d3-bg-tip': 'rgba(255,255,255,0.92)',
|
||||
'--d3-text-primary': 'rgba(0,0,0,0.87)',
|
||||
'--d3-text-secondary': 'rgba(0,0,0,0.6)',
|
||||
'--d3-text-inactive': 'rgba(0,0,0,0.35)',
|
||||
'--d3-text-muted': 'rgba(0,0,0,0.25)',
|
||||
'--d3-text-dimLabel': '#b07040',
|
||||
'--d3-border-default': 'rgba(0,0,0,0.10)',
|
||||
'--d3-border-subtle': 'rgba(0,0,0,0.06)',
|
||||
'--d3-border-strong': 'rgba(0,0,0,0.14)',
|
||||
'--d3-accent-main': '#f25b29',
|
||||
'--d3-accent-dim': 'rgba(242,91,41,0.08)',
|
||||
'--d3-shadow-popup': '0 8px 32px rgba(0,0,0,0.12)',
|
||||
'--d3-bg-result': '#ffffff',
|
||||
'--d3-border-result': 'rgba(0,0,0,0.08)',
|
||||
'--d3-text-result': 'rgba(0,0,0,0.87)',
|
||||
'--d3-action-btn': 'rgba(0,0,0,0.4)',
|
||||
'--d3-action-btn-hover-bg': 'rgba(0,0,0,0.06)',
|
||||
'--d3-action-btn-hover': 'rgba(0,0,0,0.7)',
|
||||
},
|
||||
nord: {
|
||||
'--d3-bg-card': '#3b4252',
|
||||
'--d3-bg-tip': 'rgba(46,52,64,0.92)',
|
||||
'--d3-text-primary': 'rgba(236,239,244,0.87)',
|
||||
'--d3-text-secondary': 'rgba(216,222,233,0.6)',
|
||||
'--d3-text-inactive': 'rgba(216,222,233,0.35)',
|
||||
'--d3-text-muted': 'rgba(216,222,233,0.25)',
|
||||
'--d3-text-dimLabel': '#5e81ac',
|
||||
'--d3-border-default': 'rgba(216,222,233,0.10)',
|
||||
'--d3-border-subtle': 'rgba(216,222,233,0.06)',
|
||||
'--d3-border-strong': 'rgba(216,222,233,0.16)',
|
||||
'--d3-accent-main': '#88c0d0',
|
||||
'--d3-accent-dim': 'rgba(136,192,208,0.08)',
|
||||
'--d3-shadow-popup': '0 8px 32px rgba(0,0,0,0.5)',
|
||||
'--d3-bg-result': '#434c5e',
|
||||
'--d3-border-result': 'rgba(216,222,233,0.10)',
|
||||
'--d3-text-result': 'rgba(236,239,244,0.87)',
|
||||
'--d3-action-btn': 'rgba(216,222,233,0.4)',
|
||||
'--d3-action-btn-hover-bg': 'rgba(216,222,233,0.08)',
|
||||
'--d3-action-btn-hover': 'rgba(216,222,233,0.7)',
|
||||
},
|
||||
solarized: {
|
||||
'--d3-bg-card': '#073642',
|
||||
'--d3-bg-tip': 'rgba(0,43,54,0.92)',
|
||||
'--d3-text-primary': 'rgba(238,232,213,0.87)',
|
||||
'--d3-text-secondary': 'rgba(147,161,161,0.7)',
|
||||
'--d3-text-inactive': 'rgba(147,161,161,0.4)',
|
||||
'--d3-text-muted': 'rgba(147,161,161,0.25)',
|
||||
'--d3-text-dimLabel': '#7a6c2e',
|
||||
'--d3-border-default': 'rgba(131,148,150,0.13)',
|
||||
'--d3-border-subtle': 'rgba(131,148,150,0.08)',
|
||||
'--d3-border-strong': 'rgba(131,148,150,0.20)',
|
||||
'--d3-accent-main': '#b58900',
|
||||
'--d3-accent-dim': 'rgba(181,137,0,0.08)',
|
||||
'--d3-shadow-popup': '0 8px 32px rgba(0,0,0,0.5)',
|
||||
'--d3-bg-result': '#0d4250',
|
||||
'--d3-border-result': 'rgba(131,148,150,0.13)',
|
||||
'--d3-text-result': 'rgba(238,232,213,0.87)',
|
||||
'--d3-action-btn': 'rgba(147,161,161,0.4)',
|
||||
'--d3-action-btn-hover-bg': 'rgba(131,148,150,0.10)',
|
||||
'--d3-action-btn-hover': 'rgba(147,161,161,0.7)',
|
||||
},
|
||||
catppuccin: {
|
||||
'--d3-bg-card': '#313244',
|
||||
'--d3-bg-tip': 'rgba(30,30,46,0.92)',
|
||||
'--d3-text-primary': 'rgba(205,214,244,0.87)',
|
||||
'--d3-text-secondary': 'rgba(186,194,222,0.7)',
|
||||
'--d3-text-inactive': 'rgba(166,173,200,0.4)',
|
||||
'--d3-text-muted': 'rgba(166,173,200,0.25)',
|
||||
'--d3-text-dimLabel': '#585b70',
|
||||
'--d3-border-default': 'rgba(205,214,244,0.08)',
|
||||
'--d3-border-subtle': 'rgba(205,214,244,0.04)',
|
||||
'--d3-border-strong': 'rgba(205,214,244,0.14)',
|
||||
'--d3-accent-main': '#cba6f7',
|
||||
'--d3-accent-dim': 'rgba(203,166,247,0.08)',
|
||||
'--d3-shadow-popup': '0 8px 32px rgba(0,0,0,0.5)',
|
||||
'--d3-bg-result': '#3a3a54',
|
||||
'--d3-border-result': 'rgba(205,214,244,0.08)',
|
||||
'--d3-text-result': 'rgba(205,214,244,0.87)',
|
||||
'--d3-action-btn': 'rgba(166,173,200,0.4)',
|
||||
'--d3-action-btn-hover-bg': 'rgba(205,214,244,0.06)',
|
||||
'--d3-action-btn-hover': 'rgba(205,214,244,0.7)',
|
||||
},
|
||||
dracula: {
|
||||
'--d3-bg-card': '#44475a',
|
||||
'--d3-bg-tip': 'rgba(40,42,54,0.92)',
|
||||
'--d3-text-primary': 'rgba(248,248,242,0.87)',
|
||||
'--d3-text-secondary': 'rgba(169,176,208,0.7)',
|
||||
'--d3-text-inactive': 'rgba(169,176,208,0.4)',
|
||||
'--d3-text-muted': 'rgba(169,176,208,0.25)',
|
||||
'--d3-text-dimLabel': '#6272a4',
|
||||
'--d3-border-default': 'rgba(248,248,242,0.08)',
|
||||
'--d3-border-subtle': 'rgba(248,248,242,0.04)',
|
||||
'--d3-border-strong': 'rgba(248,248,242,0.14)',
|
||||
'--d3-accent-main': '#bd93f9',
|
||||
'--d3-accent-dim': 'rgba(189,147,249,0.08)',
|
||||
'--d3-shadow-popup': '0 8px 32px rgba(0,0,0,0.5)',
|
||||
'--d3-bg-result': '#4f5266',
|
||||
'--d3-border-result': 'rgba(248,248,242,0.08)',
|
||||
'--d3-text-result': 'rgba(248,248,242,0.87)',
|
||||
'--d3-action-btn': 'rgba(169,176,208,0.4)',
|
||||
'--d3-action-btn-hover-bg': 'rgba(248,248,242,0.06)',
|
||||
'--d3-action-btn-hover': 'rgba(248,248,242,0.7)',
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* 팝업용 CSS 변수 맵 조회.
|
||||
* ThemeMode('system' | 'light' | 'dark') 또는 테마 키를 받아 해당 변수 맵 반환.
|
||||
* 'system' 또는 알 수 없는 값은 'dark'로 폴백.
|
||||
*/
|
||||
export function getPopupThemeVars(themeKey: string): PopupThemeVars {
|
||||
const key = themeKey as PopupThemeKey
|
||||
return POPUP_THEME_VARS[key] ?? POPUP_THEME_VARS.dark
|
||||
}
|
||||
|
||||
/**
|
||||
* 팝업 BrowserWindow에 insertCSS로 주입할 CSS 문자열 반환.
|
||||
* `:root { --d3-bg-card: #242427; ... }`
|
||||
*/
|
||||
export function buildPopupThemeCss(themeKey: string): string {
|
||||
const vars = getPopupThemeVars(themeKey)
|
||||
const declarations = Object.entries(vars)
|
||||
.map(([prop, value]) => ` ${prop}: ${value};`)
|
||||
.join('\n')
|
||||
return `:root {\n${declarations}\n}`
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue