UNPKG

zod-form-radix

Version:

Radix UI integration for zod-form-kit

42 lines (41 loc) 6 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; // React import not needed with new JSX transform import * as SelectPrimitive from '@radix-ui/react-select'; import { Label } from '../label'; import { cn } from '../../lib/utils'; export function DiscriminatedUnionField({ name, label, value = {}, onChange, error, required, discriminator, variants, errors, path, className = '' }) { const currentVariant = value[discriminator]; const variantOptions = Object.keys(variants); const handleVariantChange = (newVariant) => { // Reset the object with just the discriminator when variant changes const newValue = { [discriminator]: newVariant }; onChange(path, newValue); }; const handleVariantPropertyChange = (propertyName, propertyValue) => { const newValue = { ...value, [propertyName]: propertyValue }; onChange(path, newValue); }; return (_jsxs("div", { className: cn("space-y-4", className), children: [label && (_jsxs(Label, { children: [label, required && _jsx("span", { className: "text-red-500 ml-1", children: "*" })] })), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: `${name}-discriminator`, children: "Type" }), _jsxs(SelectPrimitive.Root, { value: currentVariant || '', onValueChange: handleVariantChange, children: [_jsxs(SelectPrimitive.Trigger, { id: `${name}-discriminator`, className: "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", children: [_jsx(SelectPrimitive.Value, { placeholder: "Select type..." }), _jsx(SelectPrimitive.Icon, { asChild: true, children: _jsx("svg", { className: "h-4 w-4 opacity-50", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("polyline", { points: "6,9 12,15 18,9" }) }) })] }), _jsx(SelectPrimitive.Portal, { children: _jsx(SelectPrimitive.Content, { className: "relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md", children: _jsx(SelectPrimitive.Viewport, { className: "p-1", children: variantOptions.map((variant) => (_jsxs(SelectPrimitive.Item, { value: variant, className: "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", children: [_jsx(SelectPrimitive.ItemIndicator, { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: _jsx("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("polyline", { points: "20,6 9,17 4,12" }) }) }), _jsx(SelectPrimitive.ItemText, { children: variant })] }, variant))) }) }) })] })] }), currentVariant && variants[currentVariant] && (_jsxs("div", { className: "space-y-4 p-4 border rounded-lg bg-card", children: [_jsxs("h4", { className: "text-sm font-semibold text-card-foreground", children: [currentVariant, " Properties"] }), _jsx("div", { className: "space-y-3", children: Object.entries(variants[currentVariant].properties || {}).map(([propertyName, propertySchema]) => { // Skip the discriminator property as it's handled above if (propertyName === discriminator) return null; const propertyPath = `${path}.${propertyName}`; const propertyValue = value[propertyName]; const propertyError = errors[propertyPath]; return (_jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { htmlFor: `${name}-${propertyName}`, children: [propertySchema.label || propertyName, propertySchema.required && _jsx("span", { className: "text-red-500 ml-1", children: "*" })] }), renderVariantPropertyField(`${name}-${propertyName}`, propertyName, propertyValue, propertySchema, propertyError, (newValue) => handleVariantPropertyChange(propertyName, newValue)), propertyError && (_jsx("p", { className: "text-sm text-red-500 mt-1", children: propertyError }))] }, propertyName)); }) })] })), error && (_jsx("p", { className: "text-sm text-red-500 mt-1", children: error }))] })); } // Helper function to render variant property fields function renderVariantPropertyField(id, name, value, schema, error, onChange) { const baseInputClasses = cn("w-full px-3 py-2 border border-input rounded-md bg-background", error && "border-red-500 focus-visible:ring-red-500"); switch (schema.type) { case 'string': return (_jsx("input", { id: id, name: name, type: "text", value: value || '', onChange: (e) => onChange(e.target.value), className: baseInputClasses, placeholder: `Enter ${schema.label || name}` })); case 'number': return (_jsx("input", { id: id, name: name, type: "number", value: value || 0, onChange: (e) => onChange(Number(e.target.value)), className: baseInputClasses, min: schema.min, max: schema.max, step: schema.step })); case 'boolean': return (_jsxs("div", { className: "flex items-center space-x-2", children: [_jsx("input", { id: id, name: name, type: "checkbox", checked: value || false, onChange: (e) => onChange(e.target.checked), className: "h-4 w-4 rounded border-input" }), _jsx("span", { className: "text-sm", children: "Yes" })] })); default: return (_jsxs("div", { className: "text-sm text-muted-foreground p-2 border border-dashed rounded", children: ["Unsupported property type: ", schema.type, _jsx("br", {}), "Current value: ", JSON.stringify(value)] })); } }