mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
feat: add UserProfilePopup to UserAvatar and update CoursesActions to show profile popups for authors
This commit is contained in:
parent
5a2732258f
commit
04c5b845fb
6 changed files with 264 additions and 9 deletions
|
|
@ -18,6 +18,7 @@ import { useContributorStatus } from '../../../../hooks/useContributorStatus'
|
||||||
|
|
||||||
interface Author {
|
interface Author {
|
||||||
user: {
|
user: {
|
||||||
|
id: string
|
||||||
user_uuid: string
|
user_uuid: string
|
||||||
avatar_image: string
|
avatar_image: string
|
||||||
first_name: string
|
first_name: string
|
||||||
|
|
@ -66,6 +67,8 @@ const AuthorInfo = ({ author, isMobile }: { author: Author, isMobile: boolean })
|
||||||
avatar_url={author.user.avatar_image ? getUserAvatarMediaDirectory(author.user.user_uuid, author.user.avatar_image) : ''}
|
avatar_url={author.user.avatar_image ? getUserAvatarMediaDirectory(author.user.user_uuid, author.user.avatar_image) : ''}
|
||||||
predefined_avatar={author.user.avatar_image ? undefined : 'empty'}
|
predefined_avatar={author.user.avatar_image ? undefined : 'empty'}
|
||||||
width={isMobile ? 60 : 100}
|
width={isMobile ? 60 : 100}
|
||||||
|
showProfilePopup={true}
|
||||||
|
userId={author.user.user_uuid}
|
||||||
/>
|
/>
|
||||||
<div className="md:-space-y-2">
|
<div className="md:-space-y-2">
|
||||||
<div className="text-[12px] text-neutral-400 font-semibold">Author</div>
|
<div className="text-[12px] text-neutral-400 font-semibold">Author</div>
|
||||||
|
|
@ -115,6 +118,8 @@ const MultipleAuthors = ({ authors, isMobile }: { authors: Author[], isMobile: b
|
||||||
avatar_url={author.user.avatar_image ? getUserAvatarMediaDirectory(author.user.user_uuid, author.user.avatar_image) : ''}
|
avatar_url={author.user.avatar_image ? getUserAvatarMediaDirectory(author.user.user_uuid, author.user.avatar_image) : ''}
|
||||||
predefined_avatar={author.user.avatar_image ? undefined : 'empty'}
|
predefined_avatar={author.user.avatar_image ? undefined : 'empty'}
|
||||||
width={avatarSize}
|
width={avatarSize}
|
||||||
|
showProfilePopup={true}
|
||||||
|
userId={author.user.id}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { getUriWithOrg } from '@services/config/config'
|
||||||
import { useParams } from 'next/navigation'
|
import { useParams } from 'next/navigation'
|
||||||
import { getUserAvatarMediaDirectory } from '@services/media/media'
|
import { getUserAvatarMediaDirectory } from '@services/media/media'
|
||||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
import UserProfilePopup from './UserProfilePopup'
|
||||||
|
|
||||||
type UserAvatarProps = {
|
type UserAvatarProps = {
|
||||||
width?: number
|
width?: number
|
||||||
|
|
@ -13,6 +14,8 @@ type UserAvatarProps = {
|
||||||
borderColor?: string
|
borderColor?: string
|
||||||
predefined_avatar?: 'ai' | 'empty'
|
predefined_avatar?: 'ai' | 'empty'
|
||||||
backgroundColor?: 'bg-white' | 'bg-gray-100'
|
backgroundColor?: 'bg-white' | 'bg-gray-100'
|
||||||
|
showProfilePopup?: boolean
|
||||||
|
userId?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function UserAvatar(props: UserAvatarProps) {
|
function UserAvatar(props: UserAvatarProps) {
|
||||||
|
|
@ -69,7 +72,7 @@ function UserAvatar(props: UserAvatarProps) {
|
||||||
return getUriWithOrg(params.orgslug, '/empty_avatar.png')
|
return getUriWithOrg(params.orgslug, '/empty_avatar.png')
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
const avatarImage = (
|
||||||
<img
|
<img
|
||||||
alt="User Avatar"
|
alt="User Avatar"
|
||||||
width={props.width ?? 50}
|
width={props.width ?? 50}
|
||||||
|
|
@ -88,6 +91,16 @@ function UserAvatar(props: UserAvatarProps) {
|
||||||
`}
|
`}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (props.showProfilePopup && props.userId) {
|
||||||
|
return (
|
||||||
|
<UserProfilePopup userId={props.userId}>
|
||||||
|
{avatarImage}
|
||||||
|
</UserProfilePopup>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return avatarImage
|
||||||
}
|
}
|
||||||
|
|
||||||
export default UserAvatar
|
export default UserAvatar
|
||||||
|
|
|
||||||
159
apps/web/components/Objects/UserProfilePopup.tsx
Normal file
159
apps/web/components/Objects/UserProfilePopup.tsx
Normal file
|
|
@ -0,0 +1,159 @@
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { HoverCard, HoverCardContent, HoverCardTrigger } from "@/components/ui/hover-card"
|
||||||
|
import { MapPin, Building2, Globe, Briefcase, GraduationCap, Link, Users, Calendar, Lightbulb, Loader2, ExternalLink } from 'lucide-react'
|
||||||
|
import { getUser } from '@services/users/users'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
import { Badge } from '@/components/ui/badge'
|
||||||
|
import { useRouter } from 'next/navigation'
|
||||||
|
|
||||||
|
type UserProfilePopupProps = {
|
||||||
|
children: React.ReactNode
|
||||||
|
userId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserData = {
|
||||||
|
first_name: string
|
||||||
|
last_name: string
|
||||||
|
username: string
|
||||||
|
bio?: string
|
||||||
|
avatar_image?: string
|
||||||
|
details?: {
|
||||||
|
[key: string]: {
|
||||||
|
id: string
|
||||||
|
label: string
|
||||||
|
icon: string
|
||||||
|
text: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ICON_MAP = {
|
||||||
|
'briefcase': Briefcase,
|
||||||
|
'graduation-cap': GraduationCap,
|
||||||
|
'map-pin': MapPin,
|
||||||
|
'building-2': Building2,
|
||||||
|
'speciality': Lightbulb,
|
||||||
|
'globe': Globe,
|
||||||
|
'link': Link,
|
||||||
|
'users': Users,
|
||||||
|
'calendar': Calendar,
|
||||||
|
} as const
|
||||||
|
|
||||||
|
const UserProfilePopup = ({ children, userId }: UserProfilePopupProps) => {
|
||||||
|
const session = useLHSession() as any
|
||||||
|
const router = useRouter()
|
||||||
|
const [userData, setUserData] = useState<UserData | null>(null)
|
||||||
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
const [error, setError] = useState<string | null>(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchUserData = async () => {
|
||||||
|
if (!userId) return
|
||||||
|
|
||||||
|
setIsLoading(true)
|
||||||
|
setError(null)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = await getUser(userId, session?.data?.tokens?.access_token)
|
||||||
|
setUserData(data)
|
||||||
|
} catch (err) {
|
||||||
|
setError('Failed to load user data')
|
||||||
|
console.error('Error fetching user data:', err)
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchUserData()
|
||||||
|
}, [userId, session?.data?.tokens?.access_token])
|
||||||
|
|
||||||
|
const IconComponent = ({ iconName }: { iconName: string }) => {
|
||||||
|
const IconElement = ICON_MAP[iconName as keyof typeof ICON_MAP]
|
||||||
|
if (!IconElement) return null
|
||||||
|
return <IconElement className="w-4 h-4 text-gray-500" />
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<HoverCard openDelay={100} closeDelay={150}>
|
||||||
|
<HoverCardTrigger asChild>
|
||||||
|
{children}
|
||||||
|
</HoverCardTrigger>
|
||||||
|
<HoverCardContent className="w-96 bg-white/95 backdrop-blur-md p-0 nice-shadow">
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="flex items-center justify-center py-8">
|
||||||
|
<Loader2 className="w-6 h-6 animate-spin text-gray-400" />
|
||||||
|
</div>
|
||||||
|
) : error ? (
|
||||||
|
<div className="text-sm text-red-500 p-4">{error}</div>
|
||||||
|
) : userData ? (
|
||||||
|
<div>
|
||||||
|
{/* Header with Avatar and Name */}
|
||||||
|
<div className="relative">
|
||||||
|
{/* Background gradient */}
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-b from-gray-100/30 to-transparent h-28 rounded-t-lg" />
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div className="relative px-5 pt-5 pb-4">
|
||||||
|
<div className="flex items-start gap-4">
|
||||||
|
{/* Avatar */}
|
||||||
|
<div className="flex-shrink-0">
|
||||||
|
<div className="rounded-full">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Name, Bio, and Button */}
|
||||||
|
<div className="flex-1 min-w-0">
|
||||||
|
<div className="flex items-center justify-between gap-2">
|
||||||
|
<div className="flex items-center gap-2 min-w-0">
|
||||||
|
<h4 className="font-semibold text-gray-900 truncate">
|
||||||
|
{userData.first_name} {userData.last_name}
|
||||||
|
</h4>
|
||||||
|
{userData.username && (
|
||||||
|
<Badge variant="outline" className="text-xs font-normal text-gray-500 px-2 truncate">
|
||||||
|
@{userData.username}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className="h-6 w-6 text-gray-600 hover:text-gray-900 flex-shrink-0"
|
||||||
|
onClick={() => router.push(`/profile/${userId}`)}
|
||||||
|
>
|
||||||
|
<ExternalLink className="w-4 h-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
{userData.bio && (
|
||||||
|
<p className="text-sm text-gray-500 mt-1.5 line-clamp-4 leading-normal">
|
||||||
|
{userData.bio}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Details */}
|
||||||
|
{userData.details && Object.values(userData.details).length > 0 && (
|
||||||
|
<div className="px-5 pb-4 space-y-2.5 border-t border-gray-100 pt-3.5">
|
||||||
|
{Object.values(userData.details).map((detail) => (
|
||||||
|
<div key={detail.id} className="flex items-center gap-2.5">
|
||||||
|
<IconComponent iconName={detail.icon} />
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<span className="text-xs text-gray-500">{detail.label}</span>
|
||||||
|
<span className="text-sm text-gray-700">{detail.text}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</HoverCardContent>
|
||||||
|
</HoverCard>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UserProfilePopup
|
||||||
44
apps/web/components/ui/hover-card.tsx
Normal file
44
apps/web/components/ui/hover-card.tsx
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
"use client"
|
||||||
|
|
||||||
|
import * as React from "react"
|
||||||
|
import * as HoverCardPrimitive from "@radix-ui/react-hover-card"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function HoverCard({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof HoverCardPrimitive.Root>) {
|
||||||
|
return <HoverCardPrimitive.Root data-slot="hover-card" {...props} />
|
||||||
|
}
|
||||||
|
|
||||||
|
function HoverCardTrigger({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof HoverCardPrimitive.Trigger>) {
|
||||||
|
return (
|
||||||
|
<HoverCardPrimitive.Trigger data-slot="hover-card-trigger" {...props} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function HoverCardContent({
|
||||||
|
className,
|
||||||
|
align = "center",
|
||||||
|
sideOffset = 4,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof HoverCardPrimitive.Content>) {
|
||||||
|
return (
|
||||||
|
<HoverCardPrimitive.Portal data-slot="hover-card-portal">
|
||||||
|
<HoverCardPrimitive.Content
|
||||||
|
data-slot="hover-card-content"
|
||||||
|
align={align}
|
||||||
|
sideOffset={sideOffset}
|
||||||
|
className={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 origin-(--radix-hover-card-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</HoverCardPrimitive.Portal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { HoverCard, HoverCardTrigger, HoverCardContent }
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
"@radix-ui/react-dialog": "^1.1.6",
|
"@radix-ui/react-dialog": "^1.1.6",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
||||||
"@radix-ui/react-form": "^0.0.3",
|
"@radix-ui/react-form": "^0.0.3",
|
||||||
|
"@radix-ui/react-hover-card": "^1.1.6",
|
||||||
"@radix-ui/react-icons": "^1.3.2",
|
"@radix-ui/react-icons": "^1.3.2",
|
||||||
"@radix-ui/react-label": "^2.1.2",
|
"@radix-ui/react-label": "^2.1.2",
|
||||||
"@radix-ui/react-select": "^2.1.6",
|
"@radix-ui/react-select": "^2.1.6",
|
||||||
|
|
|
||||||
49
apps/web/pnpm-lock.yaml
generated
49
apps/web/pnpm-lock.yaml
generated
|
|
@ -39,6 +39,9 @@ importers:
|
||||||
'@radix-ui/react-form':
|
'@radix-ui/react-form':
|
||||||
specifier: ^0.0.3
|
specifier: ^0.0.3
|
||||||
version: 0.0.3(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
version: 0.0.3(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
'@radix-ui/react-hover-card':
|
||||||
|
specifier: ^1.1.6
|
||||||
|
version: 1.1.6(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
'@radix-ui/react-icons':
|
'@radix-ui/react-icons':
|
||||||
specifier: ^1.3.2
|
specifier: ^1.3.2
|
||||||
version: 1.3.2(react@19.0.0)
|
version: 1.3.2(react@19.0.0)
|
||||||
|
|
@ -802,6 +805,19 @@ packages:
|
||||||
'@types/react-dom':
|
'@types/react-dom':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-hover-card@1.1.6':
|
||||||
|
resolution: {integrity: sha512-E4ozl35jq0VRlrdc4dhHrNSV0JqBb4Jy73WAhBEK7JoYnQ83ED5r0Rb/XdVKw89ReAJN38N492BAPBZQ57VmqQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': 19.0.10
|
||||||
|
'@types/react-dom': 19.0.4
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@radix-ui/react-icons@1.3.2':
|
'@radix-ui/react-icons@1.3.2':
|
||||||
resolution: {integrity: sha512-fyQIhGDhzfc9pK2kH6Pl9c4BDJGfMkPqkyIgYDthyNYoNg3wVhoJMMh19WS4Up/1KMPFVpNsT2q3WmXn2N1m6g==}
|
resolution: {integrity: sha512-fyQIhGDhzfc9pK2kH6Pl9c4BDJGfMkPqkyIgYDthyNYoNg3wVhoJMMh19WS4Up/1KMPFVpNsT2q3WmXn2N1m6g==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|
@ -4007,6 +4023,23 @@ snapshots:
|
||||||
'@types/react': 19.0.10
|
'@types/react': 19.0.10
|
||||||
'@types/react-dom': 19.0.4(@types/react@19.0.10)
|
'@types/react-dom': 19.0.4(@types/react@19.0.10)
|
||||||
|
|
||||||
|
'@radix-ui/react-hover-card@1.1.6(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/primitive': 1.1.1
|
||||||
|
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.10)(react@19.0.0)
|
||||||
|
'@radix-ui/react-context': 1.1.1(@types/react@19.0.10)(react@19.0.0)
|
||||||
|
'@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
'@radix-ui/react-popper': 1.2.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
'@radix-ui/react-portal': 1.1.4(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
'@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
'@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.10)(react@19.0.0)
|
||||||
|
react: 19.0.0
|
||||||
|
react-dom: 19.0.0(react@19.0.0)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.0.10
|
||||||
|
'@types/react-dom': 19.0.4(@types/react@19.0.10)
|
||||||
|
|
||||||
'@radix-ui/react-icons@1.3.2(react@19.0.0)':
|
'@radix-ui/react-icons@1.3.2(react@19.0.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 19.0.0
|
react: 19.0.0
|
||||||
|
|
@ -5365,8 +5398,8 @@ snapshots:
|
||||||
'@typescript-eslint/parser': 8.28.0(eslint@8.57.1)(typescript@5.4.4)
|
'@typescript-eslint/parser': 8.28.0(eslint@8.57.1)(typescript@5.4.4)
|
||||||
eslint: 8.57.1
|
eslint: 8.57.1
|
||||||
eslint-import-resolver-node: 0.3.9
|
eslint-import-resolver-node: 0.3.9
|
||||||
eslint-import-resolver-typescript: 3.10.0(eslint-plugin-import@2.31.0)(eslint@8.57.1)
|
eslint-import-resolver-typescript: 3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.28.0(eslint@8.57.1)(typescript@5.4.4))(eslint@8.57.1))(eslint@8.57.1)
|
||||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.28.0(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-typescript@3.10.0)(eslint@8.57.1)
|
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.28.0(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.28.0(eslint@8.57.1)(typescript@5.4.4))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
|
||||||
eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1)
|
eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1)
|
||||||
eslint-plugin-react: 7.37.4(eslint@8.57.1)
|
eslint-plugin-react: 7.37.4(eslint@8.57.1)
|
||||||
eslint-plugin-react-hooks: 5.2.0(eslint@8.57.1)
|
eslint-plugin-react-hooks: 5.2.0(eslint@8.57.1)
|
||||||
|
|
@ -5385,7 +5418,7 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0)(eslint@8.57.1):
|
eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.28.0(eslint@8.57.1)(typescript@5.4.4))(eslint@8.57.1))(eslint@8.57.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nolyfill/is-core-module': 1.0.39
|
'@nolyfill/is-core-module': 1.0.39
|
||||||
debug: 4.4.0
|
debug: 4.4.0
|
||||||
|
|
@ -5396,22 +5429,22 @@ snapshots:
|
||||||
tinyglobby: 0.2.12
|
tinyglobby: 0.2.12
|
||||||
unrs-resolver: 1.3.2
|
unrs-resolver: 1.3.2
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.28.0(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-typescript@3.10.0)(eslint@8.57.1)
|
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.28.0(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.28.0(eslint@8.57.1)(typescript@5.4.4))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.28.0(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1):
|
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.28.0(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.28.0(eslint@8.57.1)(typescript@5.4.4))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 3.2.7
|
debug: 3.2.7
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@typescript-eslint/parser': 8.28.0(eslint@8.57.1)(typescript@5.4.4)
|
'@typescript-eslint/parser': 8.28.0(eslint@8.57.1)(typescript@5.4.4)
|
||||||
eslint: 8.57.1
|
eslint: 8.57.1
|
||||||
eslint-import-resolver-node: 0.3.9
|
eslint-import-resolver-node: 0.3.9
|
||||||
eslint-import-resolver-typescript: 3.10.0(eslint-plugin-import@2.31.0)(eslint@8.57.1)
|
eslint-import-resolver-typescript: 3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.28.0(eslint@8.57.1)(typescript@5.4.4))(eslint@8.57.1))(eslint@8.57.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.28.0(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-typescript@3.10.0)(eslint@8.57.1):
|
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.28.0(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.28.0(eslint@8.57.1)(typescript@5.4.4))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rtsao/scc': 1.1.0
|
'@rtsao/scc': 1.1.0
|
||||||
array-includes: 3.1.8
|
array-includes: 3.1.8
|
||||||
|
|
@ -5422,7 +5455,7 @@ snapshots:
|
||||||
doctrine: 2.1.0
|
doctrine: 2.1.0
|
||||||
eslint: 8.57.1
|
eslint: 8.57.1
|
||||||
eslint-import-resolver-node: 0.3.9
|
eslint-import-resolver-node: 0.3.9
|
||||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.28.0(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1)
|
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.28.0(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.28.0(eslint@8.57.1)(typescript@5.4.4))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
|
||||||
hasown: 2.0.2
|
hasown: 2.0.2
|
||||||
is-core-module: 2.16.1
|
is-core-module: 2.16.1
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue