Skip to main content

Create Product Block

CreateProduct is a controlled product creation form built on MUI.

Installation

npm install @nodeblocks/frontend-create-product-block

What You Need

ItemWhy it matters
dataSingle source of truth for form state; includes fields like title, categoryId, quantity, tags, prefecture, and image
onDataChangeReceives updated state plus metadata for validation, analytics, or side effects
errors (optional)Field errors keyed by bracket-notation paths
labels (optional)Root copy for section titles, field labels, button text, dropzone messages, and unit suffixes
placeholders (optional)Root placeholder copy for text, number, and select fields
selectOptions (optional)Dropdown options for category, type, option, and prefecture fields
tagTypes and tags (optional)Enables the tags section in BasicInfo.TagsField
onRejectAttachment (optional)Called when the image dropzone rejects a file
Controlled component

CreateProduct does not own form state. Keep state in your app and pass it through data. The default shape includes title, categoryId, typeId, optionId, quantity, description, details, tags, prefecture, city, onlineAvailability, inventoryNotes, availableFrom, availableUntil, additionalDetails, and image.

Code Examples

Live Editor
function Example() {
  const defaultData = {
    title: '',
    categoryId: '',
    typeId: '',
    optionId: '',
    quantity: '',
    description: '',
    details: '',
    tags: [],
    prefecture: '',
    city: '',
    onlineAvailability: false,
    inventoryNotes: '',
    availableFrom: '',
    availableUntil: '',
    additionalDetails: '',
    image: null,
  };

  const [data, setData] = React.useState(defaultData);
  const prefectureOptions = [
    { value: 'Hokkaido', label: 'Hokkaido' },
    { value: 'Tokyo', label: 'Tokyo' },
    { value: 'Osaka', label: 'Osaka' },
    { value: 'Okinawa', label: 'Okinawa' },
  ];

  return (
    <CreateProduct
      data={data}
      onDataChange={setData}
      selectOptions={{
        categoryOptions: [
          { value: 'electronics', label: 'Electronics' },
          { value: 'clothing', label: 'Clothing' },
        ],
        typeOptions: [
          { value: 'physical', label: 'Physical' },
          { value: 'digital', label: 'Digital' },
        ],
        optionOptions: [
          { value: 'standard', label: 'Standard' },
          { value: 'premium', label: 'Premium' },
        ],
        prefectureOptions,
      }}
      tagTypes={[
        { id: '100', label: 'Highlights' },
        { id: '200', label: 'Shipping' },
      ]}
      tags={[
        { id: '101', typeId: '100', label: 'Best seller' },
        { id: '201', typeId: '200', label: 'Ships from Japan' },
      ]}
      onSubmit={(event) => {
        event.preventDefault();
        setData((current) => ({ ...current }));
      }}
    />
  );
}
Result
Loading...

Important Props

Core Props

PropTypeRequiredDefaultDescription
dataCreateProductFormData ({ title, categoryId, typeId, optionId, quantity, description, details, tags, prefecture, city, onlineAvailability, inventoryNotes, availableFrom, availableUntil, additionalDetails, image } or extended Record<string, unknown>)Yes-Controlled form data object
onDataChange(data, meta) => voidYes-Called on updates; meta includes name, value, cause (input, change, blur, clear, reset, programmatic), and optional event
errors{ [fieldName: string]: string | string[] }NoundefinedField errors keyed by bracket-notation paths such as title, categoryId, image, or nested custom paths
labels{ mainInfoSectionTitle?, titleField?, dropzoneDropHere?, dropzoneUploadImage?, dropzoneSubtitle?, dropzoneImageAlt?, dropzoneOptionsButton?, dropzoneReplaceFile?, dropzoneDeleteFile?, basicInfoSectionTitle?, categoryField?, typeField?, optionField?, quantityField?, quantityUnit?, descriptionField?, detailsField?, tagsField?, additionalInfoTitle?, additionalInfoSubtitle?, prefectureField?, cityField?, onlineAvailabilityField?, inventoryNotesField?, availableFromField?, availableUntilField?, additionalDetailsField?, submitButton? }NomainInfoSectionTitle: 'Create a Product', titleField: 'Title', dropzoneDropHere: 'Drop the image here...', dropzoneUploadImage: 'Upload product image', dropzoneSubtitle: 'PNG, JPG up to 2MB', dropzoneImageAlt: 'Selected', dropzoneOptionsButton: 'Options', dropzoneReplaceFile: 'Select a new file', dropzoneDeleteFile: 'Delete', basicInfoSectionTitle: 'Basic Information', categoryField: 'Category', typeField: 'Type', optionField: 'Option', quantityField: 'Quantity', quantityUnit: 'pcs', descriptionField: 'Description', detailsField: 'Details', tagsField: 'Tags', additionalInfoTitle: 'Inventory', additionalInfoSubtitle: 'Location', prefectureField: 'Prefecture', cityField: 'City', onlineAvailabilityField: 'Online Availability', inventoryNotesField: 'Inventory Notes', availableFromField: 'Available From', availableUntilField: 'Available Until', additionalDetailsField: 'Additional Details', submitButton: 'Submit'Root copy for the title, sections, field labels, dropzone text, and submit button
placeholders{ titleField?, categoryField?, typeField?, optionField?, quantityField?, descriptionField?, detailsField?, prefectureField?, cityField?, inventoryNotesField?, additionalDetailsField? }NotitleField: 'Enter title', categoryField: 'Select category', typeField: 'Select type', optionField: 'Select option', quantityField: 'Enter quantity', descriptionField: 'Describe the product', detailsField: 'Enter details', prefectureField: 'Enter prefecture', cityField: 'Enter city', inventoryNotesField: 'Notes about inventory', additionalDetailsField: 'Enter additional details'Root placeholder copy for text, number, and select fields
selectOptions{ categoryOptions?, typeOptions?, optionOptions?, prefectureOptions? }NoundefinedDropdown option sets for the select fields; omitted groups render as empty lists
tagTypesTagType[]NoundefinedEnables grouped rendering in BasicInfo.TagsField
tagsTag[]NoundefinedAvailable tags rendered in BasicInfo.TagsField
onRejectAttachment(file: File, error: DropzoneFileError) => voidNoundefinedCalled when the dropzone rejects an image file

Content Props

No additional root-only content props are exposed beyond labels, placeholders, selectOptions, tagTypes, and tags.

Layout and Composition Props

PropTypeRequiredDefaultDescription
componentStackProps<'form'>['component']No'form'Root container element
childrenReactNode or block override functionNoundefinedPass JSX children for compound components, or a function to override blocks
classNamestringNoundefinedAdditional class name on the root container
sxStackProps<'form'>['sx']NoundefinedMUI sx styling for the root container

Inherits StackProps<'form'> props except children. The root renders mainInfo, basicInfo, additionalInfo, and actions by default. The internal input primitives are exported separately for custom layouts: TextField, NumberField, TimeField, CheckboxField, and SelectField.

Default UI Blocks

BlockMUI base component(s)Notes
CreateProductStack + LocalizationProviderRoot provider and layout container; defaults to component="form" with centered content and a fixed max width
MainInfoStackTop section for image upload and title
MainInfo.SectionTitleTypographyDefault copy is Create a Product
MainInfo.DropzoneBox + Button + Menu + Typographyname="image", default drop message Drop the image here..., upload prompt Upload product image, subtitle PNG, JPG up to 2MB, options button Options
MainInfo.TitleFieldTextFieldname="title", default label Title, default placeholder Enter title, max length 100
BasicInfoStackMiddle section for catalog, quantity, description, details, and tags
BasicInfo.SectionTitleTypographyDefault copy is Basic Information
BasicInfo.CategoryFieldSelectFieldname="categoryId", default label Category, default placeholder Select category
BasicInfo.TypeFieldSelectFieldname="typeId", default label Type, default placeholder Select type
BasicInfo.OptionFieldSelectFieldname="optionId", default label Option, default placeholder Select option
BasicInfo.QuantityFieldFormControl + FormLabel + OutlinedInputname="quantity", default label Quantity, default placeholder Enter quantity, unit suffix pcs
BasicInfo.DescriptionFieldTextFieldname="description", default label Description, default placeholder Describe the product, multiline
BasicInfo.DetailsFieldTextFieldname="details", default label Details, default placeholder Enter details, multiline
BasicInfo.TagsFieldFormControl + FormLabel + FormGroup + Checkboxname="tags", default label Tags; rendered only when both tagTypes and tags are provided
AdditionalInfoStackLower section for inventory and availability details
AdditionalInfo.TitleTypographyDefault copy is Inventory
AdditionalInfo.SubtitleTypographyDefault copy is Location
AdditionalInfo.PrefectureFieldSelectFieldname="prefecture", default label Prefecture, default placeholder Select prefecture
AdditionalInfo.CityFieldTextFieldname="city", default label City, default placeholder Enter city
AdditionalInfo.OnlineAvailabilityFieldFormControlLabel + Checkboxname="onlineAvailability", default label Online Availability
AdditionalInfo.InventoryNotesFieldTextFieldname="inventoryNotes", default label Inventory Notes, default placeholder Notes about inventory, multiline
AdditionalInfo.AvailableFromFieldTimePickername="availableFrom", default label Available From, stored as HH:mm
AdditionalInfo.AvailableUntilFieldTimePickername="availableUntil", default label Available Until, stored as HH:mm
AdditionalInfo.AdditionalDetailsFieldTextFieldname="additionalDetails", default label Additional Details, default placeholder Enter additional details, multiline
ActionsStackBottom action row centered on the page
Actions.SubmitButtonButtonDefault copy is Submit, with a leading check icon

Extra field primitives

PrimitiveMUI base component(s)Notes
TextFieldTextFieldShared controlled text primitive exported as CreateProduct.TextField
NumberFieldTextFieldShared controlled numeric primitive exported as CreateProduct.NumberField
TimeFieldTimePickerShared controlled time primitive exported as CreateProduct.TimeField; stores values as HH:mm
CheckboxFieldFormControlLabel + CheckboxShared controlled checkbox primitive exported as CreateProduct.CheckboxField
SelectFieldTextFieldShared controlled select primitive exported as CreateProduct.SelectField

TypeScript

export type CreateProductFormData =
| {
title: string;
categoryId: string;
typeId: string;
optionId: string;
quantity: string;
description: string;
details: string;
tags: Tag[];
prefecture: string;
city: string;
onlineAvailability: boolean;
inventoryNotes: string;
availableFrom: string;
availableUntil: string;
additionalDetails: string;
image: { url: string; type?: string; id?: string } | File | null;
}
| Record<string, unknown>;