33import SearchIcon from "@/app/conf/_design-system/pixelarticons/search.svg?svgr"
44import type { ResourceMetadata } from "@/resources/types"
55import clsx from "clsx"
6- import { useState , useTransition } from "react"
6+ import { ReactNode , useState , useTransition } from "react"
77
88function fuzzyMatch ( text : string , query : string ) : boolean {
99 const lowerText = text . toLowerCase ( )
@@ -23,30 +23,33 @@ function matchesSearch(resource: ResourceMetadata, query: string): boolean {
2323 resource . title ,
2424 resource . url ,
2525 resource . author ,
26- resource . kind ,
2726 resource . description ,
2827 ...resource . tags ,
2928 ] . join ( " " )
3029 return fuzzyMatch ( searchable , query )
3130}
3231
3332type TooltipState = {
34- content : string
33+ content : ReactNode
3534 x : number
3635 y : number
3736} | null
3837
3938type CellProps = {
40- children : string | undefined
41- onMouseMove : ( e : React . MouseEvent , content : string ) => void
39+ children : ReactNode | undefined
40+ onMouseMove : ( e : React . MouseEvent , content : ReactNode ) => void
4241 onMouseLeave : ( ) => void
42+ className ?: string
4343}
4444
45- function Cell ( { children, onMouseMove, onMouseLeave } : CellProps ) {
45+ function Cell ( { children, onMouseMove, onMouseLeave, className } : CellProps ) {
4646 if ( ! children ) return < td className = "px-2 py-1" />
4747 return (
4848 < td
49- className = "max-w-[200px] cursor-copy truncate px-2 py-1"
49+ className = { clsx (
50+ "max-w-[200px] cursor-copy truncate px-2 py-1" ,
51+ className ,
52+ ) }
5053 onMouseMove = { e => onMouseMove ( e , children ) }
5154 onMouseLeave = { onMouseLeave }
5255 >
@@ -62,13 +65,13 @@ type ResourcesTableProps = {
6265export function ResourcesTable ( { resources } : ResourcesTableProps ) {
6366 const [ search , setSearch ] = useState ( "" )
6467 const [ query , setQuery ] = useState ( "" )
65- const [ isPending , startTransition ] = useTransition ( )
68+ const [ _isPending , startTransition ] = useTransition ( )
6669 const [ tooltip , setTooltip ] = useState < TooltipState > ( null )
6770 const [ copiedIndex , setCopiedIndex ] = useState < number | null > ( null )
6871
6972 const filtered = resources . filter ( r => matchesSearch ( r , query ) )
7073
71- const handleMouseMove = ( e : React . MouseEvent , content : string ) => {
74+ const handleMouseMove = ( e : React . MouseEvent , content : ReactNode ) => {
7275 setTooltip ( { content, x : e . clientX , y : e . clientY } )
7376 }
7477
@@ -99,76 +102,86 @@ export function ResourcesTable({ resources }: ResourcesTableProps) {
99102 className = "w-full bg-transparent font-mono text-sm placeholder:text-neu-600 focus:outline-none dark:placeholder:text-neu-400"
100103 />
101104 </ label >
102- < table className = "w-full font-mono text-sm" >
103- < thead className = "typography-menu text-pri-base dark:text-pri-light" >
104- < tr >
105- < th className = "whitespace-nowrap px-2 py-1 text-left" > Title</ th >
106- < th className = "whitespace-nowrap px-2 py-1 text-left" > URL</ th >
107- < th className = "whitespace-nowrap px-2 py-1 text-left" > Author</ th >
108- < th className = "whitespace-nowrap px-2 py-1 text-left" > Kind</ th >
109- < th className = "whitespace-nowrap px-2 py-1 text-left" >
110- Description
111- </ th >
112- < th className = "whitespace-nowrap px-2 py-1 text-left" > Duration</ th >
113- < th className = "whitespace-nowrap px-2 py-1 text-left" > Tags</ th >
114- </ tr >
115- </ thead >
116- < tbody >
117- { filtered . map ( ( resource , i ) => (
118- < tr
119- key = { i }
120- className = { clsx (
121- "cursor-pointer border-t border-neu-200 transition-colors hover:bg-neu-50/50 hover:duration-0" ,
122- copiedIndex === i && "bg-green-100 dark:bg-green-900/30" ,
123- ) }
124- onClick = { ( ) => handleRowClick ( resource , i ) }
125- >
126- < Cell
127- onMouseMove = { handleMouseMove }
128- onMouseLeave = { handleMouseLeave }
129- >
130- { resource . title }
131- </ Cell >
132- < Cell
133- onMouseMove = { handleMouseMove }
134- onMouseLeave = { handleMouseLeave }
135- >
136- { resource . url }
137- </ Cell >
138- < Cell
139- onMouseMove = { handleMouseMove }
140- onMouseLeave = { handleMouseLeave }
141- >
142- { resource . author }
143- </ Cell >
144- < Cell
145- onMouseMove = { handleMouseMove }
146- onMouseLeave = { handleMouseLeave }
147- >
148- { resource . kind }
149- </ Cell >
150- < Cell
151- onMouseMove = { handleMouseMove }
152- onMouseLeave = { handleMouseLeave }
153- >
154- { resource . description }
155- </ Cell >
156- < Cell
157- onMouseMove = { handleMouseMove }
158- onMouseLeave = { handleMouseLeave }
159- >
160- { resource . duration }
161- </ Cell >
162- < Cell
163- onMouseMove = { handleMouseMove }
164- onMouseLeave = { handleMouseLeave }
165- >
166- { resource . tags . join ( ", " ) }
167- </ Cell >
105+ < div className = "max-w-full overflow-x-auto" >
106+ < table className = "w-full font-mono text-sm" >
107+ < thead className = "typography-menu text-pri-base dark:text-pri-light" >
108+ < tr >
109+ < th className = "whitespace-nowrap px-2 py-1 text-left font-medium" >
110+ Title
111+ </ th >
112+ < th className = "whitespace-nowrap px-2 py-1 text-left font-medium" >
113+ URL
114+ </ th >
115+ < th className = "whitespace-nowrap px-2 py-1 text-left font-medium" >
116+ Tags
117+ </ th >
118+ < th className = "whitespace-nowrap px-2 py-1 text-left font-medium" >
119+ Author
120+ </ th >
121+ < th className = "whitespace-nowrap px-2 py-1 text-left font-medium" >
122+ Description
123+ </ th >
124+ < th className = "whitespace-nowrap px-2 py-1 text-left font-medium" >
125+ Duration
126+ </ th >
168127 </ tr >
169- ) ) }
170- </ tbody >
171- </ table >
128+ </ thead >
129+ < tbody >
130+ { filtered . map ( ( resource , i ) => (
131+ < tr
132+ key = { i }
133+ className = { clsx (
134+ "cursor-pointer border-t border-neu-200 transition-colors hover:bg-neu-50/50 hover:duration-0" ,
135+ copiedIndex === i && "bg-green-100 dark:bg-green-900/30" ,
136+ ) }
137+ onClick = { ( ) => handleRowClick ( resource , i ) }
138+ >
139+ < Cell
140+ onMouseMove = { handleMouseMove }
141+ onMouseLeave = { handleMouseLeave }
142+ >
143+ { resource . title }
144+ </ Cell >
145+ < Cell
146+ onMouseMove = { handleMouseMove }
147+ onMouseLeave = { handleMouseLeave }
148+ >
149+ { resource . url }
150+ </ Cell >
151+ < Cell
152+ onMouseMove = { handleMouseMove }
153+ onMouseLeave = { handleMouseLeave }
154+ className = "flex gap-1"
155+ >
156+ { resource . tags . map ( tag => (
157+ < span key = { tag } className = "border border-neu-50 text-xs" >
158+ { tag }
159+ </ span >
160+ ) ) }
161+ </ Cell >
162+ < Cell
163+ onMouseMove = { handleMouseMove }
164+ onMouseLeave = { handleMouseLeave }
165+ >
166+ { resource . author }
167+ </ Cell >
168+ < Cell
169+ onMouseMove = { handleMouseMove }
170+ onMouseLeave = { handleMouseLeave }
171+ >
172+ { resource . description }
173+ </ Cell >
174+ < Cell
175+ onMouseMove = { handleMouseMove }
176+ onMouseLeave = { handleMouseLeave }
177+ >
178+ { resource . duration }
179+ </ Cell >
180+ </ tr >
181+ ) ) }
182+ </ tbody >
183+ </ table >
184+ </ div >
172185 { tooltip && (
173186 < div
174187 className = "pointer-events-none fixed z-50 max-w-md border border-neu-50 bg-neu-0/50 px-2 py-1 font-mono text-sm shadow-lg backdrop-blur-md"
0 commit comments