| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354 |
- 'use client';
- import { type ComponentRenderProps } from '@json-render/react';
- import { useData, useFieldValidation } from '@json-render/react';
- import { getByPath } from '@json-render/core';
- export function TextField({ element }: ComponentRenderProps) {
- const { label, valuePath, placeholder, type, checks, validateOn } = element.props as {
- label: string;
- valuePath: string;
- placeholder?: string | null;
- type?: string | null;
- checks?: Array<{ fn: string; message: string }> | null;
- validateOn?: string | null;
- };
- const { data, set } = useData();
- const value = getByPath(data, valuePath) as string | undefined;
- const { errors, validate, touch } = useFieldValidation(valuePath, {
- checks: checks ?? undefined,
- validateOn: (validateOn as 'change' | 'blur' | 'submit') ?? 'blur',
- });
- return (
- <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
- <label style={{ fontSize: 14, fontWeight: 500 }}>{label}</label>
- <input
- type={type || 'text'}
- value={value ?? ''}
- onChange={(e) => {
- set(valuePath, e.target.value);
- if (validateOn === 'change') validate();
- }}
- onBlur={() => {
- touch();
- if (validateOn === 'blur' || !validateOn) validate();
- }}
- placeholder={placeholder ?? ''}
- style={{
- padding: '8px 12px',
- borderRadius: 'var(--radius)',
- border: errors.length > 0 ? '1px solid #ef4444' : '1px solid var(--border)',
- background: 'var(--card)',
- color: 'var(--foreground)',
- fontSize: 14,
- outline: 'none',
- }}
- />
- {errors.map((error, i) => (
- <span key={i} style={{ fontSize: 12, color: '#ef4444' }}>{error}</span>
- ))}
- </div>
- );
- }
|