diff options
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/c-key-value-list/c-key-value-list.types.ts | 9 | ||||
-rw-r--r-- | src/ui/c-key-value-list/c-key-value-list.vue | 37 | ||||
-rw-r--r-- | src/ui/c-text-copyable/c-text-copyable.demo.vue | 3 | ||||
-rw-r--r-- | src/ui/c-text-copyable/c-text-copyable.vue | 17 | ||||
-rw-r--r-- | src/ui/c-tooltip/c-tooltip.demo.vue | 17 | ||||
-rw-r--r-- | src/ui/c-tooltip/c-tooltip.vue | 27 |
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> |