Field System
Fields define the inputs and outputs of operators, providing both data validation and UI hints for the node editor interface.
Field Fundamentals
Fields serve dual purposes:
- Data Schema: Validate and type-check data using Zod schemas
- UI Hints: Tell the interface how to render input controls
// Example field definition
const numberField = new NumberField(50, {
min: 0,
max: 100,
step: 1,
})
Core Field Types
Primitive Fields
NumberField
new NumberField(50, {
min: 0, // Hard minimum (validation enforced)
max: 100, // Hard maximum (validation enforced)
softMin: 10, // UI hint for slider minimum (not enforced)
softMax: 90, // UI hint for slider maximum (not enforced)
step: 1, // Increment step
})
Soft vs Hard Limits:
min/max: Validation is enforced - values outside this range will fail schema validationsoftMin/softMax: UI hints only - sliders use these bounds but values outside are allowed- Defaults:
softMin: -Infinity,softMax: Infinity
Use soft limits when you want to guide users toward reasonable values while still allowing edge cases (e.g., a radius that's usually 0-100 but could be larger).
BooleanField
new BooleanField(true)
ColorField
new ColorField('#ff0000', {
accessor: true, // Allow this field to connect to Accessor functions
transform: hexToColor // Convert to a [R, G, B] tuple array for Deck
})
Geometric Fields
PointField
new Point2DField([-74.0, 40.7], {
returnType: 'tuple', // [lng, lat] or 'object' for { lng, lat }
})
Vec2Field
new Vec2Field([0, 0], {
returnType: 'object', // { x, y } or 'tuple' for [x, y]
})
Data Fields
DataField
For open-ended data structures:
new DataField([]) // Any array or object
CompoundPropsField
For specific object schemas:
new CompoundPropsField({
view: z.object({
name: z.string(),
value: z.number()
})
})
Advanced Fields
CodeField
For JavaScript code input:
new CodeField('return data.length', {
language: 'javascript'
})
Also accepts SQL.
Field Options
Common Options
{
optional: true, // Allow undefined values
accessor: true, // Mark as accessor function
transform: (val) => val // Transform function
}
Validation
Fields use Zod schemas for runtime validation:
// Custom validation
new StringField('user@example.com', {
schema: z.string().email(), // Email validation
})
Field Connections
Creating Connections
Connections between fields are managed through the graph transformation system. In the UI, simply drag from an output handle to an input handle. Programmatically, connections are created via the edge format in project files:
// Edge format in noodles.json
{
"id": "/nodeA.out.data->/nodeB.par.input",
"source": "/nodeA",
"target": "/nodeB",
"sourceHandle": "out.data",
"targetHandle": "par.input"
}
Connection Rules
- Type Compatibility: Output type should match input type (warnings shown for mismatches)
- Single Input: Each input accepts only one connection
- Multiple Outputs: Outputs can connect to multiple inputs
- No Cycles: Connections cannot create circular dependencies
Connection Validation
import { canConnect } from './utils/can-connect'
// Check if two fields are type-compatible
const isCompatible = canConnect(sourceField, targetField)
Custom Fields
Create custom field types by extending base classes:
export class CustomField extends Field<z.ZodString> {
createSchema(options: CustomFieldOptions) {
return z.string().min(options.minLength || 0)
}
static component = 'CustomFieldComponent' // UI component name
}
UI Components
Register custom UI components:
// In field-components.tsx
const CustomFieldComponent = ({ id, field, disabled }) => (
<input
value={field.value}
onChange={e => onChange(e.target.value)}
className="custom-input"
/>
)
export const inputComponents = {
CustomField: CustomFieldComponent
}
Best Practices
Field Design
- Use descriptive names and labels
- Provide sensible default values
- Set appropriate validation constraints
- Include helpful placeholder text
Type Safety
- Leverage Zod schemas for validation
- Use TypeScript for compile-time checking
- Handle validation errors gracefully
- Provide clear error messages
Performance
- Avoid expensive validation in hot paths
- Use memoization for complex transformations
- Batch updates when possible
- Minimize unnecessary re-renders
User Experience
- Group related fields logically
- Use appropriate input types for data
- Provide visual feedback for validation
- Support keyboard navigation