CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-payloadcms--ui

UI components library for Payload CMS providing React components, hooks, forms, and styling for building admin interfaces and extensible UI elements.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

forms.mddocs/

Form System and Utilities

Complete form management system with validation, state handling, submission, and field rendering capabilities for building dynamic forms in Payload CMS admin interfaces.

Form Components

Form

Main form wrapper component that provides form context and handles state management.

interface FormProps {
  onSubmit?: (data: Record<string, unknown>, actions: FormActions) => void | Promise<void>;
  onChange?: (data: Record<string, unknown>) => void;
  initialState?: Record<string, unknown>;
  disabled?: boolean;
  readOnly?: boolean;
  validationOperation?: 'create' | 'update';
  className?: string;
  children?: React.ReactNode;
  method?: 'POST' | 'PATCH';
  action?: string;
  encType?: string;
}

interface FormActions {
  reset: () => void;
  submit: () => Promise<void>;
  validate: () => boolean;
}

function Form(props: FormProps): JSX.Element;

Usage example:

import { Form, TextField, FormSubmit } from '@payloadcms/ui';

function DocumentForm() {
  const handleSubmit = async (data, { reset }) => {
    try {
      await saveDocument(data);
      reset();
    } catch (error) {
      console.error('Save failed:', error);
    }
  };

  return (
    <Form onSubmit={handleSubmit}>
      <TextField path="title" label="Title" required />
      <TextField path="content" label="Content" />
      <FormSubmit>Save Document</FormSubmit>
    </Form>
  );
}

FormSubmit

Form submission button component.

interface FormSubmitProps {
  children?: React.ReactNode;
  disabled?: boolean;
  processing?: boolean;
  type?: 'submit' | 'button';
  className?: string;
}

function FormSubmit(props: FormSubmitProps): JSX.Element;

RenderFields

Dynamically render form fields from configuration.

interface RenderFieldsProps {
  fields: FieldConfig[];
  path?: string;
  margins?: boolean;
  className?: string;
  readOnly?: boolean;
  permissions?: Record<string, unknown>;
}

function RenderFields(props: RenderFieldsProps): JSX.Element;

Usage example:

import { RenderFields } from '@payloadcms/ui';

function DynamicForm({ fieldConfig }) {
  return (
    <Form>
      <RenderFields 
        fields={fieldConfig}
        margins={true}
      />
    </Form>
  );
}

RowLabel

Label component for repeatable row fields.

interface RowLabelProps {
  data: Record<string, unknown>;
  index: number;
  path: string;
  label?: string;
  fallback?: string;
}

function RowLabel(props: RowLabelProps): JSX.Element;

Form State Management

Field Reducer

Core field state reducer for managing field values and validation.

interface FieldAction {
  type: 'UPDATE' | 'VALIDATE' | 'RESET' | 'REMOVE' | 'REPLACE_STATE';
  path: string;
  value?: unknown;
  validate?: boolean;
  errorMessage?: string;
  disableFormData?: boolean;
}

function fieldReducer(
  state: FormState, 
  action: FieldAction
): FormState;

interface FormState {
  [path: string]: FieldState;
}

interface FieldState {
  value: unknown;
  valid: boolean;
  errorMessage?: string;
  initialValue?: unknown;
  disableFormData?: boolean;
}

Form Context Hooks

Access form state and actions through context hooks.

function useFormFields<T>(
  selector: (fields: FormFieldsContextType) => T
): T;

function useAllFormFields(): FormFieldsContextType;

function useFormSubmitted(): boolean;
function useFormProcessing(): boolean;
function useFormBackgroundProcessing(): boolean;
function useFormModified(): boolean;
function useFormInitializing(): boolean;

Form Watch Hooks

Monitor form state changes.

function useWatchForm<T>(): {
  getDataByPath: (path: string) => unknown;
  getData: () => Record<string, unknown>;
  getSiblingData: (path: string) => Record<string, unknown>;
  dispatchFields: (action: FieldAction) => void;
};

Form Utilities

withCondition

Higher-order component for conditional field rendering.

function withCondition<T extends Record<string, unknown>>(
  Component: React.ComponentType<T>
): React.ComponentType<T & ConditionalProps>;

interface ConditionalProps {
  admin?: {
    condition?: (data: Record<string, unknown>, siblingData?: Record<string, unknown>) => boolean;
  };
}

WatchCondition

Component for watching conditional field logic.

interface WatchConditionProps {
  path?: string;
  condition: (data: Record<string, unknown>, siblingData?: Record<string, unknown>) => boolean;
  children: React.ReactNode;
}

function WatchCondition(props: WatchConditionProps): JSX.Element | null;

WatchChildErrors

Component for watching and handling child field errors.

interface WatchChildErrorsProps {
  path: string;
  children?: React.ReactNode;
}

function WatchChildErrors(props: WatchChildErrorsProps): JSX.Element;

NullifyLocaleField

Field component for nullifying locale-specific data.

interface NullifyLocaleFieldProps {
  path: string;
  locale?: string;
}

function NullifyLocaleField(props: NullifyLocaleFieldProps): JSX.Element;

Row Label Context

RowLabelProvider

Context provider for row label data.

interface RowLabelProviderProps {
  children: React.ReactNode;
  data: Record<string, unknown>;
  index?: number;
  path: string;
}

function RowLabelProvider(props: RowLabelProviderProps): JSX.Element;

useRowLabel

Hook to access row label context data.

function useRowLabel(): {
  data: Record<string, unknown>;
  index?: number;
  path: string;
};

Advanced Form Patterns

Multi-Step Forms

import { Form, useForm, SetStepNav } from '@payloadcms/ui';

function MultiStepForm() {
  const { getData, validate } = useForm();
  const [currentStep, setCurrentStep] = useState(0);
  
  const steps = [
    { label: 'Basic Info', fields: basicFields },
    { label: 'Details', fields: detailFields },
    { label: 'Review', fields: [] }
  ];

  const handleNext = () => {
    if (validate()) {
      setCurrentStep(prev => prev + 1);
    }
  };

  return (
    <Form>
      <SetStepNav steps={steps} currentStep={currentStep} />
      <RenderFields fields={steps[currentStep].fields} />
      <button onClick={handleNext}>Next</button>
    </Form>
  );
}

Dynamic Field Configuration

import { RenderFields, useFormFields } from '@payloadcms/ui';

function ConditionalFields() {
  const formData = useFormFields(fields => fields);
  
  const getFieldsForType = (type: string) => {
    switch (type) {
      case 'article':
        return articleFields;
      case 'gallery':
        return galleryFields;
      default:
        return baseFields;
    }
  };

  const currentFields = getFieldsForType(formData.type?.value as string);

  return <RenderFields fields={currentFields} />;
}

Form Validation Patterns

import { useField } from '@payloadcms/ui';

function ValidatedEmailField() {
  const { value, setValue, showError, errorMessage } = useField<string>({
    path: 'email',
    validate: (val) => {
      if (!val) return 'Email is required';
      if (!/\S+@\S+\.\S+/.test(val)) return 'Invalid email format';
      return true;
    }
  });

  return (
    <div>
      <input
        type="email"
        value={value || ''}
        onChange={(e) => setValue(e.target.value)}
      />
      {showError && <span className="error">{errorMessage}</span>}
    </div>
  );
}

Types

interface FormFieldsContextType {
  [path: string]: FieldState;
}

interface FieldState {
  value: unknown;
  valid: boolean;
  errorMessage?: string;
  initialValue?: unknown;
  disableFormData?: boolean;
}

interface FieldConfig {
  type: string;
  name: string;
  label?: string;
  required?: boolean;
  admin?: {
    readOnly?: boolean;
    disabled?: boolean;
    hidden?: boolean;
    condition?: (data: Record<string, unknown>) => boolean;
    description?: string;
    placeholder?: string;
  };
  validate?: (value: unknown, options: ValidateOptions) => string | true;
}

interface ValidateOptions {
  data: Record<string, unknown>;
  siblingData: Record<string, unknown>;
  operation: 'create' | 'update';
  id?: string | number;
}

interface ConditionalProps {
  admin?: {
    condition?: (
      data: Record<string, unknown>, 
      siblingData?: Record<string, unknown>
    ) => boolean;
  };
}

Install with Tessl CLI

npx tessl i tessl/npm-payloadcms--ui

docs

components.md

fields.md

forms.md

hooks.md

icons.md

index.md

providers.md

utilities.md

tile.json