You've already forked obsidian-visualiser
Progressing on profile edition and thumbnail cropping
This commit is contained in:
@@ -15,13 +15,6 @@ const reset = (_: MouseEvent) => {
|
||||
dispX.value = 0;
|
||||
dispY.value = 0;
|
||||
}
|
||||
function clamp(x: number, min: number, max: number): number {
|
||||
if (x > max)
|
||||
return max;
|
||||
if (x < min)
|
||||
return min;
|
||||
return x;
|
||||
}
|
||||
function edgePos(side: 'bottom' | 'top' | 'left' | 'right', pos: { x: number, y: number }, offset: number): { x: number, y: number } {
|
||||
switch (side) {
|
||||
case "left":
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
<template>
|
||||
<HoverPopup @before-show="fetch" :class="[{'is-loaded': fetched}, file?.type === 'Markdown' ? 'overflow-auto' : 'overflow-hidden']">
|
||||
<HoverPopup @before-show="fetch">
|
||||
<template #content>
|
||||
<Suspense suspensible>
|
||||
<div v-if="pending" class="loading w-[550px] h-[450px]"></div>
|
||||
<template v-else-if="!!file">
|
||||
<div v-if="file.type === 'Markdown'" class="p-6 ms-6">
|
||||
<ProseH1>{{ file.title }}</ProseH1>
|
||||
<Markdown :content="file.content"></Markdown>
|
||||
</div>
|
||||
<div v-else-if="file.type === 'Canvas'" class="w-[550px] h-[450px] overflow-hidden">
|
||||
<CanvasRenderer :canvas="JSON.parse(file.content) " />
|
||||
</div>
|
||||
<div :class="[{'is-loaded': fetched}, file?.type === 'Markdown' ? 'overflow-auto' : 'overflow-hidden']">
|
||||
<div v-if="pending" class="loading w-[550px] h-[450px]"></div>
|
||||
<template v-else-if="!!file">
|
||||
<div v-if="file.type === 'Markdown'" class="p-6 ms-6">
|
||||
<ProseH1>{{ file.title }}</ProseH1>
|
||||
<Markdown :content="file.content"></Markdown>
|
||||
</div>
|
||||
<div v-else-if="file.type === 'Canvas'" class="w-[550px] h-[450px] overflow-hidden">
|
||||
<CanvasRenderer :canvas="JSON.parse(file.content) " />
|
||||
</div>
|
||||
<div class="h-100 w-100 flex flex-1 flex-col justify-center items-center" v-else>
|
||||
<div class="text-3xl font-extralight tracking-wide text-light-60 dark:text-dark-60">Fichier vide</div>
|
||||
<div class="text-lg text-light-60 dark:text-dark-60">Cette page est vide</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="h-100 w-100 flex flex-1 flex-col justify-center items-center" v-else>
|
||||
<div class="text-3xl font-extralight tracking-wide text-light-60 dark:text-dark-60">Fichier vide</div>
|
||||
<div class="text-lg text-light-60 dark:text-dark-60">Cette page est vide</div>
|
||||
<div class="text-3xl font-extralight tracking-wide text-light-60 dark:text-dark-60">Impossible d'afficher</div>
|
||||
<div class="text-lg text-light-60 dark:text-dark-60">Cette page est impossible à traiter</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="h-100 w-100 flex flex-1 flex-col justify-center items-center" v-else>
|
||||
<div class="text-3xl font-extralight tracking-wide text-light-60 dark:text-dark-60">Impossible d'afficher</div>
|
||||
<div class="text-lg text-light-60 dark:text-dark-60">Cette page est impossible à traiter</div>
|
||||
</div>
|
||||
<template #fallback><div class="loading w-[550px] h-[450px]"></div></template>
|
||||
</Suspense>
|
||||
</template>
|
||||
<template #default><slot name="default"></slot></template>
|
||||
|
||||
@@ -1,22 +1,25 @@
|
||||
<template>
|
||||
<HoverPopup class="mw-[400px]" @before-show="fetch">
|
||||
<HoverPopup @before-show="fetch">
|
||||
<template #content>
|
||||
<Suspense>
|
||||
<div v-if="fetched === false" class="loading w-[400px] h-[150px]"></div>
|
||||
<template v-else-if="!!data">
|
||||
<div v-if="data.description" class="pb-4 pt-3 px-8">
|
||||
<span class="text-2xl font-semibold">#{{ data.tag }}</span>
|
||||
<Markdown :content="data.description"></Markdown>
|
||||
</div>
|
||||
<Suspense suspensible>
|
||||
<div class="mw-[400px]">
|
||||
<div v-if="fetched === false" class="loading w-[400px] h-[150px]"></div>
|
||||
<template v-else-if="!!data">
|
||||
<div v-if="data.description" class="pb-4 pt-3 px-8">
|
||||
<span class="text-2xl font-semibold">#{{ data.tag }}</span>
|
||||
<Markdown :content="data.description"></Markdown>
|
||||
</div>
|
||||
<div class="h-100 w-100 flex flex-1 flex-col justify-center items-center" v-else>
|
||||
<div class="text-3xl font-extralight tracking-wide text-light-60 dark:text-dark-60">Fichier vide</div>
|
||||
<div class="text-lg text-light-60 dark:text-dark-60">Cette page est vide</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="h-100 w-100 flex flex-1 flex-col justify-center items-center" v-else>
|
||||
<div class="text-3xl font-extralight tracking-wide text-light-60 dark:text-dark-60">Fichier vide</div>
|
||||
<div class="text-lg text-light-60 dark:text-dark-60">Cette page est vide</div>
|
||||
<div class="text-3xl font-extralight tracking-wide text-light-60 dark:text-dark-60">Impossible d'afficher</div>
|
||||
<div class="text-lg text-light-60 dark:text-dark-60">Cette page est impossible à traiter</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="h-100 w-100 flex flex-1 flex-col justify-center items-center" v-else>
|
||||
<div class="text-3xl font-extralight tracking-wide text-light-60 dark:text-dark-60">Impossible d'afficher</div>
|
||||
<div class="text-lg text-light-60 dark:text-dark-60">Cette page est impossible à traiter</div>
|
||||
</div>
|
||||
<template #fallback><div class="loading w-[400px] h-[150px]"></div></template>
|
||||
</Suspense>
|
||||
</template>
|
||||
<template #default>
|
||||
|
||||
41
components/standard/Dialog.vue
Normal file
41
components/standard/Dialog.vue
Normal file
@@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<Teleport to="#teleports" v-if="visible">
|
||||
<div @click.self="() => !focused && hide()" class="z-[100] absolute top-0 bottom-0 left-0 right-0 bg-light-0 dark:bg-dark-0 !bg-opacity-80 flex justify-center items-center">
|
||||
<div class="relative border border-light-35 dark:border-dark-35 bg-light-0 dark:bg-dark-0 min-h-40 min-w-72">
|
||||
<span v-if="closeIcon" class="cursor-pointer absolute top-1 right-1 flex hover:opacity-75" @click="() => hide()"><Icon :width="20" :height="20" icon="icons/close" /></span>
|
||||
<div class="p-6" :class="$attrs.class">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = defineProps({
|
||||
focused: {
|
||||
type: Boolean,
|
||||
defualt: false,
|
||||
},
|
||||
closeIcon: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['show', 'hide']);
|
||||
const visible = ref(false);
|
||||
|
||||
function show()
|
||||
{
|
||||
visible.value = true;
|
||||
emit('show');
|
||||
}
|
||||
function hide()
|
||||
{
|
||||
visible.value = false;
|
||||
emit('hide');
|
||||
}
|
||||
|
||||
defineExpose({hide, show});
|
||||
</script>
|
||||
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<Teleport to="#teleports">
|
||||
<div v-show="display" :class="$attrs.class" class="absolute border-2 border-light-35 dark:border-dark-35 max-w-[550px] max-h-[450px] bg-light-0 dark:bg-dark-0 text-light-100 dark:text-dark-100" :style="pos"
|
||||
<Teleport to="#teleports" v-if="display">
|
||||
<div class="absolute border-2 border-light-35 dark:border-dark-35 max-w-[550px] max-h-[450px] bg-light-0 dark:bg-dark-0 text-light-100 dark:text-dark-100 overflow-hidden" :style="pos"
|
||||
@mouseenter="debounce(show, 250)" @mouseleave="debounce(() => { emit('beforeHide'); display = false }, 250)">
|
||||
<slot name="content"></slot>
|
||||
</div>
|
||||
</Teleport>
|
||||
<span ref="el" @mouseenter="debounce(show, 250)" @mouseleave="debounce(() => { emit('beforeHide'); display = false }, 250)">
|
||||
<span ref="el" :class="$attrs.class" @mouseenter="debounce(show, 250)" @mouseleave="debounce(() => { emit('beforeHide'); display = false }, 250)">
|
||||
<slot name="default"></slot>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
@@ -13,11 +13,9 @@ watchEffect(() => err.value = props.error);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<template></template>
|
||||
<div class="m-1">
|
||||
<div class="m-1 flex justify-between items-center gap-8">
|
||||
<label v-if="title" class="pe-4">{{ title }}</label>
|
||||
<Input @input="err = false" :class="{ 'input-has-error': !!err }" v-model="model"
|
||||
v-bind="$attrs" />
|
||||
<span v-if="err && typeof err === 'string'" class="text-light-red dark:text-dark-red block pb-2">{{ err }}</span>
|
||||
<Input class="flex-1" @input="err = false" :class="{ 'input-has-error': !!err }" v-model="model" v-bind="$attrs" />
|
||||
</div>
|
||||
<span v-if="err && typeof err === 'string'" class="text-light-red dark:text-dark-red block pb-2">{{ err }}</span>
|
||||
</template>
|
||||
@@ -58,10 +58,9 @@ onUnmounted(() => {
|
||||
<ThemeSwitch />
|
||||
<NuxtLink @click="hideNavigation" class="" :to="{ path: '/user/profile', force: true }"><div class=" hover:border-opacity-70 flex border p-px border-light-70 dark:border-dark-70">
|
||||
<Icon v-if="!loggedIn" icon="icons/user-login" :width=28 :height=28 />
|
||||
<picture v-else :width=28 :height=28 class="flex" >
|
||||
<source :src="`/users/${user?.id}/small.jpg`" :width=28 :height=28 />
|
||||
<Icon :icon="`users/unknown`" :width=28 :height=28 ></Icon>
|
||||
</picture>
|
||||
<Picture v-else :src="`/users/${user?.id}/small.jpg`" :width=28 :height=28 class="flex" >
|
||||
<Icon :icon="`icons/unknown`" :width=28 :height=28 ></Icon>
|
||||
</Picture>
|
||||
</div></NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
31
components/standard/Picture.vue
Normal file
31
components/standard/Picture.vue
Normal file
@@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<span>
|
||||
<img v-show="src && !fallback" @load="hideFallback" @error="showFallback" :src="src" :width="width" :height="height" />
|
||||
<span v-show="!src || fallback"><slot></slot></span>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = defineProps({
|
||||
src: {
|
||||
type: String,
|
||||
},
|
||||
width: {
|
||||
type: Number,
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
}
|
||||
});
|
||||
|
||||
const fallback = ref(false);
|
||||
|
||||
const showFallback = () => toggleFallback(true);
|
||||
const hideFallback = () => toggleFallback(false);
|
||||
|
||||
function toggleFallback(toggle: boolean): void
|
||||
{
|
||||
console.log("Something happened")
|
||||
fallback.value = toggle;
|
||||
}
|
||||
</script>
|
||||
27
components/standard/Upload.vue
Normal file
27
components/standard/Upload.vue
Normal file
@@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<label>
|
||||
<slot></slot>
|
||||
<input ref="input" :accept="accept" :multiple="multiple" type="file" class="hidden" @change.self="(e) => files = [...(e.target as HTMLInputElement)?.files ?? []]"/>
|
||||
</label>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = defineProps({
|
||||
accept: {
|
||||
type: String,
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
}
|
||||
});
|
||||
|
||||
const input = useTemplateRef('input');
|
||||
const files = ref<File[]>([]);
|
||||
|
||||
watch([files], () => emit('change', files.value));
|
||||
|
||||
const emit = defineEmits(['change']);
|
||||
|
||||
defineExpose({ files });
|
||||
</script>
|
||||
Reference in New Issue
Block a user