203 lines
6.8 KiB
TypeScript
203 lines
6.8 KiB
TypeScript
"use client"
|
|
|
|
import type { ComponentType, CSSProperties, ReactNode } from "react"
|
|
import { Clock, FolderInput, Tag } from "lucide-react"
|
|
import {
|
|
Sheet,
|
|
SheetContent,
|
|
SheetHeader,
|
|
SheetTitle,
|
|
} from "@/components/ui/sheet"
|
|
import { cn } from "@/lib/utils"
|
|
import { EmailLabelPickerBlock } from "@/components/gmail/email-label-picker-block"
|
|
import type { MoveTarget } from "@/components/gmail/move-to-menu-items"
|
|
|
|
function SheetActionRow({
|
|
children,
|
|
onClick,
|
|
className,
|
|
style,
|
|
}: {
|
|
children: ReactNode
|
|
onClick: () => void
|
|
className?: string
|
|
style?: CSSProperties
|
|
}) {
|
|
return (
|
|
<button
|
|
type="button"
|
|
className={cn(
|
|
"flex w-full items-center gap-3 px-4 py-3 text-left text-sm text-[#3c4043] transition-colors hover:bg-[#f1f3f4] active:bg-[#e8eaed]",
|
|
className
|
|
)}
|
|
style={style}
|
|
onClick={onClick}
|
|
>
|
|
{children}
|
|
</button>
|
|
)
|
|
}
|
|
|
|
const SheetLabelItem: ComponentType<{
|
|
children: ReactNode
|
|
onSelect?: (event: Event) => void
|
|
className?: string
|
|
}> = ({ children, onSelect, className }) => (
|
|
<div
|
|
role="button"
|
|
tabIndex={0}
|
|
className={cn(
|
|
"flex w-full cursor-pointer items-center gap-3 px-4 py-2.5 text-left text-sm text-[#3c4043] transition-colors hover:bg-[#f1f3f4] active:bg-[#e8eaed] outline-none focus-visible:bg-[#f1f3f4] focus-visible:ring-2 focus-visible:ring-[#1a73e8]/30",
|
|
className
|
|
)}
|
|
onClick={(e) => onSelect?.(e as unknown as Event)}
|
|
onKeyDown={(e) => {
|
|
if (e.key === "Enter" || e.key === " ") {
|
|
e.preventDefault()
|
|
onSelect?.(e as unknown as Event)
|
|
}
|
|
}}
|
|
>
|
|
{children}
|
|
</div>
|
|
)
|
|
|
|
type CatalogLabelPresence = "none" | "some" | "all"
|
|
|
|
export type MobileXsBulkSheetsProps = {
|
|
moveSheetOpen: boolean
|
|
onMoveSheetOpenChange: (open: boolean) => void
|
|
labelSheetOpen: boolean
|
|
onLabelSheetOpenChange: (open: boolean) => void
|
|
labelPickerQuery: string
|
|
onLabelPickerQueryChange: (query: string) => void
|
|
catalogLabels: string[]
|
|
moveTargets: { recents: MoveTarget[]; system: MoveTarget[]; folders: MoveTarget[] }
|
|
onMoveTo: (targetId: string) => void
|
|
getLabelPresence: (label: string) => CatalogLabelPresence
|
|
onToggleCatalogLabel: (label: string) => void
|
|
onCreateLabel: (label: string) => void
|
|
}
|
|
|
|
export function MobileXsBulkSheets({
|
|
moveSheetOpen,
|
|
onMoveSheetOpenChange,
|
|
labelSheetOpen,
|
|
onLabelSheetOpenChange,
|
|
labelPickerQuery,
|
|
onLabelPickerQueryChange,
|
|
catalogLabels,
|
|
moveTargets,
|
|
onMoveTo,
|
|
getLabelPresence,
|
|
onToggleCatalogLabel,
|
|
onCreateLabel,
|
|
}: MobileXsBulkSheetsProps) {
|
|
return (
|
|
<>
|
|
<Sheet open={moveSheetOpen} onOpenChange={onMoveSheetOpenChange}>
|
|
<SheetContent
|
|
side="bottom"
|
|
className="max-h-[min(85vh,520px)] gap-0 overflow-hidden rounded-t-2xl border-[#dadce0] px-0 pb-[max(1rem,env(safe-area-inset-bottom))] pt-2 [&>button]:top-3.5 [&>button]:right-3.5"
|
|
>
|
|
<SheetHeader className="border-b border-[#eceff1] px-4 pb-3 text-left">
|
|
<SheetTitle className="text-base font-medium text-[#3c4043]">
|
|
Déplacer vers
|
|
</SheetTitle>
|
|
</SheetHeader>
|
|
<div className="flex flex-col overflow-y-auto py-1">
|
|
{moveTargets.recents.length > 0 && (
|
|
<>
|
|
<div className="px-4 py-1.5 text-[11px] font-medium uppercase tracking-wide text-[#5f6368]">
|
|
Récents
|
|
</div>
|
|
{moveTargets.recents.map((t) => (
|
|
<SheetActionRow
|
|
key={`recent-${t.id}`}
|
|
onClick={() => {
|
|
onMoveTo(t.id)
|
|
onMoveSheetOpenChange(false)
|
|
}}
|
|
>
|
|
<span className="flex items-center gap-2">
|
|
{t.icon ?? <FolderInput className="size-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />}
|
|
<Clock className="size-3 shrink-0 text-[#9aa0a6]" strokeWidth={1.5} />
|
|
</span>
|
|
{t.label}
|
|
</SheetActionRow>
|
|
))}
|
|
<div className="mx-4 border-b border-[#eceff1]" />
|
|
</>
|
|
)}
|
|
{moveTargets.system.map((t) => (
|
|
<SheetActionRow
|
|
key={t.id}
|
|
onClick={() => {
|
|
onMoveTo(t.id)
|
|
onMoveSheetOpenChange(false)
|
|
}}
|
|
>
|
|
{t.icon ?? <FolderInput className="size-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />}
|
|
{t.label}
|
|
</SheetActionRow>
|
|
))}
|
|
{moveTargets.folders.length > 0 && (
|
|
<>
|
|
<div className="mx-4 border-b border-[#eceff1]" />
|
|
<div className="px-4 py-1.5 text-[11px] font-medium uppercase tracking-wide text-[#5f6368]">
|
|
Dossiers
|
|
</div>
|
|
{moveTargets.folders.map((t) => (
|
|
<SheetActionRow
|
|
key={t.id}
|
|
onClick={() => {
|
|
onMoveTo(t.id)
|
|
onMoveSheetOpenChange(false)
|
|
}}
|
|
style={t.depth > 0 ? { paddingLeft: `${16 + t.depth * 16}px` } : undefined}
|
|
>
|
|
{t.icon ?? <FolderInput className="size-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />}
|
|
{t.label}
|
|
</SheetActionRow>
|
|
))}
|
|
</>
|
|
)}
|
|
</div>
|
|
</SheetContent>
|
|
</Sheet>
|
|
|
|
<Sheet
|
|
open={labelSheetOpen}
|
|
onOpenChange={(open) => {
|
|
onLabelSheetOpenChange(open)
|
|
if (!open) onLabelPickerQueryChange("")
|
|
}}
|
|
>
|
|
<SheetContent
|
|
side="bottom"
|
|
className="max-h-[min(85vh,520px)] gap-0 overflow-hidden rounded-t-2xl border-[#dadce0] px-0 pb-[max(1rem,env(safe-area-inset-bottom))] pt-2 [&>button]:top-3.5 [&>button]:right-3.5"
|
|
>
|
|
<SheetHeader className="shrink-0 border-b border-[#eceff1] px-4 pb-3 text-left">
|
|
<SheetTitle className="flex items-center gap-2 text-base font-medium text-[#3c4043]">
|
|
<Tag className="size-[18px] text-[#5f6368]" strokeWidth={1.5} />
|
|
Ajouter le libellé
|
|
</SheetTitle>
|
|
</SheetHeader>
|
|
<div className="flex min-h-0 flex-1 flex-col overflow-hidden">
|
|
<EmailLabelPickerBlock
|
|
query={labelPickerQuery}
|
|
onQueryChange={onLabelPickerQueryChange}
|
|
catalogLabels={catalogLabels}
|
|
Item={SheetLabelItem}
|
|
getLabelPresence={getLabelPresence}
|
|
onToggleCatalogLabel={onToggleCatalogLabel}
|
|
onCreateLabel={onCreateLabel}
|
|
listClassName="max-h-[min(50vh,280px)] flex-1"
|
|
/>
|
|
</div>
|
|
</SheetContent>
|
|
</Sheet>
|
|
</>
|
|
)
|
|
}
|