aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/TextareaCopyable.vue98
-rw-r--r--src/tools/json-viewer/json-viewer.vue16
-rw-r--r--src/tools/sql-prettify/sql-prettify.vue15
3 files changed, 102 insertions, 27 deletions
diff --git a/src/components/TextareaCopyable.vue b/src/components/TextareaCopyable.vue
new file mode 100644
index 0000000..49fb96d
--- /dev/null
+++ b/src/components/TextareaCopyable.vue
@@ -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>
diff --git a/src/tools/json-viewer/json-viewer.vue b/src/tools/json-viewer/json-viewer.vue
index 701aebc..00af91d 100644
--- a/src/tools/json-viewer/json-viewer.vue
+++ b/src/tools/json-viewer/json-viewer.vue
@@ -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: [
diff --git a/src/tools/sql-prettify/sql-prettify.vue b/src/tools/sql-prettify/sql-prettify.vue
index 5cbeba9..9f1e4fe 100644
--- a/src/tools/sql-prettify/sql-prettify.vue
+++ b/src/tools/sql-prettify/sql-prettify.vue
@@ -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>