import type { ReactNode, ElementType, HTMLAttributes } from "react"; import { createElement } from "react"; import type { ExtractRecordPaths, HintedString } from "ra-core"; import { FieldTitle, useRecordContext, useResourceContext, useTranslate, } from "ra-core"; import { cn } from "@/lib/utils"; import { TextField } from "@/components/admin/text-field"; /** * Displays a labeled field-value pair with flexible rendering options. * * Supports either vertical or inline layout. * It can render children, use a custom field component, or display a TextField by default. * To be used with RecordContext, e.g. inside Show, or inside ArrayField to display array items. * * @see {@link https://marmelab.com/shadcn-admin-kit/docs/recordfield/ RecordField documentation} * * @example * import { NumberField, RecordField, Show } from '@/components/admin'; * * const PostShow = () => ( * *
* * `${record.width}x${record.height}`} * /> * * * *
*
* ); */ export const RecordField = < RecordType extends Record = Record, >( props: RecordFieldProps, ) => { const { children, className, empty, field, label, render, resource: _, source, record: recordProp, variant, ...rest } = props; const resource = useResourceContext(props); const record = useRecordContext({ recordProp }); const translate = useTranslate(); if (!source && !label && !render) return null; return (
{label !== "" && label !== false ? (
) : null} {children ? ( {children} ) : render ? ( record && ( {render(record) || (typeof empty === "string" ? translate(empty, { _: empty }) : empty)} ) ) : field ? ( createElement(field, { source, empty, className: "flex-1", }) ) : source ? ( ) : null}
); }; // FIXME remove custom type when using TypeScript >= 5.4 as it is now native type NoInfer = T extends infer U ? U : never; export interface RecordFieldProps< RecordType extends Record = Record, > extends HTMLAttributes { children?: ReactNode; className?: string; empty?: ReactNode; field?: ElementType; label?: ReactNode; render?: (record: RecordType) => React.ReactNode; resource?: string; source?: NoInfer>>; record?: RecordType; variant?: "default" | "inline"; }