From 9ddf068049c58758053100b2a2450f6f8042b856 Mon Sep 17 00:00:00 2001 From: OCbwoy3 Date: Fri, 14 Feb 2025 11:59:11 +0200 Subject: [PATCH] a --- .editorconfig | 12 + .prettierrc | 5 + .../discovery/omni-recommendation/route.ts | 52 ++ app/api/thumbnails/batch/route.ts | 52 ++ app/favicon.ico | Bin 25931 -> 0 bytes app/globals.css | 108 ++- app/page.tsx | 171 ++-- bun.lockb | Bin 62008 -> 132154 bytes components.json | 21 + components/gameCard.tsx | 64 ++ components/lazyLoadedImage.tsx | 24 + components/ui/accordion.tsx | 57 ++ components/ui/alert-dialog.tsx | 141 ++++ components/ui/alert.tsx | 59 ++ components/ui/aspect-ratio.tsx | 7 + components/ui/avatar.tsx | 50 ++ components/ui/badge.tsx | 36 + components/ui/breadcrumb.tsx | 115 +++ components/ui/button.tsx | 57 ++ components/ui/calendar.tsx | 76 ++ components/ui/card.tsx | 76 ++ components/ui/carousel.tsx | 262 ++++++ components/ui/chart.tsx | 365 +++++++++ components/ui/checkbox.tsx | 30 + components/ui/collapsible.tsx | 11 + components/ui/command.tsx | 153 ++++ components/ui/context-menu.tsx | 200 +++++ components/ui/dialog.tsx | 122 +++ components/ui/drawer.tsx | 118 +++ components/ui/dropdown-menu.tsx | 201 +++++ components/ui/form.tsx | 178 ++++ components/ui/hover-card.tsx | 29 + components/ui/input-otp.tsx | 71 ++ components/ui/input.tsx | 22 + components/ui/label.tsx | 26 + components/ui/menubar.tsx | 256 ++++++ components/ui/navigation-menu.tsx | 128 +++ components/ui/pagination.tsx | 117 +++ components/ui/popover.tsx | 33 + components/ui/progress.tsx | 28 + components/ui/radio-group.tsx | 44 + components/ui/resizable.tsx | 45 ++ components/ui/scroll-area.tsx | 48 ++ components/ui/select.tsx | 159 ++++ components/ui/separator.tsx | 31 + components/ui/sheet.tsx | 140 ++++ components/ui/sidebar.tsx | 763 ++++++++++++++++++ components/ui/skeleton.tsx | 15 + components/ui/slider.tsx | 28 + components/ui/sonner.tsx | 31 + components/ui/switch.tsx | 29 + components/ui/table.tsx | 120 +++ components/ui/tabs.tsx | 55 ++ components/ui/textarea.tsx | 22 + components/ui/toast.tsx | 129 +++ components/ui/toaster.tsx | 35 + components/ui/toggle-group.tsx | 61 ++ components/ui/toggle.tsx | 45 ++ components/ui/tooltip.tsx | 32 + hooks/use-lazy-load.ts | 24 + hooks/use-mobile.tsx | 19 + hooks/use-toast.ts | 194 +++++ lib/omniRecommendation.ts | 80 ++ lib/roblox.ts | 9 + lib/thumbnailLoader.ts | 52 ++ lib/utils.ts | 6 + package.json | 47 +- public/file.svg | 1 - public/globe.svg | 1 - public/next.svg | 1 - public/vercel.svg | 1 - public/window.svg | 1 - tailwind.config.ts | 92 ++- 73 files changed, 5767 insertions(+), 126 deletions(-) create mode 100644 .editorconfig create mode 100644 .prettierrc create mode 100644 app/api/discovery/omni-recommendation/route.ts create mode 100644 app/api/thumbnails/batch/route.ts delete mode 100644 app/favicon.ico create mode 100644 components.json create mode 100644 components/gameCard.tsx create mode 100644 components/lazyLoadedImage.tsx create mode 100644 components/ui/accordion.tsx create mode 100644 components/ui/alert-dialog.tsx create mode 100644 components/ui/alert.tsx create mode 100644 components/ui/aspect-ratio.tsx create mode 100644 components/ui/avatar.tsx create mode 100644 components/ui/badge.tsx create mode 100644 components/ui/breadcrumb.tsx create mode 100644 components/ui/button.tsx create mode 100644 components/ui/calendar.tsx create mode 100644 components/ui/card.tsx create mode 100644 components/ui/carousel.tsx create mode 100644 components/ui/chart.tsx create mode 100644 components/ui/checkbox.tsx create mode 100644 components/ui/collapsible.tsx create mode 100644 components/ui/command.tsx create mode 100644 components/ui/context-menu.tsx create mode 100644 components/ui/dialog.tsx create mode 100644 components/ui/drawer.tsx create mode 100644 components/ui/dropdown-menu.tsx create mode 100644 components/ui/form.tsx create mode 100644 components/ui/hover-card.tsx create mode 100644 components/ui/input-otp.tsx create mode 100644 components/ui/input.tsx create mode 100644 components/ui/label.tsx create mode 100644 components/ui/menubar.tsx create mode 100644 components/ui/navigation-menu.tsx create mode 100644 components/ui/pagination.tsx create mode 100644 components/ui/popover.tsx create mode 100644 components/ui/progress.tsx create mode 100644 components/ui/radio-group.tsx create mode 100644 components/ui/resizable.tsx create mode 100644 components/ui/scroll-area.tsx create mode 100644 components/ui/select.tsx create mode 100644 components/ui/separator.tsx create mode 100644 components/ui/sheet.tsx create mode 100644 components/ui/sidebar.tsx create mode 100644 components/ui/skeleton.tsx create mode 100644 components/ui/slider.tsx create mode 100644 components/ui/sonner.tsx create mode 100644 components/ui/switch.tsx create mode 100644 components/ui/table.tsx create mode 100644 components/ui/tabs.tsx create mode 100644 components/ui/textarea.tsx create mode 100644 components/ui/toast.tsx create mode 100644 components/ui/toaster.tsx create mode 100644 components/ui/toggle-group.tsx create mode 100644 components/ui/toggle.tsx create mode 100644 components/ui/tooltip.tsx create mode 100644 hooks/use-lazy-load.ts create mode 100644 hooks/use-mobile.tsx create mode 100644 hooks/use-toast.ts create mode 100644 lib/omniRecommendation.ts create mode 100644 lib/roblox.ts create mode 100644 lib/thumbnailLoader.ts create mode 100644 lib/utils.ts delete mode 100644 public/file.svg delete mode 100644 public/globe.svg delete mode 100644 public/next.svg delete mode 100644 public/vercel.svg delete mode 100644 public/window.svg diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..633a125 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +indent_style = tab +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = false +insert_final_newline = false \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..1035938 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +{ + "tabWidth": 4, + "useTabs": true, + "semi": true +} diff --git a/app/api/discovery/omni-recommendation/route.ts b/app/api/discovery/omni-recommendation/route.ts new file mode 100644 index 0000000..ef15d14 --- /dev/null +++ b/app/api/discovery/omni-recommendation/route.ts @@ -0,0 +1,52 @@ +import { type NextRequest, NextResponse } from "next/server" + +export async function GET(request: NextRequest) { + const { searchParams } = new URL(request.url); + const apiUrl = "https://apis.roblox.com/discovery-api/omni-recommendation"; + + const url = `${apiUrl}?${searchParams.toString()}`; + + try { + const response = await fetch(url, { + headers: { + "User-Agent": "OCbwoy3ChanAI/1.0", + "Accept": "application/json, text/plain, */*", + "Accept-Encoding": "gzip, deflate, br, zstd", + "Content-Type": "application/json;charset=UTF-8", + "Cookie": request.headers.get("Authorization") || "", + }, + }); + + return NextResponse.json(await response.json()); + } catch (error) { + console.error("Error proxying request:", error); + return NextResponse.json({ error: "Internal Server Error" }); + } +} + +export async function POST(request: NextRequest) { + const { searchParams } = new URL(request.url); + const apiUrl = "https://apis.roblox.com/discovery-api/omni-recommendation"; + const url = `${apiUrl}?${searchParams.toString()}`; + + try { + const body = await request.json() + const response = await fetch(url, { + method: "POST", + headers: { + "User-Agent": "OCbwoy3ChanAI/1.0", + "Accept": "application/json, text/plain, */*", + "Accept-Encoding": "gzip, deflate, br, zstd", + "Content-Type": "application/json;charset=UTF-8", + "Cookie": request.headers.get("Authorization") || "", + }, + body: JSON.stringify(body), + }); + + return NextResponse.json(await response.json()); + } catch (error) { + console.error("Error proxying request:", error); + return NextResponse.json({ error: "Internal Server Error" }); + } +} + diff --git a/app/api/thumbnails/batch/route.ts b/app/api/thumbnails/batch/route.ts new file mode 100644 index 0000000..2d0a12c --- /dev/null +++ b/app/api/thumbnails/batch/route.ts @@ -0,0 +1,52 @@ +import { type NextRequest, NextResponse } from "next/server" + +export async function GET(request: NextRequest) { + const { searchParams } = new URL(request.url); + const apiUrl = "https://thumbnails.roblox.com/v1/batch"; + + const url = `${apiUrl}?${searchParams.toString()}`; + + try { + const response = await fetch(url, { + headers: { + "User-Agent": "OCbwoy3ChanAI/1.0", + "Accept": "application/json, text/plain, */*", + "Accept-Encoding": "gzip, deflate, br, zstd", + "Content-Type": "application/json;charset=UTF-8", + "Cookie": request.headers.get("Authorization") || "", + }, + }); + + return NextResponse.json(await response.json()); + } catch (error) { + console.error("Error proxying request:", error); + return NextResponse.json({ error: "Internal Server Error" }); + } +} + +export async function POST(request: NextRequest) { + const { searchParams } = new URL(request.url); + const apiUrl = "https://thumbnails.roblox.com/v1/batch"; + const url = `${apiUrl}?${searchParams.toString()}`; + + try { + const body = await request.json() + const response = await fetch(url, { + method: "POST", + headers: { + "User-Agent": "OCbwoy3ChanAI/1.0", + "Accept": "application/json, text/plain, */*", + "Accept-Encoding": "gzip, deflate, br, zstd", + "Content-Type": "application/json;charset=UTF-8", + "Cookie": request.headers.get("Authorization") || "", + }, + body: JSON.stringify(body), + }); + + return NextResponse.json(await response.json()); + } catch (error) { + console.error("Error proxying request:", error); + return NextResponse.json({ error: "Internal Server Error" }); + } +} + diff --git a/app/favicon.ico b/app/favicon.ico deleted file mode 100644 index 718d6fea4835ec2d246af9800eddb7ffb276240c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25931 zcmZQzU}Run5D);-3Je;o3=D1z3=9eiP`(HQLmn#wgMk5*ugkzNO_Bi&7#S28dgT}x z_PH@IXfQA^2!Ql4K-7U1u!2cq2o(kfhFAs$hFwq$VuQp8=~ZB0U|7Jw!0?HIf#E+I z28n^>Kx(j=W5K|{@BmE@x)~roNDW9WvKjIW3=EHm&C##7#P05^!xk!|6jLm-T&3ASEJyyYuElyPfrKwgJF;!klsj`UJxxWFaQ7T+qeJG z!Qa1s|C^ec!t}yuklx)OeaJXFI~!g5|GvIHm>y&rq!)yd#r|`0a{fPi_AK0tCr_UI zmynP^Q3JIPq!;7{3^^|^um2!7gA4(=2dW-j9Y`-I3_xLlBFD(c_%qnb&gL5G2XA(VlEp^<@s;RO_f*dQ^G97qkt7NHrS#lXPO%D}*IiGhLP zCp4X-ry~#_BnMIhQVY_9W(>((83qQ1X$%YupYhlUvKJc$=>h2lnL)C}3=9l`3=9kp z$*>pQEg&;MW|88CA_fMA-&C+0<`$4yATx<^14tcAAGK+a+4$VxPi23jyB`z|AUm+R zL7IVq;RzMP9Nlgh|1kpt1IR9PH%zC4-7q(R>_WC5R9t86WV=CaMUY-R7-T2N?hrg`z;5N>;P`*~^l75q@a4;w|2jH4 zV7&y)2HD+2Kn>U&cXxMqyN{4VdV71pdWbL=RByf{LLJyVP+Oaj-JmwDxVSi2JrU-D z>;_??)N5;N|Ns2?GhQcTWn~d%7SwGZyFp<s4i#N~i9XU_Zwr4^{z#Fz<+dr%r6 zMlD#4n3&lA$B!RlI04ir@bvTqt0BRDklmm>0LlwQ>&2EI*RNmyAJn%X!ETV9AiF_j z0H`b=+I~JgUUcqS%@r0kd2%lNyu-==7Q`5*$u*=x&TxsAj=bE zZ``=?|C={&{*#d3U}l2qI#8VlvKxj$bs|ijDB9TAm{1*q%N&qhFneLN6axbTsBM5t z54FTWZ5(Xv50E=RZ6i<{iCT7{n*%Z%WCzGDTo}|wMAt_xKFDlb_9Bae)PdYeEqg&` zfy_jN|n@P@ujPsqO&j0qF&qfz51E#6W#XP@fXi zw*>Vuak&K~2T}u43(`Z19mJ>w^{qjDY*1etRBzI&|4oeBM%9dlz-R~zu@C??LJSxf z7!r`j33X}e2~GycG>#7g149-A1H)zp28JID3=H3)Y>=2YR1HWiO&vp|;ld0I3}MhY zpc_#4;;I8+;vheP)PlygLFF~b3?i+gnle=e28M1bjw6E1Qlpyda2q5Bb@zJ``ZKU_ zCq#qH1o;DG2W}UTF9T}p+@XQH(ftLoBZz!wV(0|5ExH&O82-`0?J&Q9>;l;dvKzxe zBna>`Ffgp8qq|}5htVLrL2e+y$#A70eLDuw?Jz%p+`tES6>$tuysaAqZio2+yxIYNp4)X)ZZ6G(|iU&~r z0aH6zX^Fg=&2e~mc;K}Yi~B%s2Du&7 z)dY=?k)+?%)%E|MKYu84H%v1TbCTHH2I|Lw+z#rKVv{E*wrbTXm=nmR$(&<>xeeCW zhVed1J^##f$Fp}a(P7s$;Zw}aY1ptcaQ9NBDq zmx9Zk_{2f_Kyx_sax1z$AiF_sz~@Fna-etvr9IG`8oK$k z;)Co0*$J|nko$<02hC}M<~C{NW|+AkJ3w=_#JYU}oD67J zqeW_jXPU1s185fr2Loe!CIbsd2?GNIXrC1W1JeQ~mQ42`uq3O5`|S;cmwcctgT4vrZv zlYNXPuhKXtqH$%0(X}HpFG@(db9NsrjCXjtvExBom$Xm?$BEhRcVFn=*I%9geed46 zm;e3^y*xP}fBAXd^6sIDDUFTmG+fdb2wxDi;C#XSg~g9y7h`P0I|uFs zd>PCYO9k!A7>SP8vW&m`Wf^X{Ftj4CMomm=|3Faka~dYfoa2I-boUY6Bs-C?`-S% z#q+@WKqbS}eWD5<(;pPGtYnvC%MgfTkYeyW!gGSb#Ybb2weSuW3;6|?e#MYD8@czr?#;FYM2X8vGzOYQtPf#^re!=T;#3764!`?cb4IB$@ zdvnd#VK33tV>`$A!gFFrql?6g#*k%9{!G6aHS2cCY~TxHe$!aWs*>Y~Bl@ zs!Po$H}|fX{gWa7q)L*45SxYL^XmuL8$|B&@%`}nW}G0QAjoWLXuwh)_|cwi$&a$4 z4;LR={W1FIeZ)Zl#Mi1;RemegWeiJU$TKe4DXXuz}^I zBAeBN`#K5I56ndVo;MRWVKHvBa+s9NrssBZKJ$_fKc6&|+6!K=VVW>O{h`QR_J-z$ zDe*FQ`pXKe6i!+&%LeY7&B({)`SEDucHV+&<8z-cWHWl4Sk&Xba30g1sq2zIUfjcL z(`#m=*3C8Hx>2d~!T+oeZhd+-b?yB}OG2c77~kUB%leA9fn|29^}9VBQ&y$S71poI zZP?4G_hVATF^B3W<$4>WKderP6?dO{i=mo1$NSC$*Ca;fIsgA^1gs1y_5Blan@!Gn z_N7})hj|aAJb53hxxXjgC-;Hvk>9osNfOL+&VKi9xa}UAeN!}UPUvN}8^>;3`!P$? zu%VIh1oQ6nt09XHb*rk?p${kqKu0{@+LxN+*r-$xs!nSHRjHScO1)9ms! zbJ;$XbVAGK2RQKr( zw}X%{^OhaonYNZ(FX^x7-p%{R`c~RKyN_a%SINu1^|aW^)UjJgbiW1PWwss8hPPL# zII-=RD!e?kZKcFr?SGT9m~&R&ag7pUWIil-Tuou+sbH%|R$XQr7<0e97Toeb#@$eA z>2vXfMJoi3D#}gHW6s%~bNE=-$+(8Vgtyxr{F846A3NfZ%C>{?>~_Xo96O&cDNI_$ zSTOZJ%VUY)wj&OuJO#6MZFD=}!tC&LKmUcv`**c1yYS4&LHWQ=rej}Oe2f_uJ5HJ+ zui{~JoFSe)gJmB3HYPU@Zsnpv4PlwL|NS4hG=EyMrlWC%-dsczZM>`%OvirLk#j2`x%4g8_p=> zf8ed~kpF;XgA31--o{Xk59N&O)O=ho$*??mwQ_d@cd+J8AyMX+#uvmREhH;gEErVu zGNl?=HQx3d@m|Anv>}pbPT!jki6>&$3Qga_bHHTEm*Wkb$pW2|*RdRRFlO74_JFzJ zGmFqvlVc3W7Pb86y`Zlp$ei>*fceiqhU3itW~eB7N;lNCbKfvO>7=D=n83-LuP|Sj zVHcy{LXM=>O;MK%a2BK9MxqrI>E3vWjPZ+!|%sh@psrBsHN0o#mo%f zlceyN=ZpK#Z;Y!SX{FCu&#-vn%l5`2ZYGbFJU@0dib&pQ-lETtWXMz~+2D8L!{Y;y z4K6$#jRib=dTv`bzI$A7QKq&$WZwh0o?Gn}U-;#Y^#P8D2kw7%Seziveq6r3=J7P$XerIf>i%JW zZ(eO%S?pGEYu)5Wx0n9Nt35m0eEotye>T_s{dH{DE-OjK-8~2R1E;U_ieGXr)H};! zTA@M3hX==Gt;fBt-Y z*e-AO?fw1uubJVs|AM1#*>iC2*JnTk}(0RNd_x844?XWc(EC1N+EPsFRn4q%TinzC{u3JyO_Ak-nL$V~pZ=MHJ zG=ooR?XOP!`RQqI0rx468_6sdmKqo18s`1`X40qTy6krT;WplN^TPk=Z(mS)%yuJ4 zMoi1TIy-KAyzATJM}PgQ+R6HMRr)ukHil47-R{O0)iU9sT3mCimENJJJsiLh{QDpr8nFce{yS{`=c|S@h}ldZn-LsQ+JQU#njko9Af#>c-;k&5w;3Vg)|B`8yf0 zh)FoxZ;$s}`+d%o=nGcN8(6Jw+43nL@UQZIsry)=)HZ(Z?9kStlICCZbs0p@oNL9CX;4XTLw@vhI%T>v}s`|8^KXw)*-@;X{JR&4+F+w;65! z>ONc$wmtr&`~K%k?lgtHWVrjac98)?xaZHctA4oc`g>~ax6dz%ecOw;qppfs6v%t+ z2)v`^;9u`;!SVXr=gnM2+)+!puiTxMsKapocll|C8^JHb<0_ZV=WE}mw|#->+eH2n z^D8&*_AmK!Eu>8OZk@Dw9?#kbj!HZJd^&wqd&}bRAHpvRd=DLE)n{Cl;cd}z>Fx7$ zmM3Cc-1OsG__nV;%G7hfw>p*K&59R6vul277T$Pmez#<@9N#m084L9X(px1Oq@%qZx4u3j-@;E?mA}z&EMn_s_2^PsB{( z;^mtCrdK}@mu%bj<7nj(BZju(2}^FDKhJPM_r}iR^sSP`x6iO&$b3~caY_`g1(#x7 zfQXlUPjbWRzwdUvUUy)2&9PX9bz*n+R&U>2_4U<`$w7a%8WzapJ-+gw>iyfLyI6$x zFqY)Vfl~42w6jIK%HC#$JX^Q_Ulsd(F%vESQ$B*skGt!p{-?asm3#!P43p! zt!FCYmRf6lCHGZDq-2lwp92j%4GU$Ky#4msm;o*`*`%KJ!S|z9=CM~B3weBInP`S? zpD(Xi#Qn=~%B#{>X8YecV?#X@f|g$=LPKS-^EnDTzc03 z^>#^~Ij_&QU1#|4L+8D#?ChfldL)hKG%~Z#n!3_x=gz0oqUY?|waX~H)XJ4@U(=S^ zd+Otu3z+nHJPeb)b}=!R{En^tdR5eEM(N8d!TzP|c6IGO>B*Da;6GvB(oaWJo7ow7 z8KjOmMy>w)hwaawb=g}NOx)!nYk%C7;hvmB;PnH%3;w?}K2ZKjd)*GDzda!{na>3u zn8z4;Z|MU=;{)&P*?)6CGG*{pzuWz5z8!PHZ&9{?QCqX7)}>{gVC22tA=r3*;gtzZ zc`F+mmuDyVbWRM6f0Aod1|XcaP!c>_xK~_x_hY(&)MR z@1J|$|AHJ7xa;Wpn$OwyeNQvLWYn-UI^i&>L}J6qx6h9Y+--``eIf31eR5*MFFzB> zhRKC@=BcZs88~d0=XD5c$#a~2XGY}1y*`#!k81SeijOn=n$Ef6vZg`8tE~MSLSoAA zmPYAHOgr-8o&2E{G0Y1%9WDw=TP@p|{I=xxPtiHmY$tSI91lvm{@YOXI>Q%Fok-P? ziHx`J)`@brcY|Z_#@9p6^Vu5Y`E~a2t4!M>q;a60J9=`q#IV z@dZo9RkuGazn3v=pD()lZw>b&;fD1VQMxajgZ@n4IX5KzI>QAHkD#=M?)031w+dH39Tzi>6f7tT+I87EDVII-&X z`Tlb=jnhx*zHkq!xxUjp!Ck81-p8d2XEYm32;DwE{^r)G3;hdkte@|~yg>87#?LW! zjca!QJvIH$1<{?Xe?~-_%Tmga>U`<-MYFhr*vN&4_I@(x~RBeKkF88hc!0S z`{vB9(Tm-6We0!FlykW?>A%0ee!eDt|GmnmQ^Oy5yBJPSdf>a4Y04tig~c&4lf}2s zmtP7BBazcz^WHGVaEnZ1J2t6BN%thf-2`rNJ(Fj*>r{)Ule$468f7;*U|Gy*W{*%l5 zTOK-HaL|j`aA0Gp_>+RA{(s(?$*|0sUa`s2Hz03+g6RG2`SHv5?TgDhm{8KnwRCyC z#;;YoXEw(a{r*{e%<)p?=Vvc(H~kA~e{QP`*)b?lp zL??Af{+QC-@MiY6UW+7GcDAZ7FCOYdZgP45PchngzFqB{UTJfy?Ca}zB`4?QA3Kot zjlnLfEXZCtsi8T7nT@AIW7{9M!;T^Q+^$~D{QRmT`e5}N#trpVWk&>`+wEHD+w0t5r>n512Z%`a14Zow1Dh`kBR#PrMax+9R+%EBdRz6U%efJAO07 zGit1t|FwMoR)Ygq>xzC~JruK}`b+M?fIp&l{;y-KP!0*P+&44NeqaBox6}QU7d)JL zeW}_zZvNWq3~SbFa@`G)=nZ4`S+BU`zSxzlgR5RAaKA6$Ww_67A@2~x%3Sn2)G@5b z@u}FFS$AxAJl4JURI1^7fse;SKMg|oqYPMJ!@?_FGDQT8&(e{BZuwx zw`5*sY75)2Lvlg%gwyL)8zmlm`QP;Vz9~bm#YW8wYq>%a8fMoNi9{vwF-Pf2?9jWW zn3AaNaGl}9x#vvx=Y4L7dYhicJR#bkVDFx1ZC|7q<~>=W;K|Ci;M_fGJ?|@$=aXUAx%aQg2Q;bK-5fhwG1&<~+w-rKo8teP2y$ zxm#v8RXw%%GvVbIqoN-Xvuma)9DNWhBXDPT`TEU8PraIpXL?<$YYds4_OGg%;mq09 z4By!&R7hONvgel+lg--tAaJVd-Mmi>AF_&>5Bxk>;|`MC{?{fYqC{gmSW<5dW5Ie8 zbA~(8A2h!&`e)sGzOs00{OYi^F72&6Cv+o1GOxT{^w)m2G(%h6o)^>R{GV|9{5v*< z?FoT@ZNt8B+t1=>`t&RA0apWa(@wEnf2ZliuHvtWxX1M+_n;GNUBiBRrmkZ@yuLEr zb6GH*d;60={dekaW-t_Si@loo`Txq>u0gBV541YoZTQ^f^z04$-MaESh3%L3)&8C{ z)n@k5snHj9GMoNR`FuvBvcy)kgu{y=m2oJn(;SoJ-bo7QQF z?wP~*p#4VopVp;$=U!Rv{JSY~v&oA&iZh&Vb{Jisu2pWye4z1wyZ7A*UyI+V%`f_$ zx_Mdgub12G7nt4Tw(vS7$-q{_q47yluC$!Z|H+odlnrX$;+pMwj{8p82hHlel;>cs zvz=!bhs8nLiC_O0{Z8H6#y_<`@1XB&Gt2DjpM1?fAA0$BI}^Lt)Ga~$4Y6&hOY=^F zoe{P9=+j3E`t}d!P0r`G>$&uK>b@mYikPdIi!L1yQTY5h;pw-}Vb$OIcbC3?W@2Ju zu{vz+siMU13ko(fy!#p$6g9=B`bmnnj2^q2oaNNL%5@=+_WgcWthevSqc@^{s#>QR zcn^GdczABO7XwZ54X~)P<>c^xYl7AFT?Jp9G0(NzxpLBKX>%}bl||o z<8rgVX5Rb0Snjlz{p%a+*$)`hHl#N^{^_j5cBDa+r{MPb%?(}mf3Gm%crk5~G{>cW z4MFCl19EH@4e^0LBc~{^H9UOBT4b)?z&gEyky|oh`~Por4@`1au(I|3N1X;!Du+aiuujP;PhJ66ABBYIoTO^E)B5%-tw=T(J(=V zdG>_G>zU=*PexvlV|e_iPpP}fWtBma1J9CU40pdZPML4HW*Pf|4}Tf=MVCC}@01W= zb~8NC{-q!x`$A0UW#)uAcY=OwcT^6yFjQa@N=?uVx*g@)b@dyA#CL&)XztQy5G@8D zIExDP4qUBoTzX56K{<~9gDu$CmOKIKtApy&_D+*ycrVRWkk?SfnBuI&b}4nivgP)h zW4!qrzVBsQA?~22lB7_}mR0r3`1aOs3>Es-j56FWj>rocDzF75HYoqE`TqRa{7~<; zwhU@V;u@Z@hWPHx6JVZbbinezsiu9g;4=0DzpI)2nbkkHg9Z~^Bp*z=pU)7T?Rz!f z+hBji{~m@rAt_Dq4zc3QNeV@5&lHZiA3h?rjs3tDYlhVg>pwwsNj!LU$M8UUVi5Oj z=7d{!)DzeZ1Un8bP>=$Jiyco)?`!>^Eg$#FqzPP*{@MKFb8YKjnpGrJfGXLU%TSbhkEai`CH_Vp%J8^Bp#&?{5Ar8rN z?csM3&7NY*@a(0dbZbWgG-R zj$xEsaJp7&gJQxDhl7jE7<|6)F0ek(%c+v&z~gfGfW7jp6Y2Nd{&GDK+se%s#v~&# zrGwE>ppUWa?{Q}9!>+|&?gs8;oPGR^?a6h_-%R!|xS!;}6LR!GUdum4ft{a>#S8Z^ z8N{6mYk16%%mA`(tKkRXJKMHwi~jq*>$T_s-<`I67M>k<#X)jc4ITP#wK_PLZfE6} z-OiZcw!9OmmdZY&{K%b}i!%+A;rJpDJ98@qHwE;H+jkXVJk4%eZ#; zyx1>cF^kde>we~fFZN}gml!q}FgF};r~?Pxf{wF*R0VSZ`+K|ST6e&dO2-@~JqEMaGy{XAdY?+@>XoX_09blHr~G2H(1)FJDX zf8FJGj0XHu8V?vHFw}b-aX2P9T)^$`w2t9kssD@p5+^j6a~=mb zT$wum&oWDn6JPdz;;Z|R%zmHEszU!o1W!r}quz&~avP3K`7|Si;l#nM(P&xDBMopeSY?43i4)8yXQZ$of5ZWdFU`pb-geU)+mYqp)2~)95Yk2*$ zp0mJrzu9ij6^cIYRxv&)MdbmNr|bR(JY24N<=IppW42=t&7X&OUp(R{mD`Y;U$fb4 z<$O-#3-T{@*)L@hJbohAd60+4`JNo}qYQ>F_Ehm@ZgSAhAdMC{e^!oTvpjQqtWWg z-!g~2jFL?Y+8Tt3@30f&v7r{+aU2^dT%Pnq^Aw*Q@R=Seq=%BqQ1DDGH#gaz^srgz|UUIS8OBu z|EHH4=Shd|3Ey9TOJdt0dsFg2d1E&NpTef)3M=O_<{jM1_n_>tQRR}&1iiJ*@Wz2kW>yeH6!XCy90gK}f z%wY-#mES*};q{+m1KWc%ncobaJv=8Ej(Fs?uK4{}Dtvw|_XEFUCDEm9pH${A+AzCu zdE-+C(SN)SlN6YZ7&s@zs%iEK^02fqC^r~0N_9+b)Zw&MUC$iy1^BqeK=YtC8IfuR%mEA9Al4rDLICnt#6{FqDOa=@7 z_#_KvBZju{fQC00zrK)SkZSB>sODE^%3J@CMdq@_hbrraV@oRU*7p_9XP9%?Vd*la wdX7Ep0SmV?<}=qE3jUeNlEI)NX8hs5!~LCnS#P>PizgX8UHx3vIVCg!02|oaVE_OC diff --git a/app/globals.css b/app/globals.css index 6b717ad..a4d605b 100644 --- a/app/globals.css +++ b/app/globals.css @@ -2,20 +2,98 @@ @tailwind components; @tailwind utilities; -:root { - --background: #ffffff; - --foreground: #171717; -} - -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } -} - body { - color: var(--foreground); - background: var(--background); - font-family: Arial, Helvetica, sans-serif; + font-family: Arial, Helvetica, sans-serif; +} + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 0 0% 3.9%; + --card: 0 0% 100%; + --card-foreground: 0 0% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 0 0% 3.9%; + --primary: 0 0% 9%; + --primary-foreground: 0 0% 98%; + --secondary: 0 0% 96.1%; + --secondary-foreground: 0 0% 9%; + --muted: 0 0% 96.1%; + --muted-foreground: 0 0% 45.1%; + --accent: 0 0% 96.1%; + --accent-foreground: 0 0% 9%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + --border: 0 0% 89.8%; + --input: 0 0% 89.8%; + --ring: 0 0% 3.9%; + --chart-1: 12 76% 61%; + --chart-2: 173 58% 39%; + --chart-3: 197 37% 24%; + --chart-4: 43 74% 66%; + --chart-5: 27 87% 67%; + --radius: 0.5rem; + --sidebar-background: 0 0% 98%; + --sidebar-foreground: 240 5.3% 26.1%; + --sidebar-primary: 240 5.9% 10%; + --sidebar-primary-foreground: 0 0% 98%; + --sidebar-accent: 240 4.8% 95.9%; + --sidebar-accent-foreground: 240 5.9% 10%; + --sidebar-border: 220 13% 91%; + --sidebar-ring: 217.2 91.2% 59.8%; + } + .dark { + --background: 0 0% 3.9%; + --foreground: 0 0% 98%; + --card: 0 0% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 0 0% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 0 0% 98%; + --primary-foreground: 0 0% 9%; + --secondary: 0 0% 14.9%; + --secondary-foreground: 0 0% 98%; + --muted: 0 0% 14.9%; + --muted-foreground: 0 0% 63.9%; + --accent: 0 0% 14.9%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + --border: 0 0% 14.9%; + --input: 0 0% 14.9%; + --ring: 0 0% 83.1%; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; + --sidebar-background: 240 5.9% 10%; + --sidebar-foreground: 240 4.8% 95.9%; + --sidebar-primary: 224.3 76.3% 48%; + --sidebar-primary-foreground: 0 0% 100%; + --sidebar-accent: 240 3.7% 15.9%; + --sidebar-accent-foreground: 240 4.8% 95.9%; + --sidebar-border: 240 3.7% 15.9%; + --sidebar-ring: 217.2 91.2% 59.8%; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} + +/* https://dev.to/derick1530/how-to-create-scrollable-element-in-tailwind-without-a-scrollbar-4mbd */ +@layer utilities { + .no-scrollbar::-webkit-scrollbar { + display: none; + } + .no-scrollbar { + -ms-overflow-style: none; + scrollbar-width: 0; + } } diff --git a/app/page.tsx b/app/page.tsx index 9007252..09233ec 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,101 +1,78 @@ -import Image from "next/image"; +"use client"; + +import { GameCard } from "@/components/gameCard"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { + getOmniRecommendationsHome, + OmniRecommendation, +} from "@/lib/omniRecommendation"; +import { loadThumbnails, ThumbnailRequest } from "@/lib/thumbnailLoader"; +import { useEffect, useState } from "react"; export default function Home() { - return ( -
-
- Next.js logo -
    -
  1. - Get started by editing{" "} - - app/page.tsx - - . -
  2. -
  3. Save and see your changes instantly.
  4. -
+ const [rec, setRec] = useState(null); + const SORTS_ALLOWED_IDS = [100000003, 100000001]; + useEffect(() => { + (async () => { + const r = await getOmniRecommendationsHome(); + console.log("[ROBLOX]", "got omni recommendation from api", r); + let th: ThumbnailRequest[] = []; + r.sorts.filter(a=>SORTS_ALLOWED_IDS.includes(a.topicId)).forEach(b=>{ + (b.recommendationList || []).forEach(c=>{ + th.push({ + type: "GameThumbnail", + targetId: r.contentMetadata.Game[c.contentId.toString()].rootPlaceId, + format: "webp", + size: "384x216" + }) + }) + }); + loadThumbnails(th).catch(a=>console.error(a)) + setRec(r); + })(); + }, []); - -
- -
- ); + if (!rec) { + return ( +
+ + +
+
+ Loading... +
+
+
+
+
+ ); + } + + return ( +
+ {"roblox x next.js when"} +
+ {"experimental (functional) roblox.com clone"} +
+ {rec.sorts + .filter((a) => SORTS_ALLOWED_IDS.includes(a.topicId)) + .map((sort, idx) => ( +
+

{sort.topic}

+
+ {(sort.recommendationList || []).map( + (recommendation, idxb) => { + const game = + rec.contentMetadata.Game[ + recommendation.contentId.toString() + ]; + return ; + } + )} +
+
+ ))} +
+
+ ); } diff --git a/bun.lockb b/bun.lockb index da9d9835ecec7b8af4da32b7180c43c2a9bc5f9b..7856b31efc955bcbdb9edfd517a75b2f59865a6b 100755 GIT binary patch literal 132154 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 diff --git a/components.json b/components.json new file mode 100644 index 0000000..dea737b --- /dev/null +++ b/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "tailwind.config.ts", + "css": "app/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "iconLibrary": "lucide" +} \ No newline at end of file diff --git a/components/gameCard.tsx b/components/gameCard.tsx new file mode 100644 index 0000000..9f83944 --- /dev/null +++ b/components/gameCard.tsx @@ -0,0 +1,64 @@ +import { useGameThumbnailLazyLoad } from "@/hooks/use-lazy-load"; +import { ContentMetadata } from "@/lib/omniRecommendation"; +import LazyLoadedImage from "./lazyLoadedImage"; +import { ContextMenu, ContextMenuContent, ContextMenuSeparator, ContextMenuTrigger } from "./ui/context-menu"; +import { ContextMenuItem } from "@radix-ui/react-context-menu"; + +interface GameCardProps { + game: ContentMetadata; +} + +export function GameCard({ game }: GameCardProps) { + return ( + + +
+
+ {game.primaryMediaAsset ? ( + + ) : ( +
+ No image +
+ )} +
+
+ {game.playerCount.toLocaleString()} +
+
+
+ + + {game.name} + + + {Math.round((game.totalUpVotes/(game.totalUpVotes+game.totalDownVotes))*100)}% rating - {game.playerCount} players + + + {window.location.href = (`https://roblox.com/games/${game.rootPlaceId}`)}}> + Open + + {window.location.href = (`roblox://placeId=${game.rootPlaceId}`)}}> + Play + + + {navigator.clipboard.writeText(`https://roblox.com/games/${game.rootPlaceId}`)}}> + copy game url + + {navigator.clipboard.writeText(`${game.rootPlaceId}`)}}> + copy game id + + {navigator.clipboard.writeText(`${game.universeId}`)}}> + copy universe id + + {navigator.clipboard.writeText(`roblox://placeId=${game.rootPlaceId}`)}}> + copy roblox:// uri + + +
+ ); +} diff --git a/components/lazyLoadedImage.tsx b/components/lazyLoadedImage.tsx new file mode 100644 index 0000000..55b2dee --- /dev/null +++ b/components/lazyLoadedImage.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { useGameThumbnailLazyLoad } from '@/hooks/use-lazy-load'; + +interface LazyLoadedImageProps { + imgId: string; + alt: string; + [prop: string]: string +} + +const LazyLoadedImage: React.FC = ({ imgId, alt, ...props }: LazyLoadedImageProps) => { + const imgUrl = useGameThumbnailLazyLoad(imgId); + + return ( +
+ {imgUrl ? ( + {alt} + ) : ( +

Loading...

+ )} +
+ ); +}; + +export default LazyLoadedImage; \ No newline at end of file diff --git a/components/ui/accordion.tsx b/components/ui/accordion.tsx new file mode 100644 index 0000000..2f55a32 --- /dev/null +++ b/components/ui/accordion.tsx @@ -0,0 +1,57 @@ +"use client" + +import * as React from "react" +import * as AccordionPrimitive from "@radix-ui/react-accordion" +import { ChevronDown } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Accordion = AccordionPrimitive.Root + +const AccordionItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AccordionItem.displayName = "AccordionItem" + +const AccordionTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + svg]:rotate-180", + className + )} + {...props} + > + {children} + + + +)) +AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName + +const AccordionContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + +
{children}
+
+)) +AccordionContent.displayName = AccordionPrimitive.Content.displayName + +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } diff --git a/components/ui/alert-dialog.tsx b/components/ui/alert-dialog.tsx new file mode 100644 index 0000000..57760f2 --- /dev/null +++ b/components/ui/alert-dialog.tsx @@ -0,0 +1,141 @@ +"use client" + +import * as React from "react" +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" + +import { cn } from "@/lib/utils" +import { buttonVariants } from "@/components/ui/button" + +const AlertDialog = AlertDialogPrimitive.Root + +const AlertDialogTrigger = AlertDialogPrimitive.Trigger + +const AlertDialogPortal = AlertDialogPrimitive.Portal + +const AlertDialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName + +const AlertDialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + +)) +AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName + +const AlertDialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +AlertDialogHeader.displayName = "AlertDialogHeader" + +const AlertDialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +AlertDialogFooter.displayName = "AlertDialogFooter" + +const AlertDialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName + +const AlertDialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogDescription.displayName = + AlertDialogPrimitive.Description.displayName + +const AlertDialogAction = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName + +const AlertDialogCancel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName + +export { + AlertDialog, + AlertDialogPortal, + AlertDialogOverlay, + AlertDialogTrigger, + AlertDialogContent, + AlertDialogHeader, + AlertDialogFooter, + AlertDialogTitle, + AlertDialogDescription, + AlertDialogAction, + AlertDialogCancel, +} diff --git a/components/ui/alert.tsx b/components/ui/alert.tsx new file mode 100644 index 0000000..5afd41d --- /dev/null +++ b/components/ui/alert.tsx @@ -0,0 +1,59 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const alertVariants = cva( + "relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7", + { + variants: { + variant: { + default: "bg-background text-foreground", + destructive: + "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +const Alert = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes & VariantProps +>(({ className, variant, ...props }, ref) => ( +
+)) +Alert.displayName = "Alert" + +const AlertTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +AlertTitle.displayName = "AlertTitle" + +const AlertDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +AlertDescription.displayName = "AlertDescription" + +export { Alert, AlertTitle, AlertDescription } diff --git a/components/ui/aspect-ratio.tsx b/components/ui/aspect-ratio.tsx new file mode 100644 index 0000000..d6a5226 --- /dev/null +++ b/components/ui/aspect-ratio.tsx @@ -0,0 +1,7 @@ +"use client" + +import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio" + +const AspectRatio = AspectRatioPrimitive.Root + +export { AspectRatio } diff --git a/components/ui/avatar.tsx b/components/ui/avatar.tsx new file mode 100644 index 0000000..51e507b --- /dev/null +++ b/components/ui/avatar.tsx @@ -0,0 +1,50 @@ +"use client" + +import * as React from "react" +import * as AvatarPrimitive from "@radix-ui/react-avatar" + +import { cn } from "@/lib/utils" + +const Avatar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Avatar.displayName = AvatarPrimitive.Root.displayName + +const AvatarImage = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarImage.displayName = AvatarPrimitive.Image.displayName + +const AvatarFallback = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName + +export { Avatar, AvatarImage, AvatarFallback } diff --git a/components/ui/badge.tsx b/components/ui/badge.tsx new file mode 100644 index 0000000..e87d62b --- /dev/null +++ b/components/ui/badge.tsx @@ -0,0 +1,36 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const badgeVariants = cva( + "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + { + variants: { + variant: { + default: + "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80", + secondary: + "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + destructive: + "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80", + outline: "text-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +export interface BadgeProps + extends React.HTMLAttributes, + VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return ( +
+ ) +} + +export { Badge, badgeVariants } diff --git a/components/ui/breadcrumb.tsx b/components/ui/breadcrumb.tsx new file mode 100644 index 0000000..60e6c96 --- /dev/null +++ b/components/ui/breadcrumb.tsx @@ -0,0 +1,115 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { ChevronRight, MoreHorizontal } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Breadcrumb = React.forwardRef< + HTMLElement, + React.ComponentPropsWithoutRef<"nav"> & { + separator?: React.ReactNode + } +>(({ ...props }, ref) =>