Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UploadedMedia > image preview by url #247

Merged
merged 1 commit into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 47 additions & 18 deletions packages/vue3/src/_dev/App.vue
Original file line number Diff line number Diff line change
@@ -1,34 +1,63 @@
<script setup lang="ts">
import 'uno.css';
import '../assets/main.css';
import { ref, watch } from 'vue';
import { MediaInput, UploadedMedia } from '~/components';

const attachments = ref<File[]>([]);
const disabled = ref(false);
const limit = 4;

const checkLimit = () => {
disabled.value = attachments.value.length >= limit;
};

const deleteFile = (file: File) => {
const idx = attachments.value.indexOf(file);
if (idx > -1) {
attachments.value.splice(idx, 1);
checkLimit();
}
};
watch(attachments, () => {
checkLimit();
});
</script>

<template>
<div class="container">
<i class="i-youcan:table-header" />
<i class="i-youcan:table-footer" />
<i class="i-youcan:table" />
<i class="i-youcan:row" />
<i class="i-youcan:column" />
<i class="i-youcan:table-style" />
<i class="i-youcan:cell" />
<i class="i-youcan:cell-style" />
<i class="i-youcan:image-legend" />
<i class="i-youcan:text-alt" />
<i class="i-youcan:open-link" />
<i class="i-youcan:corners-in" />
<i class="i-youcan:image-position" />
<i class="i-youcan:vertical-align" />
<i class="i-youcan:table-style" />
<div class="files-grid">
<UploadedMedia
v-for="(attachment, index) in attachments"
:key="index"
:file="attachment"
@delete="deleteFile(attachment)"
/>
</div>
<MediaInput v-model="attachments" :limit="limit" :disabled="disabled" />
<div class="files-grid">
<UploadedMedia
file="https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885_1280.jpg"
/>
</div>
</div>
</template>

<style scoped>
.container {
display: flex;
position: relative;
flex-direction: column;
width: 500px;
margin: 40px auto;
row-gap: 20px;
align-items: center;
justify-content: center;
width: 300px;
min-height: 140px;
}

.file-grid {
position: absolute;
right: 0;
bottom: 0;
left: 0;
}
</style>
2 changes: 1 addition & 1 deletion packages/vue3/src/components/Thumbnail/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ export interface ThumbnailProps {
size: ThumbnailSize
src?: string
alt?: string
objectFit: ObjectFit
objectFit?: ObjectFit
}
28 changes: 22 additions & 6 deletions packages/vue3/src/components/Upload/UploadedMedia.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,38 @@ import {
const props = defineProps<UploadedProps>();
const emit = defineEmits(['delete']);

const isImage = computed(() => props.file.type.startsWith('image/'));
const isFile = computed(() => props.file instanceof File && props.file.type.startsWith('image/'));

const isImage = computed(() => isFile.value || typeof props.file === 'string');

const fileName = computed(() => {
if (isFile.value) {
return (props.file as File).name;
}

return '';
});

const dataUrl = ref<string | null>(null);
const previewing = ref(false);
const togglePreview = (override = !previewing.value) => previewing.value = override;

onMounted(() => {
Utils.toDataUrl(props.file)
.then(res => (dataUrl.value = res))
.catch();
if (props.file instanceof File) {
Utils.toDataUrl(props.file)
.then(res => (dataUrl.value = res))
.catch();
}
else if (typeof props.file === 'string') {
dataUrl.value = props.file;
}
});
</script>

<template>
<div tabindex="0" class="file">
<div>
<Thumbnail class="preview" :alt="file.name" :src="isImage && dataUrl ? dataUrl : undefined" size="large" />
<Thumbnail class="preview" :alt="fileName" :src="isImage && dataUrl ? dataUrl : undefined" size="large" />
</div>
<div class="actions">
<TertiaryButton
Expand Down Expand Up @@ -58,7 +74,7 @@ onMounted(() => {
<i class="i-youcan:x" />
</template>
</TertiaryButton>
<img :src="dataUrl ?? undefined" :alt="file.name">
<img :src="dataUrl ?? undefined" :alt="fileName">
</div>
</Teleport>
</div>
Expand Down
6 changes: 3 additions & 3 deletions packages/vue3/src/components/Upload/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ export interface MediaInputProps {
modelValue: File[]
limit?: number
disabled?: boolean
label: string
label?: string
subLabel?: string
highlightedLabel: string
highlightedLabel?: string
}

export interface UploadedProps {
file: File
file: File | string
progress?: number
error?: string
}
Loading