ultisuite-client/components/drive/richtext/docs-format-menu-presets.tsx
R3D347HR4Y 303b2b1074
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
wow
2026-06-11 01:22:40 +02:00

204 lines
5.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import type { ReactNode } from "react"
import {
DOCS_BULLET_STYLE_PRESETS,
DOCS_ORDERED_STYLE_PRESETS,
type DocsBulletStyleId,
type DocsChecklistStyleId,
type DocsOrderedStyleId,
} from "@/lib/drive/docs-list-styles"
import { cn } from "@/lib/utils"
function PresetButton({
disabled,
active,
onClick,
children,
className,
label,
}: {
disabled?: boolean
active?: boolean
onClick?: () => void
children: ReactNode
className?: string
label: string
}) {
return (
<button
type="button"
disabled={disabled}
aria-label={label}
aria-pressed={active}
onClick={onClick}
className={cn(
"rounded border border-[#dadce0] bg-white p-2 text-left text-[10px] leading-tight text-[#3c4043]",
"transition-colors hover:bg-[#f1f3f4] disabled:cursor-not-allowed disabled:opacity-50",
"dark:border-border dark:bg-background dark:text-foreground dark:hover:bg-muted",
active && "border-[#1a73e8] ring-1 ring-[#1a73e8]",
className
)}
>
{children}
</button>
)
}
export function DocsFormatColumnPresets({ disabled }: { disabled?: boolean }) {
return (
<div className="grid grid-cols-3 gap-2 px-1">
{[1, 2, 3].map((count) => (
<PresetButton
key={count}
disabled={disabled}
active={count === 1}
label={`${count} colonne${count > 1 ? "s" : ""}`}
className="flex h-14 items-stretch justify-center gap-0.5 p-1.5"
>
{Array.from({ length: count }, (_, index) => (
<span
key={index}
className="flex flex-1 flex-col justify-center gap-0.5 rounded-sm bg-[#e8eaed] px-0.5 py-1 dark:bg-muted"
>
<span className="block h-px w-full bg-[#9aa0a6]" />
<span className="block h-px w-full bg-[#9aa0a6]" />
<span className="block h-px w-3/4 bg-[#9aa0a6]" />
</span>
))}
</PresetButton>
))}
</div>
)
}
const NUMBERED_PRESET_LINES: Record<DocsOrderedStyleId, readonly string[]> = {
decimal: ["1.", " a.", " i."],
"decimal-paren": ["1)", " a)", " i)"],
outline: ["1.", " 1.1.", " 1.1.1."],
"upper-alpha": ["A.", " a.", " i.", "B."],
"upper-roman": ["I.", " A.", " 1.", "II."],
"zero-padded": ["01.", "02."],
}
export function DocsFormatNumberedPresets({
disabled,
activeStyleId,
onSelect,
}: {
disabled?: boolean
activeStyleId?: DocsOrderedStyleId | null | "mixed"
onSelect: (styleId: DocsOrderedStyleId) => void
}) {
return (
<div className="grid grid-cols-3 gap-2">
{DOCS_ORDERED_STYLE_PRESETS.map((preset) => (
<PresetButton
key={preset.id}
disabled={disabled}
active={activeStyleId !== "mixed" && activeStyleId === preset.id}
label={`Liste numérotée ${preset.id}`}
onClick={() => onSelect(preset.id)}
className="min-h-[72px] font-mono"
>
{NUMBERED_PRESET_LINES[preset.id].map((line) => (
<span key={line} className="block whitespace-pre">
{line}
</span>
))}
</PresetButton>
))}
</div>
)
}
export function DocsFormatBulletPresets({
disabled,
activeStyleId,
onSelect,
}: {
disabled?: boolean
activeStyleId?: DocsBulletStyleId | null | "mixed"
onSelect: (styleId: DocsBulletStyleId) => void
}) {
const symbols: Record<DocsBulletStyleId, string> = {
disc: "•",
circle: "◦",
square: "▪",
arrow: "➤",
check: "✓",
dash: "",
}
return (
<div className="grid grid-cols-3 gap-2">
{DOCS_BULLET_STYLE_PRESETS.map((preset) => (
<PresetButton
key={preset.id}
disabled={disabled}
active={activeStyleId !== "mixed" && activeStyleId === preset.id}
label={`Liste à puces ${preset.id}`}
onClick={() => onSelect(preset.id)}
className="min-h-[56px]"
>
<span className="block">
{symbols[preset.id]} Élément
</span>
<span className="block">
{symbols[preset.id]} Élément
</span>
</PresetButton>
))}
</div>
)
}
export function DocsFormatChecklistPresets({
disabled,
activeStyleId,
onSelect,
}: {
disabled?: boolean
activeStyleId?: DocsChecklistStyleId | null | "mixed"
onSelect: (styleId: DocsChecklistStyleId) => void
}) {
return (
<div className="grid grid-cols-2 gap-2">
<PresetButton
disabled={disabled}
active={activeStyleId !== "mixed" && activeStyleId === "strikethrough"}
label="Checklist avec texte barré"
className="min-h-[56px]"
onClick={() => onSelect("strikethrough")}
>
<span className="flex items-center gap-1.5">
<span className="inline-flex size-3 shrink-0 rounded-sm border border-[#5f6368]" />
Tâche
</span>
<span className="flex items-center gap-1.5 line-through opacity-70">
<span className="inline-flex size-3 shrink-0 items-center justify-center rounded-sm border border-[#1a73e8] bg-[#1a73e8] text-[8px] text-white">
</span>
Terminé
</span>
</PresetButton>
<PresetButton
disabled={disabled}
active={activeStyleId !== "mixed" && activeStyleId === "simple"}
label="Checklist simple"
className="min-h-[56px]"
onClick={() => onSelect("simple")}
>
<span className="flex items-center gap-1.5">
<span className="inline-flex size-3 shrink-0 rounded-sm border border-[#5f6368]" />
Tâche
</span>
<span className="flex items-center gap-1.5">
<span className="inline-flex size-3 shrink-0 rounded-sm border border-[#5f6368]" />
Tâche
</span>
</PresetButton>
</div>
)
}