import React, { Suspense } from 'react';
import { Box, Text } from '@wix/design-system';
import type { Field, PatternsFieldType } from '@wix/bex-core';
import type { Control } from '@wix/bex-core/form';
import { EntityPageReferenceField } from './EntityPageReferenceField';
import {
FormShortText,
FormLongText,
FormNumber,
FormCheckbox,
FormDateInput,
FormDateTime,
FormTime,
FormUrl,
FormEmail,
FormColor,
FormImageInput,
FormVideo,
} from '@wix/patterns-fields';
// Heavy renderers pull large editors (Ricos, draft-js) and media SDKs
// (@wix/media). Loading them lazily keeps that weight out of the @wix/patterns
// main bundle — it moves into an async chunk fetched only when an entity page
// first renders a field of that type. @wix/patterns-fields is side-effect-free,
// so a dynamic import of one heavy export splits into its own chunk even though
// the light renderers above are imported statically from the same package.
// FormDocument, FormMediaGallery, and FormRichContent are not on the package
// main entry — they ship from their own subpaths. Mirrors the FieldCell.tsx
// pattern.
function lazyField
(
load: () => Promise<{ default: React.ComponentType
}>,
) {
const Lazy = React.lazy(load);
return function LazyField(props: P) {
return (
);
};
}
const FormAudio = lazyField(async () => ({
default: (await import('@wix/patterns-fields')).FormAudio,
}));
const FormRichText = lazyField(async () => ({
default: (await import('@wix/patterns-fields')).FormRichText,
}));
const FormMultiDocument = lazyField(async () => ({
default: (await import('@wix/patterns-fields')).FormMultiDocument,
}));
const FormDocument = lazyField(async () => ({
default: (await import('@wix/patterns-fields/form-document-field'))
.FormDocument,
}));
const FormMediaGallery = lazyField(async () => ({
default: (await import('@wix/patterns-fields/form-media-gallery-field'))
.FormMediaGallery,
}));
const FormRichContent = lazyField(async () => ({
default: (await import('@wix/patterns-fields/form-rich-content-input'))
.FormRichContent,
}));
// Reference / MultiReference have no form renderer in @wix/patterns-fields yet,
// so those types are still skipped (see remaining-issues.md #2).
const FIELD_INPUTS: Partial<
Record>
> = {
SHORT_TEXT: FormShortText,
UNKNOWN: FormShortText,
LONG_TEXT: FormLongText,
NUMBER: FormNumber,
BOOLEAN: FormCheckbox,
DATE: FormDateInput,
DATETIME: FormDateTime,
TIME: FormTime,
URL: FormUrl,
EMAIL: FormEmail,
COLOR: FormColor,
IMAGE: FormImageInput,
VIDEO: FormVideo,
AUDIO: FormAudio,
MEDIA_GALLERY: FormMediaGallery,
RICH_TEXT: FormRichText,
RICH_CONTENT: FormRichContent,
DOCUMENT: FormDocument,
MULTI_DOCUMENT: FormMultiDocument,
};
export interface EntityPageFieldProps {
field: Field;
formControl: Control;
/** The entity, used by each renderer to seed its form default value. */
data: Record;
}
// Each renderer owns its own react-hook-form wiring (useController keyed on
// field.id), so this only needs to pick the renderer and pass the field.
export function EntityPageField({
field,
formControl,
data,
}: EntityPageFieldProps) {
// Reference fields need referenced-collection data, so they go through a
// wrapper (resolves the referenced source, fetches items) rather than the
// uniform dispatcher below.
const isReference =
field.type === 'REFERENCE' || field.type === 'MULTI_REFERENCE';
const FieldInput = FIELD_INPUTS[field.type];
if (!isReference && !FieldInput) {
return null;
}
const ScalarInput = FieldInput as React.ComponentType;
const inner = isReference ? (
) : (
);
return (
{inner}
{field.helpText && (
{field.helpText}
)}
);
}