feat: add slides generation tool with multiple slide types
- Add slides.tool.ts with support for title, bullets, chart, stats, table, cards, timeline, quote, comparison, equation, image, summary slide types - Chart types: bar, horizontal-bar, line, donut, radar - Integrate with agent executor and canvas system - Add multilingual support (en/fr) - Various UI improvements and bug fixes Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
||||
Search,
|
||||
Clock,
|
||||
AlertCircle,
|
||||
Menu,
|
||||
} from 'lucide-react'
|
||||
import { Note, Notebook } from '@/lib/types'
|
||||
import { restoreNote, permanentDeleteNote, emptyTrash } from '@/app/actions/notes'
|
||||
@@ -139,16 +140,26 @@ export function TrashClient({
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col bg-[#F9F8F6] dark:bg-[#1a1a1a]">
|
||||
<header className="px-12 pt-12 pb-8 flex flex-col gap-6 sticky top-0 bg-[#F9F8F6]/80 dark:bg-[#1a1a1a]/80 backdrop-blur-md z-30 border-b border-border/20">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="space-y-1">
|
||||
<h1 className="text-4xl font-memento-serif font-medium text-foreground flex items-center gap-4">
|
||||
{t('sidebar.trash')} <Trash2 size={28} className="text-rose-400 opacity-40" />
|
||||
</h1>
|
||||
<p className="text-[10px] text-muted-foreground font-bold uppercase tracking-[0.3em] opacity-60">
|
||||
{t('trash.autoDelete30')}
|
||||
</p>
|
||||
</div>
|
||||
<header className="px-4 sm:px-8 md:px-12 pt-6 sm:pt-10 md:pt-12 pb-5 sm:pb-6 md:pb-8 flex flex-col gap-4 sm:gap-6 sticky top-0 bg-[#F9F8F6]/80 dark:bg-[#1a1a1a]/80 backdrop-blur-md z-30 border-b border-border/20">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<div className="flex items-center gap-3 min-w-0">
|
||||
{/* Hamburger mobile */}
|
||||
<button
|
||||
className="md:hidden p-2 -ms-1 text-foreground hover:bg-foreground/5 rounded-lg transition-colors shrink-0"
|
||||
onClick={() => window.dispatchEvent(new CustomEvent('open-mobile-sidebar'))}
|
||||
aria-label="Ouvrir la navigation"
|
||||
>
|
||||
<Menu size={22} />
|
||||
</button>
|
||||
<div className="space-y-1 min-w-0">
|
||||
<h1 className="text-2xl sm:text-3xl md:text-4xl font-memento-serif font-medium text-foreground flex items-center gap-3">
|
||||
{t('sidebar.trash')} <Trash2 size={28} className="text-rose-400 opacity-40" />
|
||||
</h1>
|
||||
<p className="text-[10px] text-muted-foreground font-bold uppercase tracking-[0.3em] opacity-60">
|
||||
{t('trash.autoDelete30')}
|
||||
</p>
|
||||
</div>
|
||||
</div>{/* end flex items-center gap-3 */}
|
||||
|
||||
{items.length > 0 && (
|
||||
<button
|
||||
@@ -161,24 +172,24 @@ export function TrashClient({
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-6">
|
||||
<div className="group relative flex-1 max-w-xl">
|
||||
<div className="flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-6">
|
||||
<div className="group relative flex-1">
|
||||
<Search className="absolute left-4 top-1/2 -translate-y-1/2 text-muted-foreground group-focus-within:text-foreground transition-colors" size={16} />
|
||||
<input
|
||||
type="text"
|
||||
placeholder={t('common.search')}
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
className="w-full bg-white dark:bg-white/5 border border-border/40 rounded-2xl pl-12 pr-6 py-4 text-sm outline-none focus:ring-4 ring-foreground/5 transition-all shadow-sm"
|
||||
className="w-full bg-white dark:bg-white/5 border border-border/40 rounded-2xl pl-12 pr-6 py-3 sm:py-4 text-sm outline-none focus:ring-4 ring-foreground/5 transition-all shadow-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex bg-white dark:bg-white/5 p-1 rounded-2xl border border-border shadow-sm">
|
||||
<div className="flex bg-white dark:bg-white/5 p-1 rounded-2xl border border-border shadow-sm shrink-0">
|
||||
{(['all', 'notes', 'notebooks'] as FilterType[]).map(type => (
|
||||
<button
|
||||
key={type}
|
||||
onClick={() => setFilterType(type)}
|
||||
className={`px-6 py-3 rounded-xl text-[10px] font-bold uppercase tracking-widest transition-all
|
||||
className={`px-3 sm:px-6 py-2 sm:py-3 rounded-xl text-[10px] font-bold uppercase tracking-widest transition-all
|
||||
${filterType === type ? 'bg-foreground text-background shadow-lg' : 'text-muted-foreground hover:text-foreground'}`}
|
||||
>
|
||||
{type === 'all' ? t('trash.filterAll') : type === 'notes' ? t('nav.notes') : t('nav.notebooks')}
|
||||
@@ -188,9 +199,9 @@ export function TrashClient({
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main className="flex-1 px-12 py-12 overflow-y-auto">
|
||||
<main className="flex-1 px-4 sm:px-8 md:px-12 py-6 sm:py-8 md:py-12 overflow-y-auto">
|
||||
{items.length > 0 ? (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 sm:gap-6 md:gap-8">
|
||||
<AnimatePresence mode="popLayout">
|
||||
{items.map(item => {
|
||||
const daysLeft = getDaysRemaining(item.deletedAt)
|
||||
@@ -281,7 +292,7 @@ export function TrashClient({
|
||||
)}
|
||||
</main>
|
||||
|
||||
<footer className="px-12 py-6 bg-white/50 dark:bg-white/5 border-t border-border flex items-center gap-4">
|
||||
<footer className="px-4 sm:px-8 md:px-12 py-3 sm:py-4 md:py-6 bg-white/50 dark:bg-white/5 border-t border-border flex items-center gap-3">
|
||||
<AlertCircle size={14} className="text-muted-foreground" />
|
||||
<p className="text-[10px] text-muted-foreground font-medium uppercase tracking-widest">
|
||||
{t('trash.notebookRestoreHint')}
|
||||
|
||||
Reference in New Issue
Block a user