Add sync, Tree, Markdown, content editor.

This commit is contained in:
2024-11-10 15:41:47 +01:00
parent 41951d7603
commit 721e7ff3db
32 changed files with 658 additions and 124 deletions

View File

@@ -1,6 +1,6 @@
<template>
<DialogRoot v-if="!priority">
<DialogTrigger asChild><Button>{{ label }}</Button></DialogTrigger>
<DialogRoot v-if="!priority" v-model="model">
<DialogTrigger asChild><Button v-if="!!label">{{ label }}</Button><slot name="trigger" /></DialogTrigger>
<DialogPortal v-if="!disabled">
<DialogOverlay class="bg-light-0 dark:bg-dark-0 opacity-70 fixed inset-0 z-40" />
<DialogContent class="data-[state=open]:animate-contentShow fixed top-[50%] left-[50%] max-h-[85vh] w-[90vw] max-w-[450px] translate-x-[-50%] translate-y-[-50%] bg-light-10 dark:bg-dark-10 border border-light-30 dark:border-dark-30 p-6 z-50 text-light-100 dark:text-dark-100">
@@ -13,8 +13,8 @@
</DialogContent>
</DialogPortal>
</DialogRoot>
<AlertDialogRoot v-else>
<AlertDialogTrigger asChild><Button>{{ label }}</Button></AlertDialogTrigger>
<AlertDialogRoot v-else v-model="model">
<AlertDialogTrigger asChild><Button v-if="!!label">{{ label }}</Button><slot name="trigger" /></AlertDialogTrigger>
<AlertDialogPortal v-if="!disabled">
<AlertDialogOverlay class="bg-light-0 dark:bg-dark-0 opacity-70 fixed inset-0 z-40" />
<AlertDialogContent class="data-[state=open]:animate-contentShow fixed top-[50%] left-[50%] max-h-[85vh] w-[90vw] max-w-[450px] translate-x-[-50%] translate-y-[-50%] bg-light-10 dark:bg-dark-10 border border-light-30 dark:border-dark-30 p-6 z-50 text-light-100 dark:text-dark-100">
@@ -35,4 +35,5 @@ const { label, title, description, priority = false, disabled = false, iconClose
disabled?: boolean
iconClose?: boolean
}>();
const model = defineModel();
</script>

View File

@@ -6,8 +6,8 @@
<ToastClose v-if="toast.closeable" aria-label="Close" class="text-xl -translate-y-2 translate-x-4 cursor-pointer"><span aria-hidden>×</span></ToastClose>
<ToastDescription v-if="toast.content" class="text-sm col-span-8 text-light-70 dark:text-dark-70" asChild><span>{{ toast.content }}</span></ToastDescription>
</div>
<TimerProgress v-if="toast.timer" shape="thin" :delay="toast.duration" class="mb-0 mt-0 w-full group-data-[type=error]:bg-light-red dark:group-data-[type=error]:bg-dark-red group-data-[type=error]:bg-opacity-50 dark:group-data-[type=error]:bg-opacity-50 group-data-[type=error]:*:bg-light-red dark:group-data-[type=error]:*:bg-dark-red
group-data-[type=success]:bg-light-green dark:group-data-[type=success]:bg-dark-green group-data-[type=success]:bg-opacity-50 dark:group-data-[type=success]:bg-opacity-50 group-data-[type=success]:*:bg-light-green dark:group-data-[type=success]:*:bg-dark-green" @finish="() => tryClose(toast, false)" />
<TimerProgress v-if="toast.timer" shape="thin" :delay="toast.duration" class="mb-0 mt-0 w-full group-data-[type=error]:bg-light-redBack dark:group-data-[type=error]:bg-dark-redBack group-data-[type=error]:*:bg-light-red dark:group-data-[type=error]:*:bg-dark-red
group-data-[type=success]:bg-light-greenBack dark:group-data-[type=success]:bg-dark-greenBack group-data-[type=success]:*:bg-light-green dark:group-data-[type=success]:*:bg-dark-green" @finish="() => tryClose(toast, false)" />
</ToastRoot>
<ToastViewport class="fixed bottom-0 right-0 flex flex-col p-6 gap-2 max-w-[512px] z-50 outline-none min-w-72" />
@@ -37,16 +37,14 @@ function tryClose(config: ExtraToastConfig, state: boolean)
.ToastRoot[data-type='error'] {
@apply border-light-red;
@apply dark:border-dark-red;
@apply bg-light-red;
@apply dark:bg-dark-red;
@apply bg-opacity-15;
@apply bg-light-redBack;
@apply dark:bg-dark-redBack;
}
.ToastRoot[data-type='success'] {
@apply border-light-green;
@apply dark:border-dark-green;
@apply bg-light-green;
@apply dark:bg-dark-green;
@apply bg-opacity-15;
@apply bg-light-greenBack;
@apply dark:bg-dark-greenBack;
}
.ToastRoot[data-state='open'] {
animation: slideIn .15s cubic-bezier(0.16, 1, 0.3, 1);

View File

@@ -1,3 +1,25 @@
<template>
</template>
<TreeRoot v-slot="{ flattenItems }" class="list-none select-none text-light-100 dark:text-dark-100 p-2 font-medium xl:text-base text-sm cursor-pointer" :items="model" :get-key="(item) => item.link ?? item.label">
<TreeItem v-for="item in flattenItems" v-slot="{ isExpanded }" :key="item._id" :style="{ 'padding-left': `${item.level - 0.5}em` }" v-bind="item.bind" class="flex items-center px-2 outline-none relative">
<NuxtLink :href="item.value.link && !item.hasChildren ? { name: 'explore-path', params: { path: item.value.link } } : undefined" no-prefetch class="flex flex-1 items-center" active-class="text-accent-blue">
<Icon v-if="item.hasChildren" icon="radix-icons:chevron-right" :class="{ 'rotate-90': isExpanded }" class="h-4 w-4 transition-transform absolute" :style="{ 'left': `${item.level - 1}em` }" />
<div class="pl-3 py-1 flex-1 truncate border-light-35 dark:border-dark-35 hover:border-accent-blue" :class="{ 'border-s': !item.hasChildren }" :data-tag="item.value.tag">
{{ item.value.label }}
</div>
</NuxtLink>
</TreeItem>
</TreeRoot>
</template>
<script setup lang="ts">
import { Icon } from '@iconify/vue/dist/iconify.js';
interface TreeItem
{
label: string
link?: string
tag?: string
children?: TreeItem[]
}
const model = defineModel<TreeItem[]>();
</script>