diff --git a/examples/getstarted/src/api/kitchensink/content-types/kitchensink/schema.json b/examples/getstarted/src/api/kitchensink/content-types/kitchensink/schema.json index dbe74efca1..4a0e03e0f6 100644 --- a/examples/getstarted/src/api/kitchensink/content-types/kitchensink/schema.json +++ b/examples/getstarted/src/api/kitchensink/content-types/kitchensink/schema.json @@ -133,7 +133,10 @@ }, "custom_field": { "type": "customField", - "customField": "plugin::mycustomfields.color" + "customField": "plugin::mycustomfields.color", + "options": { + "format": "hex" + } } } } diff --git a/examples/getstarted/src/plugins/mycustomfields/admin/src/components/ColorPicker/ColorPickerInput/index.js b/examples/getstarted/src/plugins/mycustomfields/admin/src/components/ColorPicker/ColorPickerInput/index.js index 002f89e5e9..1e5919489a 100644 --- a/examples/getstarted/src/plugins/mycustomfields/admin/src/components/ColorPicker/ColorPickerInput/index.js +++ b/examples/getstarted/src/plugins/mycustomfields/admin/src/components/ColorPicker/ColorPickerInput/index.js @@ -1,7 +1,37 @@ import React from 'react'; +import { Stack } from '@strapi/design-system/Stack'; +import { Field, FieldHint, FieldError, FieldLabel } from '@strapi/design-system/Field'; +import { useIntl } from 'react-intl'; -const ColorPickerInput = () => { - return
TODO: Color Picker Input Component
; +const ColorPickerInput = ({ + attribute, + description, + error, + hint, + id, + intlLabel, + name, + onChange, + required, + value, +}) => { + const { formatMessage } = useIntl(); + + return ( + + + {formatMessage(intlLabel)} + + + + + + ); }; export default ColorPickerInput; diff --git a/packages/core/admin/admin/src/content-manager/components/Inputs/index.js b/packages/core/admin/admin/src/content-manager/components/Inputs/index.js index 3f59cd56cf..fe47ee28c3 100644 --- a/packages/core/admin/admin/src/content-manager/components/Inputs/index.js +++ b/packages/core/admin/admin/src/content-manager/components/Inputs/index.js @@ -5,7 +5,7 @@ import get from 'lodash/get'; import omit from 'lodash/omit'; import take from 'lodash/take'; import isEqual from 'react-fast-compare'; -import { GenericInput, NotAllowedInput, useLibrary } from '@strapi/helper-plugin'; +import { GenericInput, NotAllowedInput, useLibrary, useCustomFields } from '@strapi/helper-plugin'; import { useContentTypeLayout } from '../../hooks'; import { getFieldName } from '../../utils'; import Wysiwyg from '../Wysiwyg'; @@ -39,9 +39,10 @@ function Inputs({ const { fields } = useLibrary(); const { formatMessage } = useIntl(); const { contentType: currentContentTypeLayout } = useContentTypeLayout(); + const customFieldsRegistry = useCustomFields(); const disabled = useMemo(() => !get(metadatas, 'editable', true), [metadatas]); - const type = fieldSchema.type; + const { type, customField: customFieldUid } = fieldSchema; const error = get(formErrors, [keys], null); const fieldName = useMemo(() => { @@ -164,6 +165,19 @@ function Inputs({ const { label, description, placeholder, visible } = metadatas; + // Memoize the component to avoid remounting it and losing state + const CustomFieldInput = useMemo(() => { + if (customFieldUid) { + const customField = customFieldsRegistry.get(customFieldUid); + const CustomFieldInput = React.lazy(customField.components.Input); + + return CustomFieldInput; + } + + // Not a custom field, component won't be used + return null; + }, [customFieldUid, customFieldsRegistry]); + if (visible === false) { return null; } @@ -217,6 +231,18 @@ function Inputs({ ); } + const customInputs = { + json: InputJSON, + uid: InputUID, + media: fields.media, + wysiwyg: Wysiwyg, + ...fields, + }; + + if (customFieldUid) { + customInputs[customFieldUid] = CustomFieldInput; + } + return ( - - {formattedContentTypeLayout.map((row, index) => { - if (isDynamicZone(row)) { - const { - 0: { - 0: { name, fieldSchema, metadatas, labelAction }, - }, - } = row; + }> + + {formattedContentTypeLayout.map((row, index) => { + if (isDynamicZone(row)) { + const { + 0: { + 0: { name, fieldSchema, metadatas, labelAction }, + }, + } = row; + + return ( + + + + + + + + ); + } return ( - - - - - - - - ); - } + + + {row.map((grid, gridIndex) => { + return ( + + {grid.map( + ({ fieldSchema, labelAction, metadatas, name, size }) => { + const isComponent = fieldSchema.type === 'component'; - return ( - - - {row.map((grid, gridIndex) => { - return ( - - {grid.map( - ({ fieldSchema, labelAction, metadatas, name, size }) => { - const isComponent = fieldSchema.type === 'component'; + if (isComponent) { + const { + component, + max, + min, + repeatable = false, + required = false, + } = fieldSchema; - if (isComponent) { - const { - component, - max, - min, - repeatable = false, - required = false, - } = fieldSchema; + return ( + + + + ); + } return ( - - + ); } - - return ( - - - - ); - } - )} - - ); - })} - - - ); - })} - + )} + + ); + })} + + + ); + })} + +