import React, { type ComponentType, type ReactNode } from 'react'; import { Text, TextSmall, Image, ImageSmall, SquareRatioChecked, SquareRatioCheckedSmall, Number, NumberSmall, Date, DateSmall, DateAndTime, DateAndTimeSmall, Time, TimeSmall, Article, ArticleSmall, RichText, RichTextSmall, Reference, ReferenceSmall, Multireference, MultireferenceSmall, Link, LinkSmall, Document, DocumentSmall, DocDuplicate, Music, MusicSmall, Location, LocationSmall, Tag, TagSmall, CodeObject, CodeObjectSmall, ProGalleries, ProGalleriesSmall, Email, EmailSmall, Database, DatabaseSmall, } from '@wix/wix-ui-icons-common'; import type { PatternsFieldType } from '@wix/bex-core'; /** * Canonical field type keys (UPPER_SNAKE_CASE). * The map is keyed by these values; incoming camelCase strings * are normalised before lookup. */ export type FieldType = | 'SHORT_TEXT' | 'LONG_TEXT' | 'NUMBER' | 'BOOLEAN' | 'DATE' | 'DATE_TIME' | 'DATETIME' | 'TIME' | 'URL' | 'EMAIL' | 'IMAGE' | 'MEDIA_GALLERY' | 'AUDIO' | 'DOCUMENT' | 'MULTI_DOCUMENT' | 'RICH_TEXT' | 'RICH_CONTENT' | 'REFERENCE' | 'MULTI_REFERENCE' | 'OBJECT' | 'ARRAY' | 'ADDRESS' | 'COLOR' | 'INTEGER' | 'DECIMAL' | 'CHECKBOX' | 'DROPDOWN' | 'FILES' | 'MULTI_SELECT'; /** * Converts any casing (camelCase, snake_case, etc.) to a canonical FieldType. * e.g. "shortText" → "SHORT_TEXT", "dateTime" → "DATE_TIME". * Already UPPER_SNAKE_CASE strings pass through unchanged. */ export function toFieldType(value: string): FieldType { return value.replace(/([a-z])([A-Z])/g, '$1_$2').toUpperCase() as FieldType; } interface FieldPrefixIconEntry { small: ComponentType; medium: ComponentType; } /** * Maps canonical UPPER_SNAKE_CASE field types to icon components (small + medium). */ const FIELD_TYPE_ICON_MAP: Partial< Record > = { SHORT_TEXT: { small: TextSmall, medium: Text }, LONG_TEXT: { small: TextSmall, medium: Text }, NUMBER: { small: NumberSmall, medium: Number }, BOOLEAN: { small: SquareRatioCheckedSmall, medium: SquareRatioChecked }, DATE: { small: DateSmall, medium: Date }, DATE_TIME: { small: DateAndTimeSmall, medium: DateAndTime }, DATETIME: { small: DateAndTimeSmall, medium: DateAndTime }, TIME: { small: TimeSmall, medium: Time }, URL: { small: LinkSmall, medium: Link }, EMAIL: { small: EmailSmall, medium: Email }, IMAGE: { small: ImageSmall, medium: Image }, MEDIA_GALLERY: { small: ProGalleriesSmall, medium: ProGalleries }, AUDIO: { small: MusicSmall, medium: Music }, DOCUMENT: { small: DocumentSmall, medium: Document }, MULTI_DOCUMENT: { small: DocumentSmall, medium: DocDuplicate }, RICH_TEXT: { small: RichTextSmall, medium: RichText }, RICH_CONTENT: { small: ArticleSmall, medium: Article }, REFERENCE: { small: ReferenceSmall, medium: Reference }, MULTI_REFERENCE: { small: MultireferenceSmall, medium: Multireference }, OBJECT: { small: CodeObjectSmall, medium: CodeObject }, ARRAY: { small: TagSmall, medium: Tag }, ADDRESS: { small: LocationSmall, medium: Location }, INTEGER: { small: NumberSmall, medium: Number }, DECIMAL: { small: NumberSmall, medium: Number }, CHECKBOX: { small: SquareRatioCheckedSmall, medium: SquareRatioChecked }, FILES: { small: DocumentSmall, medium: Document }, MULTI_SELECT: { small: TagSmall, medium: Tag }, }; /** * Returns an icon ReactNode for the given field type string and size. * Accepts both UPPER_SNAKE_CASE and camelCase input. * If the field type is not mapped (or undefined), returns an info fallback icon. * * @param fieldType - The field type string * @param size - 'small' (default, for column headers / customize panel) or 'medium' (for filters) */ const ICON_STYLE: React.CSSProperties = { display: 'flex', alignItems: 'center', }; export function getFieldTypeIcon({ fieldType, size = 'small', }: { fieldType?: FieldType | PatternsFieldType; size?: 'small' | 'medium'; }): ReactNode { const Fallback = size === 'medium' ? Database : DatabaseSmall; if (!fieldType) { return ( ); } const entry = FIELD_TYPE_ICON_MAP[fieldType]; if (!entry) { return ( ); } const Icon = size === 'medium' ? entry.medium : entry.small; return ( ); }