aboutsummaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/c-key-value-list/c-key-value-list.types.ts9
-rw-r--r--src/ui/c-key-value-list/c-key-value-list.vue37
-rw-r--r--src/ui/c-text-copyable/c-text-copyable.demo.vue3
-rw-r--r--src/ui/c-text-copyable/c-text-copyable.vue17
-rw-r--r--src/ui/c-tooltip/c-tooltip.demo.vue17
-rw-r--r--src/ui/c-tooltip/c-tooltip.vue27
6 files changed, 110 insertions, 0 deletions
diff --git a/src/ui/c-key-value-list/c-key-value-list.types.ts b/src/ui/c-key-value-list/c-key-value-list.types.ts
new file mode 100644
index 0000000..40cc4ba
--- /dev/null
+++ b/src/ui/c-key-value-list/c-key-value-list.types.ts
@@ -0,0 +1,9 @@
+export interface CKeyValueListItem {
+ label: string
+ value: string | string[] | number | boolean | undefined | null
+ hideOnNil?: boolean
+ placeholder?: string
+ showCopyButton?: boolean
+}
+
+export type CKeyValueListItems = CKeyValueListItem[];
diff --git a/src/ui/c-key-value-list/c-key-value-list.vue b/src/ui/c-key-value-list/c-key-value-list.vue
new file mode 100644
index 0000000..e3b19af
--- /dev/null
+++ b/src/ui/c-key-value-list/c-key-value-list.vue
@@ -0,0 +1,37 @@
+<script lang="ts" setup>
+import _ from 'lodash';
+import type { CKeyValueListItems } from './c-key-value-list.types';
+
+const props = withDefaults(defineProps<{ items?: CKeyValueListItems }>(), { items: () => [] });
+const { items } = toRefs(props);
+
+const formattedItems = computed(() => items.value.filter(item => !_.isNil(item.value) || !item.hideOnNil));
+</script>
+
+<template>
+ <table border-collapse table-fixed>
+ <tr v-for="item in formattedItems" :key="item.label">
+ <td py-1 pr-2 text-right font-bold>
+ {{ item.label }}
+ </td>
+
+ <td v-if="_.isArray(item.value)">
+ <div v-for="value in item.value" :key="value">
+ <c-text-copyable :value="value" :show-icon="item.showCopyButton ?? true" />
+ </div>
+ </td>
+ <td v-else-if="_.isBoolean(item.value)">
+ <c-text-copyable :value="item.value ? 'true' : 'false'" :displayed-value="item.value ? 'Yes' : 'No'" :show-icon="item.showCopyButton ?? true" />
+ </td>
+ <td v-else-if="_.isNumber(item.value)" font-mono>
+ <c-text-copyable :value="String(item.value)" :show-icon="item.showCopyButton ?? true" />
+ </td>
+ <td v-else-if="_.isNil(item.value) || item.value === ''" op-70>
+ {{ item.placeholder ?? 'N/A' }}
+ </td>
+ <td v-else>
+ <c-text-copyable :value="item.value" :show-icon="item.showCopyButton ?? true" />
+ </td>
+ </tr>
+ </table>
+</template>
diff --git a/src/ui/c-text-copyable/c-text-copyable.demo.vue b/src/ui/c-text-copyable/c-text-copyable.demo.vue
new file mode 100644
index 0000000..e2aeb1d
--- /dev/null
+++ b/src/ui/c-text-copyable/c-text-copyable.demo.vue
@@ -0,0 +1,3 @@
+<template>
+ <c-text-copyable value="value" displayed-value="displayedValue" />
+</template>
diff --git a/src/ui/c-text-copyable/c-text-copyable.vue b/src/ui/c-text-copyable/c-text-copyable.vue
new file mode 100644
index 0000000..b78e4cd
--- /dev/null
+++ b/src/ui/c-text-copyable/c-text-copyable.vue
@@ -0,0 +1,17 @@
+<script setup lang="ts">
+import { useCopy } from '@/composable/copy';
+
+const props = withDefaults(defineProps<{ value?: string; displayedValue?: string; showIcon?: boolean }>(), { value: '', displayedValue: undefined, showIcon: true });
+const { value, displayedValue, showIcon } = toRefs(props);
+
+const { copy, isJustCopied } = useCopy({ source: value, createToast: false });
+</script>
+
+<template>
+ <c-tooltip :tooltip="isJustCopied ? 'Copied!' : 'Copy to clipboard'" cursor-pointer @click="copy">
+ <span flex items-center gap-2>
+ {{ displayedValue ?? value }}
+ <icon-mdi-content-copy v-if="showIcon" op-40 />
+ </span>
+ </c-tooltip>
+</template>
diff --git a/src/ui/c-tooltip/c-tooltip.demo.vue b/src/ui/c-tooltip/c-tooltip.demo.vue
new file mode 100644
index 0000000..d385257
--- /dev/null
+++ b/src/ui/c-tooltip/c-tooltip.demo.vue
@@ -0,0 +1,17 @@
+<template>
+ <div>
+ <c-tooltip>
+ Hover me
+
+ <template #tooltip>
+ Tooltip content
+ </template>
+ </c-tooltip>
+ </div>
+
+ <div mt-5>
+ <c-tooltip tooltip="Tooltip content">
+ Hover me
+ </c-tooltip>
+ </div>
+</template>
diff --git a/src/ui/c-tooltip/c-tooltip.vue b/src/ui/c-tooltip/c-tooltip.vue
new file mode 100644
index 0000000..cc48fe1
--- /dev/null
+++ b/src/ui/c-tooltip/c-tooltip.vue
@@ -0,0 +1,27 @@
+<script setup lang="ts">
+const props = withDefaults(defineProps<{ tooltip?: string }>(), { tooltip: '' });
+const { tooltip } = toRefs(props);
+
+const targetRef = ref();
+const isTargetHovered = useElementHover(targetRef);
+</script>
+
+<template>
+ <div class="relative" inline-block>
+ <div ref="targetRef">
+ <slot />
+ </div>
+
+ <div
+ class="absolute bottom-100% left-50% z-10 mb-5px whitespace-nowrap rounded bg-black px-12px py-6px text-sm text-white shadow-lg transition transition transition-duration-0.2s -translate-x-1/2"
+ :class="{
+ 'op-0 scale-0': isTargetHovered === false,
+ 'op-100 scale-100': isTargetHovered,
+ }"
+ >
+ <slot name="tooltip">
+ {{ tooltip }}
+ </slot>
+ </div>
+ </div>
+</template>