Merge commit '59e21db42b' into dev

This commit is contained in:
DESKTOP-RTLN3BA\$punk 2026-03-24 21:20:30 -07:00
commit ccf8454db5
10 changed files with 42 additions and 30 deletions

View file

@ -165,6 +165,7 @@ export function LocalLoginForm() {
id="email" id="email"
type="email" type="email"
required required
placeholder="you@example.com"
value={username} value={username}
onChange={(e) => setUsername(e.target.value)} onChange={(e) => setUsername(e.target.value)}
className={`mt-1 block w-full rounded-md border px-3 py-1.5 md:py-2 shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 dark:bg-gray-800 dark:text-white transition-all ${ className={`mt-1 block w-full rounded-md border px-3 py-1.5 md:py-2 shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 dark:bg-gray-800 dark:text-white transition-all ${
@ -188,6 +189,7 @@ export function LocalLoginForm() {
id="password" id="password"
type={showPassword ? "text" : "password"} type={showPassword ? "text" : "password"}
required required
placeholder="Enter your password"
value={password} value={password}
onChange={(e) => setPassword(e.target.value)} onChange={(e) => setPassword(e.target.value)}
className={`mt-1 block w-full rounded-md border pr-10 px-3 py-1.5 md:py-2 shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 dark:bg-gray-800 dark:text-white transition-all ${ className={`mt-1 block w-full rounded-md border pr-10 px-3 py-1.5 md:py-2 shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 dark:bg-gray-800 dark:text-white transition-all ${

View file

@ -231,6 +231,7 @@ export default function RegisterPage() {
id="email" id="email"
type="email" type="email"
required required
placeholder="you@example.com"
value={email} value={email}
onChange={(e) => setEmail(e.target.value)} onChange={(e) => setEmail(e.target.value)}
className={`mt-1 block w-full rounded-md border px-3 py-1.5 md:py-2 shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 dark:bg-gray-800 dark:text-white transition-all ${ className={`mt-1 block w-full rounded-md border px-3 py-1.5 md:py-2 shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 dark:bg-gray-800 dark:text-white transition-all ${
@ -253,6 +254,7 @@ export default function RegisterPage() {
id="password" id="password"
type="password" type="password"
required required
placeholder="Enter your password"
value={password} value={password}
onChange={(e) => setPassword(e.target.value)} onChange={(e) => setPassword(e.target.value)}
className={`mt-1 block w-full rounded-md border px-3 py-1.5 md:py-2 shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 dark:bg-gray-800 dark:text-white transition-all ${ className={`mt-1 block w-full rounded-md border px-3 py-1.5 md:py-2 shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 dark:bg-gray-800 dark:text-white transition-all ${
@ -275,6 +277,7 @@ export default function RegisterPage() {
id="confirmPassword" id="confirmPassword"
type="password" type="password"
required required
placeholder="Confirm your password"
value={confirmPassword} value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)} onChange={(e) => setConfirmPassword(e.target.value)}
className={`mt-1 block w-full rounded-md border px-3 py-1.5 md:py-2 shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 dark:bg-gray-800 dark:text-white transition-all ${ className={`mt-1 block w-full rounded-md border px-3 py-1.5 md:py-2 shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 dark:bg-gray-800 dark:text-white transition-all ${

View file

@ -1,6 +1,6 @@
import { ActionBarPrimitive, AuiIf, MessagePrimitive, useAuiState } from "@assistant-ui/react"; import { ActionBarPrimitive, AuiIf, MessagePrimitive, useAuiState } from "@assistant-ui/react";
import { useAtomValue } from "jotai"; import { useAtomValue } from "jotai";
import { CheckIcon, CopyIcon, FileText, Pen } from "lucide-react"; import { FileText, Pen } from "lucide-react";
import Image from "next/image"; import Image from "next/image";
import { type FC, useState } from "react"; import { type FC, useState } from "react";
import { messageDocumentsMapAtom } from "@/atoms/chat/mentioned-documents.atom"; import { messageDocumentsMapAtom } from "@/atoms/chat/mentioned-documents.atom";
@ -30,7 +30,7 @@ const UserAvatar: FC<AuthorMetadata> = ({ displayName, avatarUrl }) => {
alt={displayName || "User"} alt={displayName || "User"}
width={32} width={32}
height={32} height={32}
className="size-8 rounded-full object-cover select-none" className="size-8 rounded-full object-cover"
referrerPolicy="no-referrer" referrerPolicy="no-referrer"
onError={() => setHasError(true)} onError={() => setHasError(true)}
unoptimized unoptimized

View file

@ -277,21 +277,24 @@ const CollisionMechanism = ({
}, [cycleCollisionDetected, parentRef]); }, [cycleCollisionDetected, parentRef]);
useEffect(() => { useEffect(() => {
if (collision.detected && collision.coordinates) { if (!collision.detected || !collision.coordinates) return;
setTimeout(() => {
setCollision({ detected: false, coordinates: null });
setCycleCollisionDetected(false);
// Set beam opacity to 0
if (beamRef.current) {
beamRef.current.style.opacity = "1";
}
}, 2000);
// Reset the beam animation after a delay const timer1 = setTimeout(() => {
setTimeout(() => { setCollision({ detected: false, coordinates: null });
setBeamKey((prevKey) => prevKey + 1); setCycleCollisionDetected(false);
}, 2000); if (beamRef.current) {
} beamRef.current.style.opacity = "1";
}
}, 2000);
const timer2 = setTimeout(() => {
setBeamKey((prevKey) => prevKey + 1);
}, 2000);
return () => {
clearTimeout(timer1);
clearTimeout(timer2);
};
}, [collision]); }, [collision]);
return ( return (

View file

@ -1,7 +1,6 @@
"use client"; "use client";
import { ChevronsUpDown, Settings, UserPen } from "lucide-react"; import { ChevronsUpDown, Settings, UserPen } from "lucide-react";
import { useParams, useRouter } from "next/navigation";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
@ -29,9 +28,6 @@ export function SidebarHeader({
className, className,
}: SidebarHeaderProps) { }: SidebarHeaderProps) {
const t = useTranslations("sidebar"); const t = useTranslations("sidebar");
const router = useRouter();
const params = useParams();
const searchSpaceId = params.search_space_id as string;
return ( return (
<div className={cn("flex min-w-0 flex-1 items-center", className)}> <div className={cn("flex min-w-0 flex-1 items-center", className)}>

View file

@ -103,7 +103,7 @@ export function Pricing({
> >
{plans.map((plan, index) => ( {plans.map((plan, index) => (
<motion.div <motion.div
key={index} key={plan.name}
initial={{ y: 50, opacity: 1 }} initial={{ y: 50, opacity: 1 }}
whileInView={ whileInView={
isDesktop isDesktop
@ -193,8 +193,8 @@ export function Pricing({
</p> </p>
<ul className="mt-5 gap-2 flex flex-col"> <ul className="mt-5 gap-2 flex flex-col">
{plan.features.map((feature, idx) => ( {plan.features.map((feature) => (
<li key={idx} className="flex items-start gap-2"> <li key={feature} className="flex items-start gap-2">
<Check className="h-4 w-4 text-primary mt-1 flex-shrink-0" /> <Check className="h-4 w-4 text-primary mt-1 flex-shrink-0" />
<span className="text-left">{feature}</span> <span className="text-left">{feature}</span>
</li> </li>

View file

@ -8,6 +8,7 @@ import {
useAuiState, useAuiState,
} from "@assistant-ui/react"; } from "@assistant-ui/react";
import { CheckIcon, CopyIcon } from "lucide-react"; import { CheckIcon, CopyIcon } from "lucide-react";
import Image from "next/image";
import { type FC, type ReactNode, useState } from "react"; import { type FC, type ReactNode, useState } from "react";
import { MarkdownText } from "@/components/assistant-ui/markdown-text"; import { MarkdownText } from "@/components/assistant-ui/markdown-text";
import { ToolFallback } from "@/components/assistant-ui/tool-fallback"; import { ToolFallback } from "@/components/assistant-ui/tool-fallback";
@ -79,10 +80,11 @@ const UserAvatar: FC<AuthorMetadata & { hasError: boolean; onError: () => void }
if (avatarUrl && !hasError) { if (avatarUrl && !hasError) {
return ( return (
// biome-ignore lint/performance/noImgElement: external OAuth/profile avatar URL <Image
<img
src={avatarUrl} src={avatarUrl}
alt={displayName || "User"} alt={displayName || "User"}
width={32}
height={32}
className="size-8 rounded-full object-cover" className="size-8 rounded-full object-cover"
referrerPolicy="no-referrer" referrerPolicy="no-referrer"
onError={onError} onError={onError}

View file

@ -143,9 +143,11 @@ function CopyButton({
const [hasCopied, setHasCopied] = React.useState(false); const [hasCopied, setHasCopied] = React.useState(false);
React.useEffect(() => { React.useEffect(() => {
setTimeout(() => { if (!hasCopied) return;
const timer = setTimeout(() => {
setHasCopied(false); setHasCopied(false);
}, 2000); }, 2000);
return () => clearTimeout(timer);
}, [hasCopied]); }, [hasCopied]);
return ( return (

View file

@ -187,6 +187,7 @@ function LinkOpenButton() {
}} }}
aria-label="Open link in a new tab" aria-label="Open link in a new tab"
target="_blank" target="_blank"
rel="noopener noreferrer"
> >
<ExternalLink width={18} /> <ExternalLink width={18} />
</a> </a>

View file

@ -48,14 +48,17 @@ export function Spotlight({
useEffect(() => { useEffect(() => {
if (!parentElement) return; if (!parentElement) return;
const handleEnter = () => setIsHovered(true);
const handleLeave = () => setIsHovered(false);
parentElement.addEventListener("mousemove", handleMouseMove); parentElement.addEventListener("mousemove", handleMouseMove);
parentElement.addEventListener("mouseenter", () => setIsHovered(true)); parentElement.addEventListener("mouseenter", handleEnter);
parentElement.addEventListener("mouseleave", () => setIsHovered(false)); parentElement.addEventListener("mouseleave", handleLeave);
return () => { return () => {
parentElement.removeEventListener("mousemove", handleMouseMove); parentElement.removeEventListener("mousemove", handleMouseMove);
parentElement.removeEventListener("mouseenter", () => setIsHovered(true)); parentElement.removeEventListener("mouseenter", handleEnter);
parentElement.removeEventListener("mouseleave", () => setIsHovered(false)); parentElement.removeEventListener("mouseleave", handleLeave);
}; };
}, [parentElement, handleMouseMove]); }, [parentElement, handleMouseMove]);