[Feature] Better AnimeCard tooltip, fix watch endpoint #3
@ -1,4 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { Toaster } from 'vue-sonner';
|
||||||
import TooltipProvider from './components/ui/tooltip/TooltipProvider.vue';
|
import TooltipProvider from './components/ui/tooltip/TooltipProvider.vue';
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Result } from '~/openapi/search';
|
import type { Result } from '~/openapi/search';
|
||||||
import { Vibrant } from "node-vibrant/browser";
|
import { Vibrant } from "node-vibrant/browser";
|
||||||
import Tooltip from '../tooltip/Tooltip.vue';
|
import { HoverCard, HoverCardContent, HoverCardTrigger } from '../hover-card';
|
||||||
import TooltipTrigger from '../tooltip/TooltipTrigger.vue';
|
import { Icon } from '@iconify/vue'
|
||||||
import TooltipContent from '../tooltip/TooltipContent.vue';
|
|
||||||
|
|
||||||
interface AnimeItemProp {
|
interface AnimeItemProp {
|
||||||
item: Result
|
item: Result
|
||||||
@ -29,8 +29,8 @@ onMounted(async () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Tooltip>
|
<HoverCard>
|
||||||
<TooltipTrigger as-child>
|
<HoverCardTrigger as-child>
|
||||||
<NuxtLink :to="`/anime/${props.item.id}`" class="w-full group">
|
<NuxtLink :to="`/anime/${props.item.id}`" class="w-full group">
|
||||||
<div v-if="props.item.material_data?.anime_poster_url"
|
<div v-if="props.item.material_data?.anime_poster_url"
|
||||||
:style="{ 'background-image': 'url(' + props.item.material_data.anime_poster_url + ')', '--tw-shadow-color': 'rgb(' + vibrantColor + ')' }"
|
:style="{ 'background-image': 'url(' + props.item.material_data.anime_poster_url + ')', '--tw-shadow-color': 'rgb(' + vibrantColor + ')' }"
|
||||||
@ -38,7 +38,7 @@ onMounted(async () => {
|
|||||||
class="flex items-end justify-end p-2 rounded-md bg-cover bg-center bg-no-repeat h-96 group-hover:shadow transition-shadow">
|
class="flex items-end justify-end p-2 rounded-md bg-cover bg-center bg-no-repeat h-96 group-hover:shadow transition-shadow">
|
||||||
<div
|
<div
|
||||||
class="flex items-center px-2 py-0.5 backdrop-blur-none bg-primary/75 text-background/80 rounded-sm text-xs ">
|
class="flex items-center px-2 py-0.5 backdrop-blur-none bg-primary/75 text-background/80 rounded-sm text-xs ">
|
||||||
<Icon name="gg:play-list" />
|
<Icon icon="gg:play-list" />
|
||||||
{{ props.item.material_data?.episodes_total }}
|
{{ props.item.material_data?.episodes_total }}
|
||||||
episode
|
episode
|
||||||
</div>
|
</div>
|
||||||
@ -49,13 +49,24 @@ onMounted(async () => {
|
|||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</TooltipTrigger>
|
</HoverCardTrigger>
|
||||||
<TooltipContent side="right">
|
<HoverCardContent>
|
||||||
<div class="max-w-96">
|
<div class="flex justify-between space-x-4">
|
||||||
<span class="break-words">
|
<div class="space-y-1">
|
||||||
{{ props.item.material_data?.description }}
|
<h3 class="text-2xl font-semibold tracking-tight">
|
||||||
</span>
|
{{ props.item.title }}
|
||||||
|
</h3>
|
||||||
|
<p class="text-sm">
|
||||||
|
{{ props.item.material_data?.description }}
|
||||||
|
</p>
|
||||||
|
<div class="flex items-center pt-2">
|
||||||
|
<Icon icon="lucide:calendar" class="mr-2 h-4 w-4 opacity-70" />
|
||||||
|
<span class="text-xs text-muted-foreground">
|
||||||
|
{{ props.item.material_data?.aired_at }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</TooltipContent>
|
</HoverCardContent>
|
||||||
</Tooltip>
|
</HoverCard>
|
||||||
</template>
|
</template>
|
||||||
|
17
app/components/ui/hover-card/HoverCard.vue
Normal file
17
app/components/ui/hover-card/HoverCard.vue
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { HoverCardRoot, type HoverCardRootEmits, type HoverCardRootProps, useForwardPropsEmits } from 'reka-ui'
|
||||||
|
|
||||||
|
const props = defineProps<HoverCardRootProps>()
|
||||||
|
const emits = defineEmits<HoverCardRootEmits>()
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(props, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<HoverCardRoot
|
||||||
|
data-slot="hover-card"
|
||||||
|
v-bind="forwarded"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</HoverCardRoot>
|
||||||
|
</template>
|
39
app/components/ui/hover-card/HoverCardContent.vue
Normal file
39
app/components/ui/hover-card/HoverCardContent.vue
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { HTMLAttributes } from 'vue'
|
||||||
|
import { reactiveOmit } from '@vueuse/core'
|
||||||
|
import {
|
||||||
|
HoverCardContent,
|
||||||
|
type HoverCardContentProps,
|
||||||
|
HoverCardPortal,
|
||||||
|
useForwardProps,
|
||||||
|
} from 'reka-ui'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<HoverCardContentProps & { class?: HTMLAttributes['class'] }>(),
|
||||||
|
{
|
||||||
|
sideOffset: 4,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
const delegatedProps = reactiveOmit(props, 'class')
|
||||||
|
|
||||||
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<HoverCardPortal>
|
||||||
|
<HoverCardContent
|
||||||
|
data-slot="hover-card-content"
|
||||||
|
v-bind="forwardedProps"
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-64 rounded-md border p-4 shadow-md outline-hidden',
|
||||||
|
props.class,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</HoverCardContent>
|
||||||
|
</HoverCardPortal>
|
||||||
|
</template>
|
14
app/components/ui/hover-card/HoverCardTrigger.vue
Normal file
14
app/components/ui/hover-card/HoverCardTrigger.vue
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { HoverCardTrigger, type HoverCardTriggerProps } from 'reka-ui'
|
||||||
|
|
||||||
|
const props = defineProps<HoverCardTriggerProps>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<HoverCardTrigger
|
||||||
|
data-slot="hover-card-trigger"
|
||||||
|
v-bind="props"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</HoverCardTrigger>
|
||||||
|
</template>
|
3
app/components/ui/hover-card/index.ts
Normal file
3
app/components/ui/hover-card/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export { default as HoverCard } from './HoverCard.vue'
|
||||||
|
export { default as HoverCardContent } from './HoverCardContent.vue'
|
||||||
|
export { default as HoverCardTrigger } from './HoverCardTrigger.vue'
|
@ -61,8 +61,10 @@ watchEffect(async () => {
|
|||||||
mediaHash: mediaHash as string,
|
mediaHash: mediaHash as string,
|
||||||
}
|
}
|
||||||
|
|
||||||
const videoParams: VideoParams = {
|
const videoParams: any = {
|
||||||
translationDTO: translationDto,
|
mediaType: mediaType as string,
|
||||||
|
mediaId: mediaId as string,
|
||||||
|
mediaHash: mediaHash as string,
|
||||||
episode: Number(episode as string),
|
episode: Number(episode as string),
|
||||||
quality: '360',
|
quality: '360',
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user