mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-27 21:33:41 +02:00
Replace the free-form trigger-config form with a structured schedule editor built on an orthogonal cron model: separate frequency, time, and day-of-week/day-of-month dimensions map to and from cron expressions via a dedicated grammar and mapping layer, with validation and a human-readable describe() summary. The grammar suite drives the editor against a combinatorially generated corpus of 51,755 distinct cron expressions - every token form of every field, crossed - each judged against a reference robfig/cron v3 parser. Add a server-side /autopilot/cron-preview endpoint (plus schema and React Query hook) so the editor shows upcoming run times, and echo wildcard-carrying cron lists correctly instead of collapsing them. Supporting pieces: timezone-aware formatting helper, segmented-toggle and debounced-value utilities, a reworked time-input, and refreshed en/ja/ko/zh-Hans locale strings.
46 lines
1.3 KiB
TypeScript
46 lines
1.3 KiB
TypeScript
"use client";
|
|
|
|
import type { ReactNode } from "react";
|
|
import { cn } from "@multica/ui/lib/utils";
|
|
|
|
/** A pill-button group for picking between mutually exclusive modes: the active
|
|
* option lifts to the background, the rest stay muted. One control for every
|
|
* either/or, so switching mode always looks and works the same wherever it
|
|
* appears. */
|
|
export function SegmentedToggle<T extends string>({
|
|
value,
|
|
options,
|
|
onChange,
|
|
buttonClassName,
|
|
}: {
|
|
value: T;
|
|
options: ReadonlyArray<readonly [T, ReactNode]>;
|
|
onChange: (value: T) => void;
|
|
/** Overrides the compact default sizing (text-xs px-2 py-1). */
|
|
buttonClassName?: string;
|
|
}) {
|
|
return (
|
|
<div className="grid auto-cols-fr grid-flow-col gap-1 rounded-md bg-muted p-1">
|
|
{options.map(([key, label]) => (
|
|
<button
|
|
key={key}
|
|
type="button"
|
|
aria-pressed={value === key}
|
|
onClick={() => {
|
|
if (key !== value) onChange(key);
|
|
}}
|
|
className={cn(
|
|
"rounded-sm font-medium transition-colors",
|
|
buttonClassName ?? "px-2 py-1 text-xs",
|
|
value === key
|
|
? "bg-background text-foreground shadow-sm"
|
|
: "text-muted-foreground hover:text-foreground",
|
|
)}
|
|
>
|
|
{label}
|
|
</button>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|