'use client'; /** * CronScheduler Client Component * * Compact cron builder. The default surface is a single popover trigger * that reads like a value input ("Weekdays at 09:00") — the schedule * editor lives inside the popover, following the ui-core combobox * pattern. Pass `inline` to render the editor expanded without a popover. */ import { useState } from 'react'; import { Calendar, ChevronsUpDown, Check, Copy } from 'lucide-react'; import { Popover, PopoverContent, PopoverTrigger, } from '@djangocfg/ui-core/components'; import { cn } from '@djangocfg/ui-core/lib'; import { CronSchedulerProvider } from './context/CronSchedulerContext'; import { useCronType, useCronPreview, useCronSize } from './context/hooks'; import { ScheduleTypeSelector, TimeSelector, DayChips, MonthDayGrid, CustomInput, } from './components'; import type { CronSchedulerProps } from './types'; // ============================================================================ // Schedule editor (shared by inline + popover modes) // ============================================================================ interface ScheduleEditorProps { timeFormat: '12h' | '24h'; disabled: boolean; } function ScheduleEditor({ timeFormat, disabled }: ScheduleEditorProps) { const { type } = useCronType(); const size = useCronSize(); const isSm = size === 'sm'; return (
{type !== 'custom' && ( )} {type === 'weekly' && } {type === 'monthly' && } {type === 'custom' && }
); } // ============================================================================ // Cron expression line (shared) // ============================================================================ function CronExpressionLine({ allowCopy, className, }: { allowCopy: boolean; className?: string; }) { const [copied, setCopied] = useState(false); const { cronExpression, isValid } = useCronPreview(); const isSm = useCronSize() === 'sm'; const handleCopy = async (e: React.MouseEvent) => { e.stopPropagation(); try { await navigator.clipboard.writeText(cronExpression); setCopied(true); setTimeout(() => setCopied(false), 2000); } catch (err) { console.error('Failed to copy:', err); } }; return (
{cronExpression} {allowCopy && ( )}
); } // ============================================================================ // Compact popover trigger (default surface) // ============================================================================ interface CompactTriggerProps { showCronExpression: boolean; allowCopy: boolean; timeFormat: '12h' | '24h'; disabled: boolean; placeholder: string; className?: string; } function CompactTrigger({ showCronExpression, allowCopy, timeFormat, disabled, placeholder, className, }: CompactTriggerProps) { const [open, setOpen] = useState(false); const { humanDescription, isValid } = useCronPreview(); const isSm = useCronSize() === 'sm'; return (
{showCronExpression && ( )}
); } // ============================================================================ // Inline variant (editor expanded, no popover) // ============================================================================ interface InlineSchedulerProps extends ScheduleEditorProps { showCronExpression: boolean; allowCopy: boolean; className?: string; } function InlineScheduler({ timeFormat, disabled, showCronExpression, allowCopy, className, }: InlineSchedulerProps) { const isSm = useCronSize() === 'sm'; return (
); } function InlinePreview({ showCronExpression, allowCopy, }: { showCronExpression: boolean; allowCopy: boolean; }) { const { humanDescription, isValid } = useCronPreview(); const isSm = useCronSize() === 'sm'; return (
{showCronExpression && ( )}
); } // ============================================================================ // Main Component (with Provider) // ============================================================================ /** * CronScheduler - compact cron expression builder * * Default surface is a single popover trigger that reads the schedule as * plain text ("Weekdays at 09:00"). Pass `inline` for the legacy expanded * layout. * * @example * * * @example * // Legacy expanded layout * */ export function CronScheduler({ value, onChange, defaultType = 'daily', showCronExpression = false, allowCopy = false, timeFormat = '24h', disabled = false, inline = false, placeholder = 'Set a schedule', size = 'default', className, }: CronSchedulerProps) { return ( {inline ? ( ) : ( )} ); } export default CronScheduler;