Hero Image Slider

Hi @all
I have created Hero Slider custom components by next js 14 but when i am doing drag and drop it is showing Builder block error like that.
API KEY:(dcff97ec8e7b44bca67378abcef9e3de)

This is my builder regestry:—

Builder.registerComponent(KiboHeroCarousel, {
name: ‘KiboHeroCarousel’,
inputs: [
{
name: ‘carouselItem’,
type: ‘list’,
defaultValue: [
{
imageUrl:
https://cdn-sb.mozu.com/26507-m1/cms/files/655bb09f-e5f2-4027-8cf6-76d0363172d1’,
mobileImageUrl:
https://cdn-sb.mozu.com/26507-m1/cms/files/655bb09f-e5f2-4027-8cf6-76d0363172d1’,
imageAlt: ‘image Alt text’,
title: ‘Check Off Your List Event’,
subtitle: ‘Save up to 50%’,
description: ‘Shop early to get your holiday gifts on time.’,
buttonText: ‘Shop Holiday Items on Sale’,
buttonLink: ‘https://’,
},
{
imageUrl:
https://cdn-sb.mozu.com/26507-m1/cms/files/7b763015-5d76-4c3c-a5fd-6a14a476b56c’,
mobileImageUrl:
https://cdn-sb.mozu.com/26507-m1/cms/files/7b763015-5d76-4c3c-a5fd-6a14a476b56c’,
imageAlt: ‘image Alt text’,
title: ‘Save upto 70%’,
subtitle: ‘Check Off Your List Event’,
description: ‘Shop early to get your holiday gifts on time.’,
buttonText: ‘Shop Holiday Items on Sale’,
contentPosition: ‘right’,
buttonLink: ‘https://’,
},
],
subFields: [
{
name: ‘mobileImageUrl’,
type: ‘file’,
},
{
name: ‘mobileImageUrl’,
type: ‘file’,
},
{
name: ‘imageAlt’,
type: ‘string’,
},
{
name: ‘title’,
type: ‘string’,
},
{
name: ‘subtitle’,
type: ‘string’,
},
{
name: ‘description’,
type: ‘string’,
},
{
name: ‘buttonText’,
type: ‘string’,
},
{
name: ‘buttonLink’,
type: ‘string’,
},
],
},
],
})

This is my code
import React from ‘react’

import {
Button,
useMediaQuery,
Card,
CardContent,
Typography,
useTheme,
CardMedia,
} from ‘@mui/material’
import { styled } from ‘@mui/system’
import { useRouter } from ‘next/router’
import Carousel from ‘react-material-ui-carousel’
import KiboImage from ‘…/common/KiboImage/KiboImage’

interface ItemProps {
imageUrl: string
mobileImageUrl: string
imageAlt: string
title?: string
subtitle?: string
description?: string
buttonText?: string
buttonLink: string
}
export interface HeroCarouselProps {
carouselItem: ItemProps
}

const MainStyle = styled(‘div’)({
display: ‘flex’,
color: ‘grey.700’,
})

const KiboHeroCarousel = ({ carouselItem }: HeroCarouselProps) => {
return (
<>
{carouselItem?.length > 0 && (

<Carousel navButtonsAlwaysVisible={true} swipe={true} sx={{ width: ‘100%’ }}>
{carouselItem?.map((item: ItemProps, index: any) => {
return <HeroItem {…item} key={index} />
})}


)}
</>
)
}

const styles = {
contentStyle: {
display: ‘flex’,
flexDirection: ‘column’,
justifyContent: ‘space-between’,
height: ‘600px’,
width: ‘100%’,
margin: ‘0px’,
padding: ‘0px’,
outline: ‘none’,
borderRadius: ‘0px’,
},
cardStyle: {
display: ‘flex’,
flexDirection: ‘column’,
marginBottom: ‘5%’,
backgroundColor: ‘common.white’,
opacity: ‘0.99’,
color: ‘common.black’,
justifyContent: ‘center’,
width: { xs: ‘80%’, md: ‘50%’ },
gap: 2,
},
nameStyle: {
width: ‘100%’,
textAlign: ‘center’,
fontWeight: 600,
},
desStyle: {
width: ‘100%’,
textAlign: ‘center’,
},
subTitleStyle: {
width: ‘100%’,
textAlign: ‘center’,
fontWeight: 800,
},
}

function HeroItem(props: ItemProps) {
const kiboTheme = useTheme()
const router = useRouter()
const mobileView = useMediaQuery(kiboTheme.breakpoints.down(‘md’))

const {
imageUrl,
mobileImageUrl,
imageAlt,
title,
subtitle,
description,
buttonText,
buttonLink,
} = props

return (

<CardMedia
sx={{
width: ‘100%’,
height: ‘100%’,
position: ‘relative’,
display: ‘flex’,
flexDirection: ‘column’,
justifyContent: { xs: ‘end’, md: ‘center’ },
}}
>
<KiboImage
src={mobileView ? mobileImageUrl : imageUrl}
alt={imageUrl ? imageAlt : ‘product-image-alt’}
layout=“fill”
objectFit=“cover”
data-testid=“product-image”
/>

    <CardContent
      sx={{
        display: 'flex',
        justifyContent: 'center',
      }}
    >
      <CardContent sx={styles.cardStyle}>
        <Typography variant="h2" sx={styles.nameStyle}>
          {title}
        </Typography>
        <Typography variant="h1" sx={styles.subTitleStyle}>
          {subtitle}
        </Typography>
        <Typography style={{ fontSize: mobileView ? '0.75rem' : '1rem' }} sx={styles.desStyle}>
          {description}
        </Typography>

        <Button
          variant="contained"
          sx={{ fontSize: mobileView ? '0.5rem' : '1rem' }}
          onClick={() => {
            router.push(buttonLink)
          }}
        >
          {buttonText}
        </Button>
      </CardContent>
    </CardContent>
  </CardMedia>
</Card>

)
}

export default KiboHeroCarousel;
please check and confirm me where is my fault and where i am doing mistakes…

API KEY:(dcff97ec8e7b44bca67378abcef9e3de)

Hello @Soumyaranjan,

Welcome to the builder.io forum post.

It seems there are issues with the registerComponent inputs, specifically a type error, and there are two inputs for mobileImageUrl.

I’ve tested your code with a few modifications and managed to get the carousel working. Here’s the modified code:

import React from 'react';
import { Button, useMediaQuery, Card, CardContent, Typography, useTheme, CardMedia } from '@mui/material';
import { styled } from '@mui/system';
import { useRouter } from 'next/router';
import Carousel from 'react-material-ui-carousel';
import Image from 'next/image';


interface ItemProps {
  imageUrl: string;
  mobileImageUrl: string;
  imageAlt: string;
  title?: string;
  subtitle?: string;
  description?: string;
  buttonText?: string;
  buttonLink: string;
}

export interface HeroCarouselProps {
  carouselItem: ItemProps[];
}

const MainStyle = styled('div')({
  display: 'flex',
  color: 'grey.700',
});

const HeroCarousel = ({ carouselItem }: HeroCarouselProps) => {
  return (
    <>
      {carouselItem?.length > 0 && (
        <Carousel navButtonsAlwaysVisible={true} swipe={true} sx={{ width: '100%' }}>
          {carouselItem?.map((item: ItemProps, index: any) => {
            return <HeroItem {...item} key={index} />;
          })}
        </Carousel>
      )}
    </>
  );
};

const styles = {
  contentStyle: {
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'space-between',
    height: '600px',
    width: '100%',
    margin: '0px',
    padding: '0px',
    outline: 'none',
    borderRadius: '0px',
  },
  cardStyle: {
    display: 'flex',
    flexDirection: 'column',
    marginBottom: '5%',
    backgroundColor: 'common.white',
    opacity: '0.99',
    color: 'common.black',
    justifyContent: 'center',
    width: { xs: '80%', md: '50%' },
    gap: 2,
  },
  nameStyle: {
    width: '100%',
    textAlign: 'center',
    fontWeight: 600,
  },
  desStyle: {
    width: '100%',
    textAlign: 'center',
  },
  subTitleStyle: {
    width: '100%',
    textAlign: 'center',
    fontWeight: 800,
  },
};

function HeroItem(props: ItemProps) {
  const kiboTheme = useTheme();
  const router = useRouter();
  const mobileView = useMediaQuery(kiboTheme.breakpoints.down('md'));

  const { imageUrl, mobileImageUrl, imageAlt, title, subtitle, description, buttonText, buttonLink } = props;

  return (
    <CardMedia
      sx={{
        width: '100%',
        height: '100%',
        position: 'relative',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: { xs: 'end', md: 'center' },
      }}
    >
      <Image
        src={mobileView ? mobileImageUrl : imageUrl}
        alt={imageAlt || 'product-image-alt'}
        width={400}
        height={300}
      />
      <CardContent sx={{ display: 'flex', justifyContent: 'center' }}>
        <CardContent sx={styles.cardStyle}>
          <Typography variant="h2" sx={styles.nameStyle}>
            {title}
          </Typography>
          <Typography variant="h1" sx={styles.subTitleStyle}>
            {subtitle}
          </Typography>
          <Typography style={{ fontSize: mobileView ? '0.75rem' : '1rem' }} sx={styles.desStyle}>
            {description}
          </Typography>
          <Button
            variant="contained"
            sx={{ fontSize: mobileView ? '0.5rem' : '1rem' }}
            onClick={() => {
              router.push(buttonLink);
            }}
          >
            {buttonText}
          </Button>
        </CardContent>
      </CardContent>
    </CardMedia>
  );
}

export default HeroCarousel;

Register component with the Builder:

Builder.registerComponent(HeroCarousel, {
  name: 'HeroCarousel',
  inputs: [
    {
      name: 'carouselItem',
      type: 'list',
      defaultValue: [
        {
          imageUrl: 'https://cdn.builder.io/api/v1/image/assets%2Fc782aff3c66f48acb425981b997feb10%2Fcaccbc5f7a224ef1a08f8efbb79d567e',
          mobileImageUrl: 'https://cdn.builder.io/api/v1/image/assets%2Fc782aff3c66f48acb425981b997feb10%2F28c7b1407cf44530994c12504421606e',
          imageAlt: 'image Alt text',
          title: 'Check Off Your List Event',
          subtitle: 'Save up to 50%',
          description: 'Shop early to get your holiday gifts on time.',
          buttonText: 'Shop Holiday Items on Sale',
          contentPosition: 'right',
          buttonLink: 'https://builder.io',
        },
        {
          imageUrl: 'https://cdn.builder.io/api/v1/image/assets%2Fc782aff3c66f48acb425981b997feb10%2F73dd3ce0e5424489ab09dc10f10e41c4',
          mobileImageUrl: 'https://cdn.builder.io/api/v1/image/assets%2Fc782aff3c66f48acb425981b997feb10%2Fa52821d3083140ef85bd790d47ec147d',
          imageAlt: 'image Alt text',
          title: 'Save upto 70%',
          subtitle: 'Check Off Your List Event',
          description: 'Shop early to get your holiday gifts on time.',
          buttonText: 'Shop Holiday Items on Sale',
          contentPosition: 'right',
          buttonLink: 'https://builder.io',
        },
      ],
      subFields: [
        {
          name: 'imageUrl',
          type: 'file',
        },
        {
          name: 'mobileImageUrl',
          type: 'file',
        },
        {
          name: 'imageAlt',
          type: 'string',
        },
        {
          name: 'title',
          type: 'string',
        },
        {
          name: 'subtitle',
          type: 'string',
        },
        {
          name: 'description',
          type: 'string',
        },
        {
          name: 'buttonText',
          type: 'string',
        },
        {
          name: 'contentPosition',
          type: 'string',
        },
        {
          name: 'buttonLink',
          type: 'string',
        },
      ],
    },
  ],
})

Hope this helps!

Thanks,