refactor: replace inline labels with reusable FieldLabel component in dialogs
This commit is contained in:
parent
77bed648ae
commit
63c1b95f20
25 changed files with 329 additions and 323 deletions
|
|
@ -73,13 +73,13 @@ export const BLOCK_GROUPS: BlockGroup[] = [
|
|||
{
|
||||
kind: "sampler",
|
||||
title: "Samplers",
|
||||
description: "Numeric + categorical blocks.",
|
||||
description: "Fast deterministic columns from distributions and categories.",
|
||||
icon: DiceFaces03Icon,
|
||||
},
|
||||
{
|
||||
kind: "seed",
|
||||
title: "Seed",
|
||||
description: "Columns from a seed dataset.",
|
||||
description: "Bootstrap generation from an existing dataset.",
|
||||
icon: Plant01Icon,
|
||||
},
|
||||
{
|
||||
|
|
@ -91,7 +91,7 @@ export const BLOCK_GROUPS: BlockGroup[] = [
|
|||
{
|
||||
kind: "expression",
|
||||
title: "Expression",
|
||||
description: "Derived columns with Jinja.",
|
||||
description: "Derive columns with Jinja templates.",
|
||||
icon: FunctionIcon,
|
||||
},
|
||||
];
|
||||
|
|
@ -101,7 +101,7 @@ const BLOCK_DEFINITIONS: BlockDefinition[] = [
|
|||
kind: "seed",
|
||||
type: "seed",
|
||||
title: "Seed (Hugging Face)",
|
||||
description: "Configure a HF seed dataset.",
|
||||
description: "Load real rows from HF and use them as generation context.",
|
||||
icon: Plant01Icon,
|
||||
dialogKey: "seed",
|
||||
createConfig: (id, existing) => makeSeedConfig(id, existing),
|
||||
|
|
@ -110,7 +110,7 @@ const BLOCK_DEFINITIONS: BlockDefinition[] = [
|
|||
kind: "sampler",
|
||||
type: "category",
|
||||
title: "Category",
|
||||
description: "Pick from a list of values.",
|
||||
description: "Define categorical values with optional weights and conditions.",
|
||||
icon: Tag01Icon,
|
||||
dialogKey: "category",
|
||||
createConfig: (id, existing) => makeSamplerConfig(id, "category", existing),
|
||||
|
|
@ -119,7 +119,7 @@ const BLOCK_DEFINITIONS: BlockDefinition[] = [
|
|||
kind: "sampler",
|
||||
type: "subcategory",
|
||||
title: "Subcategory",
|
||||
description: "Map sub-values to a category.",
|
||||
description: "Define hierarchical values mapped to a parent category.",
|
||||
icon: TagsIcon,
|
||||
dialogKey: "subcategory",
|
||||
createConfig: (id, existing) => makeSamplerConfig(id, "subcategory", existing),
|
||||
|
|
@ -128,7 +128,7 @@ const BLOCK_DEFINITIONS: BlockDefinition[] = [
|
|||
kind: "sampler",
|
||||
type: "uniform",
|
||||
title: "Uniform",
|
||||
description: "Random number between low/high.",
|
||||
description: "Sample evenly between low and high.",
|
||||
icon: EqualSignIcon,
|
||||
dialogKey: "uniform",
|
||||
createConfig: (id, existing) => makeSamplerConfig(id, "uniform", existing),
|
||||
|
|
@ -137,7 +137,7 @@ const BLOCK_DEFINITIONS: BlockDefinition[] = [
|
|||
kind: "sampler",
|
||||
type: "gaussian",
|
||||
title: "Gaussian",
|
||||
description: "Normal distribution sampler.",
|
||||
description: "Sample from a normal distribution (mean/stddev).",
|
||||
icon: Parabola02Icon,
|
||||
dialogKey: "gaussian",
|
||||
createConfig: (id, existing) => makeSamplerConfig(id, "gaussian", existing),
|
||||
|
|
@ -146,7 +146,7 @@ const BLOCK_DEFINITIONS: BlockDefinition[] = [
|
|||
kind: "sampler",
|
||||
type: "bernoulli",
|
||||
title: "Bernoulli",
|
||||
description: "Binary sampler with probability.",
|
||||
description: "Sample binary outcomes from probability p.",
|
||||
icon: EqualSignIcon,
|
||||
dialogKey: "bernoulli",
|
||||
createConfig: (id, existing) => makeSamplerConfig(id, "bernoulli", existing),
|
||||
|
|
@ -155,7 +155,7 @@ const BLOCK_DEFINITIONS: BlockDefinition[] = [
|
|||
kind: "sampler",
|
||||
type: "datetime",
|
||||
title: "Datetime",
|
||||
description: "Date/time range sampler.",
|
||||
description: "Sample timestamps within a start/end range.",
|
||||
icon: Clock01Icon,
|
||||
dialogKey: "datetime",
|
||||
createConfig: (id, existing) => makeSamplerConfig(id, "datetime", existing),
|
||||
|
|
@ -164,7 +164,7 @@ const BLOCK_DEFINITIONS: BlockDefinition[] = [
|
|||
kind: "sampler",
|
||||
type: "timedelta",
|
||||
title: "Timedelta",
|
||||
description: "Offset from datetime column.",
|
||||
description: "Sample time offsets from a reference datetime column.",
|
||||
icon: Clock01Icon,
|
||||
dialogKey: "timedelta",
|
||||
createConfig: (id, existing) => makeSamplerConfig(id, "timedelta", existing),
|
||||
|
|
@ -173,7 +173,7 @@ const BLOCK_DEFINITIONS: BlockDefinition[] = [
|
|||
kind: "sampler",
|
||||
type: "uuid",
|
||||
title: "UUID",
|
||||
description: "UUID string sampler.",
|
||||
description: "Generate unique identifiers with optional formatting.",
|
||||
icon: FingerPrintIcon,
|
||||
dialogKey: "uuid",
|
||||
createConfig: (id, existing) => makeSamplerConfig(id, "uuid", existing),
|
||||
|
|
@ -182,7 +182,7 @@ const BLOCK_DEFINITIONS: BlockDefinition[] = [
|
|||
kind: "sampler",
|
||||
type: "person",
|
||||
title: "Person",
|
||||
description: "Faker person sampler.",
|
||||
description: "Generate realistic synthetic people with faker attributes.",
|
||||
icon: UserAccountIcon,
|
||||
dialogKey: "person",
|
||||
createConfig: (id, existing) => makeSamplerConfig(id, "person", existing),
|
||||
|
|
@ -191,7 +191,7 @@ const BLOCK_DEFINITIONS: BlockDefinition[] = [
|
|||
kind: "llm",
|
||||
type: "text",
|
||||
title: "LLM Text",
|
||||
description: "Free-form prompt generation.",
|
||||
description: "Generate natural language text from prompt templates.",
|
||||
icon: PencilEdit02Icon,
|
||||
dialogKey: "llm",
|
||||
createConfig: (id, existing) => makeLlmConfig(id, "text", existing),
|
||||
|
|
@ -200,7 +200,7 @@ const BLOCK_DEFINITIONS: BlockDefinition[] = [
|
|||
kind: "llm",
|
||||
type: "structured",
|
||||
title: "LLM Structured",
|
||||
description: "JSON output via schema.",
|
||||
description: "Generate JSON constrained to a schema.",
|
||||
icon: CodeIcon,
|
||||
dialogKey: "llm",
|
||||
createConfig: (id, existing) => makeLlmConfig(id, "structured", existing),
|
||||
|
|
@ -209,7 +209,7 @@ const BLOCK_DEFINITIONS: BlockDefinition[] = [
|
|||
kind: "llm",
|
||||
type: "code",
|
||||
title: "LLM Code",
|
||||
description: "Generate code or SQL.",
|
||||
description: "Generate code in a chosen language with clean extraction.",
|
||||
icon: CodeSimpleIcon,
|
||||
dialogKey: "llm",
|
||||
createConfig: (id, existing) => makeLlmConfig(id, "code", existing),
|
||||
|
|
@ -218,7 +218,7 @@ const BLOCK_DEFINITIONS: BlockDefinition[] = [
|
|||
kind: "llm",
|
||||
type: "judge",
|
||||
title: "LLM Judge",
|
||||
description: "Score outputs with criteria.",
|
||||
description: "Score generated outputs with rubric-based criteria.",
|
||||
icon: BalanceScaleIcon,
|
||||
dialogKey: "llm",
|
||||
createConfig: (id, existing) => makeLlmConfig(id, "judge", existing),
|
||||
|
|
@ -227,7 +227,7 @@ const BLOCK_DEFINITIONS: BlockDefinition[] = [
|
|||
kind: "llm",
|
||||
type: "model_provider",
|
||||
title: "Model Provider",
|
||||
description: "Endpoint, auth, and provider settings.",
|
||||
description: "Define endpoint and auth settings for model access.",
|
||||
icon: Shield02Icon,
|
||||
dialogKey: "model_provider",
|
||||
createConfig: (id, existing) => makeModelProviderConfig(id, existing),
|
||||
|
|
@ -236,7 +236,7 @@ const BLOCK_DEFINITIONS: BlockDefinition[] = [
|
|||
kind: "llm",
|
||||
type: "model_config",
|
||||
title: "Model Config",
|
||||
description: "Alias, model, provider, and inference params.",
|
||||
description: "Bind alias to model, provider, and inference settings.",
|
||||
icon: Plant01Icon,
|
||||
dialogKey: "model_config",
|
||||
createConfig: (id, existing) => makeModelConfig(id, existing),
|
||||
|
|
@ -245,7 +245,7 @@ const BLOCK_DEFINITIONS: BlockDefinition[] = [
|
|||
kind: "expression",
|
||||
type: "expression",
|
||||
title: "Expression",
|
||||
description: "Transform columns with Jinja.",
|
||||
description: "Transform/combine columns using Jinja expressions.",
|
||||
icon: FunctionIcon,
|
||||
dialogKey: "expression",
|
||||
createConfig: (id, existing) => makeExpressionConfig(id, existing),
|
||||
|
|
|
|||
|
|
@ -253,6 +253,7 @@ export function BlockSheet({
|
|||
description={item.description}
|
||||
isActive={index === 0}
|
||||
onClick={() => {
|
||||
setSheetOpen(false);
|
||||
if (item.kind === "sampler") {
|
||||
onAddSampler(item.type as SamplerType);
|
||||
} else if (item.kind === "seed") {
|
||||
|
|
|
|||
|
|
@ -365,7 +365,7 @@ function RecipeGraphNodeBase({
|
|||
openConfig(id);
|
||||
}}
|
||||
>
|
||||
Details
|
||||
Configure
|
||||
</Button>
|
||||
</BaseNodeHeader>
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { Textarea } from "@/components/ui/textarea";
|
|||
import type { ReactElement } from "react";
|
||||
import type { ExpressionConfig, ExpressionDtype } from "../../types";
|
||||
import { AvailableVariables } from "../shared/available-variables";
|
||||
import { FieldLabel } from "../shared/field-label";
|
||||
import { NameField } from "../shared/name-field";
|
||||
|
||||
const DTYPE_OPTIONS: ExpressionDtype[] = ["str", "int", "float", "bool"];
|
||||
|
|
@ -38,12 +39,11 @@ export function ExpressionDialog({
|
|||
onChange={(value) => onUpdate({ name: value })}
|
||||
/>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Output type"
|
||||
htmlFor={dtypeId}
|
||||
>
|
||||
Output type
|
||||
</label>
|
||||
hint="Cast expression output type in final dataset."
|
||||
/>
|
||||
<Select
|
||||
value={config.dtype}
|
||||
onValueChange={(value) =>
|
||||
|
|
@ -63,12 +63,11 @@ export function ExpressionDialog({
|
|||
</Select>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Expression (Jinja2)"
|
||||
htmlFor={exprId}
|
||||
>
|
||||
Expression (Jinja2)
|
||||
</label>
|
||||
hint="Use Jinja to combine or transform existing columns."
|
||||
/>
|
||||
<Textarea
|
||||
id={exprId}
|
||||
className="corner-squircle nodrag"
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {
|
|||
} from "@/components/ui/dialog";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { type ReactElement, useState } from "react";
|
||||
import { FieldLabel } from "./shared/field-label";
|
||||
|
||||
type ImportDialogProps = {
|
||||
open: boolean;
|
||||
|
|
@ -55,12 +56,11 @@ export function ImportDialog({
|
|||
<DialogTitle>Import recipe</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="JSON payload"
|
||||
htmlFor={payloadId}
|
||||
>
|
||||
JSON payload
|
||||
</label>
|
||||
hint="Paste exported recipe payload JSON."
|
||||
/>
|
||||
<Textarea
|
||||
id={payloadId}
|
||||
className="corner-squircle nodrag min-h-[220px]"
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import { Textarea } from "@/components/ui/textarea";
|
|||
import { type ReactElement, type RefObject } from "react";
|
||||
import type { LlmConfig } from "../../types";
|
||||
import { AvailableVariables } from "../shared/available-variables";
|
||||
import { FieldLabel } from "../shared/field-label";
|
||||
import { NameField } from "../shared/name-field";
|
||||
|
||||
const CODE_LANG_OPTIONS = [
|
||||
|
|
@ -75,12 +76,11 @@ export function LlmGeneralTab({
|
|||
</div>
|
||||
)}
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Model alias"
|
||||
htmlFor={modelAliasId}
|
||||
>
|
||||
Model alias
|
||||
</label>
|
||||
hint="Alias must match a Model Config block."
|
||||
/>
|
||||
<div ref={modelAliasAnchorRef}>
|
||||
<Combobox
|
||||
items={modelConfigAliases}
|
||||
|
|
@ -117,12 +117,11 @@ export function LlmGeneralTab({
|
|||
</div>
|
||||
{config.llm_type === "code" && (
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Code language"
|
||||
htmlFor={codeLangId}
|
||||
>
|
||||
Code language
|
||||
</label>
|
||||
hint="Target language for LLM code generation."
|
||||
/>
|
||||
<Select
|
||||
value={config.code_lang ?? "python"}
|
||||
onValueChange={(value) => onUpdate({ code_lang: value })}
|
||||
|
|
@ -141,12 +140,11 @@ export function LlmGeneralTab({
|
|||
</div>
|
||||
)}
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Prompt"
|
||||
htmlFor={promptId}
|
||||
>
|
||||
Prompt
|
||||
</label>
|
||||
hint="Jinja template. references other columns via {{ variable }}."
|
||||
/>
|
||||
<Textarea
|
||||
id={promptId}
|
||||
className="corner-squircle nodrag"
|
||||
|
|
@ -156,12 +154,11 @@ export function LlmGeneralTab({
|
|||
</div>
|
||||
{config.llm_type === "structured" && (
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Output format (JSON schema)"
|
||||
htmlFor={outputFormatId}
|
||||
>
|
||||
Output format (JSON schema)
|
||||
</label>
|
||||
hint="Schema used to constrain structured JSON output."
|
||||
/>
|
||||
<Textarea
|
||||
id={outputFormatId}
|
||||
className="corner-squircle nodrag"
|
||||
|
|
@ -173,12 +170,11 @@ export function LlmGeneralTab({
|
|||
</div>
|
||||
)}
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="System prompt (optional)"
|
||||
htmlFor={systemPromptId}
|
||||
>
|
||||
System prompt (optional)
|
||||
</label>
|
||||
hint="Global behavior instructions prepended before prompt."
|
||||
/>
|
||||
<Textarea
|
||||
id={systemPromptId}
|
||||
className="corner-squircle nodrag"
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import {
|
|||
toApiProvider,
|
||||
} from "./mcp-tools/helpers";
|
||||
import { ToolConfigsSection } from "./mcp-tools/tool-configs-section";
|
||||
import { FieldLabel } from "../shared/field-label";
|
||||
|
||||
type LlmMcpToolsTabProps = {
|
||||
config: LlmConfig;
|
||||
|
|
@ -236,9 +237,10 @@ export function LlmMcpToolsTab({
|
|||
return (
|
||||
<div className="space-y-5">
|
||||
<div className="grid gap-2">
|
||||
<label className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Active tool alias
|
||||
</label>
|
||||
<FieldLabel
|
||||
label="Active tool alias"
|
||||
hint="Tool alias selected here is used by this LLM column."
|
||||
/>
|
||||
{toolAliasOptions.length > 0 ? (
|
||||
<Select
|
||||
value={activeToolAlias}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { Button } from "@/components/ui/button";
|
|||
import { Input } from "@/components/ui/input";
|
||||
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import type { LlmMcpProviderConfig, McpEnvVar } from "../../../types";
|
||||
import { FieldLabel } from "../../shared/field-label";
|
||||
|
||||
type McpProvidersSectionProps = {
|
||||
providers: LlmMcpProviderConfig[];
|
||||
|
|
@ -44,9 +45,10 @@ export function McpProvidersSection({
|
|||
return (
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
MCP servers
|
||||
</p>
|
||||
<FieldLabel
|
||||
label="MCP servers"
|
||||
hint="Server definitions used by tool configs for tool calls."
|
||||
/>
|
||||
<Button type="button" size="xs" variant="outline" onClick={onAddProvider}>
|
||||
<HugeiconsIcon icon={PlusSignIcon} className="size-3.5" />
|
||||
Add MCP server
|
||||
|
|
@ -72,9 +74,10 @@ export function McpProvidersSection({
|
|||
className="space-y-3 border-b border-border/40 pb-4 last:border-b-0"
|
||||
>
|
||||
<div className="grid gap-2">
|
||||
<label className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Name
|
||||
</label>
|
||||
<FieldLabel
|
||||
label="Name"
|
||||
hint="Unique provider name referenced by tool configs."
|
||||
/>
|
||||
<Input
|
||||
value={provider.name}
|
||||
placeholder="MCP server name"
|
||||
|
|
@ -102,9 +105,10 @@ export function McpProvidersSection({
|
|||
{provider.provider_type === "stdio" ? (
|
||||
<div className="space-y-3">
|
||||
<div className="grid gap-2">
|
||||
<label className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Command to launch
|
||||
</label>
|
||||
<FieldLabel
|
||||
label="Command to launch"
|
||||
hint="Executable used to start stdio MCP server."
|
||||
/>
|
||||
<Input
|
||||
value={provider.command ?? ""}
|
||||
placeholder="npx"
|
||||
|
|
@ -117,9 +121,10 @@ export function McpProvidersSection({
|
|||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<p className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Arguments
|
||||
</p>
|
||||
<FieldLabel
|
||||
label="Arguments"
|
||||
hint="CLI args passed to MCP command."
|
||||
/>
|
||||
{args.map((arg, argIndex) => (
|
||||
<div key={`${provider.id}-arg-${argIndex}`} className="flex gap-2">
|
||||
<Input
|
||||
|
|
@ -150,9 +155,10 @@ export function McpProvidersSection({
|
|||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<p className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Environment variables
|
||||
</p>
|
||||
<FieldLabel
|
||||
label="Environment variables"
|
||||
hint="Key/value env vars for MCP process."
|
||||
/>
|
||||
{envVars.map((item, envIndex) => (
|
||||
<div
|
||||
key={`${provider.id}-env-${envIndex}`}
|
||||
|
|
@ -199,9 +205,10 @@ export function McpProvidersSection({
|
|||
) : (
|
||||
<div className="space-y-2">
|
||||
<div className="grid gap-2">
|
||||
<label className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Endpoint
|
||||
</label>
|
||||
<FieldLabel
|
||||
label="Endpoint"
|
||||
hint="Streamable HTTP MCP server URL."
|
||||
/>
|
||||
<Input
|
||||
value={provider.endpoint ?? ""}
|
||||
placeholder="https://example.com/mcp"
|
||||
|
|
@ -213,9 +220,10 @@ export function McpProvidersSection({
|
|||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
API key env (optional)
|
||||
</label>
|
||||
<FieldLabel
|
||||
label="API key env (optional)"
|
||||
hint="Env var name for endpoint auth token."
|
||||
/>
|
||||
<Input
|
||||
value={provider.api_key_env ?? ""}
|
||||
placeholder="MCP_API_KEY"
|
||||
|
|
@ -228,9 +236,10 @@ export function McpProvidersSection({
|
|||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
API key (optional)
|
||||
</label>
|
||||
<FieldLabel
|
||||
label="API key (optional)"
|
||||
hint="Inline token for endpoint auth."
|
||||
/>
|
||||
<Input
|
||||
value={provider.api_key ?? ""}
|
||||
placeholder="api key"
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { Input } from "@/components/ui/input";
|
|||
import { ChipInput } from "../../../components/chip-input";
|
||||
import type { LlmToolConfig } from "../../../types";
|
||||
import { addUnique, collectToolSuggestions } from "./helpers";
|
||||
import { FieldLabel } from "../../shared/field-label";
|
||||
|
||||
type ToolConfigsSectionProps = {
|
||||
toolConfigs: LlmToolConfig[];
|
||||
|
|
@ -30,9 +31,10 @@ export function ToolConfigsSection({
|
|||
return (
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Tool configs
|
||||
</p>
|
||||
<FieldLabel
|
||||
label="Tool configs"
|
||||
hint="Map a tool alias to MCP providers and allowed tools."
|
||||
/>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
type="button"
|
||||
|
|
@ -63,9 +65,10 @@ export function ToolConfigsSection({
|
|||
className="space-y-3 border-b border-border/40 pb-4 last:border-b-0"
|
||||
>
|
||||
<div className="grid gap-2">
|
||||
<label className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Tool alias
|
||||
</label>
|
||||
<FieldLabel
|
||||
label="Tool alias"
|
||||
hint="Alias referenced by LLM column tool_alias."
|
||||
/>
|
||||
<Input
|
||||
value={toolConfig.tool_alias}
|
||||
placeholder="context7_tools"
|
||||
|
|
@ -79,9 +82,10 @@ export function ToolConfigsSection({
|
|||
</div>
|
||||
|
||||
<div className="grid gap-2">
|
||||
<label className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Providers
|
||||
</label>
|
||||
<FieldLabel
|
||||
label="Providers"
|
||||
hint="MCP provider names this alias can call."
|
||||
/>
|
||||
<ChipInput
|
||||
values={toolConfig.providers}
|
||||
suggestions={providerNameSuggestions}
|
||||
|
|
@ -102,9 +106,10 @@ export function ToolConfigsSection({
|
|||
</div>
|
||||
|
||||
<div className="grid gap-2">
|
||||
<label className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Allow tools (optional)
|
||||
</label>
|
||||
<FieldLabel
|
||||
label="Allow tools (optional)"
|
||||
hint="Optional allowlist of tool names."
|
||||
/>
|
||||
<ChipInput
|
||||
// biome-ignore lint/style/useNamingConvention: api schema
|
||||
values={toolConfig.allow_tools ?? []}
|
||||
|
|
@ -129,9 +134,10 @@ export function ToolConfigsSection({
|
|||
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div className="grid gap-2">
|
||||
<label className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Max turns
|
||||
</label>
|
||||
<FieldLabel
|
||||
label="Max turns"
|
||||
hint="Max tool-calling turns before forcing completion."
|
||||
/>
|
||||
<Input
|
||||
value={toolConfig.max_tool_call_turns ?? ""}
|
||||
onChange={(event) =>
|
||||
|
|
@ -143,9 +149,10 @@ export function ToolConfigsSection({
|
|||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Timeout sec
|
||||
</label>
|
||||
<FieldLabel
|
||||
label="Timeout sec"
|
||||
hint="Timeout per tool call."
|
||||
/>
|
||||
<Input
|
||||
value={toolConfig.timeout_sec ?? ""}
|
||||
onChange={(event) =>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Button } from "@/components/ui/button";
|
||||
import { type ReactElement } from "react";
|
||||
import type { LlmConfig, Score } from "../../types";
|
||||
import { FieldLabel } from "../shared/field-label";
|
||||
|
||||
type LlmScoresTabProps = {
|
||||
config: LlmConfig;
|
||||
|
|
@ -38,9 +39,10 @@ export function LlmScoresTab({
|
|||
return (
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Scorers
|
||||
</p>
|
||||
<FieldLabel
|
||||
label="Scorers"
|
||||
hint="Rubrics used by LLM Judge to score each generated row."
|
||||
/>
|
||||
<Button type="button" size="xs" variant="outline" onClick={addScore}>
|
||||
Add scorer block
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import {
|
|||
import { Input } from "@/components/ui/input";
|
||||
import { type ReactElement, useRef } from "react";
|
||||
import type { ModelConfig } from "../../types";
|
||||
import { FieldLabel } from "../shared/field-label";
|
||||
import { NameField } from "../shared/name-field";
|
||||
|
||||
type ModelConfigDialogProps = {
|
||||
|
|
@ -49,12 +50,11 @@ export function ModelConfigDialog({
|
|||
onChange={(value) => onUpdate({ name: value })}
|
||||
/>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Model"
|
||||
htmlFor={modelId}
|
||||
>
|
||||
Model
|
||||
</label>
|
||||
hint="Exact model id string sent to provider."
|
||||
/>
|
||||
<Input
|
||||
id={modelId}
|
||||
className="nodrag"
|
||||
|
|
@ -64,12 +64,11 @@ export function ModelConfigDialog({
|
|||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Provider name"
|
||||
htmlFor={providerId}
|
||||
>
|
||||
Provider name
|
||||
</label>
|
||||
hint="Must match a Model Provider block name."
|
||||
/>
|
||||
<div ref={providerAnchorRef}>
|
||||
<Combobox
|
||||
items={providerOptions}
|
||||
|
|
@ -111,9 +110,10 @@ export function ModelConfigDialog({
|
|||
</p>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Inference
|
||||
</label>
|
||||
<FieldLabel
|
||||
label="Inference"
|
||||
hint="Runtime generation params for this model alias."
|
||||
/>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<Input
|
||||
id={tempId}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Input } from "@/components/ui/input";
|
|||
import { Textarea } from "@/components/ui/textarea";
|
||||
import type { ReactElement } from "react";
|
||||
import type { ModelProviderConfig } from "../../types";
|
||||
import { FieldLabel } from "../shared/field-label";
|
||||
import { NameField } from "../shared/name-field";
|
||||
|
||||
type ModelProviderDialogProps = {
|
||||
|
|
@ -33,12 +34,11 @@ export function ModelProviderDialog({
|
|||
onChange={(value) => onUpdate({ name: value })}
|
||||
/>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Provider type"
|
||||
htmlFor={providerTypeId}
|
||||
>
|
||||
Provider type
|
||||
</label>
|
||||
hint="Provider adapter type, e.g. openai or openrouter."
|
||||
/>
|
||||
<Input
|
||||
id={providerTypeId}
|
||||
className="nodrag"
|
||||
|
|
@ -50,12 +50,11 @@ export function ModelProviderDialog({
|
|||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Endpoint"
|
||||
htmlFor={endpointId}
|
||||
>
|
||||
Endpoint
|
||||
</label>
|
||||
hint="Base API URL used for model requests."
|
||||
/>
|
||||
<Input
|
||||
id={endpointId}
|
||||
className="nodrag"
|
||||
|
|
@ -65,12 +64,11 @@ export function ModelProviderDialog({
|
|||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="API key env (optional)"
|
||||
htmlFor={apiKeyEnvId}
|
||||
>
|
||||
API key env (optional)
|
||||
</label>
|
||||
hint="Env var name to read secret key from runtime."
|
||||
/>
|
||||
<Input
|
||||
id={apiKeyEnvId}
|
||||
className="nodrag"
|
||||
|
|
@ -80,12 +78,11 @@ export function ModelProviderDialog({
|
|||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="API key (optional)"
|
||||
htmlFor={apiKeyId}
|
||||
>
|
||||
API key (optional)
|
||||
</label>
|
||||
hint="Inline key. prefer env var for safer configs."
|
||||
/>
|
||||
<Input
|
||||
id={apiKeyId}
|
||||
className="nodrag"
|
||||
|
|
@ -94,12 +91,11 @@ export function ModelProviderDialog({
|
|||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Extra headers (JSON)"
|
||||
htmlFor={extraHeadersId}
|
||||
>
|
||||
Extra headers (JSON)
|
||||
</label>
|
||||
hint="Optional request headers merged into every call."
|
||||
/>
|
||||
<Textarea
|
||||
id={extraHeadersId}
|
||||
className="corner-squircle nodrag"
|
||||
|
|
@ -111,12 +107,11 @@ export function ModelProviderDialog({
|
|||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Extra body (JSON)"
|
||||
htmlFor={extraBodyId}
|
||||
>
|
||||
Extra body (JSON)
|
||||
</label>
|
||||
hint="Optional payload fields merged into requests."
|
||||
/>
|
||||
<Textarea
|
||||
id={extraBodyId}
|
||||
className="corner-squircle nodrag"
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {
|
|||
} from "@/components/ui/dialog";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { type ReactElement } from "react";
|
||||
import { FieldLabel } from "./shared/field-label";
|
||||
|
||||
type PreviewDialogProps = {
|
||||
open: boolean;
|
||||
|
|
@ -78,12 +79,11 @@ export function PreviewDialog({
|
|||
</div>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Number of records"
|
||||
htmlFor="preview-rows"
|
||||
>
|
||||
Number of records
|
||||
</label>
|
||||
hint="Target rows for preview run."
|
||||
/>
|
||||
<Input
|
||||
id="preview-rows"
|
||||
type="number"
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { type ReactElement, useMemo } from "react";
|
|||
import type { RecipeProcessorConfig } from "../types";
|
||||
import { buildDefaultSchemaTransform } from "../utils/processors";
|
||||
import { AvailableVariables } from "./shared/available-variables";
|
||||
import { FieldLabel } from "./shared/field-label";
|
||||
type ProcessorsDialogProps = {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
|
|
@ -90,12 +91,11 @@ export function ProcessorsDialog({
|
|||
<div className="space-y-3">
|
||||
<AvailableVariables configId="" />
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Name"
|
||||
htmlFor={nameId}
|
||||
>
|
||||
Name
|
||||
</label>
|
||||
hint="Processor name shown in graph and payload."
|
||||
/>
|
||||
<Input
|
||||
id={nameId}
|
||||
className="nodrag"
|
||||
|
|
@ -104,12 +104,11 @@ export function ProcessorsDialog({
|
|||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Template (JSON)"
|
||||
htmlFor={templateId}
|
||||
>
|
||||
Template (JSON)
|
||||
</label>
|
||||
hint="Target output schema template using Jinja references."
|
||||
/>
|
||||
<Textarea
|
||||
id={templateId}
|
||||
className="corner-squircle nodrag min-h-[220px]"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Input } from "@/components/ui/input";
|
|||
import type { ReactElement } from "react";
|
||||
import type { SamplerConfig } from "../../types";
|
||||
import { NameField } from "../shared/name-field";
|
||||
import { FieldLabel } from "../shared/field-label";
|
||||
|
||||
type BernoulliDialogProps = {
|
||||
config: SamplerConfig;
|
||||
|
|
@ -20,12 +21,11 @@ export function BernoulliDialog({
|
|||
onChange={(value) => onUpdate({ name: value })}
|
||||
/>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Probability (p)"
|
||||
htmlFor={pId}
|
||||
>
|
||||
Probability (p)
|
||||
</label>
|
||||
hint="Success probability in [0, 1]."
|
||||
/>
|
||||
<Input
|
||||
id={pId}
|
||||
type="number"
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { Input } from "@/components/ui/input";
|
|||
import { type ReactElement, useState } from "react";
|
||||
import type { SamplerConfig } from "../../types";
|
||||
import { ChipInput } from "../../components/chip-input";
|
||||
import { FieldLabel } from "../shared/field-label";
|
||||
import { NameField } from "../shared/name-field";
|
||||
|
||||
type CategoryDialogProps = {
|
||||
|
|
@ -85,9 +86,10 @@ export function CategoryDialog({
|
|||
/>
|
||||
<div className="space-y-3">
|
||||
<div className="grid gap-2">
|
||||
<p className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Values
|
||||
</p>
|
||||
<FieldLabel
|
||||
label="Values"
|
||||
hint="Define allowed categorical values for this column."
|
||||
/>
|
||||
<ChipInput
|
||||
values={config.values ?? []}
|
||||
onAdd={(value) => {
|
||||
|
|
@ -132,9 +134,10 @@ export function CategoryDialog({
|
|||
</CollapsibleTrigger>
|
||||
<CollapsibleContent className="space-y-3 border-t border-border/60 p-3">
|
||||
<div className="grid gap-2">
|
||||
<p className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Weights (optional)
|
||||
</p>
|
||||
<FieldLabel
|
||||
label="Weights (optional)"
|
||||
hint="Set selection probability per value."
|
||||
/>
|
||||
{(config.values ?? []).length === 0 ? (
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Add values first, then set optional weights.
|
||||
|
|
@ -165,9 +168,10 @@ export function CategoryDialog({
|
|||
)}
|
||||
</div>
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<p className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Conditional params (category)
|
||||
</p>
|
||||
<FieldLabel
|
||||
label="Conditional params (category)"
|
||||
hint="Override category values/weights when condition matches."
|
||||
/>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{conditionalCount} rules
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
import type { ReactElement } from "react";
|
||||
import type { SamplerConfig } from "../../types";
|
||||
import { NameField } from "../shared/name-field";
|
||||
import { FieldLabel } from "../shared/field-label";
|
||||
|
||||
const DATETIME_UNITS = [
|
||||
"second",
|
||||
|
|
@ -47,12 +48,11 @@ export function DatetimeDialog({
|
|||
<div className="grid gap-3">
|
||||
<div className="grid gap-2 sm:grid-cols-2">
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Start"
|
||||
htmlFor={startId}
|
||||
>
|
||||
Start
|
||||
</label>
|
||||
hint="Earliest datetime allowed."
|
||||
/>
|
||||
<Input
|
||||
id={startId}
|
||||
type="datetime-local"
|
||||
|
|
@ -64,12 +64,11 @@ export function DatetimeDialog({
|
|||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="End"
|
||||
htmlFor={endId}
|
||||
>
|
||||
End
|
||||
</label>
|
||||
hint="Latest datetime allowed."
|
||||
/>
|
||||
<Input
|
||||
id={endId}
|
||||
type="datetime-local"
|
||||
|
|
@ -82,12 +81,11 @@ export function DatetimeDialog({
|
|||
</div>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Unit"
|
||||
htmlFor={unitId}
|
||||
>
|
||||
Unit
|
||||
</label>
|
||||
hint="Sampling granularity for generated timestamps."
|
||||
/>
|
||||
<Select
|
||||
value={config.datetime_unit ?? ""}
|
||||
onValueChange={(value) => updateField("datetime_unit", value)}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
import type { ReactElement } from "react";
|
||||
import type { SamplerConfig } from "../../types";
|
||||
import { NameField } from "../shared/name-field";
|
||||
import { FieldLabel } from "../shared/field-label";
|
||||
|
||||
type GaussianDialogProps = {
|
||||
config: SamplerConfig;
|
||||
|
|
@ -30,12 +31,11 @@ export function GaussianDialog({
|
|||
/>
|
||||
<div className="grid gap-3 sm:grid-cols-2">
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Mean"
|
||||
htmlFor={meanId}
|
||||
>
|
||||
Mean
|
||||
</label>
|
||||
hint="Center of the normal distribution."
|
||||
/>
|
||||
<Input
|
||||
id={meanId}
|
||||
type="number"
|
||||
|
|
@ -45,12 +45,11 @@ export function GaussianDialog({
|
|||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Std"
|
||||
htmlFor={stdId}
|
||||
>
|
||||
Std
|
||||
</label>
|
||||
hint="Standard deviation. must be > 0."
|
||||
/>
|
||||
<Input
|
||||
id={stdId}
|
||||
type="number"
|
||||
|
|
@ -61,12 +60,11 @@ export function GaussianDialog({
|
|||
</div>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Convert to"
|
||||
htmlFor={convertId}
|
||||
>
|
||||
Convert to
|
||||
</label>
|
||||
hint="Optionally cast sampled values before output."
|
||||
/>
|
||||
<Select
|
||||
value={config.convert_to ?? "none"}
|
||||
onValueChange={(value) =>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
import { type ReactElement, useEffect } from "react";
|
||||
import type { SamplerConfig } from "../../types";
|
||||
import { NameField } from "../shared/name-field";
|
||||
import { FieldLabel } from "../shared/field-label";
|
||||
|
||||
type PersonDialogProps = {
|
||||
config: SamplerConfig;
|
||||
|
|
@ -55,12 +56,11 @@ export function PersonDialog({
|
|||
</div>
|
||||
<div className="grid gap-3 sm:grid-cols-2">
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Locale"
|
||||
htmlFor={localeId}
|
||||
>
|
||||
Locale
|
||||
</label>
|
||||
hint="Faker locale e.g. en_US."
|
||||
/>
|
||||
<Input
|
||||
id={localeId}
|
||||
className="nodrag"
|
||||
|
|
@ -71,12 +71,11 @@ export function PersonDialog({
|
|||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Sex"
|
||||
htmlFor={sexId}
|
||||
>
|
||||
Sex
|
||||
</label>
|
||||
hint="Optional demographic filter."
|
||||
/>
|
||||
<Select
|
||||
value={config.person_sex?.trim() ? config.person_sex : "any"}
|
||||
onValueChange={(value) =>
|
||||
|
|
@ -94,12 +93,11 @@ export function PersonDialog({
|
|||
</Select>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Age range"
|
||||
htmlFor={ageRangeId}
|
||||
>
|
||||
Age range
|
||||
</label>
|
||||
hint="Range format: min-max, e.g. 18-70."
|
||||
/>
|
||||
<Input
|
||||
id={ageRangeId}
|
||||
className="nodrag"
|
||||
|
|
@ -111,12 +109,11 @@ export function PersonDialog({
|
|||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="City"
|
||||
htmlFor={cityId}
|
||||
>
|
||||
City
|
||||
</label>
|
||||
hint="Optional city bias for faker generation."
|
||||
/>
|
||||
<Input
|
||||
id={cityId}
|
||||
className="nodrag"
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { type ReactElement, useCallback, useEffect, useMemo } from "react";
|
|||
import type { SamplerConfig } from "../../types";
|
||||
import { ChipInput } from "../../components/chip-input";
|
||||
import { NameField } from "../shared/name-field";
|
||||
import { FieldLabel } from "../shared/field-label";
|
||||
|
||||
type SubcategoryDialogProps = {
|
||||
config: SamplerConfig;
|
||||
|
|
@ -71,12 +72,11 @@ export function SubcategoryDialog({
|
|||
/>
|
||||
<div className="space-y-3">
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Parent category column"
|
||||
htmlFor={parentSelectId}
|
||||
>
|
||||
Parent category column
|
||||
</label>
|
||||
hint="Category column this block maps from."
|
||||
/>
|
||||
<Select
|
||||
value={config.subcategory_parent ?? ""}
|
||||
onValueChange={(value) => {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
import type { ReactElement } from "react";
|
||||
import type { SamplerConfig } from "../../types";
|
||||
import { NameField } from "../shared/name-field";
|
||||
import { FieldLabel } from "../shared/field-label";
|
||||
|
||||
const TIMEDELTA_UNITS: Array<"D" | "h" | "m" | "s"> = ["D", "h", "m", "s"];
|
||||
const NONE_VALUE = "__none";
|
||||
|
|
@ -42,12 +43,11 @@ export function TimedeltaDialog({
|
|||
/>
|
||||
<div className="grid gap-3 sm:grid-cols-2">
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="dt_min"
|
||||
htmlFor={dtMinId}
|
||||
>
|
||||
dt_min
|
||||
</label>
|
||||
hint="Minimum offset from reference datetime."
|
||||
/>
|
||||
<Input
|
||||
id={dtMinId}
|
||||
type="number"
|
||||
|
|
@ -57,12 +57,11 @@ export function TimedeltaDialog({
|
|||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="dt_max"
|
||||
htmlFor={dtMaxId}
|
||||
>
|
||||
dt_max
|
||||
</label>
|
||||
hint="Maximum offset from reference datetime."
|
||||
/>
|
||||
<Input
|
||||
id={dtMaxId}
|
||||
type="number"
|
||||
|
|
@ -73,12 +72,11 @@ export function TimedeltaDialog({
|
|||
</div>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Unit"
|
||||
htmlFor={unitId}
|
||||
>
|
||||
Unit
|
||||
</label>
|
||||
hint="Offset unit. D/h/m/s."
|
||||
/>
|
||||
<Select
|
||||
value={config.timedelta_unit ?? "D"}
|
||||
onValueChange={(value) =>
|
||||
|
|
@ -98,12 +96,11 @@ export function TimedeltaDialog({
|
|||
</Select>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Reference datetime column"
|
||||
htmlFor={referenceId}
|
||||
>
|
||||
Reference datetime column
|
||||
</label>
|
||||
hint="Datetime column used as anchor before offset."
|
||||
/>
|
||||
<Select
|
||||
value={config.reference_column_name?.trim() || NONE_VALUE}
|
||||
onValueChange={(value) =>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
import type { ReactElement } from "react";
|
||||
import type { SamplerConfig } from "../../types";
|
||||
import { NameField } from "../shared/name-field";
|
||||
import { FieldLabel } from "../shared/field-label";
|
||||
|
||||
type UniformDialogProps = {
|
||||
config: SamplerConfig;
|
||||
|
|
@ -30,12 +31,11 @@ export function UniformDialog({
|
|||
/>
|
||||
<div className="grid gap-3 sm:grid-cols-2">
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Low"
|
||||
htmlFor={lowId}
|
||||
>
|
||||
Low
|
||||
</label>
|
||||
hint="Minimum sampled value."
|
||||
/>
|
||||
<Input
|
||||
id={lowId}
|
||||
type="number"
|
||||
|
|
@ -45,12 +45,11 @@ export function UniformDialog({
|
|||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="High"
|
||||
htmlFor={highId}
|
||||
>
|
||||
High
|
||||
</label>
|
||||
hint="Maximum sampled value."
|
||||
/>
|
||||
<Input
|
||||
id={highId}
|
||||
type="number"
|
||||
|
|
@ -61,12 +60,11 @@ export function UniformDialog({
|
|||
</div>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Convert to"
|
||||
htmlFor={convertId}
|
||||
>
|
||||
Convert to
|
||||
</label>
|
||||
hint="Optionally cast sampled values before output."
|
||||
/>
|
||||
<Select
|
||||
value={config.convert_to ?? "none"}
|
||||
onValueChange={(value) =>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Input } from "@/components/ui/input";
|
|||
import type { ReactElement } from "react";
|
||||
import type { SamplerConfig } from "../../types";
|
||||
import { NameField } from "../shared/name-field";
|
||||
import { FieldLabel } from "../shared/field-label";
|
||||
|
||||
type UuidDialogProps = {
|
||||
config: SamplerConfig;
|
||||
|
|
@ -26,12 +27,11 @@ export function UuidDialog({
|
|||
onChange={(value) => onUpdate({ name: value })}
|
||||
/>
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="UUID format (optional)"
|
||||
htmlFor={uuidId}
|
||||
>
|
||||
UUID format (optional)
|
||||
</label>
|
||||
hint="Optional formatter e.g. prefix:, short, uppercase."
|
||||
/>
|
||||
<Input
|
||||
id={uuidId}
|
||||
className="nodrag"
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import type {
|
|||
SeedSamplingStrategy,
|
||||
SeedSelectionType,
|
||||
} from "../../types";
|
||||
import { FieldLabel } from "../shared/field-label";
|
||||
|
||||
const SAMPLING_OPTIONS: Array<{ value: SeedSamplingStrategy; label: string }> = [
|
||||
{ value: "ordered", label: "Ordered" },
|
||||
|
|
@ -125,12 +126,11 @@ export function SeedDialog({ config, onUpdate }: SeedDialogProps): ReactElement
|
|||
<TabsContent value="config" className="pt-3">
|
||||
<div className="space-y-4">
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="HF dataset URL"
|
||||
htmlFor={urlId}
|
||||
>
|
||||
HF dataset URL
|
||||
</label>
|
||||
hint="Dataset URL or org/repo used to bootstrap seed columns."
|
||||
/>
|
||||
<div className="flex items-center gap-2">
|
||||
<Input
|
||||
id={urlId}
|
||||
|
|
@ -159,12 +159,11 @@ export function SeedDialog({ config, onUpdate }: SeedDialogProps): ReactElement
|
|||
|
||||
{(config.seed_splits?.length ?? 0) > 0 && (
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Split"
|
||||
htmlFor={splitId}
|
||||
>
|
||||
Split
|
||||
</label>
|
||||
hint="Dataset split to sample from (train/validation/test)."
|
||||
/>
|
||||
<Select
|
||||
value={config.hf_split ?? ""}
|
||||
onValueChange={(value) => {
|
||||
|
|
@ -187,12 +186,11 @@ export function SeedDialog({ config, onUpdate }: SeedDialogProps): ReactElement
|
|||
)}
|
||||
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="HF path (auto)"
|
||||
htmlFor={pathId}
|
||||
>
|
||||
HF path (auto)
|
||||
</label>
|
||||
hint="Resolved dataset file path/pattern."
|
||||
/>
|
||||
<Input
|
||||
id={pathId}
|
||||
className="nodrag"
|
||||
|
|
@ -203,12 +201,11 @@ export function SeedDialog({ config, onUpdate }: SeedDialogProps): ReactElement
|
|||
</div>
|
||||
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="HF token (optional)"
|
||||
htmlFor={tokenId}
|
||||
>
|
||||
HF token (optional)
|
||||
</label>
|
||||
hint="Optional private dataset access token."
|
||||
/>
|
||||
<Input
|
||||
id={tokenId}
|
||||
className="nodrag"
|
||||
|
|
@ -219,12 +216,11 @@ export function SeedDialog({ config, onUpdate }: SeedDialogProps): ReactElement
|
|||
</div>
|
||||
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Sampling strategy"
|
||||
htmlFor={samplingId}
|
||||
>
|
||||
Sampling strategy
|
||||
</label>
|
||||
hint="Ordered keeps row order. shuffle randomizes sampled rows."
|
||||
/>
|
||||
<Select
|
||||
value={config.sampling_strategy}
|
||||
onValueChange={(value) =>
|
||||
|
|
@ -245,12 +241,11 @@ export function SeedDialog({ config, onUpdate }: SeedDialogProps): ReactElement
|
|||
</div>
|
||||
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Selection strategy"
|
||||
htmlFor={selectionId}
|
||||
>
|
||||
Selection strategy
|
||||
</label>
|
||||
hint="Select all, a row range, or partition block."
|
||||
/>
|
||||
<Select
|
||||
value={config.selection_type}
|
||||
onValueChange={(value) =>
|
||||
|
|
@ -273,9 +268,10 @@ export function SeedDialog({ config, onUpdate }: SeedDialogProps): ReactElement
|
|||
{config.selection_type === "index_range" && (
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div className="grid gap-2">
|
||||
<label className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Start
|
||||
</label>
|
||||
<FieldLabel
|
||||
label="Start"
|
||||
hint="Inclusive start row index for index_range."
|
||||
/>
|
||||
<Input
|
||||
className="nodrag"
|
||||
inputMode="numeric"
|
||||
|
|
@ -284,9 +280,10 @@ export function SeedDialog({ config, onUpdate }: SeedDialogProps): ReactElement
|
|||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
End
|
||||
</label>
|
||||
<FieldLabel
|
||||
label="End"
|
||||
hint="Inclusive end row index for index_range."
|
||||
/>
|
||||
<Input
|
||||
className="nodrag"
|
||||
inputMode="numeric"
|
||||
|
|
@ -300,9 +297,10 @@ export function SeedDialog({ config, onUpdate }: SeedDialogProps): ReactElement
|
|||
{config.selection_type === "partition_block" && (
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div className="grid gap-2">
|
||||
<label className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Index
|
||||
</label>
|
||||
<FieldLabel
|
||||
label="Index"
|
||||
hint="Partition index to load."
|
||||
/>
|
||||
<Input
|
||||
className="nodrag"
|
||||
inputMode="numeric"
|
||||
|
|
@ -311,9 +309,10 @@ export function SeedDialog({ config, onUpdate }: SeedDialogProps): ReactElement
|
|||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label className="text-xs font-semibold uppercase text-muted-foreground">
|
||||
Partitions
|
||||
</label>
|
||||
<FieldLabel
|
||||
label="Partitions"
|
||||
hint="Total number of partitions."
|
||||
/>
|
||||
<Input
|
||||
className="nodrag"
|
||||
inputMode="numeric"
|
||||
|
|
|
|||
|
|
@ -1,27 +1,32 @@
|
|||
import { Input } from "@/components/ui/input";
|
||||
import { type ReactElement, useId } from "react";
|
||||
import { FieldLabel } from "./field-label";
|
||||
|
||||
type NameFieldProps = {
|
||||
id?: string;
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
hint?: string;
|
||||
};
|
||||
|
||||
export function NameField({
|
||||
id,
|
||||
value,
|
||||
onChange,
|
||||
hint,
|
||||
}: NameFieldProps): ReactElement {
|
||||
const fallbackId = useId();
|
||||
const inputId = id ?? fallbackId;
|
||||
return (
|
||||
<div className="grid gap-2">
|
||||
<label
|
||||
className="text-xs font-semibold uppercase text-muted-foreground"
|
||||
<FieldLabel
|
||||
label="Column name"
|
||||
htmlFor={inputId}
|
||||
>
|
||||
Column name
|
||||
</label>
|
||||
hint={
|
||||
hint ??
|
||||
"Unique field name used in templates and final dataset output."
|
||||
}
|
||||
/>
|
||||
<Input
|
||||
id={inputId}
|
||||
className="nodrag"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue