rewrote pipeline as draggable card strip with per-rule config popovers, added right-click menus to pipeline cards, sidebar tree, and file list, preset import/export with BRU format support, new rules (hash, swap, truncate, sanitize, padding, randomize, text editor, folder name, transliterate), settings dialog with all sections, overlay collision containment, tooltips on icon buttons, empty pipeline default
66 lines
2.4 KiB
TypeScript
66 lines
2.4 KiB
TypeScript
import { useRuleStore } from "@/stores/ruleStore";
|
|
import { Input } from "@/components/ui/input";
|
|
import { SegmentedControl } from "@/components/ui/segmented-control";
|
|
import type { CaseConfig as CaseConfigType } from "@/types/rules";
|
|
|
|
const basicModes = [
|
|
{ value: "Same", label: "Same" },
|
|
{ value: "Upper", label: "UPPER" },
|
|
{ value: "Lower", label: "lower" },
|
|
{ value: "Title", label: "Title" },
|
|
{ value: "Sentence", label: "Sent." },
|
|
{ value: "SmartTitle", label: "Smart" },
|
|
{ value: "Invert", label: "iNVERT" },
|
|
{ value: "Random", label: "rAnD" },
|
|
] as const;
|
|
|
|
const devModes = [
|
|
{ value: "CamelCase", label: "camelCase" },
|
|
{ value: "PascalCase", label: "Pascal" },
|
|
{ value: "SnakeCase", label: "snake_case" },
|
|
{ value: "KebabCase", label: "kebab-case" },
|
|
{ value: "DotCase", label: "dot.case" },
|
|
] as const;
|
|
|
|
export function CaseConfig({ ruleId }: { ruleId: string }) {
|
|
const rule = useRuleStore((s) => s.pipeline.find((r) => r.id === ruleId))?.config as CaseConfigType | undefined;
|
|
const updateRule = useRuleStore((s) => s.updateRule);
|
|
if (!rule) return null;
|
|
const update = (changes: Partial<CaseConfigType>) => updateRule(ruleId, changes);
|
|
|
|
const devValues = ["CamelCase", "PascalCase", "SnakeCase", "KebabCase", "DotCase"];
|
|
const isDevMode = devValues.includes(rule.mode);
|
|
|
|
return (
|
|
<div className="flex flex-col gap-3 text-sm">
|
|
<div className="flex flex-col gap-1">
|
|
<span className="text-xs text-muted-foreground">Text case</span>
|
|
<SegmentedControl
|
|
value={isDevMode ? ("" as typeof rule.mode) : rule.mode}
|
|
onChange={(m) => update({ mode: m })}
|
|
options={basicModes}
|
|
size="sm"
|
|
/>
|
|
</div>
|
|
<div className="flex flex-col gap-1">
|
|
<span className="text-xs text-muted-foreground">Developer case</span>
|
|
<SegmentedControl
|
|
value={isDevMode ? rule.mode : ("" as typeof rule.mode)}
|
|
onChange={(m) => update({ mode: m })}
|
|
options={devModes}
|
|
size="sm"
|
|
/>
|
|
</div>
|
|
<label className="flex flex-col gap-1">
|
|
<span className="text-xs text-muted-foreground">Exceptions (comma-separated)</span>
|
|
<Input
|
|
value={rule.exceptions}
|
|
onChange={(e) => update({ exceptions: e.target.value })}
|
|
placeholder="e.g. USB, HTML, API"
|
|
className="h-8 text-xs font-mono"
|
|
/>
|
|
</label>
|
|
</div>
|
|
);
|
|
}
|