[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/ProductPrice/index.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import classNames from 'classnames'
// import PropTypes from 'prop-types'
import { isNil, head, last, sort, equals } from 'ramda'
import { FormattedMessage, injectIntl } from 'react-intl'
import IOMessage from '../../../NativeTypes/IOMessage'
import { useRuntime } from '../../../../../../vtex.render-runtime'
import formatCurrency from '../../../FormatCurrency/formatCurrency'
import useCssHandles from '../../../CssHandles/useCssHandles'

import ProductPriceLoader from './Loader'
import PricePropTypes from './propTypes'
import Installments from './Installments'
import Price from './Price'

import productPrice from './styles.css'

const CSS_HANDLES = ['price_className',
  'price_loader',
  'price_listPriceContainer',
  'price_listPriceLabel',
  'price_listPrice',
  'price_listPriceRange',
  'price_sellingPriceRange',
  'price_sellingPriceContainer',
  'price_sellingPriceLabel',
  'price_sellingPrice',
  'price_savingsContainer',
  'price_savings',
  'price_savings_value',
  'price_installment',
  'price_interestRate',
  'price_installmentContainer']

const isValidPriceRange = priceRange => {
  const [lowPrice, highPrice] = priceRange
  return priceRange.length === 2 && lowPrice !== highPrice
}

const getPriceRange = prices => {
  const sortedPrices = sort((a, b) => a - b, prices)
  return [head(sortedPrices), last(sortedPrices)]
}

const canShowListPrice = props => {
  const {
    sellingPriceList,
    sellingPrice,
    listPrice,
    listPriceList,
    showListPrice,
    showListPriceRange,
    showSellingPriceRange,
  } = props

  if (!showListPrice) {
    return false
  }

  const sellingPriceRange =
    (sellingPriceList && getPriceRange(sellingPriceList)) || []
  const listPriceRange = (listPriceList && getPriceRange(listPriceList)) || []

  const showingSellingPriceRange =
    showSellingPriceRange && isValidPriceRange(sellingPriceRange)
  const showingListPriceRange =
    showListPriceRange && isValidPriceRange(listPriceRange)

  const sellingPriceToShow = showingSellingPriceRange
    ? sellingPriceRange
    : sellingPrice
  const listPriceToShow = showingListPriceRange ? listPriceRange : listPrice

  return !equals(listPriceToShow, sellingPriceToShow)
}

/**
 * The Price component. Shows the prices information of the Product Summary.
 */
const ProductPrice = (props, context) => {
  const {
    sellingPriceList,
    sellingPrice,
    listPrice,
    listPriceList,
    showListPrice,
    showSellingPriceRange,
    showListPriceRange,
    showInstallments,
    showLabels,
    showSavings,
    labelSellingPrice,
    labelListPrice,
    // labelSavings,
    className,
    loaderClass,
    listPriceContainerClass,
    listPriceLabelClass,
    listPriceClass,
    listPriceRangeClass,
    sellingPriceRangeClass,
    sellingPriceContainerClass,
    sellingPriceLabelClass,
    sellingPriceClass,
    savingsContainerClass,
    savingsClass,
    installments,
    installmentClass,
    interestRateClass,
    installmentContainerClass,
    styles,
    intl,
  } = props

  const { culture } = useRuntime()

  const handles = useCssHandles(CSS_HANDLES)

  // let { classes } = props

  // avoiding undefined verifications
  // classes = {
  //   ...PriceWithIntl.defaultProps.classes,
  //   ...classes,
  // }

  if ((showListPrice && isNil(listPrice)) || isNil(sellingPrice)) {
    return <ProductPriceLoader loaderClass={`${loaderClass} ${handles.price_loader}`} {...styles} />
  }

  const mayShowListPrice = canShowListPrice(props)

  const sellingPriceRange = sellingPriceList && getPriceRange(sellingPriceList)
  const listPriceRange = listPriceList && getPriceRange(listPriceList)

  return (
    <div className={classNames(productPrice.priceContainer, className, handles.price_className)}>
      {mayShowListPrice && (
        <div
          className={classNames(
            productPrice.listPrice,
            listPriceContainerClass,
            handles.price_listPriceContainer
          )}
        >
          {showLabels && (
            <div
              className={classNames(
                productPrice.listPriceLabel,
                listPriceLabelClass,
                handles.price_listPriceLabel,
                'dib ph2 t-small-ns t-mini'
              )}
            >
              <IOMessage id={labelListPrice} />
            </div>
          )}
          <Price
            showPriceRange={showListPriceRange}
            priceRange={listPriceRange}
            price={listPrice}
            rangeContainerClasses={classNames(
              productPrice.listPriceValue,
              listPriceRangeClass,
              handles.price_listPriceRange,
            )}
            singleContainerClasses={classNames(
              productPrice.listPriceValue,
              listPriceClass,
              handles.price_listPrice
            )}
          />
        </div>
      )}
      <div
        className={classNames(
          productPrice.sellingPrice,
          productPrice.sellingPriceContainer,
          sellingPriceContainerClass,
          handles.price_sellingPriceContainer
        )}
      >
        {showLabels && mayShowListPrice && (
          <div
            className={classNames(
              productPrice.sellingPriceLabel,
              sellingPriceLabelClass,
              handles.price_sellingPriceLabel
            )}
          >
            <IOMessage id={labelSellingPrice} />
          </div>
        )}
        <Price
          showPriceRange={showSellingPriceRange}
          priceRange={sellingPriceRange}
          price={sellingPrice}
          rangeContainerClasses={classNames(
            productPrice.sellingPrice,
            productPrice.sellingPriceValue,
            productPrice['sellingPriceValue--range'],
            sellingPriceRangeClass,
            handles.price_sellingPriceRange
          )}
          singleContainerClasses={classNames(
            productPrice.sellingPrice,
            productPrice.sellingPriceValue,
            sellingPriceClass,
            handles.price_sellingPrice
          )}
        />
      </div>
      {showInstallments && (
        <Installments
          installments={installments}
          showLabels={showLabels}
          className={`${installmentContainerClass} ${handles.price_installmentContainer}`}
          interestRateClass={`${interestRateClass} ${handles.price_interestRate}`}
          installmentClass={`${installmentClass} ${handles.price_installment}`}
        />
      )}
      {mayShowListPrice && showSavings && (listPrice - sellingPrice > 0) && (
        <div
          className={classNames(
            productPrice.savingPrice,
            savingsContainerClass,
            handles.price_savingsContainer
          )}
        >
          <div
            className={classNames(productPrice.savingPriceValue, savingsClass, handles.price_savings)}
          >
            <FormattedMessage
              id="store/pricing.savings"
              values={{
                savings:
                <span
                  className={handles.price_savings_value}>
                    {formatCurrency({
                      intl,
                      culture,
                      value: listPrice - sellingPrice,
                  })}
                </span>
              }}
            />
          </div>
        </div>
      )}
    </div>
  )
}

ProductPrice.propTypes = PricePropTypes

const PriceWithIntl = injectIntl(ProductPrice)

PriceWithIntl.defaultProps = {
  showSellingPriceRange: false,
  showListPriceRange: false,
  showListPrice: true,
  showLabels: true,
  showInstallments: false,
  showSavings: false,
  labelSellingPrice: null,
  labelListPrice: null,
}

PriceWithIntl.schema = {
  title: 'admin/editor.productPrice.title',
  description: 'admin/editor.productPrice.description',
  type: 'object',
  properties: {
    showSellingPriceRange: {
      type: 'boolean',
      title: 'admin/editor.productPrice.showSellingPriceRange',
      default: PriceWithIntl.defaultProps.showSellingPriceRange,
      isLayout: true,
    },
    showListPriceRange: {
      type: 'boolean',
      title: 'admin/editor.productPrice.showListPriceRange',
      default: PriceWithIntl.defaultProps.showListPriceRange,
      isLayout: true,
    },
    showListPrice: {
      type: 'boolean',
      title: 'admin/editor.productPrice.showListPrice',
      default: PriceWithIntl.defaultProps.showListPrice,
      isLayout: true,
    },
    showLabels: {
      type: 'boolean',
      title: 'admin/editor.productPrice.showLabels',
      default: PriceWithIntl.defaultProps.showLabels,
      isLayout: true,
    },
    showInstallments: {
      type: 'boolean',
      title: 'admin/editor.productPrice.showInstallments',
      default: PriceWithIntl.defaultProps.showInstallments,
      isLayout: true,
    },
    showSavings: {
      type: 'boolean',
      title: 'admin/editor.productPrice.showSavings',
      default: PriceWithIntl.defaultProps.showSavings,
      isLayout: true,
    },
  },
}

export default PriceWithIntl

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/ProductPrice/Installments.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { Fragment } from 'react'
import { useRuntime } from '../../../../../../vtex.render-runtime'
import { injectIntl } from 'react-intl'
import classNames from 'classnames'
import { isEmpty } from 'ramda'
import { FormattedMessage } from 'react-intl'
import PropTypes from 'prop-types'
import formatCurrency from '../../../FormatCurrency/formatCurrency'

import PricePropTypes from './propTypes'

import productPrice from './styles.css'

/** Installments component */
const Installments = ({
  showLabels,
  installments = [],
  className,
  installmentClass,
  interestRateClass,
  intl,
}) => {
  const { culture } = useRuntime()

  if (
    !installments ||
    isEmpty(
      installments.filter(
        ({ NumberOfInstallments }) => NumberOfInstallments > 1
      )
    )
  ) {
    return null
  }

  const noInterestRateInstallments = installments.filter(
    installment =>
      !installment.InterestRate && installment.NumberOfInstallments > 1
  )

  /*
   * - The selected installment will be the one with the highest `NumberOfInstallments`;
   * - If there is no 'interest-free' installments, the normal installments will be analyzed.
   */
  const installment = (isEmpty(noInterestRateInstallments)
    ? installments
    : noInterestRateInstallments
  ).reduce((previous, current) =>
    previous.NumberOfInstallments > current.NumberOfInstallments
      ? previous
      : current
  )

  const formattedInstallmentPrice = formatCurrency({
    intl,
    culture,
    value: installment.Value,
  })

  const [installmentsElement, installmentPriceElement, timesElement] = [
    installment.NumberOfInstallments,
    formattedInstallmentPrice,
    <Fragment key="x">x</Fragment>,
  ].map((element, index) => (
    <span className={installmentClass} key={index}>
      {element}
    </span>
  ))

  return (
    <div className={classNames(productPrice.installmentsPrice, className)}>
      {showLabels ? (
        <FormattedMessage
          id="store/pricing.installment-display"
          values={{
            installments: installmentsElement,
            installmentPrice: installmentPriceElement,
            times: timesElement,
          }}
        />
      ) : (
        <Fragment>
          {installmentsElement}
          {timesElement} {installmentPriceElement}
        </Fragment>
      )}
      {!installment.InterestRate && (
        <div
          className={classNames(
            productPrice.interestRatePrice,
            interestRateClass
          )}
        >
          <FormattedMessage id="store/pricing.interest-free" />
        </div>
      )}
    </div>
  )
}

Installments.propTypes = {
  /** Classes to be applied to the root element */
  className: PropTypes.string,
  /** Classes to be applied to installment value element */
  installmentClass: PropTypes.string,
  /** Classes to be applied to interest rate element */
  interestRateClass: PropTypes.string,
  /** Product installments to be displayed */
  installments: PricePropTypes.installments,
  /** Pages editor config to display labels */
  showLabels: PropTypes.bool.isRequired,
}

export default injectIntl(Installments)

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/ProductPrice/propTypes.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import PropTypes from 'prop-types'

export default {
  /** Product list of selling prices */
  sellingPriceList: PropTypes.arrayOf(PropTypes.number),
  /** Product list of list prices */
  listPriceList: PropTypes.arrayOf(PropTypes.number),
  /** Product selling price */
  sellingPrice: PropTypes.number,
  /** Product list price */
  listPrice: PropTypes.number,
  /** Set visibility of selling prices range */
  showSellingPriceRange: PropTypes.bool.isRequired,
  /** Set visibility of list prices range */
  showListPriceRange: PropTypes.bool.isRequired,
  /** Set visibility of list price */
  showListPrice: PropTypes.bool.isRequired,
  /** Set visibility of labels */
  showLabels: PropTypes.bool.isRequired,
  /** Set visibility of installments */
  showInstallments: PropTypes.bool.isRequired,
  /** Set visibility of savings */
  showSavings: PropTypes.bool,
  /** Text to the selling price's label */
  labelSellingPrice: PropTypes.string,
  /** Text to the list price's label */
  labelListPrice: PropTypes.string,
  /** Available installments */
  installments: PropTypes.arrayOf(
    PropTypes.shape({
      /** Installment value */
      Value: PropTypes.number.isRequired,
      /** Interest rate (zero if interest-free) */
      InterestRate: PropTypes.number.isRequired,
      /** Calculated total value */
      TotalValuePlusInterestRate: PropTypes.number,
      /** Number of installments */
      NumberOfInstallments: PropTypes.number.isRequired,
      /** Installment offer name */
      Name: PropTypes.string,
    })
  ),
  /** Classes to be applied to root element */
  className: PropTypes.string,
  /** Classes to be applied to loader root element */
  loaderClass: PropTypes.string,
  /** Classes to be applied to container of list price */
  listPriceContainerClass: PropTypes.string,
  /** Classes to be applied to label of price */
  listPriceLabelClass: PropTypes.string,
  /** Classes to be applied to price value */
  listPriceClass: PropTypes.string,
  /** Classes to be applied to range selling prices value */
  sellingPriceRangeClass: PropTypes.string,
  /** Classes to be applied to range list prices value */
  listPriceRangeClass: PropTypes.string,
  /** Classes to be applied to selling price container */
  sellingPriceContainerClass: PropTypes.string,
  /** Classes to be applied to selling price label */
  sellingPriceLabelClass: PropTypes.string,
  /** Classes to be applied to selling price value */
  sellingPriceClass: PropTypes.string,
  /** Classes to be applied to savings container */
  savingsContainerClass: PropTypes.string,
  /** Classes to be applied to savings */
  savingsClass: PropTypes.string,
  /** Classes to be applied to installment element */
  installmentClass: PropTypes.string,
  /** Classes to be applied to installment container */
  installmentContainerClass: PropTypes.string,
  /** Classes to be applied to interest rate element */
  interestRateClass: PropTypes.string,
  /** Component and content loader styles */
  styles: PropTypes.object,
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/ProductPrice/Price.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { injectIntl } from 'react-intl'
import { useRuntime } from '../../../../../../vtex.render-runtime'
import formatCurrency from '../../../FormatCurrency/formatCurrency'
import FormattedCurrency from '../../../FormatCurrency/FormattedCurrency'

const isValidPriceRange = priceRange => {
  const [lowPrice, highPrice] = priceRange
  return priceRange.length === 2 && lowPrice !== highPrice
}

const formatPriceRange = (intl, culture, rawPriceRange) => {
  const priceRangeFormatted = (rawPriceRange || []).map(value =>
    formatCurrency({ intl, culture, value })
  )

  return priceRangeFormatted.join(' - ')
}

const Price = ({
  showPriceRange,
  priceRange,
  price,
  rangeContainerClasses,
  singleContainerClasses,
  intl,
}) => {
  const { culture } = useRuntime()

  const mustShowPriceRange =
    showPriceRange && priceRange && isValidPriceRange(priceRange)

  if (mustShowPriceRange) {
    return (
      <span className={rangeContainerClasses}>
        {formatPriceRange(intl, culture, priceRange)}
      </span>
    )
  }

  return (
    <span className={singleContainerClasses}>
      <FormattedCurrency value={price} />
    </span>
  )
}

export default injectIntl(Price)

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/ProductPrice/Loader.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import classNames from 'classnames'
import ContentLoader from 'react-content-loader'
import productPrice from './styles.css'

const ProductPriceLoader = (loaderProps = {}) => {
  const { loaderClass, ...props } = loaderProps
  return (
    <div
      className={classNames(
        productPrice.priceContainer,
        productPrice.priceLoaderContainer,
        loaderClass
      )}
    >
      <ContentLoader
        style={{
          width: '100%',
          height: '100%',
        }}
        width={300}
        height={70}
        preserveAspectRatio="xMinYMin meet"
        {...props}
      >
        <rect
          height="0.75em"
          width="50%"
          x="25%"
          {...loaderProps[productPrice.listPriceLoader]}
        />
        <rect {...loaderProps[productPrice.sellingPriceLabelLoader]} />
        <rect
          height="1em"
          width="70%"
          x="15%"
          y="1.25em"
          {...loaderProps[productPrice.sellingPriceLoader]}
        />
        <rect
          height="0.75em"
          width="80%"
          x="10%"
          y="2.75em"
          {...loaderProps[productPrice.installmentsPriceLoader]}
        />
        <rect {...loaderProps[productPrice.savingsPriceLoader]} />
      </ContentLoader>
    </div>
  )
}

export default ProductPriceLoader

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/AvailabilitySubscriber/styles.css from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```css
/**
* AvailabilitySubscriber CSS Module
*/

.subscriberContainer {}

.title {}

.subscribeLabel {}

.form {}

.content {}

.input {}

.inputName {}

.inputEmail {}

.submit {}

.success {}

.error {}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/AvailabilitySubscriber/Wrapper.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { useContext } from 'react'
import ProductContext from '../../../ProductContext/ProductContext'
import { path } from 'ramda'

import AvailabilitySubscriber from './index'

const isAvailable = commertialOffer =>
  Number.isNaN(+path(['AvailableQuantity'], commertialOffer)) ||
  path(['AvailableQuantity'], commertialOffer) > 0

const AvailabilitySubscriberWrapper = props => {
  const valuesFromContext = useContext(ProductContext)

  const commertialOffer = path(
    ['selectedItem', 'sellers', 0, 'commertialOffer'],
    valuesFromContext
  )

  const available = props.available != null ? props.available : isAvailable(commertialOffer)

  // Render component only if product is out of sales
  if (available) return null

  const skuId = props.skuId != null ? props.skuId : path(['selectedItem', 'itemId'], valuesFromContext)

  return <AvailabilitySubscriber skuId={skuId} />
}

export default AvailabilitySubscriberWrapper

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/AvailabilitySubscriber/index.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { ApolloConsumer } from 'react-apollo'
import { injectIntl } from 'react-intl'

import Button from '../../../Styleguide/Button'
import Input from '../../../Styleguide/Input'
import { loader } from 'graphql.macro'

const ADD_TO_AVAILABILITY_SUBSCRIBER_MUTATION = loader('./mutations/addToAvailabilitySubscriberMutation.gql')

import styles from './styles.css'

/**
 * Represents the availability subscriber form, that's shown when
 * the product isn't available.
 */
class AvailabilitySubscriber extends Component {
  emailInput = React.createRef()
  nameInput = React.createRef()

  state = {
    name: '',
    email: '',
    emailError: '',
    hasBlurredEmail: false,
    isLoading: false,
    sendStatus: '',
  }

  static propTypes = {
    /** The id of the current product sku */
    skuId: PropTypes.string.isRequired,
  }

  validateEmail = email => {
    const { emailError } = this.state

    const emailRegex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/

    let error = ''

    if (!emailRegex.test(email.toLowerCase())) {
      error = 'store/availability-subscriber.invalid-email'
    }

    if (error !== emailError) {
      this.setState({
        emailError: error,
      })
    }
  }

  handleEmailBlur = () => {
    if (this.state.hasBlurredEmail) {
      return
    }

    this.setState({
      hasBlurredEmail: true,
    })
  }

  handleInputChange = e => {
    this.setState({
      [e.target.name]: e.target.value,
    })

    if (e.target.name === 'email') {
      this.validateEmail(e.target.value)
    }
  }

  handleSubmit = (e, client) => {
    e.preventDefault()
    const variables = {
      acronym: 'AS',
      document: {
        fields: [
          {
            key: 'skuId',
            value: this.props.skuId,
          },
          {
            key: 'name',
            value: this.state.name,
          },
          {
            key: 'email',
            value: this.state.email,
          },
          {
            key: 'notificationSend',
            value: 'false',
          },
          {
            key: 'createdAt',
            value: new Date().toISOString(),
          },
          {
            key: 'sendAt',
            value: null,
          },
        ],
      },
    }
    this.setState({
      isLoading: true,
    })
    client
      .mutate({
        mutation: ADD_TO_AVAILABILITY_SUBSCRIBER_MUTATION,
        variables,
      })
      .then(
        mutationRes => {
          this.setState({
            name: '',
            email: '',
            isLoading: false,
            sendStatus: 'success',
          })
        },
        mutationErr => {
          this.setState({
            isLoading: false,
            sendStatus: 'error',
          })
        }
      )
    const event = new Event('message:success')
    event.details = {
      success: true,
      message: this.translate('store/availability-subscriber.added-message'),
    }
    document.dispatchEvent(event)
  }

  translate = id => this.props.intl.formatMessage({ id })

  componentDidMount() {
    this.setState({
      email: this.emailInput.value || '',
      name: this.nameInput.value || '',
    })
  }

  render() {
    const {
      name,
      email,
      emailError,
      hasBlurredEmail,
      isLoading,
      sendStatus,
    } = this.state

    const isFormDisabled =
      name === '' || email === '' || emailError !== '' || isLoading

    let emailErrorMessage = ''

    if (hasBlurredEmail && emailError !== '') {
      emailErrorMessage = this.translate(emailError)
    }

    return (
      <ApolloConsumer>
        {client => (
          <div className={styles.subscriberContainer}>
            <div className={`${styles.title} t-body mb3`}>
              {this.translate('store/availability-subscriber.title')}
            </div>
            <div className={`${styles.subscribeLabel} t-small fw3`}>
              {this.translate('store/availability-subscriber.subscribe-label')}
            </div>
            <form
              className={`${styles.form} mb4`}
              onSubmit={e => this.handleSubmit(e, client)}
            >
              <div
                className={`${styles.content} flex-ns justify-between mt4 mw6`}
              >
                <div
                  className={`${styles.input} ${
                    styles.inputName
                  } w-100 mr5 mb4`}
                >
                  <Input
                    name="name"
                    type="text"
                    placeholder={this.translate(
                      'store/availability-subscriber.name-placeholder'
                    )}
                    value={name}
                    onChange={this.handleInputChange}
                    ref={e => {
                      this.nameInput = e
                    }}
                  />
                </div>
                <div
                  className={`${styles.input} ${
                    styles.inputEmail
                  } w-100 mr5 mb4`}
                >
                  <Input
                    name="email"
                    type="text"
                    placeholder={this.translate(
                      'store/availability-subscriber.email-placeholder'
                    )}
                    value={email}
                    onChange={this.handleInputChange}
                    onBlur={this.handleEmailBlur}
                    error={hasBlurredEmail && !!emailError}
                    errorMessage={emailErrorMessage}
                    ref={e => {
                      this.emailInput = e
                    }}
                  />
                </div>
                <div className={`${styles.submit} flex items-center mb4`}>
                  <Button
                    type="submit"
                    variation="primary"
                    size="small"
                    disabled={isFormDisabled}
                    isLoading={isLoading}
                  >
                    {this.translate('store/availability-subscriber.send-label')}
                  </Button>
                </div>
              </div>
              {sendStatus === 'success' && (
                <div className={`${styles.success} t-body c-success`}>
                  {this.translate('store/availability-subscriber.added-message')}
                </div>
              )}
              {sendStatus === 'error' && (
                <div className={`${styles.error} c-danger`}>
                  {this.translate('store/availability-subscriber.error-message')}
                </div>
              )}
            </form>
          </div>
        )}
      </ApolloConsumer>
    )
  }
}

export default injectIntl(AvailabilitySubscriber)

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/ProductName/Wrapper.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { useContext } from 'react'
import { path, isEmpty } from 'ramda'
import ProductContext from '../../../ProductContext/ProductContext'

import ProductName from './index'

const styles = {
  'vtex-product-name__brand--loader': {
    x: 0,
    width: '100%',
    height: '1.631em',
  },
  'vtex-product-name__sku--loader': {
    x: 0,
    y: '2.569em',
    width: '10.311em',
    height: '1.045em',
  },
}

const ProductNameWrapper = props => {
  const valuesFromContext = useContext(ProductContext)

  const productNameProps = () => {
    if (!valuesFromContext || isEmpty(valuesFromContext)) {
      return props
    }

    const { product, selectedItem } = valuesFromContext
    return {
      ...props,
      tag: props.tag || 'h1',
      name: props.name || path(['productName'], product),
      skuName: props.skuName || path(['name'], selectedItem),
      productReference:
        props.productReference || path(['productReference'], product),
      brandName: props.brandName || path(['brand'], product),
      styles: props.styles || styles,
      className: props.className || 't-heading-4',
    }
  }

  return <ProductName {...productNameProps()} />
}

ProductNameWrapper.schema = {
  title: 'admin/editor.productName.title',
  description: 'admin/editor.productName.description',
  type: 'object',
  properties: {
    showBrandName: {
      type: 'boolean',
      title: 'admin/editor.productName.showBrandName.title',
      default: false,
      isLayout: true,
    },
    showSku: {
      type: 'boolean',
      title: 'admin/editor.productName.showSku.title',
      default: false,
      isLayout: true,
    },
    showProductReference: {
      type: 'boolean',
      title: 'admin/editor.productName.showProductReference.title',
      default: false,
      isLayout: true,
    },
  },
}

export default ProductNameWrapper

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/ProductName/index.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import PropTypes from 'prop-types'
import React from 'react'
import ContentLoader from 'react-content-loader'
import classNames from 'classnames'
import useCssHandles from '../../../CssHandles/useCssHandles'

const CSS_HANDLES = [
  'productNameContainer',
  'productBrand',
  'productSku',
  'productReference',
  'productNameLoader',
  'productNameBrandLoader',
  'productNameSkuLoader',
]

/**
 * Name component. Show name and relevant SKU information of the Product Summary
 */
const ProductName = ({
  productReferenceClass,
  brandNameClass,
  skuNameClass,
  loaderClass,
  className,
  name,
  styles,
  skuName,
  showSku = false,
  brandName,
  showBrandName = false,
  productReference,
  showProductReference = false,
  tag: Wrapper = 'div',
}) => {
  const handles = useCssHandles(CSS_HANDLES)

  const Loader = (loaderProps = {}) => (
    <div
      className={classNames(
        handles.productNameContainer,
        handles.productNameLoader,
        loaderProps.className
      )}
    >
      <ContentLoader
        style={{
          width: '100%',
          height: '100%',
        }}
        width={456}
        height={100}
        preserveAspectRatio="xMinYMin meet"
        {...loaderProps}
      >
        <rect
          height="1.125em"
          width="75%"
          x="15%"
          {...loaderProps[handles.productNameBrandLoader]}
        />
        <rect
          height="1.125em"
          width="50%"
          x="25%"
          y="1.75em"
          {...loaderProps[handles.productNameSkuLoader]}
        />
      </ContentLoader>
    </div>
  )

  if (!name) {
    return <Loader className={loaderClass} {...styles} />
  }

  return (
    <Wrapper
      className={classNames(handles.productNameContainer, 'mv0', className)}
    >
      <span className={classNames(handles.productBrand, brandNameClass)}>
        {name} {showBrandName && brandName && `- ${brandName}`}
      </span>
      {showSku && skuName && (
        <span className={classNames(handles.productBrand, skuNameClass)}>
          {skuName}
        </span>
      )}
      {showProductReference && productReference && (
        <span
          className={classNames(
            handles.productReference,
            productReferenceClass
          )}
        >
          {`REF: ${productReference}`}
        </span>
      )}
    </Wrapper>
  )
}

ProductName.propTypes = {
  /** Name of the product */
  name: PropTypes.string,
  /** Selected SKU name */
  skuName: PropTypes.string,
  /** Show sku */
  showSku: PropTypes.bool,
  /** Product reference */
  productReference: PropTypes.string,
  /** Show product reference */
  showProductReference: PropTypes.bool,
  /** Brand name */
  brandName: PropTypes.string,
  /** Show brand name */
  showBrandName: PropTypes.bool,
  /** Component and content loader styles */
  styles: PropTypes.object,
  /** Classes to be applied to root element */
  className: PropTypes.string,
  /** Classes to be applied to brandName element */
  brandNameClass: PropTypes.string,
  /** Classes to be applied to skuName element */
  skuNameClass: PropTypes.string,
  /** Classes to be applied to productReference element */
  productReferenceClass: PropTypes.string,
  /** Classes to be applied to loader root element */
  loaderClass: PropTypes.string,
  /** HTML tag to be used in the component container */
  tag: PropTypes.oneOf(['div', 'h1', 'h2', 'h3']),
}

export default ProductName

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/SKUSelector/index.tsx from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, {
  useState,
  useEffect,
  useMemo,
  memo,
  useCallback,
  FC,
} from 'react'
import { filter, head, isEmpty, compose, keys, length } from 'ramda'
import { useRuntime } from '../../../../../../vtex.render-runtime'
import useResponsiveValue from '../../../ResponsiveValues/useResponsiveValue'
import ProductDispatchContext from '../../../ProductContext/ProductDispatchContext'
const { useProductDispatch } = ProductDispatchContext

import SKUSelector, { ShowValueForVariation } from './components/SKUSelector'
import {
  parseSku,
  isColor,
  uniqueOptionToSelect,
  findItemWithSelectedVariations,
} from './utils'
import {
  Image,
  ImageMap,
  Variations,
  SelectedVariations,
  SelectorProductItem,
  InitialSelectionType,
  DisplayMode,
} from './types'
import useEffectSkipMount from './components/hooks/useEffectSkipMount'

const keyCount = compose(length, keys)
const filterSelected = filter(Boolean)

const buildEmptySelectedVariation = (variations: Variations) => {
  const variationNames = Object.keys(variations)
  const result = {} as Record<string, null>
  for (const variationName of variationNames) {
    result[variationName] = null
  }
  return result
}

/** receives an item and the variations object, returns the selected variations for that item */
const selectedVariationFromItem = (
  item: SelectorProductItem,
  variations: Variations
) => {
  const variationNames = Object.keys(variations)
  const result = {} as Record<string, string>
  for (const variationName of variationNames) {
    result[variationName] = item.variationValues[variationName]
  }
  return result
}

function useColorImages(items: SelectorProductItem[], imageRegexText: string) {
  const imageRegex = new RegExp(imageRegexText, 'i')

  return items.map(item => {
    if (!item.images) {
      return item
    }

    const hasVariationImage = item.images.some(
      image => image.imageLabel && imageRegex.test(image.imageLabel)
    )
    return {
      ...item,
      images: item.images.filter(image => {
        if (!image.imageLabel) {
          // if it doesn't have a variation image, it wont remove images without a label
          return !hasVariationImage
        }
        return imageRegex.test(image.imageLabel)
      }),
    }
  })
}

const useImagesMap = (
  items: SelectorProductItem[],
  variations: Variations,
  thumbnailImage?: string
) => {
  return useMemo(() => {
    if (thumbnailImage) {
      items = useColorImages(items, thumbnailImage)
    }

    const variationNames = Object.keys(variations)
    const result: ImageMap = {}
    for (const variationName of variationNames) {
      // Today, only "Color" variation should show image, need to find a more resilient way to tell this, waiting for backend
      if (!isColor(variationName)) {
        continue
      }
      const imageMap = {} as Record<string, Image | undefined>
      const variationValues = variations[variationName]
      for (const variationValue of variationValues) {
        const item = items.find(
          sku => sku.variationValues[variationName] === variationValue
        )
        imageMap[variationValue] = item && head(item.images)
      }
      result[variationName] = imageMap
    }
    return result
  }, [items, variations])
}

const useAllSelectedEvent = (
  selectedVariations: SelectedVariations | null,
  variationsCount: number
) => {
  const dispatch = useProductDispatch()
  useEffect(() => {
    if (dispatch && selectedVariations) {
      const selectedNotNull = filterSelected(selectedVariations)
      const selectedCount = keyCount(selectedNotNull)
      const allSelected = selectedCount === variationsCount
      dispatch({
        type: 'SKU_SELECTOR_SET_VARIATIONS_SELECTED',
        args: { allSelected },
      })
    }
  }, [dispatch, selectedVariations, variationsCount])
}

interface Props {
  skuItems: ProductItem[]
  onSKUSelected?: (skuId: string) => void
  seeMoreLabel: string
  maxItems?: number
  variations: Variations
  skuSelected: ProductItem
  hideImpossibleCombinations?: boolean
  showValueForVariation?: ShowValueForVariation
  imageHeight?: number
  imageWidth?: number
  thumbnailImage?: string
  showVariationsLabels?: boolean
  variationsSpacing?: number
  showVariationsErrorMessage?: boolean
  initialSelection?: InitialSelectionType
  displayMode?: any
  sliderDisplayThreshold?: number
  sliderArrowSize?: number
  sliderItemsPerPage?: any
}

const getNewSelectedVariations = (
  query: any,
  skuSelected: ProductItem,
  variations: Variations,
  initialSelection?: InitialSelectionType
) => {
  const hasSkuInQuery = Boolean(query?.skuId)
  const parsedSku = parseSku(skuSelected)
  const emptyVariations = buildEmptySelectedVariation(variations)

  if (hasSkuInQuery || initialSelection === InitialSelectionType.complete) {
    return selectedVariationFromItem(parsedSku, variations)
  } else if (initialSelection === InitialSelectionType.image) {
    const colorVariationName = parsedSku.variations.find(isColor)
    return {
      ...emptyVariations,
      ...(colorVariationName
        ? {
            [colorVariationName]: parsedSku.variationValues[colorVariationName],
          }
        : {}),
    }
  }

  return emptyVariations
}

/**
 * Display a list of SKU items of a product and its specifications.
 */
const SKUSelectorContainer: FC<Props> = ({
  skuItems = [],
  onSKUSelected,
  seeMoreLabel,
  maxItems = 10,
  variations,
  skuSelected,
  imageWidth,
  imageHeight,
  thumbnailImage,
  variationsSpacing,
  showVariationsLabels = true,
  displayMode = DisplayMode.default,
  hideImpossibleCombinations = true,
  showVariationsErrorMessage = true,
  showValueForVariation = ShowValueForVariation.none,
  initialSelection = InitialSelectionType.complete,
  sliderDisplayThreshold = 3,
  sliderArrowSize = 12,
  sliderItemsPerPage = {
    desktop: 3,
    tablet: 2,
    phone: 1,
  },
}) => {
  const variationsCount = keyCount(variations)
  const { query } = useRuntime()
  const responsiveDisplayMode = useResponsiveValue(displayMode)

  const parsedItems = useMemo(() => skuItems.map(parseSku), [skuItems])
  const { setQuery } = useRuntime()
  const redirectToSku = (skuId: string) => {
    setQuery(
      { skuId },
      {
        replace: true,
      }
    )
  }

  const [selectedVariations, setSelectedVariations] = useState<
    SelectedVariations
  >(() =>
    getNewSelectedVariations(query, skuSelected, variations, initialSelection)
  )
  useAllSelectedEvent(selectedVariations, variationsCount)

  useEffectSkipMount(() => {
    setSelectedVariations(
      getNewSelectedVariations(query, skuSelected, variations, initialSelection)
    )
  }, [variations])

  // No need to add skuSelected and onSKUSelected to dependency array since that would result in infinite loops
  useEffect(() => {
    if (skuSelected && onSKUSelected) {
      onSKUSelected(skuSelected.itemId)
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [skuSelected.itemId])

  const imagesMap = useImagesMap(parsedItems, variations, thumbnailImage)

  const onSelectItem = useCallback(
    ({
      name: variationName,
      value: variationValue,
      skuId,
      isMainAndImpossible,
      possibleItems,
    }) => {
      const isRemoving = selectedVariations![variationName] === variationValue
      const newSelectedVariation = !isMainAndImpossible
        ? {
            ...selectedVariations,
            [variationName]: isRemoving ? null : variationValue,
          }
        : {
            ...buildEmptySelectedVariation(variations),
            [variationName]: variationValue,
          }
      // Set here for a better response to user
      setSelectedVariations(newSelectedVariation)
      const uniqueOptions = isRemoving
        ? {}
        : uniqueOptionToSelect(
            possibleItems,
            newSelectedVariation,
            isMainAndImpossible
          )
      const finalSelected = {
        ...newSelectedVariation,
        ...uniqueOptions,
      }
      if (!isEmpty(uniqueOptions)) {
        setSelectedVariations(finalSelected)
      }

      const selectedNotNull = filterSelected(finalSelected)
      const selectedCount = keyCount(selectedNotNull)
      const allSelected = selectedCount === variationsCount
      let skuIdToRedirect = skuId
      if (!skuIdToRedirect || !isEmpty(uniqueOptions)) {
        const newItem = findItemWithSelectedVariations(
          possibleItems,
          finalSelected
        )
        skuIdToRedirect = newItem!.itemId
      }

      if (isRemoving) {
        // If its just removing, no need to do anything.
        return
      }

      if (onSKUSelected) {
        onSKUSelected(skuIdToRedirect)
      } else {
        if (allSelected || isColor(variationName)) {
          redirectToSku(skuIdToRedirect)
        }
      }
    },
    // Adding selectedVariations, variationsCount and onSKUSelected causes an infinite loop
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [selectedVariations, variations, onSKUSelected]
  )

  return (
    <SKUSelector
      maxItems={maxItems}
      imagesMap={imagesMap}
      skuItems={parsedItems}
      variations={variations}
      imageWidth={imageWidth}
      displayMode={responsiveDisplayMode}
      imageHeight={imageHeight}
      seeMoreLabel={seeMoreLabel}
      onSelectItem={onSelectItem}
      variationsSpacing={variationsSpacing}
      selectedVariations={selectedVariations}
      showVariationsLabels={showVariationsLabels}
      showValueForVariation={showValueForVariation}
      hideImpossibleCombinations={hideImpossibleCombinations}
      showVariationsErrorMessage={showVariationsErrorMessage}
      sliderDisplayThreshold={sliderDisplayThreshold}
      sliderArrowSize={sliderArrowSize}
      sliderItemsPerPage={sliderItemsPerPage}
    />
  )
}

export default memo(SKUSelectorContainer)

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/SKUSelector/styles.css from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```css
/**
*   SKU Selector CSS Module
*/
.skuSelectorContainer {
}
.skuSelectorSubcontainer {
}
.skuSelectorName {
}
.skuSelectorNameContainer {
}
.skuSelectorNameSeparator {
}
.skuSelectorSelectorImageValue {
}
.skuSelectorTextContainer {
}

.skuSelectorSelectContainer {}

.skuSelectorItem {
  font-size: 90%;
  height: 36px;
}

.skuSelectorItemImage {
  padding: 0;
  height: 40px;
  width: 40px;
}

.skuSelectorItem p {
  margin: 0;
  padding-top: 10px;
}

.skuSelectorBagde {
  font-size: 0.71429rem;
  background-color: #ff4136;
  border-radius: 50%;
  color: #fff;
  height: 18px;
  line-height: 18px;
  right: -5px;
  text-align: center;
  top: -6px;
  width: 18px;
  position: absolute;
  padding: 3px;
}

.diagonalCross {
  background-image: linear-gradient(
    to top right,
    transparent 44%,
    rgba(0, 0, 0, 0.3) 48%,
    currentColor 48%,
    currentColor 52%,
    transparent 52%
  );
}

.frameAround {
  bottom: -0.25rem;
  top: -0.25rem;
  left: -0.25rem;
  right: -0.25rem;
}

.seeMoreButton {
}

.skuSelectorOptionsList {
}

.skuSelectorItemTextValue {
}

.skuSelectorItemImageValue {
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/SKUSelector/Wrapper.tsx from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useMemo, useEffect } from 'react'
import { pick } from 'ramda'
import useProduct from '../../../ProductContext/useProduct'
import ProductDispatchContext from '../../../ProductContext/ProductDispatchContext'
const { useProductDispatch } = ProductDispatchContext
import useResponsiveValues from '../../../ResponsiveValues/useResponsiveValues'

import SKUSelector from './index'
import { Variations, InitialSelectionType, DisplayMode } from './types'
import { ShowValueForVariation } from './components/SKUSelector'

const getVariationsFromItems = (
  skuItems: ProductItem[],
  visibleVariations?: string[]
) => {
  const variations: Variations = {}
  const variationsSet: Record<string, Set<string>> = {}

  for (const skuItem of skuItems) {
    for (const currentVariation of skuItem.variations) {
      const { name, values } = currentVariation
      if (
        !visibleVariations ||
        visibleVariations.includes(name.toLowerCase().trim())
      ) {
        const value = values[0]
        const currentSet = variationsSet[name] || new Set()
        currentSet.add(value)
        variationsSet[name] = currentSet
      }
    }
  }
  const variationsNames = Object.keys(variationsSet)
  // Transform set back to array
  for (const variationName of variationsNames) {
    const set = variationsSet[variationName]
    variations[variationName] = Array.from(set)
  }
  return variations
}

const getVariationsFromSpecifications = (
  skuSpecifications: SkuSpecification[],
  visibleVariations?: string[]
) => {
  const variations: Variations = {}
  for (const specification of skuSpecifications) {
    if (
      !visibleVariations ||
      visibleVariations.includes(specification.field.name.toLowerCase().trim())
    ) {
      variations[specification.field.name] = specification.values.map(
        value => value.name
      )
    }
  }
  return variations
}

const useVariations = (
  skuItems: ProductItem[],
  skuSpecifications: SkuSpecification[],
  shouldNotShow: boolean,
  visibleVariations?: string[]
) => {
  const isSkuSpecificationsEmpty = skuSpecifications.length === 0
  /* if the skuSpecifications array has values, then it should be used to find
   * the variations, which will come ordered the same way they are in the catalog */
  const variationsSource = isSkuSpecificationsEmpty
    ? skuItems
    : skuSpecifications
  const result = useMemo(() => {
    if (
      shouldNotShow ||
      (visibleVariations && visibleVariations.length === 0)
    ) {
      return {}
    }
    let formattedVisibleVariations = visibleVariations
    if (visibleVariations) {
      formattedVisibleVariations = visibleVariations.map(variation =>
        variation.toLowerCase().trim()
      )
    }

    return isSkuSpecificationsEmpty
      ? getVariationsFromItems(
          variationsSource as ProductItem[],
          formattedVisibleVariations
        )
      : getVariationsFromSpecifications(
          variationsSource as SkuSpecification[],
          formattedVisibleVariations
        )
  }, [
    variationsSource,
    shouldNotShow,
    visibleVariations,
    isSkuSpecificationsEmpty,
  ])
  return result
}

interface Props {
  skuItems: ProductItem[]
  skuSelected: ProductItem
  onSKUSelected?: (skuId: string) => void
  maxItems?: number
  visibility?: string
  seeMoreLabel: string
  hideImpossibleCombinations?: boolean
  showValueNameForImageVariation?: boolean
  showValueForVariation?: ShowValueForVariation
  imageHeight?: any
  imageWidth?: any
  thumbnailImage?: string
  visibleVariations?: string[]
  showVariationsLabels?: boolean
  variationsSpacing?: number
  showVariationsErrorMessage?: boolean
  initialSelection?: InitialSelectionType
  displayMode?: any
  sliderDisplayThreshold?: number
  sliderArrowSize?: number
  sliderItemsPerPage?: any
}

const SKUSelectorWrapper: StorefrontFC<Props> = props => {
  const valuesFromContext = useProduct() as any
  const dispatch = useProductDispatch()
  const { imageHeight, imageWidth } = useResponsiveValues(
    pick(['imageHeight', 'imageWidth'], props)
  )
  const skuItems =
    props.skuItems != null
      ? props.skuItems
      : valuesFromContext?.product?.items ?? []

  const skuSelected =
    props.skuSelected != null
      ? props.skuSelected
      : valuesFromContext.selectedItem

  const visibility = props.visibility != null ? props.visibility : 'always'

  const shouldNotShow =
    skuItems.length === 0 ||
    !skuSelected?.variations ||
    skuSelected.variations.length === 0 ||
    (visibility === 'more-than-one' && skuItems.length === 1)

  const skuSpecifications = valuesFromContext?.product?.skuSpecifications ?? []
  const variations = useVariations(
    skuItems,
    skuSpecifications,
    shouldNotShow,
    props.visibleVariations
  )

  useEffect(() => {
    if (dispatch) {
      dispatch({
        type: 'SKU_SELECTOR_SET_IS_VISIBLE',
        args: { isVisible: !shouldNotShow },
      })
    }
  }, [shouldNotShow, dispatch])

  if (shouldNotShow || !skuSelected) {
    return null
  }

  let showValueForVariation = ShowValueForVariation.none
  if (props.showValueForVariation) {
    showValueForVariation = props.showValueForVariation
  } else if (props.showValueNameForImageVariation) {
    showValueForVariation = ShowValueForVariation.image
  }

  return (
    <SKUSelector
      skuItems={skuItems}
      variations={variations}
      imageWidth={imageWidth}
      skuSelected={skuSelected}
      maxItems={props.maxItems}
      imageHeight={imageHeight}
      displayMode={props.displayMode}
      seeMoreLabel={props.seeMoreLabel}
      onSKUSelected={props.onSKUSelected}
      thumbnailImage={props.thumbnailImage}
      initialSelection={props.initialSelection}
      variationsSpacing={props.variationsSpacing}
      showValueForVariation={showValueForVariation}
      showVariationsLabels={props.showVariationsLabels}
      hideImpossibleCombinations={props.hideImpossibleCombinations}
      showVariationsErrorMessage={props.showVariationsErrorMessage}
      sliderItemsPerPage={props.sliderItemsPerPage}
      sliderArrowSize={props.sliderArrowSize}
      sliderDisplayThreshold={props.sliderDisplayThreshold}
    />
  )
}

SKUSelectorWrapper.schema = {
  title: 'admin/editor.skuSelector.title',
  description: 'admin/editor.skuSelector.description',
}

export default SKUSelectorWrapper

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/AutocompleteResults/styles.css from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```css
.resultsList {
  max-height: 60vh;
}

.resultsList a,
.resultsList div {
  text-decoration: none;
  color: #727273;
}

.resultsList a:hover {
  background-color: #f2f4f5;
}

.resultsItemImage {
  width: 50px;
}

@media only screen and (max-width: 49rem) {
  .resultsList {
    margin: 0px;
    max-height: calc(100vh - 6.2rem);
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/AutocompleteResults/index.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
/* eslint-disable jsx-a11y/anchor-is-valid */
import React, { Fragment, useMemo } from 'react'
import classnames from 'classnames'
import PropTypes from 'prop-types'
import { FormattedMessage } from 'react-intl'
import { graphql } from 'react-apollo'
import Spinner from '../../../Styleguide/Spinner'
import { Link, useRuntime } from '../../../../../../vtex.render-runtime'
import useCssHandles from '../../../CssHandles/useCssHandles'

// This import should NOT be removed
// import styles from './styles.css'
import { loader } from 'graphql.macro'

const autocomplete = loader('./queries/autocomplete.gql')

const MIN_RESULTS_WIDTH = 320
const CSS_HANDLES = [
  'resultsItem',
  'resultsList',
  'searchTerm',
  'resultsItemImage',
  'spinnerContainer',
  'spinnerInnerContainer',
  'resultsItemName',
]

const getImageUrl = image => {
  const imageUrl = (image.match(/https?:(.*?)"/g) || [''])[0]
  return imageUrl.replace(/https?:/, '').replace(/-25-25/g, '-50-50')
}

const getLinkProps = element => {
  let page = 'store.product'
  let params = { slug: element.slug, id: element.productId }
  let query = ''
  const terms = element.slug.split('/')

  if (element.criteria) {
    // This param is only useful to track terms searched
    // See: https://support.google.com/analytics/answer/1012264
    const paramForSearchTracking = '&_c=' + terms[0]

    page = 'store.search'
    params = { term: terms[0] }
    query = `map=c,ft&rest=${terms.slice(1).join(',')}` + paramForSearchTracking
  }

  return { page, params, query }
}

/** List of search results to be displayed*/
const AutocompleteResults = ({
  parentContainer,
  isOpen,
  data = {}, // when inputValue is '', query is skipped and value is undefined
  inputValue,
  closeMenu,
  onClearInput,
  getItemProps,
  getMenuProps,
  highlightedIndex,
  attemptPageTypeSearch,
  customSearchPageUrl,
}) => {
  const items = data.autocomplete ? data.autocomplete.itemsReturned : []
  const {
    hints: { mobile },
  } = useRuntime()
  const handles = useCssHandles(CSS_HANDLES)

  const listStyle = useMemo(
    () => ({
      width: Math.max(
        MIN_RESULTS_WIDTH,
        (parentContainer.current && parentContainer.current.offsetWidth) || 0
      ),
    }),
    /* with the isOpen here this will be called
    only when you open or close the ResultList */
    [parentContainer]
  )

  const listClassNames = classnames(
    handles.resultsList,
    'z-max w-100 bl-ns bb br-ns bw1 b--muted-4 bg-base c-on-base t-body left-0 list pv4 ph0 mv0 list overflow-y-auto',
    mobile ? 'fixed' : 'absolute',
    { dn: !isOpen || !inputValue }
  )

  const handleItemClick = () => {
    onClearInput()
    closeMenu()
  }

  const getListItemClassNames = ({
    itemIndex = -1,
    highlightedIndex = -2,
    hasThumb = false,
  } = {}) => {
    const highlightClass = highlightedIndex === itemIndex ? 'bg-muted-5' : ''
    return `pointer pa4 outline-0 ${handles.resultsItem} ${highlightClass} ${
      hasThumb ? 'flex justify-start' : 'db w-100'
    }`
  }

  const WrappedSpinner = () => (
    <div className={`w-100 flex justify-center ${handles.spinnerContainer}`}>
      <div className={`${handles.spinnerInnerContainer} w3 ma0`}>
        <Spinner />
      </div>
    </div>
  )

  const fullTextSearchLabel = (
    <FormattedMessage
      id="store/search.searchFor"
      values={{
        term: <span className={handles.searchTerm}>{`"${inputValue}"`}</span>,
      }}
    />
  )

  const renderSearchByClick = inputValue => {
    return customSearchPageUrl ? (
      <Link
        className={getListItemClassNames({
          itemIndex: 0,
          highlightedIndex,
        })}
        to={customSearchPageUrl.replace(/\$\{term\}/g, inputValue)}
      >
        {fullTextSearchLabel}
      </Link>
    ) : (
      <Link
        page="store.search"
        params={{ term: inputValue }}
        query="map=ft"
        className={getListItemClassNames({
          itemIndex: 0,
          highlightedIndex,
        })}
      >
        {fullTextSearchLabel}
      </Link>
    )
  }

  return (
    <div style={listStyle}>
      <ul className={listClassNames} {...getMenuProps()}>
        {isOpen ? (
          data.loading ? (
            <div className={getListItemClassNames({})}>
              <WrappedSpinner />
            </div>
          ) : (
            <Fragment>
              <li
                {...getItemProps({
                  key: 'ft' + inputValue,
                  item: { term: inputValue },
                  index: 0,
                  onClick: handleItemClick,
                })}
              >
                {attemptPageTypeSearch ? (
                  <a
                    href="#"
                    onClick={event => event.preventDefault()}
                    className={getListItemClassNames({
                      itemIndex: 0,
                      highlightedIndex,
                    })}
                  >
                    {fullTextSearchLabel}
                  </a>
                ) : (
                  renderSearchByClick(inputValue)
                )}
              </li>

              {items.map((item, index) => {
                return (
                  <li
                    {...getItemProps({
                      key: item.name + index,
                      index: index + 1,
                      item,
                      onClick: handleItemClick,
                    })}
                  >
                    <Link
                      {...getLinkProps(item)}
                      className={getListItemClassNames({
                        itemIndex: index + 1,
                        highlightedIndex,
                        hasThumb: !!item.thumb,
                      })}
                    >
                      {item.thumb && (
                        <img
                          width={50}
                          height={50}
                          alt={item.name}
                          className={`${handles.resultsItemImage} mr4`}
                          src={getImageUrl(item.thumb)}
                        />
                      )}
                      <div
                        className={`${handles.resultsItemName} flex justify-start items-center`}
                      >
                        {item.name}
                      </div>
                    </Link>
                  </li>
                )
              })}
            </Fragment>
          )
        ) : null}
      </ul>
    </div>
  )
}

const itemProps = PropTypes.shape({
  /** Image of the product*/
  thumb: PropTypes.string,
  /** Name of the product*/
  name: PropTypes.string,
  /** Link to the product*/
  href: PropTypes.string,
  /** Slug of the product*/
  slug: PropTypes.string,
  /** Criteria of the product*/
  criteria: PropTypes.string,
})

AutocompleteResults.propTypes = {
  /** Graphql data response. */
  data: PropTypes.shape({
    autocomplete: PropTypes.shape({
      itemsReturned: PropTypes.arrayOf(itemProps),
    }),
    loading: PropTypes.bool.isRequired,
  }),
  /** Downshift specific prop*/
  highlightedIndex: PropTypes.number,
  /** Search query*/
  inputValue: PropTypes.string.isRequired,
  /** Closes the options box. */
  closeMenu: PropTypes.func,
  /** Clears the input */
  onClearInput: PropTypes.func,
  /** Downshift function */
  getItemProps: PropTypes.func,
  /** A template for a custom url. It can have a substring ${term} used as placeholder to interpolate the searched term. (e.g. `/search?query=${term}`) */
  customSearchPageUrl: PropTypes.string,
  isOpen: PropTypes.bool,
  getMenuProps: PropTypes.func,
  attemptPageTypeSearch: PropTypes.bool,
}

const AutocompleteResultsWithData = graphql(autocomplete, {
  skip: ({ inputValue }) => !inputValue,
  options: props => ({
    variables: {
      inputValue: props.inputValue,
    },
  }),
})(AutocompleteResults)

export default AutocompleteResultsWithData

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/Newsletter/index.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { Component, Fragment } from 'react'
import { graphql } from 'react-apollo'
import { compose } from 'ramda'
import PropTypes from 'prop-types'
import { injectIntl } from 'react-intl'
import Input from '../../../Styleguide/Input'
import Button from '../../../Styleguide/Button'
import withCssHandles from '../../../CssHandles/withCssHandles'
import formatIOMessage from '../../../NativeTypes/formatIOMessage'
import { loader } from 'graphql.macro'

const SUBSCRIBE_NEWSLETTER = loader('./mutations/subscribeNewsletter.graphql')

const EMAIL_REGEX = /^[A-z0-9+_-]+(?:\.[A-z0-9+_-]+)*@(?:[A-z0-9](?:[A-z0-9-]*[A-z0-9])?\.)+[A-z0-9](?:[A-z0-9-]*[A-z0-9])?$/
const CSS_HANDLES = [
  'newsletter',
  'confirmation',
  'container',
  'confirmationTitle',
  'confirmationText',
  'form',
  'inputGroup',
  'buttonContainer',
  'label',
  'error',
]

class Newsletter extends Component {
  state = {
    email: '',
    loading: false,
    error: null,
    success: null,
    invalidEmail: false,
  }

  inputRef = React.createRef()

  componentDidMount() {
    this.mounted = true
  }

  componentWillUnmount() {
    this.mounted = false
  }

  safeSetState(...params) {
    if (this.mounted) {
      this.setState(...params)
    }
  }

  handleChangeEmail = e => {
    this.setState({ email: e.target.value })
  }

  validateEmail = () => {
    return EMAIL_REGEX.test(this.state.email)
  }

  handleSubmit = e => {
    e.preventDefault()
    if (!this.validateEmail()) {
      this.setState({ invalidEmail: true })
      if (this.inputRef && this.inputRef.current) {
        this.inputRef.current.focus()
      }
      return
    }

    this.setState({
      invalidEmail: false,
      loading: true,
      error: null,
      success: null,
    })

    this.props
      .subscribeNewsletter({ variables: { email: this.state.email } })
      .then(() => {
        this.safeSetState({ success: true, loading: false })
      })
      .catch(e => {
        this.safeSetState({ error: true, loading: false })
      })
  }

  render() {
    const { hideLabel, intl, submit, label, placeholder, cssHandles } = this.props
    const submitText = formatIOMessage({ id: submit, intl })
    const labelText = formatIOMessage({ id: label, intl })
    const placeholderText = formatIOMessage({ id: placeholder, intl })
    const confirmationTitle = formatIOMessage({
      id: 'store/newsletter.confirmationTitle',
      intl,
    })
    const confirmationText = formatIOMessage({
      id: 'store/newsletter.confirmationText',
      intl,
    })
    const invalidEmailText = formatIOMessage({
      id: 'store/newsletter.invalidEmail',
      intl,
    })
    const errorMsg = formatIOMessage({
      id: 'store/newsletter.error',
      intl,
    })

    return (
      <div
        className={`${cssHandles.newsletter} ${
          this.state.success ? cssHandles.confirmation : ''
        } w-100`}
      >
        <div className={`${cssHandles.container} mw9 mr-auto ml-auto pv9`}>
          {this.state.success ? (
            <Fragment>
              <div className={`${cssHandles.confirmationTitle} t-heading-3 pb4 tc`}>
                {confirmationTitle}
              </div>
              <div className={`${cssHandles.confirmationText} t-body tc`}>
                {confirmationText}
              </div>
            </Fragment>
          ) : (
            <form className={`${cssHandles.form} mw6 center tc ph5 ph0-ns`}>
              <label
                className={`${cssHandles.label} t-heading-3 tc ${
                  hideLabel ? 'dn' : ''
                }`}
                htmlFor="newsletter-input"
              >
                {labelText}
              </label>
              <div className={`${cssHandles.inputGroup} flex-ns pt5`}>
                <Input
                  ref={this.inputRef}
                  id="newsletter-input"
                  errorMessage={
                    this.state.invalidEmail ? invalidEmailText : null
                  }
                  placeholder={placeholderText}
                  name="newsletter"
                  value={this.state.email}
                  onChange={this.handleChangeEmail}
                />
                <div
                  className={`${
                    cssHandles.buttonContainer
                  } pl4-ns flex-none pt3 pt0-ns`}
                >
                  <Button
                    variation="primary"
                    type="submit"
                    onClick={this.handleSubmit}
                    isLoading={this.state.loading}
                  >
                    {submitText}
                  </Button>
                </div>
              </div>
              {this.state.error && (
                <div className={`${cssHandles.error} c-danger t-body pt5`}>
                  {errorMsg}
                </div>
              )}
            </form>
          )}
        </div>
      </div>
    )
  }
}

Newsletter.defaultProps = {
  hideLabel: false,
  showTerms: false,
}

Newsletter.propTypes = {
  hideLabel: PropTypes.bool.isRequired,
  showTerms: PropTypes.bool.isRequired,
  label: PropTypes.string,
  placeholder: PropTypes.string,
  submit: PropTypes.string,
  subscribeNewsletter: PropTypes.func.isRequired,
}

Newsletter.getSchema = () => {
  return {
    title: 'admin/editor.newsletter.title',
    description: 'admin/editor.newsletter.description',
    type: 'object',
    properties: {
      hideLabel: {
        type: 'boolean',
        title: 'admin/editor.newsletter.hideLabel',
        default: false,
        isLayout: true,
      },
    },
  }
}

export default compose(
  graphql(SUBSCRIBE_NEWSLETTER, { name: 'subscribeNewsletter' }),
  withCssHandles(CSS_HANDLES),
  injectIntl
)(Newsletter)
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/ProductHighlights/styles.css from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```css
/**
*   ProductHighlights CSS Modules
*/

.highlightContent {}
.itemHighlight {}
.highlightTitle {}
.highlightValue {}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/ProductHighlights/Wrapper.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { useContext } from 'react'
import ProductContext from '../../../ProductContext/ProductContext'
import { isEmpty, propOr } from 'ramda'

import ProductHighlights from './index'

const ProductHighlightsWrapper = (props) => {
  const { conditional } = props

  const valuesFromContext = useContext(ProductContext)

  const getHighlights = () => {
    const { product } = valuesFromContext

    const choose = propOr('', 'highlight', conditional)

    if (choose === 'admin/editor.product-details.highlights.chooseDefault') {
      const typeHighlight = propOr('', 'typeHighlight', conditional)
      const highlightName = typeHighlight.trim()
      const names = highlightName.split(',')
      const specificationGroups = propOr([], 'specificationGroups', product)

      return names.reduce((acc, item) => {
        const highlightSpecificationGroup = specificationGroups.filter(
          x => x.name.toLowerCase() === item.trim().toLowerCase()
        )[0]
        const highlight = propOr(
          [],
          'specifications',
          highlightSpecificationGroup
        )
        return acc.concat(highlight)
      }, [])
    }

    if (choose === 'admin/editor.product-details.highlights.chooseDefaultSpecification') {
      const typeSpecifications = propOr('', 'typeSpecifications', conditional)
      const specificationNames = typeSpecifications.trim().split(',')
      const allSpecifications = propOr([], 'properties', product)

      return specificationNames.reduce((acc, item) => {
        const highlight = allSpecifications.filter(
          x => x.name.toLowerCase() === item.trim().toLowerCase()
        )
        return acc.concat(highlight)
      }, [])
    }

    if (choose === 'admin/editor.product-details.highlights.allSpecifications') {
      return propOr([], 'properties', product)
    }
  }

  const productHighlightsProps = () => {
    if (!valuesFromContext || isEmpty(valuesFromContext)) {
      return props
    }

    return {
      ...props,
      highlights: props.highlights || getHighlights(),
    }
  }

  return (
    <ProductHighlights { ...productHighlightsProps() } />
  )
}

ProductHighlightsWrapper.schema = {
  // @TODO review title and description
  title: 'admin/editor.product-details.title',
  description: 'admin/editor.product-details.description',
  type: 'object',
  definitions: {
    highlightGroupDefault: {
      title: 'highlightGroupDefault',
      type: 'object',
      properties: {
        highlight: {
          title: 'admin/editor.product-details.highlights.default',
          type: 'string',
          enum: [
            'admin/editor.product-details.highlights.allSpecifications',
            'admin/editor.product-details.highlights.chooseDefault',
            'admin/editor.product-details.highlights.chooseDefaultSpecification',
          ],
          default: 'admin/editor.product-details.highlights.allSpecifications',
        },
      },
      required: ['highlight'],
      dependencies: {
        highlight: {
          oneOf: [
            {
              properties: {
                highlight: {
                  enum: [
                    'admin/editor.product-details.highlights.allSpecifications',
                  ],
                },
              },
            },
            {
              properties: {
                highlight: {
                  enum: ['admin/editor.product-details.highlights.chooseDefault'],
                },
                typeHighlight: {
                  type: 'string',
                  title: 'admin/editor.product-details.highlights.title',
                },
              },
              required: [''],
            },
            {
              properties: {
                highlight: {
                  enum: [
                    'admin/editor.product-details.highlights.chooseDefaultSpecification',
                  ],
                },
                typeSpecifications: {
                  type: 'string',
                  title:
                    'admin/editor.product-details.highlights.typeSpecifications.title',
                },
              },
              required: [''],
            },
          ],
        },
      },
    },
  },
  properties: {
    showHighlight: {
      type: 'boolean',
      title: 'admin/editor.product-details.showHighlight.title',
      default: false,
      isLayout: false,
    },
    conditional: {
      title: 'Conditional',
      $ref: '#/definitions/highlightGroupDefault',
    },
  },
}

export default ProductHighlightsWrapper
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/ProductHighlights/index.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { Component, Fragment } from 'react'
import PropTypes from 'prop-types'
import { injectIntl } from 'react-intl'
import HtmlParser from 'react-html-parser'

import styles from './styles.css'

/**
 * Product highlights Component.
 * Render the highlights specifications of a product.
 */
const ProductHighlights = ({ ...props }) => {
  const { highlights } = props
  return (
    <div className={`${styles.highlightContent} pt3 pb5`}>
      {highlights.map((item, i) => (
        <div
          className={`${styles.itemHighlight} pv2`}
          data-name={item.name}
          data-value={item.values[0]}
          key={i}
        >
          <span
            className={`${styles.highlightTitle} t-body c-on-base fw7 pr3 `}
          >
            {HtmlParser(item.name)}
            {': '}
          </span>
          <span
            className={`${styles.highlightValue} t-body c-muted-1 lh-copy `}
          >
            {HtmlParser(item.values[0])}
          </span>
        </div>
      ))}
    </div>
  )
}

ProductHighlights.defaultProps = {
  highlights: [],
}

ProductHighlights.propTypes = {
  /** Specifications that will be displayed on the table */
  highlights: PropTypes.arrayOf(
    PropTypes.shape({
      /** Highlight name */
      name: PropTypes.string.isRequired,
      /** Highlight value */
      values: PropTypes.arrayOf(PropTypes.string).isRequired,
    })
  ),
}

export default injectIntl(ProductHighlights)

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/UserAddress/AddressInfo.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { Fragment } from 'react'
import { ExtensionPoint, useChildBlock } from '../../../../../../vtex.render-runtime'
import { pathOr } from 'ramda'
import { injectIntl, FormattedMessage } from 'react-intl'
import IconLocationMarker from '../../../StoreIcons/IconLocationMarker'

const AddressInfo = ({ inverted, inline, orderForm, intl }) => {
  const { shippingData } = orderForm
  if (!shippingData || !shippingData.address) return

  const { street, number, complement, addressType } = shippingData.address

  const displayStreet = number ? `${street}, ${number}` : street

  const displayAddress =
    complement && complement !== ''
      ? `${displayStreet} - ${complement}`
      : `${displayStreet}`

  const isPickup = addressType === 'pickup'
  const friendlyName = pathOr(
    '',
    ['pickupPointCheckedIn', 'friendlyName'],
    orderForm
  )

  const hasModal = !!useChildBlock({ id: 'modal' })

  return (
    <div className={`flex ${inline ? 'items-end' : 'items-center flex-auto'}`}>
      <div className="flex flex-auto">
        <div
          className={`mr3 flex items-center ${
            inverted ? 'c-on-base--inverted' : 'c-muted-2'
          }`}
        >
          <IconLocationMarker size={27} viewBox={'0 0 21 27'} />
        </div>
        <div className="flex flex-auto flex-column">
          <div
            className={`t-small ${
              inverted ? 'c-on-base--inverted' : 'c-muted-2'
            }`}
          >
            {isPickup ? (
              <FormattedMessage
                id="store/user-address.pickup"
                values={{ name: friendlyName }}
              />
            ) : (
              <FormattedMessage id="store/user-address.order" />
            )}
          </div>
          <div className="truncate">{displayAddress}</div>
        </div>
      </div>
      {hasModal && (
        <Fragment>
          <div
            className={`bl bw1 mh4 ${inline ? 'nb2' : ''} ${
              inverted ? 'b--on-base--inverted' : 'b--muted-5'
            }`}
            style={{
              height: '1.5rem',
            }}
          />
          <div className="flex items-center">
            <ExtensionPoint
              id="modal"
              centered
              buttonLabel={intl.formatMessage({
                id: 'store/user-address.change',
              })}
              buttonClass={
                inverted ? 'c-on-base--inverted' : 'c-action-primary'
              }
              showTopBar={false}
            />
          </div>
        </Fragment>
      )}
    </div>
  )
}

export default injectIntl(AddressInfo)

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/UserAddress/index.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import PropTypes from 'prop-types'
import React from 'react'
import { graphql } from 'react-apollo'

import Container from '../Container'
import AddressInfo from './AddressInfo'
import { loader } from 'graphql.macro'

const addressQuery = loader('../../../StoreResources/queries/address.gql')

const UserAddress = ({ variation, addressQuery }) => {
  const { orderForm } = addressQuery
  const { shippingData } = orderForm || {}

  if (!orderForm || !shippingData || !shippingData.address) {
    return null
  }

  const isInline = variation === 'inline'
  const isInverted = !isInline

  return isInline ? (
    <div
      className="ph5"
      style={{
        maxWidth: '30rem',
      }}
    >
      {
        <AddressInfo
          inverted={isInverted}
          inline={isInline}
          orderForm={orderForm}
        />
      }
    </div>
  ) : (
    <div className="bg-base--inverted c-on-base--inverted flex ph5 pointer pv3">
      <Container className="flex justify-center w-100 left-0">
        <div className="w-100 mw9 flex">
          <AddressInfo
            inverted={isInverted}
            inline={isInline}
            orderForm={orderForm}
          />
        </div>
      </Container>
    </div>
  )
}

UserAddress.propTypes = {
  variation: PropTypes.oneOf(['inline', 'bar']).isRequired,
  addressQuery: PropTypes.object.isRequired,
}

const withAddressQuery = graphql(addressQuery, {
  name: 'addressQuery',
  options: () => ({ ssr: false }),
})

export default withAddressQuery(UserAddress)

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/CategoriesHighlights/constants.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
export const ITEMS_PER_ROW = 2
export const SQUARED = 'squared'
export const RECTANGULAR = 'rectangular'

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/CategoriesHighlights/categoriesHighlights.css from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```css
.squaredCategoriesHighlights:only-child,
.rectangularCategoriesHighlights:only-child {
  display: none;
}

:global(.vtex-carousel) + .squared,
:global(.vtex-carousel) + .rectangular {
  top: -5.625rem;
}

.squaredCard,
.rectangularCard {
  background: rgba(61, 61, 61, 0.8);
  height: 18.75rem;
}

.squaredCard {
  width: 18.75rem;
}

.rectangularCard {
  width: 37.5rem;
}

.squaredCardImage,
.rectangularCardImage {
  object-fit: cover;
}

.squaredCardImage {
  width: 18.75rem;
}

.rectangularCardImage {
  width: 37.5rem;
}

@media only screen and (min-width: 20em) and (max-width: 50em) {
  :global(.vtex-carousel) + .squaredCategoriesHighlights {
    top: -3.125rem;
  }

  :global(.vtex-carousel) + .rectangularCategoriesHighlights {
    top: 0;
  }

  .squaredCard,
  .squaredCardImage {
    height: 9.375rem;
    width: 9.375rem;
  }

  .rectangularCard,
  .rectangularCardImage {
    height: 12.5rem;
    width: 100%;
  }
}

@media only screen and (min-width: 50em) and (max-width: 64em) {
  :global(.vtex-carousel) + .squaredCategoriesHighlights,
  :global(.vtex-carousel) + .rectangularCategoriesHighlights {
    top: -4.375rem;
  }

  .squaredCard,
  .rectangularCard {
    margin: 0;
    height: 12.5rem;
  }

  .squaredCard,
  .squaredCardImage {
    width: 12.5rem;
  }

  .rectangularCard,
  .rectangularCardImage {
    width: 25rem;
  }

  .squaredCardImage,
  .rectangularCardImage {
    height: 12.5rem;
  }
}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/CategoriesHighlights/index.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import categoriesHighlights from './categoriesHighlights.css'

import PropTypes from 'prop-types'
import { range, values } from 'ramda'
import React, { Component } from 'react'

import CategoryCard from './components/CategoryCard'
import { ITEMS_PER_ROW, RECTANGULAR, SQUARED } from './constants.js'

/**
 * CategoriesHighlights is a component responsible to display the
 * Categories highlighted in a department.
 */
class CategoriesHighlights extends Component {
  static propTypes = {
    /** Categories highlighted in the department */
    categoriesHighlighted: PropTypes.object,
    /** Flag which indicates if the categories highlighted should be displayed or not */
    showCategoriesHighlighted: PropTypes.bool,
    /** Number of categories highlighted to be displayed (it should be 2 or 4) */
    quantityOfItems: PropTypes.number.isRequired,
    /** Shape of the card box which wraps each category (it should be 'squared' or 'rectangular')  */
    cardShape: PropTypes.oneOf([SQUARED, RECTANGULAR]).isRequired,
  }

  static defaultProps = {
    categoriesHighlighted: {},
    showCategoriesHighlighted: false,
    quantityOfItems: ITEMS_PER_ROW,
    cardShape: SQUARED,
  }

  static uiSchema = {
    categoriesHighlighted: {
      items: {
        image: {
          'ui:widget': 'image-uploader',
        },
      },
    },
  }

  static getSchema = ({ quantityOfItems }) => {
    let categoriesHighlightedProps = {}

    range(0, quantityOfItems || ITEMS_PER_ROW).forEach(index => {
      categoriesHighlightedProps[`category${index}`] = {
        type: 'object',
        title: 'admin/editor.categoriesHighlighted.category',
        properties: {
          name: {
            type: 'string',
            default: '',
            title: 'admin/editor.categoriesHighlighted.item.categoryName',
          },
          image: {
            type: 'string',
            title: 'admin/editor.categoriesHighlighted.item.categoryImage',
            default: '',
            widget: {
              'ui:widget': 'image-uploader',
            },
          },
        },
      }
    })

    return {
      title: 'admin/editor.categoriesHighlighted.title',
      description: 'admin/editor.categoriesHighlighted.description',
      type: 'object',
      properties: {
        showCategoriesHighlighted: {
          type: 'boolean',
          title: 'admin/editor.categoriesHighlighted.showCategoriesHighlighted',
          default: false,
          isLayout: true,
        },
        quantityOfItems: {
          type: 'number',
          title: 'admin/editor.categoriesHighlighted.quantityOfItems',
          enum: [2, 4],
          default: 2,
          widget: {
            'ui:widget': 'radio',
            'ui:options': {
              inline: true,
            },
          },
          isLayout: true,
        },
        cardShape: {
          type: 'string',
          title: 'admin/editor.categoriesHighlighted.cardShape',
          enum: [SQUARED, RECTANGULAR],
          enumNames: [
            'admin/editor.categoriesHighlighted.cardShape.squared',
            'admin/editor.categoriesHighlighted.cardShape.rectangular',
          ],
          default: SQUARED,
          widget: {
            'ui:widget': 'radio',
            'ui:options': {
              inline: true,
            },
          },
          isLayout: true,
        },
        categoriesHighlighted: {
          type: 'object',
          title: 'admin/editor.categoriesHighlighted.categoriesHighlighted',
          properties: categoriesHighlightedProps,
          isLayout: false,
        },
      },
    }
  }

  render() {
    const {
      categoriesHighlighted,
      showCategoriesHighlighted,
      quantityOfItems,
      cardShape,
    } = this.props

    if (!showCategoriesHighlighted) return null

    let categories = values(categoriesHighlighted).map(category => category)
    range(categories.length, quantityOfItems).forEach(() => {
      categories.push({
        name: '',
        image: '',
      })
    })

    return (
      <div
        className={`${
          categoriesHighlights[`${cardShape}CategoriesHighlights`]
        } relative`}
      >
        <div className="flex flex-row flex-wrap items-center justify-center">
          {range(0, quantityOfItems / ITEMS_PER_ROW).map(indexRow => (
            <div
              key={`row${indexRow}`}
              className="flex flex-row flex-wrap items-center justify-center"
            >
              {range(0, ITEMS_PER_ROW).map(indexCol => (
                <CategoryCard
                  key={2 * indexRow + indexCol}
                  shape={cardShape}
                  {...categories[2 * indexRow + indexCol]}
                />
              ))}
            </div>
          ))}
        </div>
      </div>
    )
  }
}

export default CategoriesHighlights

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/Share/styles.css from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```css
.shareContainer {}
.shareLoader {}
.shareLabel {}
.shareButtons {}
.shareSocialButton {}
.shareSocialIcon {}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/Share/Wrapper.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { useContext } from 'react'
import ProductContext from '../../../ProductContext/ProductContext'
import { path, isEmpty } from 'ramda'
import { injectIntl } from 'react-intl'
import { useRuntime } from '../../../../../../vtex.render-runtime'

import Share from './index'

const ShareWrapper = props => {
  const { intl } = props

  const valuesFromContext = useContext(ProductContext)
  const { account } = useRuntime()

  const shareProps = () => {
    if (!valuesFromContext || isEmpty(valuesFromContext)) {
      return props
    }

    const { selectedItem, product } = valuesFromContext

    const title = intl.formatMessage(
      { id: 'store/share.title' },
      {
        product: path(['productName'], product),
        sku: path(['name'], selectedItem),
        store: account,
      }
    )

    return {
      ...props,
      shareLabelClass: props.shareLabelClass || 'c-muted-2 t-small mb3',
      className: props.className || 'db',
      imageUrl: props.imageUrl || path(['items', 0, 'images', 0, 'imageUrl'], product),
      loading: props.loading != null ? props.loading : !path(['name'], selectedItem),
      title: props.title || title,
    }
  }

  return <Share {...shareProps()} />
}

ShareWrapper.schema = Share.schema

export default injectIntl(ShareWrapper)

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/StoreComponents/components/Share/index.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import PropTypes from 'prop-types'
import classNames from 'classnames'
import { indexBy, prop } from 'ramda'
import React, { Component } from 'react'
import ContentLoader from 'react-content-loader'
import { FormattedMessage } from 'react-intl'

import SocialButton from './components/SocialButton'
import { SOCIAL_ENUM } from './constants/social'
import styles from './styles.css'

class Share extends Component {
  static propTypes = {
    /** Social Networks configuration */
    social: PropTypes.object,
    /** Share buttons options */
    options: PropTypes.shape({
      /** Share buttons size in pixels */
      size: PropTypes.number,
    }),
    /** Share URL title */
    title: PropTypes.string,
    /** Indcates if the component should render the Content Loader */
    loading: PropTypes.bool,
    /** Component and content loader styles */
    styles: PropTypes.object,
    /** Classes to be applied to root element  */
    className: PropTypes.string,
    /** Classes to be applied to Share label */
    shareLabelClass: PropTypes.string,
    /** Classes to be applied to social button */
    socialButtonClass: PropTypes.string,
    /** Classes to be applied to container of the buttons */
    buttonsContainerClass: PropTypes.string,
    /** Classes to be applied to icon of the button */
    socialIconClass: PropTypes.string,
    /** Classes to be applied to the Content Loader container */
    loaderContainerClass: PropTypes.string,
    /** Classes to be applied to the Content Loader */
    contentLoaderClass: PropTypes.string,
    /** Image url for share in social medias */
    imageUrl: PropTypes.string,
  }

  static Loader = (loaderProps = {}) => {
    const {
      'vtex-share__button--loader': button,
      'vtex-share__button--loader-1': button1,
      'vtex-share__button--loader-2': button2,
      'vtex-share__button--loader-3': button3,
      containerClass,
      contentLoaderClass,
      ...rest
    } = loaderProps
    const loaderStyles = {
      r: '1em',
      height: '2em',
      cy: '1em',
      ...button,
    }

    return (
      <div
        className={classNames(
          styles.shareContainer,
          styles.shareLoader,
          containerClass
        )}
      >
        <ContentLoader
          className={contentLoaderClass}
          style={{
            width: '100%',
            height: '100%',
          }}
          height="100"
          width="100"
          {...rest}
        >
          <circle cx="1em" {...loaderStyles} {...button1} />
          <circle cx="3.5em" {...loaderStyles} {...button2} />
          <circle cx="6em" {...loaderStyles} {...button3} />
        </ContentLoader>
      </div>
    )
  }

  static defaultProps = {
    social: {
      Facebook: true,
      Twitter: true,
      WhatsApp: true,
      Pinterest: true,
    },
    options: {},
    className: 'flex flex-row flex-wrap w-100',
    shareLabelClass: 'pv2 pr3 t-small',
    buttonsContainerClass: 'flex flex-row',
  }

  static schema = {
    title: 'admin/editor.share.title',
    description: 'admin/editor.share.description',
    type: 'object',
    properties: {
      social: {
        title: 'admin/editor.share.social.title',
        type: 'object',
        properties: {
          ...indexBy(
            prop('title'),
            SOCIAL_ENUM.map(socialNetwork => ({
              type: 'boolean',
              title: socialNetwork,
              default: Share.defaultProps.social[socialNetwork],
            }))
          ),
        },
      },
    },
  }

  render() {
    const {
      social,
      title,
      loading,
      options: { size },
      className,
      shareLabelClass,
      buttonsContainerClass,
      socialButtonClass,
      socialIconClass,
      loaderContainerClass,
      contentLoaderClass,
      imageUrl,
    } = this.props

    if (loading) {
      return (
        <Share.Loader
          containerClass={loaderContainerClass}
          contentLoaderClass={contentLoaderClass}
          {...this.props.styles}
        />
      )
    }

    return (
      <div className={classNames(styles.shareContainer, className)}>
        <div className={classNames(styles.shareLabel, shareLabelClass)}>
          <FormattedMessage id="store/store-components.share.label" />
        </div>
        <div className={classNames(styles.shareButtons, buttonsContainerClass)}>
          {Object.keys(social).map(
            (socialNetwork, index) =>
              social[socialNetwork] && (
                <SocialButton
                  key={index}
                  imageUrl={imageUrl}
                  url={window.location && window.location.href}
                  message={title}
                  iconClass={socialIconClass}
                  buttonClass={socialButtonClass}
                  socialEnum={socialNetwork}
                  size={size}
                />
              )
          )}
        </div>
      </div>
    )
  }
}

export default Share

```