diff options
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/c-collapse/c-collapse.demo.vue | 5 | ||||
-rw-r--r-- | src/ui/c-collapse/c-collapse.vue | 25 | ||||
-rw-r--r-- | src/ui/c-file-upload/c-file-upload.demo.vue | 3 | ||||
-rw-r--r-- | src/ui/c-file-upload/c-file-upload.vue | 95 | ||||
-rw-r--r-- | src/ui/c-key-value-list/c-key-value-list.vue | 8 | ||||
-rw-r--r-- | src/ui/c-modal-value/c-modal-value.demo.vue | 21 | ||||
-rw-r--r-- | src/ui/c-modal-value/c-modal-value.vue | 31 | ||||
-rw-r--r-- | src/ui/c-table/c-table.vue | 4 |
8 files changed, 186 insertions, 6 deletions
diff --git a/src/ui/c-collapse/c-collapse.demo.vue b/src/ui/c-collapse/c-collapse.demo.vue new file mode 100644 index 0000000..760d0ec --- /dev/null +++ b/src/ui/c-collapse/c-collapse.demo.vue @@ -0,0 +1,5 @@ +<template> + <c-collapse title="Collapse title"> + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquet iaculis class cubilia metus per nullam gravida ad venenatis. Id elementum elementum enim orci elementum justo facilisi habitant consequat. Justo eget ligula purus laoreet penatibus eros quisque fusce sociis. In eget amet sagittis dignissim eleifend proin lacinia potenti tellus. Interdum vulputate condimentum molestie pulvinar praesent accumsan quisque venenatis imperdiet. + </c-collapse> +</template> diff --git a/src/ui/c-collapse/c-collapse.vue b/src/ui/c-collapse/c-collapse.vue new file mode 100644 index 0000000..ccd7c1e --- /dev/null +++ b/src/ui/c-collapse/c-collapse.vue @@ -0,0 +1,25 @@ +<script lang="ts" setup> +const props = withDefaults(defineProps<{ title?: string }>(), { title: '' }); +const { title } = toRefs(props); + +const isCollapsed = ref(true); +</script> + +<template> + <div> + <div flex cursor-pointer items-center @click="isCollapsed = !isCollapsed"> + <icon-mdi-triangle-down :class="{ 'transform-rotate--90': isCollapsed }" op-50 transition /> + + <slot name="title"> + <span class="ml-2" font-bold>{{ title }}</span> + </slot> + </div> + + <div + v-show="!isCollapsed" + mt-2 + > + <slot /> + </div> + </div> +</template> diff --git a/src/ui/c-file-upload/c-file-upload.demo.vue b/src/ui/c-file-upload/c-file-upload.demo.vue new file mode 100644 index 0000000..eedcbd6 --- /dev/null +++ b/src/ui/c-file-upload/c-file-upload.demo.vue @@ -0,0 +1,3 @@ +<template> + <c-file-upload /> +</template> diff --git a/src/ui/c-file-upload/c-file-upload.vue b/src/ui/c-file-upload/c-file-upload.vue new file mode 100644 index 0000000..b48d8c3 --- /dev/null +++ b/src/ui/c-file-upload/c-file-upload.vue @@ -0,0 +1,95 @@ +<script lang="ts" setup> +import _ from 'lodash'; + +const props = withDefaults(defineProps<{ + multiple?: boolean + accept?: string + title?: string +}>(), { + multiple: false, + accept: undefined, + title: 'Drag and drop files here, or click to select files', +}); + +const emit = defineEmits<{ + (event: 'filesUpload', files: File[]): void + (event: 'fileUpload', file: File): void +}>(); + +const { multiple } = toRefs(props); + +const isOverDropZone = ref(false); + +const fileInput = ref<HTMLInputElement | null>(null); + +function triggerFileInput() { + fileInput.value?.click(); +} + +function handleFileInput(event: Event) { + const files = (event.target as HTMLInputElement).files; + + handleUpload(files); +} + +function handleDrop(event: DragEvent) { + event.preventDefault(); + const files = event.dataTransfer?.files; + + handleUpload(files); +} + +function handleUpload(files: FileList | null | undefined) { + if (_.isNil(files) || _.isEmpty(files)) { + return; + } + + if (multiple.value) { + emit('filesUpload', Array.from(files)); + return; + } + + emit('fileUpload', files[0]); +} +</script> + +<template> + <div + class="flex flex-col cursor-pointer items-center justify-center border-2px border-gray-300 border-opacity-50 rounded-lg border-dashed p-8 transition-colors" + :class="{ + 'border-primary border-opacity-100': isOverDropZone, + }" + @click="triggerFileInput" + @drop.prevent="handleDrop" + @dragover.prevent + @dragenter="isOverDropZone = true" + @dragleave="isOverDropZone = false" + > + <input + ref="fileInput" + type="file" + class="hidden" + :multiple="multiple" + :accept="accept" + @change="handleFileInput" + > + <slot> + <span op-70> + {{ title }} + </span> + + <!-- separator --> + <div my-4 w-full flex items-center justify-center op-70> + <div class="h-1px max-w-100px flex-1 bg-gray-300 op-50" /> + <div class="mx-2 text-gray-400"> + or + </div> + <div class="h-1px max-w-100px flex-1 bg-gray-300 op-50" /> + </div> + + <c-button> + Browse files + </c-button> + </slot> + </div> +</template> 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 index d8a2b00..d863bd5 100644 --- a/src/ui/c-key-value-list/c-key-value-list.vue +++ b/src/ui/c-key-value-list/c-key-value-list.vue @@ -9,13 +9,13 @@ const formattedItems = computed(() => items.value.filter(item => !_.isNil(item.v </script> <template> - <div my-5> - <div v-for="item in formattedItems" :key="item.label" flex gap-2 py-1 class="c-key-value-list__item"> - <div flex-basis-180px text-right font-bold class="c-key-value-list__key"> + <div flex flex-col gap-2> + <div v-for="item in formattedItems" :key="item.label" class="c-key-value-list__item"> + <div class="c-key-value-list__key" text-13px lh-normal> {{ item.label }} </div> - <c-key-value-list-item :item="item" class="c-key-value-list__value" /> + <c-key-value-list-item :item="item" class="c-key-value-list__value" font-bold lh-normal /> </div> </div> </template> diff --git a/src/ui/c-modal-value/c-modal-value.demo.vue b/src/ui/c-modal-value/c-modal-value.demo.vue new file mode 100644 index 0000000..6ebff8c --- /dev/null +++ b/src/ui/c-modal-value/c-modal-value.demo.vue @@ -0,0 +1,21 @@ +<template> + <div flex gap-2> + <c-modal-value value="lorem ipsum" label="test" /> + <c-modal-value> + <template #label="{ toggleModal }"> + <c-button class="text-left" size="small" @click="toggleModal"> + Bonjour + </c-button> + </template> + + <template #value> + <pre> + Lorem ipsum dolor sit amet consectetur adipisicing elit. + Molestias, quisquam vitae saepe dolores quas debitis ab r + ecusandae suscipit ex dignissimos minus quam repellat sunt. + Molestiae culpa blanditiis totam sapiente dignissimos. + </pre> + </template> + </c-modal-value> + </div> +</template> diff --git a/src/ui/c-modal-value/c-modal-value.vue b/src/ui/c-modal-value/c-modal-value.vue new file mode 100644 index 0000000..3b388e0 --- /dev/null +++ b/src/ui/c-modal-value/c-modal-value.vue @@ -0,0 +1,31 @@ +<script lang="ts" setup> +import { useCopy } from '@/composable/copy'; + +const props = withDefaults(defineProps<{ value: string; label?: string; copyable?: boolean }>(), { label: undefined, copyable: true }); +const { value, label } = toRefs(props); + +const { copy, isJustCopied } = useCopy({ source: value }); + +const isModalOpen = ref(false); +const toggleModal = useToggle(isModalOpen); +</script> + +<template> + <slot name="label" :value="value" :toggle-modal="toggleModal" :is-modal-open="isModalOpen"> + <c-button class="text-left" @click="isModalOpen = true"> + {{ label }} + </c-button> + </slot> + + <c-modal v-model:open="isModalOpen"> + <slot name="value" :value="value" :toggle-modal="toggleModal" :is-modal-open="isModalOpen"> + {{ value }} + </slot> + + <div mt-4 flex justify-center> + <c-button class="w-full" @click="copy"> + {{ isJustCopied ? 'Copied!' : 'Copy' }} + </c-button> + </div> + </c-modal> +</template> diff --git a/src/ui/c-table/c-table.vue b/src/ui/c-table/c-table.vue index 9354cc9..ef56989 100644 --- a/src/ui/c-table/c-table.vue +++ b/src/ui/c-table/c-table.vue @@ -39,7 +39,7 @@ const headers = computed(() => { <template> <div class="relative overflow-x-auto rounded"> <table class="w-full border-collapse text-left text-sm text-gray-500 dark:text-gray-400" role="table" :aria-label="description"> - <thead v-if="!hideHeaders" class="bg-#ffffff uppercase text-gray-700 dark:bg-#333333 dark:text-gray-400"> + <thead v-if="!hideHeaders" class="bg-#ffffff uppercase text-gray-700 dark:bg-#333333 dark:text-gray-400" border-b="1px solid dark:transparent #efeff5"> <tr> <th v-for="header in headers" :key="header.key" scope="col" class="px-6 py-3 text-xs"> {{ header.label }} @@ -54,7 +54,7 @@ const headers = computed(() => { }" > <td v-for="header in headers" :key="header.key" class="px-6 py-4"> - <slot :name="header" :row="row" :headers="headers" :value="row[header.key]"> + <slot :name="header.key" :row="row" :headers="headers" :value="row[header.key]"> {{ row[header.key] }} </slot> </td> |