refactor(display): mutualized code display
This commit is contained in:
		
							parent
							
								
									422b6eb05a
								
							
						
					
					
						commit
						0be33fb337
					
				
							
								
								
									
										98
									
								
								src/components/TextareaCopyable.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								src/components/TextareaCopyable.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,98 @@ | ||||
| <template> | ||||
|   <div style="overflow-x: hidden; width: 100%"> | ||||
|     <n-card class="result-card"> | ||||
|       <n-scrollbar | ||||
|         x-scrollable | ||||
|         trigger="none" | ||||
|         :style="height ? `min-height: ${height - 40 /* card padding */ + 10 /* negative margin compensation */}px` : ''" | ||||
|       > | ||||
|         <n-config-provider :hljs="hljs"> | ||||
|           <n-code :code="value" :language="language" :trim="false" /> | ||||
|         </n-config-provider> | ||||
|       </n-scrollbar> | ||||
|       <n-tooltip v-if="value" trigger="hover"> | ||||
|         <template #trigger> | ||||
|           <div class="copy-button" :class="[copyPlacement]"> | ||||
|             <n-button secondary circle size="large" @click="onCopyClicked"> | ||||
|               <n-icon size="22" :component="Copy" /> | ||||
|             </n-button> | ||||
|           </div> | ||||
|         </template> | ||||
|         <span>{{ tooltipText }}</span> | ||||
|       </n-tooltip> | ||||
|     </n-card> | ||||
|     <n-space v-if="copyPlacement === 'outside'" justify="center" style="margin-top: 15px"> | ||||
|       <n-button secondary @click="onCopyClicked"> {{ tooltipText }} </n-button> | ||||
|     </n-space> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script setup lang="ts"> | ||||
| import { Copy } from '@vicons/tabler'; | ||||
| import { useClipboard, useElementSize } from '@vueuse/core'; | ||||
| import hljs from 'highlight.js/lib/core'; | ||||
| import jsonHljs from 'highlight.js/lib/languages/json'; | ||||
| import sqlHljs from 'highlight.js/lib/languages/sql'; | ||||
| import { ref, toRefs } from 'vue'; | ||||
| 
 | ||||
| hljs.registerLanguage('sql', sqlHljs); | ||||
| hljs.registerLanguage('json', jsonHljs); | ||||
| 
 | ||||
| const props = withDefaults( | ||||
|   defineProps<{ | ||||
|     value: string; | ||||
|     followHeightOf?: HTMLElement | null; | ||||
|     language?: string; | ||||
|     copyPlacement?: 'top-right' | 'bottom-right' | 'outside' | 'none'; | ||||
|     copyMessage?: string; | ||||
|   }>(), | ||||
|   { | ||||
|     followHeightOf: null, | ||||
|     language: 'txt', | ||||
|     copyPlacement: 'top-right', | ||||
|     copyMessage: 'Copy to clipboard', | ||||
|   }, | ||||
| ); | ||||
| const { value, language, followHeightOf, copyPlacement, copyMessage } = toRefs(props); | ||||
| const { height } = followHeightOf ? useElementSize(followHeightOf) : { height: ref(null) }; | ||||
| 
 | ||||
| const { copy } = useClipboard({ source: value }); | ||||
| const tooltipText = ref(copyMessage.value); | ||||
| 
 | ||||
| function onCopyClicked() { | ||||
|   copy(); | ||||
|   tooltipText.value = 'Copied !'; | ||||
| 
 | ||||
|   setTimeout(() => { | ||||
|     tooltipText.value = copyMessage.value; | ||||
|   }, 2000); | ||||
| } | ||||
| </script> | ||||
| 
 | ||||
| <style lang="less" scoped> | ||||
| ::v-deep(.n-scrollbar) { | ||||
|   padding-bottom: 10px; | ||||
|   margin-bottom: -10px; | ||||
| } | ||||
| .result-card { | ||||
|   position: relative; | ||||
|   .copy-button { | ||||
|     position: absolute; | ||||
|     opacity: 1; | ||||
| 
 | ||||
|     &.top-right { | ||||
|       top: 10px; | ||||
|       right: 10px; | ||||
|     } | ||||
| 
 | ||||
|     &.bottom-right { | ||||
|       bottom: 10px; | ||||
|       right: 10px; | ||||
|     } | ||||
|     &.outside, | ||||
|     &.none { | ||||
|       display: none; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| @ -17,26 +17,16 @@ | ||||
|     /> | ||||
|   </n-form-item> | ||||
|   <n-form-item label="Prettify version of your json"> | ||||
|     <n-card class="result-card" :style="`min-height: ${inputElementHeight ?? 400}px`"> | ||||
|       <n-config-provider :hljs="hljs"> | ||||
|         <n-code :code="cleanJson" language="json" :trim="false" /> | ||||
|       </n-config-provider> | ||||
|       <n-button v-if="cleanJson" class="copy-button" secondary @click="copy">Copy</n-button> | ||||
|     </n-card> | ||||
|     <textarea-copyable :value="cleanJson" language="json" :follow-height-of="inputElement" /> | ||||
|   </n-form-item> | ||||
| </template> | ||||
| 
 | ||||
| <script setup lang="ts"> | ||||
| import { useCopy } from '@/composable/copy'; | ||||
| import TextareaCopyable from '@/components/TextareaCopyable.vue'; | ||||
| import { useValidation } from '@/composable/validation'; | ||||
| import { useElementSize } from '@vueuse/core'; | ||||
| import hljs from 'highlight.js/lib/core'; | ||||
| import json from 'highlight.js/lib/languages/json'; | ||||
| import { computed, ref } from 'vue'; | ||||
| 
 | ||||
| hljs.registerLanguage('json', json); | ||||
| const inputElement = ref<HTMLElement>(); | ||||
| const { height: inputElementHeight } = useElementSize(inputElement); | ||||
| 
 | ||||
| const rawJson = ref('{"hello": "world"}'); | ||||
| const cleanJson = computed(() => { | ||||
| @ -47,8 +37,6 @@ const cleanJson = computed(() => { | ||||
|   } | ||||
| }); | ||||
| 
 | ||||
| const { copy } = useCopy({ source: cleanJson }); | ||||
| 
 | ||||
| const rawJsonValidation = useValidation({ | ||||
|   source: rawJson, | ||||
|   rules: [ | ||||
|  | ||||
| @ -58,27 +58,17 @@ | ||||
|     /> | ||||
|   </n-form-item> | ||||
|   <n-form-item label="Prettify version of your query"> | ||||
|     <n-card class="result-card" :style="`min-height: ${inputElementHeight ?? 400}px`"> | ||||
|       <n-config-provider :hljs="hljs"> | ||||
|         <n-code :code="prettySQL" language="sql" :trim="false" /> | ||||
|       </n-config-provider> | ||||
|       <n-button v-if="prettySQL" class="copy-button" secondary @click="copy">Copy</n-button> | ||||
|     </n-card> | ||||
|     <textarea-copyable :value="prettySQL" language="sql" :follow-height-of="inputElement" /> | ||||
|   </n-form-item> | ||||
| </template> | ||||
| 
 | ||||
| <script setup lang="ts"> | ||||
| import { useCopy } from '@/composable/copy'; | ||||
| import TextareaCopyable from '@/components/TextareaCopyable.vue'; | ||||
| import { useStyleStore } from '@/stores/style.store'; | ||||
| import { useElementSize } from '@vueuse/core'; | ||||
| import hljs from 'highlight.js/lib/core'; | ||||
| import sqlHljs from 'highlight.js/lib/languages/sql'; | ||||
| import { format as formatSQL, type FormatFnOptions } from 'sql-formatter'; | ||||
| import { computed, reactive, ref } from 'vue'; | ||||
| hljs.registerLanguage('sql', sqlHljs); | ||||
| 
 | ||||
| const inputElement = ref<HTMLElement>(); | ||||
| const { height: inputElementHeight } = useElementSize(inputElement); | ||||
| const styleStore = useStyleStore(); | ||||
| const config = reactive<Partial<FormatFnOptions>>({ | ||||
|   keywordCase: 'upper', | ||||
| @ -90,7 +80,6 @@ const config = reactive<Partial<FormatFnOptions>>({ | ||||
| 
 | ||||
| const rawSQL = ref('select field1,field2,field3 from my_table where my_condition;'); | ||||
| const prettySQL = computed(() => formatSQL(rawSQL.value, config)); | ||||
| const { copy } = useCopy({ source: prettySQL }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="less" scoped> | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user