Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
Sync from GitHub via hub-sync
Browse files
src/components/hf-auth-button.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
"use client";
|
| 2 |
|
| 3 |
-
import React from "react";
|
| 4 |
import { useAuth } from "@/context/auth-context";
|
| 5 |
|
| 6 |
const SIGNIN_BADGE_URL =
|
|
@@ -37,28 +37,7 @@ export default function HfAuthButton({ variant = "badge" }: HfAuthButtonProps) {
|
|
| 37 |
const name =
|
| 38 |
oauth.userInfo?.preferred_username ?? oauth.userInfo?.name ?? "signed in";
|
| 39 |
const avatar = oauth.userInfo?.picture;
|
| 40 |
-
return
|
| 41 |
-
<div className="inline-flex items-center h-6 gap-1.5 panel-raised bg-[var(--surface-0)]/85 backdrop-blur px-1.5 text-[11px] text-slate-300">
|
| 42 |
-
{avatar && (
|
| 43 |
-
// eslint-disable-next-line @next/next/no-img-element
|
| 44 |
-
<img
|
| 45 |
-
src={avatar}
|
| 46 |
-
alt=""
|
| 47 |
-
width={20}
|
| 48 |
-
height={20}
|
| 49 |
-
className="rounded-full ring-1 ring-white/10"
|
| 50 |
-
/>
|
| 51 |
-
)}
|
| 52 |
-
<span className="tabular max-w-[8rem] truncate">{name}</span>
|
| 53 |
-
<button
|
| 54 |
-
onClick={signOut}
|
| 55 |
-
className="cursor-pointer rounded px-1 text-[9px] uppercase tracking-wide text-slate-400 hover:text-slate-100 hover:bg-white/5 transition-colors"
|
| 56 |
-
title="Sign out of Hugging Face"
|
| 57 |
-
>
|
| 58 |
-
Sign out
|
| 59 |
-
</button>
|
| 60 |
-
</div>
|
| 61 |
-
);
|
| 62 |
}
|
| 63 |
|
| 64 |
if (variant === "ghost") {
|
|
@@ -107,3 +86,88 @@ export default function HfAuthButton({ variant = "badge" }: HfAuthButtonProps) {
|
|
| 107 |
</button>
|
| 108 |
);
|
| 109 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
"use client";
|
| 2 |
|
| 3 |
+
import React, { useEffect, useRef, useState } from "react";
|
| 4 |
import { useAuth } from "@/context/auth-context";
|
| 5 |
|
| 6 |
const SIGNIN_BADGE_URL =
|
|
|
|
| 37 |
const name =
|
| 38 |
oauth.userInfo?.preferred_username ?? oauth.userInfo?.name ?? "signed in";
|
| 39 |
const avatar = oauth.userInfo?.picture;
|
| 40 |
+
return <SignedInMenu name={name} avatar={avatar} onSignOut={signOut} />;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
}
|
| 42 |
|
| 43 |
if (variant === "ghost") {
|
|
|
|
| 86 |
</button>
|
| 87 |
);
|
| 88 |
}
|
| 89 |
+
|
| 90 |
+
function SignedInMenu({
|
| 91 |
+
name,
|
| 92 |
+
avatar,
|
| 93 |
+
onSignOut,
|
| 94 |
+
}: {
|
| 95 |
+
name: string;
|
| 96 |
+
avatar?: string;
|
| 97 |
+
onSignOut: () => void;
|
| 98 |
+
}) {
|
| 99 |
+
const [open, setOpen] = useState(false);
|
| 100 |
+
const wrapperRef = useRef<HTMLDivElement>(null);
|
| 101 |
+
|
| 102 |
+
useEffect(() => {
|
| 103 |
+
if (!open) return;
|
| 104 |
+
const onDown = (e: MouseEvent) => {
|
| 105 |
+
if (
|
| 106 |
+
wrapperRef.current &&
|
| 107 |
+
!wrapperRef.current.contains(e.target as Node)
|
| 108 |
+
) {
|
| 109 |
+
setOpen(false);
|
| 110 |
+
}
|
| 111 |
+
};
|
| 112 |
+
const onKey = (e: KeyboardEvent) => {
|
| 113 |
+
if (e.key === "Escape") setOpen(false);
|
| 114 |
+
};
|
| 115 |
+
document.addEventListener("mousedown", onDown);
|
| 116 |
+
document.addEventListener("keydown", onKey);
|
| 117 |
+
return () => {
|
| 118 |
+
document.removeEventListener("mousedown", onDown);
|
| 119 |
+
document.removeEventListener("keydown", onKey);
|
| 120 |
+
};
|
| 121 |
+
}, [open]);
|
| 122 |
+
|
| 123 |
+
return (
|
| 124 |
+
<div ref={wrapperRef} className="relative inline-flex">
|
| 125 |
+
<button
|
| 126 |
+
onClick={() => setOpen((v) => !v)}
|
| 127 |
+
aria-haspopup="menu"
|
| 128 |
+
aria-expanded={open}
|
| 129 |
+
className="cursor-pointer inline-flex items-center h-6 gap-1.5 panel-raised bg-[var(--surface-0)]/85 backdrop-blur px-1.5 text-[11px] text-slate-300 hover:bg-white/[0.04] transition-colors"
|
| 130 |
+
title={`Signed in as ${name}`}
|
| 131 |
+
>
|
| 132 |
+
{avatar && (
|
| 133 |
+
// eslint-disable-next-line @next/next/no-img-element
|
| 134 |
+
<img
|
| 135 |
+
src={avatar}
|
| 136 |
+
alt=""
|
| 137 |
+
width={20}
|
| 138 |
+
height={20}
|
| 139 |
+
className="rounded-full ring-1 ring-white/10"
|
| 140 |
+
/>
|
| 141 |
+
)}
|
| 142 |
+
<span className="tabular max-w-[8rem] truncate">{name}</span>
|
| 143 |
+
<svg
|
| 144 |
+
aria-hidden
|
| 145 |
+
width="8"
|
| 146 |
+
height="8"
|
| 147 |
+
viewBox="0 0 8 8"
|
| 148 |
+
className={`text-slate-500 transition-transform ${open ? "rotate-180" : ""}`}
|
| 149 |
+
>
|
| 150 |
+
<path d="M1 2.5l3 3 3-3" stroke="currentColor" fill="none" />
|
| 151 |
+
</svg>
|
| 152 |
+
</button>
|
| 153 |
+
|
| 154 |
+
{open && (
|
| 155 |
+
<div
|
| 156 |
+
role="menu"
|
| 157 |
+
className="absolute right-0 top-full mt-1.5 min-w-[10rem] panel-raised bg-[var(--surface-1)]/98 backdrop-blur shadow-xl p-1 z-50 text-[11px]"
|
| 158 |
+
>
|
| 159 |
+
<button
|
| 160 |
+
role="menuitem"
|
| 161 |
+
onClick={() => {
|
| 162 |
+
setOpen(false);
|
| 163 |
+
onSignOut();
|
| 164 |
+
}}
|
| 165 |
+
className="cursor-pointer w-full text-left px-2 py-1.5 rounded text-slate-300 hover:bg-white/5 hover:text-slate-100 transition-colors"
|
| 166 |
+
>
|
| 167 |
+
Sign out
|
| 168 |
+
</button>
|
| 169 |
+
</div>
|
| 170 |
+
)}
|
| 171 |
+
</div>
|
| 172 |
+
);
|
| 173 |
+
}
|