UI components library for Payload CMS providing React components, hooks, forms, and styling for building admin interfaces and extensible UI elements.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
React hooks for form management, utility functions, UI state, and integration with Payload CMS admin interfaces.
Get and set form field values with validation and error handling.
function useField<TValue>(options?: {
path?: string;
validate?: (value: TValue) => string | true;
disableFormData?: boolean;
hasRows?: boolean;
potentiallyStalePath?: string;
}): FieldType<TValue>;
interface FieldType<TValue> {
value: TValue;
setValue: (value: TValue) => void;
showError: boolean;
errorMessage?: string;
valid: boolean;
disabled: boolean;
initialValue?: TValue;
reset: () => void;
validate: () => void;
}Usage example:
import { useField } from '@payloadcms/ui';
function CustomTextField() {
const {
value,
setValue,
showError,
errorMessage,
valid
} = useField<string>({
path: 'title',
validate: (val) => val?.length > 0 || 'Title is required'
});
return (
<div>
<input
value={value || ''}
onChange={(e) => setValue(e.target.value)}
className={showError ? 'error' : ''}
/>
{showError && <span className="error">{errorMessage}</span>}
</div>
);
}Access form-wide state and control functions.
function useForm(): FormContext;
interface FormContext {
getData: () => Record<string, unknown>;
submit: () => Promise<void>;
reset: () => void;
setModified: (modified: boolean) => void;
validate: () => boolean;
addFieldRow: (path: string, rowIndex?: number) => void;
removeFieldRow: (path: string, rowIndex: number) => void;
moveFieldRow: (path: string, fromIndex: number, toIndex: number) => void;
}Access the document-level form context (useful for nested forms).
function useDocumentForm(): FormContext;Get and set form field values using a selector function.
function useFormFields<Value>(
selector: (fields: FormFieldsContextType) => Value
): Value;
interface FormFieldsContextType {
[path: string]: FieldState;
}
interface FieldState {
value: unknown;
valid: boolean;
errorMessage?: string;
initialValue?: unknown;
}Get the complete form fields state.
function useAllFormFields(): FormFieldsContextType;Monitor specific aspects of form state.
function useFormSubmitted(): boolean;
function useFormProcessing(): boolean;
function useFormBackgroundProcessing(): boolean;
function useFormModified(): boolean;
function useFormInitializing(): boolean;Make API requests to Payload endpoints with loading and error states.
function usePayloadAPI<T>(
url: string,
options?: {
initialData?: T;
initialParams?: Record<string, unknown>;
}
): [{
data: T;
isError: boolean;
isLoading: boolean;
}, {
setParams: (params: Record<string, unknown>) => void;
}];Usage example:
import { usePayloadAPI } from '@payloadcms/ui';
function UserList() {
const [{ data: users, isLoading, isError }, { setParams }] = usePayloadAPI<User[]>(
'/api/users',
{ initialData: [] }
);
const handleSearch = (query: string) => {
setParams({ search: query });
};
if (isLoading) return <div>Loading...</div>;
if (isError) return <div>Error loading users</div>;
return (
<div>
{users.map(user => <div key={user.id}>{user.email}</div>)}
</div>
);
}Debounce a value with a specified delay.
function useDebounce<T>(value: T, delay: number): T;Debounce a callback function.
function useDebouncedCallback<Args extends unknown[]>(
callback: (...args: Args) => void,
delay: number,
deps?: React.DependencyList
): (...args: Args) => void;Run an effect with debouncing.
function useDebouncedEffect(
callback: () => void | (() => void),
delay: number,
deps?: React.DependencyList
): void;Listen for keyboard shortcuts.
function useHotkey(
options: {
keyCodes: string[];
cmdCtrlKey?: boolean;
editDepth?: number;
},
callback: (event: KeyboardEvent) => void
): void;Usage example:
import { useHotkey } from '@payloadcms/ui';
function DocumentEditor() {
useHotkey(
{ keyCodes: ['s'], cmdCtrlKey: true },
(event) => {
event.preventDefault();
handleSave();
}
);
return <div>Use Cmd/Ctrl+S to save</div>;
}Detect clicks outside an element.
function useClickOutside<T extends HTMLElement>(
ref: React.RefObject<T>,
callback: (event: MouseEvent) => void
): void;Create a delayed state that becomes true after a specified delay.
function useDelay(delay: number): boolean;Delay component rendering for a specified time.
function useDelayedRender(delay: number): boolean;Intersection Observer hook for detecting element visibility.
function useIntersect<T extends HTMLElement>(
ref: React.RefObject<T>
): {
isIntersecting: boolean;
entry?: IntersectionObserverEntry;
};Window resize detection hook.
function useResize(): {
width: number;
height: number;
};Throttled version of useEffect.
function useThrottledEffect(
callback: () => void | (() => void),
delay: number,
deps?: React.DependencyList
): void;Access authentication state and methods.
function useAuth<T = any>(): AuthContext<T>;
interface AuthContext<T> {
user: T | null;
token?: string;
permissions?: SanitizedPermissions;
logOut: () => Promise<void>;
refreshCookie: () => Promise<void>;
setUser: (user: T | null) => void;
strategy?: string;
}Access Payload configuration.
function useConfig(): ClientConfigContext;
interface ClientConfigContext {
config: ClientConfig;
getEntityConfig: (slug: string, type: 'collections' | 'globals') => EntityConfig;
setConfig: (config: ClientConfig) => void;
}Access translation functions.
function useTranslation(): TranslationContext;
interface TranslationContext {
t: (key: string, options?: Record<string, unknown>) => string;
i18n: {
language: string;
languages: string[];
changeLanguage: (lang: string) => void;
};
}Access current locale information.
function useLocale(): LocaleContext;
interface LocaleContext {
locale: string;
setLocale: (locale: string) => void;
}Access information about the current document.
function useDocumentInfo(): DocumentInfoContext;
interface DocumentInfoContext {
id?: string | number;
collection?: string;
global?: string;
hasPublishedDoc?: boolean;
unpublishedVersions?: number;
publishedVersions?: number;
mostRecentVersionIsAutosaved?: boolean;
initialState?: Record<string, unknown>;
}Access current CRUD operation type.
function useOperation(): string; // 'create' | 'update'Access route parameters.
function useParams(): Record<string, string>;Access and modify user preferences.
function usePreferences(): PreferencesContext;
interface PreferencesContext {
getPreference: <T = any>(key: string) => T;
setPreference: <T = any>(key: string, value: T) => void;
}Access theme configuration and switching.
function useTheme(): ThemeContext;
interface ThemeContext {
theme: Theme;
setTheme: (theme: 'light' | 'dark' | 'auto') => void;
autoMode: boolean;
}interface SanitizedPermissions {
collections: Record<string, CollectionPermission>;
globals: Record<string, GlobalPermission>;
canAccessAdmin: boolean;
}
interface CollectionPermission {
create: boolean;
read: boolean;
update: boolean;
delete: boolean;
}
interface GlobalPermission {
read: boolean;
update: boolean;
}
interface ClientConfig {
routes: {
admin: string;
api: string;
};
collections: CollectionConfig[];
globals: GlobalConfig[];
localization?: LocalizationConfig;
admin: AdminConfig;
}
interface EntityConfig {
slug: string;
labels: {
singular: string;
plural: string;
};
fields: FieldConfig[];
}
interface Theme {
name: string;
colors: Record<string, string>;
breakpoints: Record<string, string>;
}Install with Tessl CLI
npx tessl i tessl/npm-payloadcms--ui