292 lines
8.4 KiB
TypeScript
292 lines
8.4 KiB
TypeScript
"use client"
|
|
|
|
import type { ReactNode } from "react"
|
|
import {
|
|
AlignHorizontalSpaceAround,
|
|
Check,
|
|
Eye,
|
|
ListTree,
|
|
Maximize2,
|
|
MessageSquare,
|
|
MessageSquarePlus,
|
|
Pencil,
|
|
} from "lucide-react"
|
|
import {
|
|
MenubarCheckboxItem,
|
|
MenubarContent,
|
|
MenubarItem,
|
|
MenubarMenu,
|
|
MenubarSeparator,
|
|
MenubarSubContent,
|
|
MenubarSubTrigger,
|
|
MenubarTrigger,
|
|
} from "@/components/ui/menubar"
|
|
import {
|
|
DocsExclusiveMenuSub,
|
|
DocsExclusiveMenuSubRoot,
|
|
} from "@/components/drive/richtext/docs-exclusive-menu-sub"
|
|
import { DocsMenuShortcut } from "@/components/drive/richtext/docs-menu-shortcut"
|
|
import { DOCS_MENUBAR_CONTENT_PROPS } from "@/components/drive/richtext/docs-menubar-props"
|
|
import type {
|
|
DocsCommentsDisplay,
|
|
DocsEditorMode,
|
|
} from "@/lib/drive/docs-view-settings"
|
|
import { cn } from "@/lib/utils"
|
|
|
|
export type DocsViewMenuState = {
|
|
editorMode: DocsEditorMode
|
|
commentsDisplay: DocsCommentsDisplay
|
|
showLayout: boolean
|
|
showRuler: boolean
|
|
showEquationToolbar: boolean
|
|
showNonPrintableChars: boolean
|
|
}
|
|
|
|
export type DocsViewMenuActions = {
|
|
onEditorModeChange: (mode: DocsEditorMode) => void
|
|
onCommentsDisplayChange: (display: DocsCommentsDisplay) => void
|
|
onToggleOutlineSidebar: () => void
|
|
onToggleShowLayout: () => void
|
|
onToggleShowRuler: () => void
|
|
onToggleShowEquationToolbar: () => void
|
|
onToggleShowNonPrintableChars: () => void
|
|
onFullscreen: () => void
|
|
}
|
|
|
|
const EDITOR_MODES = [
|
|
{
|
|
id: "edit" as const,
|
|
label: "Édition",
|
|
description: "Modifier le document directement",
|
|
icon: Pencil,
|
|
},
|
|
{
|
|
id: "suggest" as const,
|
|
label: "Suggestion",
|
|
description: "Suggérer des modifications",
|
|
icon: MessageSquarePlus,
|
|
},
|
|
{
|
|
id: "view" as const,
|
|
label: "Affichage",
|
|
description: "Lire ou imprimer le document final",
|
|
icon: Eye,
|
|
},
|
|
] as const
|
|
|
|
const COMMENTS_OPTIONS = [
|
|
{ id: "hidden" as const, label: "Masquer les commentaires" },
|
|
{ id: "collapsed" as const, label: "Réduire les commentaires" },
|
|
{ id: "expanded" as const, label: "Développer les commentaires" },
|
|
{ id: "all" as const, label: "Afficher tous les commentaires" },
|
|
] as const
|
|
|
|
function MenuIcon({ children }: { children: ReactNode }) {
|
|
return <span className="docs-menu-item-icon">{children}</span>
|
|
}
|
|
|
|
function CheckMenuOption({
|
|
checked,
|
|
onSelect,
|
|
children,
|
|
disabled,
|
|
}: {
|
|
checked: boolean
|
|
onSelect: () => void
|
|
children: ReactNode
|
|
disabled?: boolean
|
|
}) {
|
|
return (
|
|
<MenubarItem
|
|
className="docs-menu-item relative pl-8"
|
|
disabled={disabled}
|
|
onClick={onSelect}
|
|
>
|
|
{checked ? <Check className="absolute left-2 size-4" aria-hidden /> : null}
|
|
{children}
|
|
</MenubarItem>
|
|
)
|
|
}
|
|
|
|
function ModeMenuOption({
|
|
icon: Icon,
|
|
label,
|
|
description,
|
|
selected,
|
|
onSelect,
|
|
disabled,
|
|
}: {
|
|
icon: typeof Pencil
|
|
label: string
|
|
description: string
|
|
selected: boolean
|
|
onSelect: () => void
|
|
disabled?: boolean
|
|
}) {
|
|
return (
|
|
<MenubarItem
|
|
className={cn("docs-menu-item docs-menu-mode-item items-start py-2", selected && "bg-accent/60")}
|
|
disabled={disabled}
|
|
onClick={onSelect}
|
|
>
|
|
<MenuIcon>
|
|
<Icon className="size-4" />
|
|
</MenuIcon>
|
|
<span className="flex min-w-0 flex-col gap-0.5 leading-tight">
|
|
<span className="text-sm font-normal">{label}</span>
|
|
<span className="text-xs text-[#5f6368] dark:text-muted-foreground">{description}</span>
|
|
</span>
|
|
</MenubarItem>
|
|
)
|
|
}
|
|
|
|
export function DocsViewMenu({
|
|
state,
|
|
actions,
|
|
disabled,
|
|
}: {
|
|
state: DocsViewMenuState
|
|
actions: DocsViewMenuActions
|
|
disabled?: boolean
|
|
}) {
|
|
return (
|
|
<MenubarMenu>
|
|
<MenubarTrigger className="docs-menu-trigger">Affichage</MenubarTrigger>
|
|
<MenubarContent
|
|
{...DOCS_MENUBAR_CONTENT_PROPS}
|
|
className="docs-menu-content min-w-[300px] overflow-visible"
|
|
data-docs-menu-surface
|
|
>
|
|
<DocsExclusiveMenuSubRoot>
|
|
<DocsExclusiveMenuSub id="mode">
|
|
<MenubarSubTrigger className="docs-menu-item" disabled={disabled}>
|
|
<MenuIcon>
|
|
<Pencil className="size-4" />
|
|
</MenuIcon>
|
|
Mode
|
|
</MenubarSubTrigger>
|
|
<MenubarSubContent
|
|
className="docs-menu-content docs-menu-sub-content min-w-[280px] overflow-visible"
|
|
data-docs-menu-surface
|
|
>
|
|
{EDITOR_MODES.map((mode) => (
|
|
<ModeMenuOption
|
|
key={mode.id}
|
|
icon={mode.icon}
|
|
label={mode.label}
|
|
description={mode.description}
|
|
selected={state.editorMode === mode.id}
|
|
disabled={disabled}
|
|
onSelect={() => actions.onEditorModeChange(mode.id)}
|
|
/>
|
|
))}
|
|
</MenubarSubContent>
|
|
</DocsExclusiveMenuSub>
|
|
|
|
<DocsExclusiveMenuSub id="comments">
|
|
<MenubarSubTrigger className="docs-menu-item" disabled={disabled}>
|
|
<MenuIcon>
|
|
<MessageSquare className="size-4" />
|
|
</MenuIcon>
|
|
Commentaires
|
|
</MenubarSubTrigger>
|
|
<MenubarSubContent
|
|
className="docs-menu-content docs-menu-sub-content min-w-[260px] overflow-visible"
|
|
data-docs-menu-surface
|
|
>
|
|
{COMMENTS_OPTIONS.map((option) => (
|
|
<CheckMenuOption
|
|
key={option.id}
|
|
checked={state.commentsDisplay === option.id}
|
|
disabled={disabled}
|
|
onSelect={() => actions.onCommentsDisplayChange(option.id)}
|
|
>
|
|
{option.label}
|
|
</CheckMenuOption>
|
|
))}
|
|
</MenubarSubContent>
|
|
</DocsExclusiveMenuSub>
|
|
|
|
<MenubarItem
|
|
className="docs-menu-item"
|
|
disabled={disabled}
|
|
onClick={actions.onToggleOutlineSidebar}
|
|
>
|
|
<MenuIcon>
|
|
<ListTree className="size-4" />
|
|
</MenuIcon>
|
|
Développer la barre latérale des onglets et sections
|
|
<span className="docs-menu-shortcut-sequence ml-auto text-xs text-[#5f6368] dark:text-muted-foreground">
|
|
Ctrl+⌥A Ctrl+⌥H
|
|
</span>
|
|
</MenubarItem>
|
|
|
|
<MenubarSeparator />
|
|
|
|
<DocsExclusiveMenuSub id="text-width">
|
|
<MenubarSubTrigger className="docs-menu-item" disabled>
|
|
<MenuIcon>
|
|
<AlignHorizontalSpaceAround className="size-4" />
|
|
</MenuIcon>
|
|
Largeur du texte
|
|
</MenubarSubTrigger>
|
|
<MenubarSubContent
|
|
className="docs-menu-content docs-menu-sub-content min-w-[220px] overflow-visible"
|
|
data-docs-menu-surface
|
|
>
|
|
<MenubarItem disabled className="docs-menu-item text-muted-foreground">
|
|
Bientôt disponible
|
|
</MenubarItem>
|
|
</MenubarSubContent>
|
|
</DocsExclusiveMenuSub>
|
|
|
|
<MenubarSeparator />
|
|
</DocsExclusiveMenuSubRoot>
|
|
|
|
<MenubarCheckboxItem
|
|
className="docs-menu-item docs-menu-checkbox-item"
|
|
checked={state.showLayout}
|
|
disabled={disabled}
|
|
onCheckedChange={() => actions.onToggleShowLayout()}
|
|
>
|
|
Afficher la mise en page
|
|
</MenubarCheckboxItem>
|
|
<MenubarCheckboxItem
|
|
className="docs-menu-item docs-menu-checkbox-item"
|
|
checked={state.showRuler}
|
|
disabled={disabled}
|
|
onCheckedChange={() => actions.onToggleShowRuler()}
|
|
>
|
|
Afficher la règle
|
|
</MenubarCheckboxItem>
|
|
<MenubarCheckboxItem
|
|
className="docs-menu-item docs-menu-checkbox-item"
|
|
checked={state.showEquationToolbar}
|
|
disabled={disabled}
|
|
onCheckedChange={() => actions.onToggleShowEquationToolbar()}
|
|
>
|
|
Afficher la barre d'outils d'équation
|
|
</MenubarCheckboxItem>
|
|
<MenubarCheckboxItem
|
|
className="docs-menu-item docs-menu-checkbox-item"
|
|
checked={state.showNonPrintableChars}
|
|
disabled={disabled}
|
|
onCheckedChange={() => actions.onToggleShowNonPrintableChars()}
|
|
>
|
|
Afficher les caractères non imprimables
|
|
<DocsMenuShortcut shortcutId="view.showNonPrintable" />
|
|
</MenubarCheckboxItem>
|
|
|
|
<MenubarSeparator />
|
|
|
|
<MenubarItem className="docs-menu-item" disabled={disabled} onClick={actions.onFullscreen}>
|
|
<MenuIcon>
|
|
<Maximize2 className="size-4" />
|
|
</MenuIcon>
|
|
Plein écran
|
|
</MenubarItem>
|
|
</MenubarContent>
|
|
</MenubarMenu>
|
|
)
|
|
}
|