@@ -4,6 +4,7 @@ import { postMessage } from '../vscode';
44import type { AppState } from '../App' ;
55import { DEFAULT_SCHEMAS } from '../App' ;
66import type { OrmType , WebviewMessage } from '../vscode' ;
7+ import { useCopy } from '../hooks/useCopy' ;
78
89// ── Types ─────────────────────────────────────────────────────────────────────
910
@@ -50,7 +51,7 @@ interface Props { state: AppState; setState: React.Dispatch<React.SetStateAction
5051
5152export default function Export ( { state } : Props ) {
5253 const [ panelId , setPanelId ] = useState ( 'sql-pg' ) ;
53- const [ copied , setCopied ] = useState < string | null > ( null ) ;
54+ const { copiedId , copy } = useCopy ( ) ;
5455
5556 const hasSql = ! ! ( state . postgres || state . mysql || state . sqlite ) ;
5657 const hasSvg = ! ! state . svg ;
@@ -69,13 +70,6 @@ export default function Export({ state }: Props) {
6970
7071 const selectedFile = files . find ( ( f ) => f . id === panelId ) ;
7172
72- function copyContent ( content : string , id : string ) {
73- navigator . clipboard . writeText ( content ) . then ( ( ) => {
74- setCopied ( id ) ;
75- setTimeout ( ( ) => setCopied ( null ) , 1500 ) ;
76- } ) ;
77- }
78-
7973 return (
8074 < Flex h = "100%" overflow = "hidden" >
8175
@@ -116,8 +110,8 @@ export default function Export({ state }: Props) {
116110 < >
117111 < FileHeader
118112 file = { selectedFile }
119- copied = { copied === selectedFile . id }
120- onCopy = { ( ) => copyContent ( selectedFile . content , selectedFile . id ) }
113+ copied = { copiedId === selectedFile . id }
114+ onCopy = { ( ) => copy ( selectedFile . content , selectedFile . id ) }
121115 onSave = { ( ) => saveFile ( selectedFile , state . ormType ) }
122116 />
123117 < FilePreviewBody file = { selectedFile } />
@@ -140,7 +134,7 @@ function SectionHeader({ label }: { label: string }) {
140134
141135function GroupLabel ( { label } : { label : string } ) {
142136 return (
143- < Text as = "div" py = "6px" px = "10px" pb = "2px" fontSize = "9px " fontWeight = { 600 } color = "$nodeTextDim" letterSpacing = "0.06em" >
137+ < Text as = "div" py = "6px" px = "10px" pb = "2px" fontSize = "10px " fontWeight = { 600 } color = "$nodeTextDim" letterSpacing = "0.06em" >
144138 { label }
145139 </ Text >
146140 ) ;
@@ -158,13 +152,13 @@ function FileRow({ f, active, onClick }: { f: ExportFile; active: boolean; onCli
158152 bg = { active ? 'rgba(99,102,241,0.15)' : 'transparent' }
159153 borderLeft = { active ? '2px solid $focusBorder' : '2px solid transparent' }
160154 >
161- < Box as = "span" fontSize = "10px" color = "$nodeTextDim" flexShrink = { 0 } >
155+ < Text as = "span" fontSize = "10px" color = "$nodeTextDim" flexShrink = { 0 } >
162156 { f . ext === '.sql' ? '≡' : f . ext === '.svg' || f . ext === '.pdf' ? '◫' : '{ }' }
163- </ Box >
164- < Box as = "span" flex = { 1 } fontSize = "12px" overflow = "hidden" textOverflow = "ellipsis" whiteSpace = "nowrap" color = "$nodeText" >
165- { f . label } < Box as = "span" color = "$nodeTextDim" > { f . ext } </ Box >
166- </ Box >
167- { f . isDummy && < Box as = "span" fontSize = "9px " color = "$nodeTextDim" > ~</ Box > }
157+ </ Text >
158+ < Text as = "span" flex = { 1 } fontSize = "12px" overflow = "hidden" textOverflow = "ellipsis" whiteSpace = "nowrap" color = "$nodeText" >
159+ { f . label } < Text as = "span" color = "$nodeTextDim" > { f . ext } </ Text >
160+ </ Text >
161+ { f . isDummy && < Text as = "span" fontSize = "10px " color = "$nodeTextDim" > ~</ Text > }
168162 </ Flex >
169163 ) ;
170164}
@@ -185,28 +179,28 @@ function FileHeader({ file, copied, onCopy, onSave }: {
185179 >
186180 < Text as = "span" fontWeight = { 600 } > { file . label } </ Text >
187181 < Text as = "span" color = "$nodeTextDim" > { file . ext } </ Text >
188- < Box
182+ < Text
189183 as = "span"
190- fontSize = "9px "
184+ fontSize = "10px "
191185 py = "2px"
192186 px = "6px"
193- borderRadius = "3px "
187+ borderRadius = "4px "
194188 bg = "rgba(99,102,241,0.15)"
195189 color = "#a5b4fc"
196190 border = "1px solid rgba(99,102,241,0.25)"
197191 fontWeight = { 700 }
198- > { file . lang } </ Box >
192+ > { file . lang } </ Text >
199193 { file . isDummy && (
200- < Box
194+ < Text
201195 as = "span"
202- fontSize = "9px "
196+ fontSize = "10px "
203197 py = "2px"
204198 px = "6px"
205- borderRadius = "3px "
199+ borderRadius = "4px "
206200 bg = "rgba(251,191,36,0.12)"
207201 color = "#fbbf24"
208202 border = "1px solid rgba(251,191,36,0.25)"
209- > PREVIEW</ Box >
203+ > PREVIEW</ Text >
210204 ) }
211205 < Box flex = { 1 } />
212206 < Box as = "button" onClick = { onCopy } { ...btnStyle ( copied ? 'green' : 'default' ) } >
@@ -221,38 +215,40 @@ function FilePreviewBody({ file }: { file: ExportFile }) {
221215 if ( file . id === 'erd-pdf' ) {
222216 return (
223217 < Box flex = { 1 } overflow = "auto" p = "24px" bg = "$editorBg" >
224- < Box
218+ < Text
219+ as = "div"
225220 py = "16px"
226221 px = "20px"
227222 borderRadius = "8px"
228223 bg = "rgba(99,102,241,0.08)"
229224 border = "1px solid rgba(99,102,241,0.2)"
230- fontSize = "13px "
225+ fontSize = "14px "
231226 lineHeight = { 1.8 }
232227 color = "$editorFg"
233228 >
234229 PDF export converts the ERD diagram SVG to a portable document.{ '\n\n' }
235230 Click "저장" to generate the PDF file.{ '\n' }
236231 { file . isDummy ? '⚠ ORM Editor에서 스키마를 먼저 입력하세요.' : '✓ ERD 준비 완료.' }
237- </ Box >
232+ </ Text >
238233 </ Box >
239234 ) ;
240235 }
241236
242237 if ( file . id === 'erd-svg' && file . isDummy ) {
243238 return (
244239 < Box flex = { 1 } overflow = "auto" p = "24px" bg = "$editorBg" >
245- < Box
240+ < Text
241+ as = "div"
246242 py = "16px"
247243 px = "20px"
248244 borderRadius = "8px"
249245 bg = "rgba(99,102,241,0.08)"
250246 border = "1px solid rgba(99,102,241,0.2)"
251- fontSize = "13px "
247+ fontSize = "14px "
252248 color = "$editorFg"
253249 >
254250 ⚠ ORM Editor에서 스키마를 먼저 입력하세요.
255- </ Box >
251+ </ Text >
256252 </ Box >
257253 ) ;
258254 }
@@ -261,20 +257,20 @@ function FilePreviewBody({ file }: { file: ExportFile }) {
261257 return (
262258 < Box flex = { 1 } overflow = "auto" p = "24px" bg = "$editorBg" >
263259 < Box dangerouslySetInnerHTML = { { __html : file . content } } maxWidth = "100%" />
264- < Box mt = "16px" fontSize = "11px " opacity = { 0.4 } > SVG 소스:</ Box >
265- < Box
260+ < Text as = "div" mt = "16px" fontSize = "12px " opacity = { 0.4 } > SVG 소스:</ Text >
261+ < Text
266262 as = "pre"
267263 mt = "8px"
268264 py = "10px"
269265 px = "14px"
270266 bg = "rgba(0,0,0,0.2)"
271267 borderRadius = "6px"
272- fontSize = "11px "
268+ fontSize = "12px "
273269 lineHeight = { 1.6 }
274270 whiteSpace = "pre"
275271 overflowX = "auto"
276272 color = "$editorFg"
277- > { file . content } </ Box >
273+ > { file . content } </ Text >
278274 </ Box >
279275 ) ;
280276 }
@@ -290,18 +286,18 @@ function FilePreviewBody({ file }: { file: ExportFile }) {
290286 >
291287 { file . content . split ( '\n' ) . map ( ( line , i ) => (
292288 < Flex key = { i } minH = "20px" >
293- < Box
289+ < Text
294290 as = "span"
295291 minW = "44px"
296292 pr = "10px"
297293 textAlign = "right"
298294 flexShrink = { 0 }
299- fontSize = "11px "
295+ fontSize = "12px "
300296 lineHeight = "20px"
301297 userSelect = "none"
302298 color = "$diffLinenum"
303- > { i + 1 } </ Box >
304- < Box as = "span" flex = { 1 } pr = "16px" lineHeight = "20px" whiteSpace = "pre" color = "$editorFg" > { line } </ Box >
299+ > { i + 1 } </ Text >
300+ < Text as = "span" flex = { 1 } pr = "16px" lineHeight = "20px" whiteSpace = "pre" color = "$editorFg" > { line } </ Text >
305301 </ Flex >
306302 ) ) }
307303 </ Box >
@@ -313,10 +309,10 @@ function FilePreviewBody({ file }: { file: ExportFile }) {
313309function btnStyle ( variant : 'primary' | 'default' | 'green' ) {
314310 const base = {
315311 border : 'none' as const ,
316- borderRadius : '3px ' ,
317- py : '3px ' ,
312+ borderRadius : '4px ' ,
313+ py : '4px ' ,
318314 px : '12px' ,
319- fontSize : '11px ' ,
315+ fontSize : '12px ' ,
320316 cursor : 'pointer' as const ,
321317 fontFamily : 'inherit' ,
322318 flexShrink : 0 ,
0 commit comments