ultisuite-client/components/agenda/agenda-step-adjust.tsx
R3D347HR4Y ad1370ea7e
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
feat: enhance configuration and add new demo layouts
- Introduced turbopack alias for canvas in next.config.mjs.
- Updated package.json scripts for development and branding tasks.
- Added new dependencies for Tiptap extensions.
- Implemented new demo layouts for agenda, contacts, drive, and mail applications.
- Enhanced globals.css for improved theming and splash screen animations.
- Added OAuth callback handling for drive mounts.
- Updated layout components to integrate new demo shells and improve structure.
2026-06-12 19:10:24 +02:00

218 lines
4.4 KiB
TypeScript

"use client"
import type { KeyboardEvent, ReactNode } from "react"
import { ChevronLeft, ChevronRight, Minus, Plus } from "lucide-react"
import { Button } from "@/components/ui/button"
import { cn } from "@/lib/utils"
export function handleStepAdjustKeyDown(
e: KeyboardEvent,
onDecrease: () => void,
onIncrease: () => void,
) {
if (e.key === "ArrowUp" || e.key === "+" || (e.key === "=" && !e.shiftKey)) {
e.preventDefault()
onIncrease()
} else if (e.key === "ArrowDown" || e.key === "-") {
e.preventDefault()
onDecrease()
}
}
export function StepAdjustDecreaseButton({
onClick,
disabled,
label,
className,
}: {
onClick: () => void
disabled?: boolean
label: string
className?: string
}) {
return (
<Button
type="button"
tabIndex={-1}
variant="ghost"
size="icon"
className={cn("size-7 rounded-full", className)}
aria-label={label}
disabled={disabled}
onClick={onClick}
>
<Minus className="size-4" />
</Button>
)
}
export function StepAdjustIncreaseButton({
onClick,
disabled,
label,
className,
}: {
onClick: () => void
disabled?: boolean
label: string
className?: string
}) {
return (
<Button
type="button"
tabIndex={-1}
variant="ghost"
size="icon"
className={cn("size-7 rounded-full", className)}
aria-label={label}
disabled={disabled}
onClick={onClick}
>
<Plus className="size-4" />
</Button>
)
}
/** Reculer l'heure — chevron gauche (réservé aux champs horaires). */
export function StepAdjustTimeDecreaseButton({
onClick,
disabled,
label,
className,
}: {
onClick: () => void
disabled?: boolean
label: string
className?: string
}) {
return (
<Button
type="button"
tabIndex={-1}
variant="ghost"
size="icon"
className={cn("size-7 rounded-full", className)}
aria-label={label}
disabled={disabled}
onClick={onClick}
>
<ChevronLeft className="size-4" />
</Button>
)
}
/** Avancer l'heure — chevron droit (réservé aux champs horaires). */
export function StepAdjustTimeIncreaseButton({
onClick,
disabled,
label,
className,
}: {
onClick: () => void
disabled?: boolean
label: string
className?: string
}) {
return (
<Button
type="button"
tabIndex={-1}
variant="ghost"
size="icon"
className={cn("size-7 rounded-full", className)}
aria-label={label}
disabled={disabled}
onClick={onClick}
>
<ChevronRight className="size-4" />
</Button>
)
}
export function StepAdjustGroup({
children,
className,
}: {
children: ReactNode
className?: string
}) {
return (
<div
className={cn(
"inline-flex items-center gap-1 rounded-full border border-border/70 bg-muted/40 px-1 py-0.5",
className,
)}
>
{children}
</div>
)
}
export function FocusableStepValue({
tabIndex,
value,
ariaLabel,
onDecrease,
onIncrease,
decreaseDisabled,
increaseDisabled,
decreaseLabel,
increaseLabel,
className,
buttonClassName,
valueWrapperClassName,
valueClassName,
}: {
tabIndex?: number
value: string
ariaLabel: string
onDecrease: () => void
onIncrease: () => void
decreaseDisabled?: boolean
increaseDisabled?: boolean
decreaseLabel: string
increaseLabel: string
className?: string
buttonClassName?: string
valueWrapperClassName?: string
valueClassName?: string
}) {
const valueNode = (
<span
tabIndex={tabIndex}
role="spinbutton"
aria-label={ariaLabel}
aria-valuetext={value}
onKeyDown={(e) => handleStepAdjustKeyDown(e, onDecrease, onIncrease)}
className={cn(
"cursor-default outline-none focus-visible:rounded-sm focus-visible:ring-2 focus-visible:ring-ring",
valueClassName,
)}
>
{value}
</span>
)
return (
<StepAdjustGroup className={className}>
<StepAdjustDecreaseButton
onClick={onDecrease}
disabled={decreaseDisabled}
label={decreaseLabel}
className={buttonClassName}
/>
{valueWrapperClassName ? (
<div className={valueWrapperClassName}>{valueNode}</div>
) : (
valueNode
)}
<StepAdjustIncreaseButton
onClick={onIncrease}
disabled={increaseDisabled}
label={increaseLabel}
className={buttonClassName}
/>
</StepAdjustGroup>
)
}