[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/Styleguide/components/Slider/Selector.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'

export default function Selector({
  onDragStart,
  position,
  active,
  disabled,
  value,
  displayPopup,
  formatValue,
  offset,
  icon,
}) {
  const containerClasses = classNames(
    'vtex-slider__selector-container absolute pointer',
    {
      'z-2': active,
      'z-1': !active,
      'left-0': position === 'left',
      'right-0': position === 'right',
    }
  )

  const containerStyle =
    position === 'left'
      ? { transform: `translateX(${offset}px) translateX(-50%)` }
      : { transform: `translateX(-${offset}px) translateX(50%)` }

  const dragCircleClasses = classNames(
    'vtex-slider__selector br-100 bg-action-primary flex justify-center items-center',
    {
      'bg-action-primary': active && !disabled,
    }
  )

  const popupClasses = classNames(
    'vtex-slider__selector-tooltip flex justify-center items-center relative ph3 pv2 br2 t-small ba',
    {
      'vtex-slider__tooltip--active bg-action-primary white b--action-primary': active,
      'bg-base b--muted-2 c-muted-1': !active,
    }
  )

  return (
    <div
      className={containerClasses}
      onMouseDown={onDragStart(position)}
      onTouchStart={onDragStart(position)}
      style={{
        ...containerStyle,
        willChange: 'transform',
        top: 6.5,
      }}>
      {(active || displayPopup) && (
        <div className="absolute pb4" style={{ left: '50%', bottom: '100%' }}>
          <div className={popupClasses} style={{ left: '-50%' }}>
            {formatValue(value)}
          </div>
        </div>
      )}
      <div
        className={dragCircleClasses}
        style={{
          height: '0.75rem',
          width: '0.75rem',
          boxShadow: '-1px 1px 3px rgba(0, 0, 0, 0.15)',
        }}>
        {icon}
      </div>
    </div>
  )
}

Selector.defaultProps = {
  active: false,
  disabled: false,
  value: 0,
  className: '',
  displayPopup: false,
  icon: null,
}

Selector.propTypes = {
  /** Position of the selector */
  position: PropTypes.oneOf(['left', 'right']).isRequired,
  /** onDragStart event */
  onDragStart: PropTypes.func.isRequired,
  /** If the selector is active */
  active: PropTypes.bool,
  /** If the selector is disabled */
  disabled: PropTypes.bool,
  /** Current value of the selector */
  value: PropTypes.number,
  /** Whether the popup is displayed when inactive */
  displayPopup: PropTypes.bool,
  /** Function to format the value */
  formatValue: PropTypes.func.isRequired,
  /** Margin offset value */
  offset: PropTypes.number.isRequired,
  /** Icon to show inside the handle */
  icon: PropTypes.node,
}

```


[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/Styleguide/components/Slider/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 classNames from 'classnames'

import Selector from './Selector'

const UP_EVENTS = ['mouseup', 'pointerup', 'touchend']

const MOVE_EVENT_MAP = {
  mousedown: 'mousemove',
  touchstart: 'touchmove',
  pointerdown: 'pointermove',
}

/**
 * Round the value to the nearest step multiple
 */
function quantize(value, step) {
  const numSteps = Math.round(value / step)
  const quantizedVal = numSteps * step

  return quantizedVal
}

/**
 * Get the event pageX attribute, with support for mobile events
 */
function getPageX(evt) {
  if (evt.targetTouches && evt.targetTouches.length > 0) {
    return evt.targetTouches[0].pageX
  }

  return evt.pageX
}

/**
 * Check for the esc key event
 */
function isEscKeyEvent(evt) {
  return evt.key === 'Escape' || evt.keyCode === 27
}

export default class Slider extends Component {
  sliderRef = React.createRef()

  state = {
    dragging: null,
    translate: {
      left: 0,
      right: 0,
    },
    values: {
      left:
        this.props.defaultValues && this.props.defaultValues.length > 0
          ? this.props.defaultValues[0]
          : this.props.min,
      right:
        this.props.range &&
        this.props.defaultValues &&
        this.props.defaultValues.length >= 2
          ? this.props.defaultValues[1]
          : this.props.max,
    },
  }

  componentDidUpdate(prevProps) {
    if (prevProps.min !== this.props.min || prevProps.max !== this.props.max) {
      this.setState(
        {
          translate: {
            left: 0,
            right: 0,
          },
          values: {
            left: this.props.min,
            right: this.props.max,
          },
        },
        this.updateLayout
      )
    }
  }

  componentDidMount() {
    window.addEventListener('resize', this.updateLayout)

    if (this.props.defaultValues && this.props.defaultValues.length > 0) {
      this.updateLayout()
    }
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.updateLayout)

    if (this.cancelDragEvent_) {
      this.cancelDragEvent_()
      this.cancelDragEvent_ = undefined
    }
  }

  updateLayout = () => {
    this.updatePositionForValue(this.state.values.left, 'left')
    this.updatePositionForValue(this.state.values.right, 'right')
  }

  getValueForPercent = (percentageComplete, position) => {
    const { min, max, step, range } = this.props

    const rawValue = min + percentageComplete * (max - min)

    let value

    if (rawValue !== min && rawValue !== max) {
      value = quantize(rawValue, step)
    } else {
      value = rawValue
    }

    if (value < min) {
      value = min
    } else if (value > max) {
      value = max
    }

    if (!range) {
      return value
    }

    if (position === 'left' && value >= this.state.values.right) {
      value = this.state.values.right - step
    } else if (position === 'right' && value <= this.state.values.left) {
      value = this.state.values.left + step
    }

    return value
  }

  getTranslateValueForInputValue = (value, position) => {
    const { max, min } = this.props
    const rect = this.sliderRef.current.getBoundingClientRect()
    const percentageComplete = (value - min) / (max - min)

    let translatePx = percentageComplete * rect.width

    if (position === 'right') {
      translatePx = rect.width - translatePx
    }

    return translatePx
  }

  handleSliderMouseDown = e => {
    const rect = this.sliderRef.current.getBoundingClientRect()
    const xPos = getPageX(e) - rect.left

    const leftPos = this.state.translate.left
    const rightPos = rect.width - this.state.translate.right

    let nearestPoint

    // Which one has a absolute value closer to 0
    if (
      !this.props.range ||
      Math.abs(leftPos - xPos) < Math.abs(rightPos - xPos)
    ) {
      nearestPoint = 'left'
    } else {
      nearestPoint = 'right'
    }

    this.handleDragStart(nearestPoint)(e)
  }

  handleDragStart = position => e => {
    e.stopPropagation()

    // allow only one handle to be dragged at a time
    if (this.props.disabled || this.state.dragging) {
      return
    }

    this.setState({
      dragging: position,
    })

    this.valuesBeforeDrag_ = this.state.values

    // https://reactjs.org/docs/events.html#event-pooling
    e.persist()

    const moveHandler = this.handleDrag(position)

    // The events bellow are attached to the body because we need
    // to support the dragging event *outside* of the slider bounds

    this.cancelDragEvent_ = () => {
      this.valuesBeforeDrag_ = undefined
      UP_EVENTS.forEach(evtName =>
        document.body.removeEventListener(evtName, handleUpEvent)
      )
      document.body.removeEventListener(MOVE_EVENT_MAP[e.type], moveHandler)
      document.body.removeEventListener('keydown', this.handleKeyDown)
    }

    const handleUpEvent = () => {
      this.cancelDragEvent_()
      this.handleDragEnd()
    }

    UP_EVENTS.forEach(evtName =>
      document.body.addEventListener(evtName, handleUpEvent)
    )
    document.body.addEventListener(MOVE_EVENT_MAP[e.type], moveHandler)
    document.body.addEventListener('keydown', this.handleKeyDown)

    this.updatePositionFromEvent(e, position)
  }

  updatePositionFromEvent = (e, position) => {
    const slider = this.sliderRef.current
    const rect = slider.getBoundingClientRect()

    const xPos = getPageX(e) - rect.left

    const percentageComplete = xPos / rect.width

    const value = this.getValueForPercent(percentageComplete, position)

    this.updatePositionForValue(value, position)
  }

  handleDrag = position => e => {
    e.preventDefault()
    this.updatePositionFromEvent(e, position)
  }

  updatePositionForValue = (value, position) => {
    const translatePx = this.getTranslateValueForInputValue(value, position)

    requestAnimationFrame(() => {
      this.setState({
        values: {
          ...this.state.values,
          [position]: value,
        },
        translate: {
          ...this.state.translate,
          [position]: translatePx,
        },
      })
    })
  }

  handleDragEnd = () => {
    this.setState({
      dragging: null,
    })

    this.cancelDragEvent_ = undefined

    if (this.props.range) {
      this.props.onChange([this.state.values.left, this.state.values.right])
    } else {
      this.props.onChange([this.state.values.left])
    }
  }

  handleKeyDown = evt => {
    if (!isEscKeyEvent(evt) || !this.state.dragging) {
      return
    }

    this.setState({
      dragging: false,
      values: this.valuesBeforeDrag_,
    })

    this.cancelDragEvent_()
    this.cancelDragEvent = undefined

    this.updateLayout()
  }

  render() {
    const {
      disabled,
      alwaysShowCurrentValue,
      formatValue,
      range,
      handleIcon,
    } = this.props
    const { left, right } = this.state.translate

    const lastLeftValue = this.valuesBeforeDrag_
      ? this.valuesBeforeDrag_.left
      : this.state.values.left
    const lastRightValue = this.valuesBeforeDrag_
      ? this.valuesBeforeDrag_.right
      : this.state.values.right

    const sliderSelectionStyle = range
      ? { left, right }
      : { left: 0, width: left }

    return (
      <div className="vtex-slider-container">
        <div
          className="vtex-slider w-100 relative pointer"
          style={{
            height: 24,
            // since we can't include css with the components, the
            // prefixed attributes need to be included
            MozUserSelect: 'none',
            msUserSelect: 'none',
            WebkitUserSelect: 'none',
            userSelect: 'none',
          }}
          onMouseDown={this.handleSliderMouseDown}
          onTouchStart={this.handleSliderMouseDown}>
          <div
            ref={this.sliderRef}
            className="vtex-slider__base w-100 bg-muted-4 absolute br-pill overflow-hidden"
            style={{
              height: '0.25rem',
              top: '0.7rem',
            }}>
            <div
              className={classNames('absolute h-100', {
                'bg-action-primary': !disabled,
                'bg-muted-4': disabled,
              })}
              style={sliderSelectionStyle}
            />
          </div>
          <Selector
            offset={left}
            onDragStart={this.handleDragStart}
            position="left"
            active={this.state.dragging === 'left'}
            displayPopup={alwaysShowCurrentValue}
            value={this.state.values.left}
            formatValue={formatValue}
            icon={handleIcon}
          />
          {range && (
            <Selector
              offset={right}
              onDragStart={this.handleDragStart}
              position="right"
              active={this.state.dragging === 'right'}
              displayPopup={alwaysShowCurrentValue}
              value={this.state.values.right}
              formatValue={formatValue}
              icon={handleIcon}
            />
          )}
        </div>

        <div className="flex justify-end">
          <label className="t-small c-muted-1">
            {formatValue(lastLeftValue)}
          </label>
          {range && (
            <label className="t-small c-muted-1">
              <span className="mh2">–</span>
              {formatValue(lastRightValue)}
            </label>
          )}
        </div>
      </div>
    )
  }
}

Slider.defaultProps = {
  min: 0,
  max: 10,
  step: 1,
  onChange: () => {},
  alwaysShowCurrentValue: false,
  formatValue: a => a,
  range: false,
  handleIcon: null,
}

Slider.propTypes = {
  /** Minimum supported value */
  min: PropTypes.number,
  /** Maximum supported value */
  max: PropTypes.number,
  /** onChange event */
  onChange: PropTypes.func,
  /** Step value */
  step: PropTypes.number,
  /** Whether the slider is disabled */
  disabled: PropTypes.bool,
  /** Initial values */
  defaultValues: PropTypes.arrayOf(PropTypes.number),
  /** Whether to always display current value as a popup */
  alwaysShowCurrentValue: PropTypes.bool,
  /** Function to customize the format of the value */
  formatValue: PropTypes.func,
  /** Whether to render as a range input */
  range: PropTypes.bool,
  /** Optional icon to show inside the slider handle */
  handleIcon: PropTypes.node,
}

```


[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/Styleguide/components/Slider/README.md from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```markdown
Simple slider

```jsx
<Slider
  onChange={([value]) => {}}
  min={0}
  max={99}
  step={1}
  disabled={false}
  defaultValues={[0]}
  alwaysShowCurrentValue={false}
  formatValue={a => a + 1}
/>
```

Range slider

```jsx
<Slider
  onChange={([leftValue, rightValue]) => {}}
  min={0}
  max={99}
  step={1}
  disabled={false}
  defaultValues={[0, 50]}
  alwaysShowCurrentValue={false}
  formatValue={a => a + 1}
  range
/>
```

```


[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/Styleguide/components/PageHeader/index.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'

import ArrowBack from '../icon/ArrowBack'
import Button from '../Button'

class PageHeader extends PureComponent {
  handleClick = e => {
    this.props.onLinkClick && this.props.onLinkClick(e)
  }

  render() {
    const { linkLabel, children, subtitle } = this.props

    return (
      <div className="vtex-pageHeader__container pa5 pa7-ns">
        {linkLabel && (
          <div className="vtex-pageHeader-link__container">
            <Button
              size="small"
              variation="tertiary"
              neutral
              onClick={this.handleClick}>
              <span
                className="flex align-baseline relative"
                style={{ marginLeft: '-16px' }}>
                <span className="mr3">
                  <ArrowBack color="currentColor" />
                </span>
                {linkLabel}
              </span>
            </Button>
          </div>
        )}

        <div
          className={`c-on-base flex flex-wrap flex-row justify-between
            ${linkLabel ? 'mt0' : 'mt7'}`}>
          <div className="vtex-pageHeader__title t-heading-2 order-0 flex-grow-1">
            {this.props.title}
          </div>
          {children && (
            <div
              className={`vtex-pageHeader__children order-2 order-0-ns ${
                subtitle ? 'mt5' : ''
              } mt0-ns`}>
              {children}
            </div>
          )}
          <div className="w-100" style={{ height: 0 }} />
          {subtitle && (
            <div className="vtex-pageHeader__subtitle t-body lh-copy c-muted-1 mv5 order-1 order-0-ns">
              {subtitle}
            </div>
          )}
        </div>
      </div>
    )
  }
}

PageHeader.propTypes = {
  /** Title for the header */
  title: PropTypes.node.isRequired,
  /** Subtitle for the header */
  subtitle: PropTypes.node,
  /** Label for the back button */
  linkLabel: PropTypes.node,
  onLinkClick: PropTypes.func,
  children: PropTypes.node,
}

export default PageHeader

```


[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/Styleguide/components/PageHeader/README.md from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```markdown
#### A simple header for Admin modules and Apps with simple navigation needs.

### 👍 Dos

- Keep the page title short. It's a title, after all. Use the module name in the title if it's the first page.
- Use the previous page title as the label of the back link.
- Use the main action button if it's clear what would be the most import action of the entire page. Otherwise just don't.

### 👎 Don'ts

- Don't change dynamically the main page action upon action on the page. The main action should be as static as the title is.

### Related components

<a href="#/Components/Navigation/Tabs">Tabs</a> may be used in composition with the PageHeader for the main navigation.

Default

```js
<PageHeader title="Orders" />
```

With link

```js
<PageHeader
  title="Order details"
  linkLabel="Orders"
  onLinkClick={e => {
    console.log(e)
  }}
/>
```

With children

```js
const Button = require('../Button').default

;<PageHeader
  title="Order details"
  linkLabel="Orders"
  onLinkClick={e => {
    console.log(e)
  }}>

    <Button variation="secondary">Secondary</Button>

  <Button variation="primary">Primary</Button>
</PageHeader>
```

With children and subtitle

```js
const Button = require('../Button').default

;<PageHeader
  title="Order details"
  subtitle="Some explanation or description for your page"
  linkLabel="Orders"
  onLinkClick={e => {
    console.log(e)
  }}>

    <Button variation="secondary">Secondary</Button>

  <Button variation="primary">Primary</Button>
</PageHeader>
```

```


[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/Styleguide/components/utils/index.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

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

export const childrenOf = (...types) => {
  const fieldType = PropTypes.shape({
    type: PropTypes.oneOf(types),
  })

  return PropTypes.oneOfType([fieldType, PropTypes.arrayOf(fieldType)])
}

```


[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/Styleguide/components/utils/zIndex.ts from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```typescript
export default {
  modal: 10000,
  tooltip: 11000,
}

```


[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/Styleguide/components/utils/react.ts from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```typescript
export function setRef(ref, value) {
  if (typeof ref === 'function') {
    ref(value)
  } else if (ref) {
    ref.current = value
  }
}

```


[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/Styleguide/components/utils/withDeviceHoc.tsx from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { useMedia } from 'use-media'

export enum Device {
  phone = 'phone',
  tablet = 'tablet',
  desktop = 'desktop',
}

const withDevice = Component => {
  function WithDevice(props) {
    // Taken at https://github.com/vtex-apps/device-detector/blob/master/react/useDevice.tsx#L22
    const isScreenMedium = useMedia({ minWidth: '40rem' })
    const isScreenLarge = useMedia({ minWidth: '64.1rem' })

    const device = isScreenLarge
      ? Device.desktop
      : isScreenMedium
      ? Device.tablet
      : Device.phone

    const isMobile = device.toLowerCase() === 'phone'

    return <Component device={device} isMobile={isMobile} {...props} />
  }

  return WithDevice
}

export default withDevice

```


[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/Styleguide/components/Spinner/index.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

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

import { baseClassname } from '../icon/utils'

const radius = 40
const circ = 2 * radius * Math.PI

class Spinner extends React.Component {
  render() {
    const { color, size, block } = this.props

    return (
      <svg
        className={`${baseClassname('spinner')} ${
          !color ? 'c-action-primary' : ''
        } ${block ? 'db' : ''}`}
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 100 100"
        preserveAspectRatio="xMidYMid"
        height={size}
        width={size}>
        <style>
          {`
            @keyframes vtex-spinner-rotate {
              from {
                transform-origin: 50% 50%;
                transform: rotate(0deg);
              }
              to {
                transform-origin: 50% 50%;
                transform: rotate(360deg);
              }
            }

            @keyframes vtex-spinner-fill {
              0% {
                stroke-dasharray: 0 0 2 ${circ};
              }
              50% {
                stroke-dasharray: 0 0 ${circ * 0.75} ${circ};
              }
              100% {
                stroke-dasharray: 0 ${circ - 2} ${circ * 0.75} ${circ};
              }
            }

            .vtex-spinner_circle {
              animation: vtex-spinner-fill 1.25s infinite cubic-bezier(0.455, 0.030, 0.515, 0.955), vtex-spinner-rotate 0.625s infinite linear;
            }
          `}
        </style>

        <circle
          className="vtex-spinner_circle"
          cx="50"
          cy="50"
          fill="none"
          r={radius}
          stroke={color || 'currentColor'}
          strokeWidth="10"
          strokeDasharray={`0 0 ${circ * 0.75} ${circ}`}
          strokeLinecap="round"
          strokeDashoffset="1"
        />
      </svg>
    )
  }
}

Spinner.propTypes = {
  /** Color of the spinner */
  color: PropTypes.string,
  /** Size (diameter) of the spinner */
  size: PropTypes.number,
  /** Sets the display to block */
  block: PropTypes.bool,
}

Spinner.defaultProps = {
  block: false,
  size: 40,
}

export default Spinner

```


[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/Styleguide/components/Spinner/README.md from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```markdown
#### A Spinner is a way of showing the user something is being loaded, either because of a user action or not. It should be used for short, indeterminate loading times.

### 👍 Dos

- Mind the color contrast with the background.
- For very long waiting times (10+ seconds) try giving some feedback about the progress that is being made in the background.
- If you're showing a spinner in a button make sure to make it disabled while loading.
- For very recurrent actions where the probability of success if very high consider using an optimistic approach. E.g.: a message being sent.

### 👎 Don'ts

- Only use spinners for loading times of more than 1 second. Less than that it'll cause more harm than good.
- Avoid showing too many spinners at a given time in the same screen, it'll look overwhelming.

### Related components

- If you can assess the progression of the task prefer a <a href="#/Components/Display/ProgressBar">Progress Bar</a>.
- For whole screen loading try using Skeleton Pages (work in progress).

#### Default

```js
<Spinner />
```

#### Custom color and size

```js
<span className="dib c-muted-1">
  <Spinner color="currentColor" size={20} />
</span>
```

```


[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/Styleguide/components/InputSearch/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 Input from '../Input'
import SearchIcon from '../icon/Search'
import ClearIcon from '../icon/Clear'
import { withForwardedRef, refShape } from '../../modules/withForwardedRef'

class InputSearch extends Component {
  constructor(props) {
    super(props)
    this.state = {
      hover: false,
      focus: false,
    }
  }

  static iconSizes = {
    small: 14,
    regular: 16,
    large: 18,
  }
  static separatorHeight = {
    small: 28,
    regular: 36,
    large: 44,
  }

  handleClickClear = event => {
    this.props.onChange &&
      this.props.onChange({
        ...event,
        target: {
          ...event.target,
          value: '',
        },
      })
    this.props.onClear && this.props.onClear(event)
  }

  handleSubmit = event => {
    const { onSubmit, value } = this.props
    onSubmit &&
      onSubmit({
        ...event,
        target: {
          ...event.target,
          value,
        },
        preventDefault: event.preventDefault || (() => {}),
      })
  }

  handleHovering = hover => {
    this.setState({ hover })
  }

  handleFocus = focus => {
    this.setState({ focus })
  }

  render() {
    const { hover, focus } = this.state
    const { size } = this.props
    const iconSize =
      InputSearch.iconSizes[size] || InputSearch.iconSizes.regular

    return (
      <Input
        {...this.props}
        onFocus={() => this.handleFocus(true)}
        onBlur={() => this.handleFocus(false)}
        onMouseEnter={() => this.handleHovering(true)}
        onMouseLeave={() => this.handleHovering(false)}
        onKeyUp={e => e.key === 'Enter' && this.handleSubmit(e)}
        type="search"
        suffix={
          <div className="flex flex-row items-center">
            {this.props.value && (
              <span
                tabIndex={0}
                onClick={this.handleClickClear}
                className="pointer mr4 c-muted-3">
                <ClearIcon size={iconSize} />
              </span>
            )}
            <div
              className={`mh2 bw1 bl ${
                focus ? 'b--muted-2' : hover ? 'b--muted-3' : 'b--muted-4'
              }`}
              style={{
                height:
                  InputSearch.separatorHeight[size] ||
                  InputSearch.separatorHeight.regular,
              }}
            />
            <span className="pointer pl4 c-link" onClick={this.handleSubmit}>
              <SearchIcon size={iconSize} />
            </span>
          </div>
        }
      />
    )
  }
}

InputSearch.propTypes = {
  /** @ignore Forwarded Ref */
  forwardedRef: refShape,
  onChange: PropTypes.func,
  onSubmit: PropTypes.func,
  onClear: PropTypes.func,
  size: PropTypes.string,
  value: PropTypes.string,
}

export default withForwardedRef(InputSearch)

```


[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/Styleguide/components/InputSearch/README.md from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```markdown
Sizes

```js
initialState = { value1: '', value2: '', value3: '' }
;

  <InputSearch
    placeholder="Search..."
    value={state.value1}
    label="Small"
    size="small"
    onChange={e => setState({ value1: e.target.value })}
    onSubmit={e => {
      e.preventDefault()
      console.log('submited! search this: ', e.target.value)
    }}
  />

  <InputSearch
    placeholder="Search..."
    value={state.value2}
    label="Regular"
    size="regular"
    onChange={e => setState({ value2: e.target.value })}
    onSubmit={e => {
      e.preventDefault()
      console.log('submited! search this: ', e.target.value)
    }}
  />

  <InputSearch
    placeholder="Search..."
    value={state.value3}
    label="Large"
    size="large"
    onChange={e => setState({ value3: e.target.value })}
    onSubmit={e => {
      e.preventDefault()
      console.log('submited! search this: ', e.target.value)
    }}
  />

```

```


[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/Styleguide/components/ProgressBar/index.tsx from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```tsx
import Progress from '../Progress'
import deprecated from '../../modules/deprecated'

export default deprecated({
  useNewComponent: {
    old: 'ProgressBar',
    new: 'Progress',
  },
} as any)(Progress)

```


[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/Styleguide/components/Toggle/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 DenyIcon from '../icon/Deny'
import CheckIcon from '../icon/Check'

class Toggle extends Component {
  componentDidMount() {
    if (this.props.size === 'small') {
      console.warn(
        'Toggle: value "small" for the prop "size" is deprecated—the default "regular" size is now equivalent to what the size "small" was previously.'
      )
    }
  }

  render() {
    const {
      semantic,
      disabled,
      id,
      checked,
      label,
      size,
      helpText,
    } = this.props

    let labelClass = disabled ? 'c-disabled ' : 'c-on-base '
    let classes = 'flex items-center relative br4 '
    let circleClasses = 'absolute br-100 '
    let iconDenyClasses = 'absolute flex justify-center '
    let iconCheckClasses = 'absolute flex justify-center '

    let circleStyle = {
      boxShadow: disabled ? 'none' : '0 0 10px rgba(0,0,0,0.2)',
      transform: 'scale(0.8)',
      transition: 'all .1s ease-out',
    }
    let iconStyle = {
      transition: 'left .1s ease-out, opacity .1s ease-in-out',
    }

    // Background
    if (semantic) {
      if (!disabled) {
        iconCheckClasses += 'c-success '
        iconDenyClasses += 'c-danger '

        if (!checked) {
          classes += 'bg-danger '
          iconDenyClasses += 'o-100 '
          iconCheckClasses += 'o-0 '
        } else {
          classes += 'bg-success '
          iconDenyClasses += 'o-0 '
          iconCheckClasses += 'o-100 '
        }
      } else {
        classes += 'bg-disabled '
        iconCheckClasses += 'c-on-disabled '
        iconDenyClasses += 'c-on-disabled '

        if (!checked) {
          iconDenyClasses += 'o-100 '
          iconCheckClasses += 'o-0 '
        } else {
          iconDenyClasses += 'o-0 '
          iconCheckClasses += 'o-100 '
        }
      }
    } else if (disabled) {
      classes += 'bg-disabled '
    } else {
      if (!checked) {
        classes += 'bg-muted-2 '
      }

      if (checked) {
        classes += 'bg-action-primary '
      }
    }

    // Circle
    if (disabled) {
      circleClasses += 'bg-muted-3 '
    } else {
      circleClasses += 'bg-base '
    }

    let style = {
      transition: 'background 100ms ease-out',
    }

    let checkedOffset

    switch (size) {
      case 'large':
        classes += 'h2 '
        circleClasses += 'h2 w2 '
        iconDenyClasses += 'w2 '
        iconCheckClasses += 'w2 '

        labelClass += 'ml5 '

        style = {
          ...style,
          minWidth: '3.5rem',
        }
        circleStyle = {
          ...circleStyle,
          minWidth: '2rem',
        }

        checkedOffset = '1.5rem'
        break
      default:
        style = {
          ...style,
          height: '1.25rem',
          width: '2.25rem',
          minWidth: '2.25rem',
        }
        circleStyle = {
          ...circleStyle,
          height: '1.25rem',
          width: '1.25rem',
          minWidth: '1.25rem',
        }

        iconStyle = {
          ...iconStyle,
          transform: 'scale(0.7)',
          width: '1.25rem',
        }

        labelClass += 'ml3 '

        checkedOffset = '1rem'
    }

    const checkedStyle = {
      left: checked ? checkedOffset : 0,
    }

    circleStyle = { ...circleStyle, ...checkedStyle }
    iconStyle = { ...iconStyle, ...checkedStyle }

    return (
      <label htmlFor={id}>
        <div
          className={`flex flex-row items-center relative ${!disabled &&
            'pointer'}`}>
          <div className={`vtex-toggle ${classes}`} style={style}>
            <div className={circleClasses} style={circleStyle} />
            {semantic && (
              <div className={iconDenyClasses} style={iconStyle}>
                <DenyIcon size={size === 'regular' ? 14 : 12} />
              </div>
            )}
            {semantic && (
              <div className={iconCheckClasses} style={iconStyle}>
                <CheckIcon size={size === 'regular' ? 15 : 13} />
              </div>
            )}
          </div>
          <input
            id={id}
            type="checkbox"
            className="h-100 w-100 absolute o-0 pointer"
            disabled={disabled}
            checked={checked}
            name={this.props.name}
            onClick={this.props.onClick}
            onChange={this.props.onChange}
            tabIndex={0}
          />
          {label && <span className={labelClass}>{label}</span>}
        </div>
        {helpText && (
          <div className="c-muted-1 t-small mt3 lh-title">{helpText}</div>
        )}
      </label>
    )
  }
}

Toggle.defaultProps = {
  checked: false,
  disabled: false,
  semantic: false,
  label: '',
  size: 'regular',
}

Toggle.propTypes = {
  checked: PropTypes.bool,
  semantic: PropTypes.bool,
  disabled: PropTypes.bool,
  id: PropTypes.string,
  label: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
  name: PropTypes.string,
  onChange: PropTypes.func,
  onClick: PropTypes.func,
  size: PropTypes.oneOf(['regular', 'large']),
  helpText: PropTypes.node,
}

export default Toggle

```


[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/Styleguide/components/Toggle/README.md from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```markdown
#### A Toggle is a control for turning an option ON or OFF. Its effect is usually automatically applied, which is one of the main differences compared to checkboxes, that need a submit.

### 👍 Dos
- The label should reflect the component state, like "On/Off", or "Enabled/Disabled", it shouldn't use an imperative tone (like "Enable").
- Use the Semantic variation if turning this option ON is highly recommended from your application standpoint. In doubt prefer the default variation.
- Be mindful of the default value of this field.
- It's usually a good practice to be optimistic about its effect. Even if you're not sure if the resulting network request will be successful, pretend it does and let it change its state.

### Related components
- Consider using a <a href="#/Components/Forms/Checkbox">Checkbox</a> if it's inside a form, or if the property doesn't have a clear "ON/OFF".

Default

```js
initialState = {
  checked: true,
};

  <Toggle
    checked={state.checked}
    onChange={e => setState(prevState => ({ checked: !prevState.checked }))}
  />

;
```

With labels

```js
initialState = {
  checked: true,
  checked2: false,
  checkedLarge1: true,
  checkedLarge2: false
};

    <Toggle
      label={state.checked ? "Activated" : "Deactivated"}
      checked={state.checked}
      onChange={e => setState(prevState => ({ checked: !prevState.checked }))}
    />

    <Toggle
      label={state.checked2 ? "Activated" : "Deactivated"}
      checked={state.checked2}
      onChange={e => setState(prevState => ({ checked2: !prevState.checked2 }))}
    />

    <Toggle
      label={state.checkedLarge1 ? "Activated" : "Deactivated"}
      size="large"
      checked={state.checkedLarge1}
      onChange={e =>
        setState(prevState => ({ checkedLarge1: !prevState.checkedLarge1 }))
      }
    />

    <Toggle
      label={state.checkedLarge2 ? "Activated" : "Deactivated"}
      size="large"
      checked={state.checkedLarge2}
      onChange={e =>
        setState(prevState => ({ checkedLarge2: !prevState.checkedLarge2 }))
      }
      helpText="You can add help text!"
    />

;
```

Semantic

Use the Semantic variation if turning this option ON is highly recommended from your application standpoint. In doubt prefer the default variation.

```js
initialState = {
  checked: true,
  checked2: false,
  checkedLarge1: true,
  checkedLarge2: false
};

    <Toggle
      label={state.checked ? "Activated" : "Deactivated"}
      semantic
      checked={state.checked}
      onChange={e => setState(prevState => ({ checked: !prevState.checked }))}
    />

    <Toggle
      label={state.checked2 ? "Activated" : "Deactivated"}
      semantic
      checked={state.checked2}
      onChange={e => setState(prevState => ({ checked2: !prevState.checked2 }))}
    />

;
```

Disabled

```js

    <Toggle disabled checked label="Label" />

    <Toggle disabled label="Label" />

```

```


[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/Styleguide/components/AutocompleteInput/index.tsx from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```tsx
import PropTypes from 'prop-types'
import React, { useState, useRef } from 'react'

import Spinner from '../Spinner'
import { useClickOutside, useArrowNavigation } from './hooks'
import Option, {
  AutocompleteOption,
  autocompleteOptionShape,
  getTermFromOption,
} from './Option'
import SearchInput from './SearchInput'

const propTypes = {
  /** Input props. All HTMLInput props can be added too */
  input: PropTypes.shape({
    /** Clear input handler */
    onClear: PropTypes.func.isRequired,
    /** Search by term handler (fired on enter or when clicking the search button) */
    onSearch: PropTypes.func.isRequired,
    /** Change term handler */
    onChange: PropTypes.func.isRequired,
    /** Term to be searched */
    value: PropTypes.string,
    /** Determine if the input and button should be disabled */
    disabled: PropTypes.bool.isRequired,
  }).isRequired,
  /** Options props. More details in the examples */
  options: PropTypes.shape({
    /**
     * Determine if a spinner will be shown below the given options
     * to show that more options will be added
     */
    loading: PropTypes.bool,
    /**
     * Function that makes possible to the dev to customly render option.
     * Called with all props needed: `(props: { key: string, selected: boolean, value: OptionValue, searchTerm: string, roundedBottom: boolean, icon: ReactElement, onClick: () => void }, index: number)` and should return a React Node
     */
    renderOption: PropTypes.func,
    /**
     * List of options.
     * An option could be a string (denoting a search by term) or an object
     * with `{value: any, label: string}` (denoting the search is related to an entity).
     */
    value: PropTypes.arrayOf(autocompleteOptionShape).isRequired,
    /**
     * Icon representing the entity.
     * Shown when a value is an object to show the difference
     */
    icon: PropTypes.element,
    /**
     * Callback called when an option is selected
     * (clicked or via arrow keys + enter)
     */
    onSelect: PropTypes.func.isRequired,
    /**
     * Last searched terms. Can be used to enhance the Autocomplete experience.
     * Defined with: `{
     *   value: OptionValue[],
     *   onChange: (term: string | OptionValue) => any,
     *   label: string
     * }`
     */
    lastSearched: PropTypes.shape({
      /** List of last searched options */
      value: PropTypes.arrayOf(autocompleteOptionShape).isRequired,
      /**
       * Last searched change handler.
       * Called when a term is searched or an option is selected.
       */
      onChange: PropTypes.func,
      /** Last Searched options's title */
      label: PropTypes.node.isRequired,
    }),
  }).isRequired,
}

export type AutocompleteInputProps = PropTypes.InferProps<typeof propTypes>

const AutocompleteInput: React.FunctionComponent<PropTypes.InferProps<
  typeof propTypes
>> = ({
  input: { value, onClear, onSearch, onChange, ...inputProps },
  options: {
    onSelect,
    value: options,
    renderOption,
    loading,
    lastSearched = {},
    icon,
  },
}) => {
  const [term, setTerm] = useState(value || '')
  const [showPopover, setShowPopover] = useState(false)
  const containerRef = useRef<HTMLDivElement>(null)
  const searching = term.length
  const showLastSearched =
    !searching && (lastSearched as any)?.value?.length > 0

  const getShowedOptions = (): AutocompleteOption[] => {
    if (showLastSearched) {
      return (lastSearched as any)?.value
    }
    if (searching) {
      return options
    }
    return []
  }

  const showedOptions = getShowedOptions()

  const noSelectedOptionIndex = -1
  const [selectedOptionIndex, setSelectedOptionIndex] = useArrowNavigation(
    containerRef,
    showedOptions.length,
    noSelectedOptionIndex
  )
  useClickOutside(containerRef, () => setShowPopover(false))

  const addToLastSearched = (option: AutocompleteOption) => {
    (lastSearched as any)?.onChange(option)
  }

  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Enter') {
      const selectedOption =
        selectedOptionIndex !== -1 ? showedOptions[selectedOptionIndex] : term
      addToLastSearched(selectedOption)
      setTerm(getTermFromOption(selectedOption))
      if (selectedOptionIndex !== -1) {
        onSelect(selectedOption)
      } else {
        onSearch(getTermFromOption(selectedOption))
      }
      setSelectedOptionIndex(-1)
      setShowPopover(false)
    }
  }

  const handleTermChange = (newTerm = '') => {
    if (!showPopover) {
      setShowPopover(true)
    }
    setTerm(newTerm)
    if (onChange) {
      onChange(newTerm)
    }
  }

  const handleClear = () => {
    setShowPopover(false)

    setTerm('')
    onClear()
  }

  const handleOptionClick = (option: AutocompleteOption) => {
    setTerm(getTermFromOption(option))
    onSelect(option)
    setShowPopover(false)
  }

  const getOptionProps = (option: any, index: any) => ({
    key: `${getTermFromOption(option)}-${index}`,
    selected: index === selectedOptionIndex,
    value: option,
    searchTerm: term,
    roundedBottom: index === showedOptions.length - 1,
    icon: typeof option !== 'string' && icon ? icon : null,
    onClick: () => {
      addToLastSearched(option)
      handleOptionClick(option)
    },
  })

  const renderOptions = (): React.ReactElement | React.ReactElement[] => (
    <div className="flex flex-column">
      {showLastSearched ? (
        <div className="pa4 b f6">
          {(lastSearched as any)?.label || 'Last searched terms'}
        </div>
      ) : null}
      {showedOptions.map((option, index) =>
        renderOption ? (
          renderOption(getOptionProps(option, index), index)
        ) : (
          <Option {...getOptionProps(option, index)} />
        )
      )}
    </div>
  )

  const popoverOpened = showPopover && (!!showedOptions.length || loading)

  return (
    <div ref={containerRef} className="flex flex-column w-100">
      <SearchInput
        {...inputProps}
        value={
          selectedOptionIndex === -1
            ? term
            : getTermFromOption(showedOptions[selectedOptionIndex])
        }
        roundedBottom={!popoverOpened}
        onKeyDown={handleKeyDown}
        onFocus={() => setShowPopover(true)}
        onSearch={() => onSearch(term)}
        onClear={handleClear}
        onChange={handleTermChange}
      />
      {popoverOpened ? (
        <div className="relative">
          <div className="absolute br--bottom br2 bb bl br bw1 b--muted-3 bg-base w-100 z-1 shadow-5">
            {renderOptions()}
            {loading && (
              <div className="flex flex-row justify-center items-center pa4">
                <Spinner size={20} />
              </div>
            )}
          </div>
        </div>
      ) : null}
    </div>
  )
}

AutocompleteInput.propTypes = propTypes

export default AutocompleteInput

```


[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/Styleguide/components/AutocompleteInput/Option.tsx from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```tsx
import classNames from 'classnames'
import PropTypes from 'prop-types'
import React, { useState } from 'react'

/** Structured Autocomplete option shape */
const structuredAutocompleteOptionShape = PropTypes.shape({
  value: PropTypes.any,
  label: PropTypes.string.isRequired,
})

type StructuredAutocompleteOption = PropTypes.InferType<
  typeof structuredAutocompleteOptionShape
>

export type AutocompleteOption = string | StructuredAutocompleteOption

/** Autocomplete option shape */
export const autocompleteOptionShape = PropTypes.oneOfType([
  PropTypes.string,
  structuredAutocompleteOptionShape,
])

export const getTermFromOption = (option: AutocompleteOption): string =>
  typeof option === 'string' ? option : (option?.label || '') as string

const propTypes = {
  /** Determine if the option should have a rounded bottom */
  roundedBottom: PropTypes.bool,
  /** Option icon */
  icon: PropTypes.node,
  /** Search term used to highlight it into the label */
  searchTerm: PropTypes.string.isRequired,
  /** Option title */
  value: autocompleteOptionShape.isRequired,
  /** Determine if an option is selected and should be highlighted */
  selected: PropTypes.bool.isRequired,
  /** Click handler */
  onClick: PropTypes.func.isRequired,
}

const Option: React.FunctionComponent<PropTypes.InferProps<
  typeof propTypes
>> = props => {
  const { icon, selected, roundedBottom, searchTerm, onClick } = props
  const [highlightOption, setHighlightOption] = useState(false)
  const value = getTermFromOption(props.value)

  const renderOptionValue = (): string | React.ReactElement => {
    const index = value.toLowerCase().indexOf(searchTerm.toLowerCase())
    if (index === -1) {
      return value
    }
    const prefix = value.substring(0, index)
    const match = value.substr(index, searchTerm.length)
    const suffix = value.substring(index + match.length)
    return (
      <span className="truncate">
        <span className="fw7">{prefix}</span>
        {match}
        <span className="fw7">{suffix}</span>
      </span>
    )
  }

  const buttonClasses = classNames('bn w-100 tl pointer pa4 f6', {
    'br2 br--bottom': roundedBottom,
    'bg-muted-5': highlightOption || selected,
    'bg-base': !highlightOption && !selected,
  })

  return (
    <button
      className={buttonClasses}
      onFocus={() => setHighlightOption(true)}
      onMouseEnter={() => setHighlightOption(true)}
      onMouseLeave={() => setHighlightOption(false)}
      onClick={onClick}>
      <span className="h1 flex items-center">
        <span className="mr3 c-muted-2 flex pt1">{icon}</span>
        {renderOptionValue()}
      </span>
    </button>
  )
}

Option.propTypes = propTypes

export default Option

```


[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/Styleguide/components/AutocompleteInput/README.md from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```markdown
#### AutocompleteInput is a search input which, enhanced with a suggestions pop-up, gives the user a more complete search experience when needed.

### 👍 Dos

- Help the user avoid errors.
- Semantically similar phrases or words but grammarly different should appear once. E.g.: "Dress" and "Dresses".
- Highlight the suggestions.

### 👎 Don'ts

- Exceed 10 suggestions. 6 is a great number of suggestions.

#### Simple Autocomplete mocking server responses

```jsx
import { uniq } from 'lodash'
import { useState, useRef } from 'react'

const allUsers = [
  'Ana Clara',
  'Ana Luiza',
  { value: 1, label: 'Bruno' },
  'Carlos',
  'Daniela',
]

const UsersAutocomplete = () => {
  const [term, setTerm] = useState('')
  const [loading, setLoading] = useState(false)
  const timeoutRef = useRef(null)

  const options = {
    onSelect: (...args) => console.log('onSelect: ', ...args),
    loading,
    value: !term.length
      ? []
      : allUsers.filter(user =>
          typeof user === 'string'
            ? user.toLowerCase().includes(term.toLowerCase())
            : user.label.toLowerCase().includes(term.toLowerCase())
        ),
  }

  const input = {
    onChange: term => {
      if (term) {
        setLoading(true)
        if (timeoutRef.current) {
          clearTimeout(timeoutRef.current)
        }
        timeoutRef.current = setTimeout(() => {
          setLoading(false)
          setTerm(term)
          timeoutRef.current = null
        }, 1000)
      } else {
        setTerm(term)
      }
    },
    onSearch: (...args) => console.log('onSearch:', ...args),
    onClear: () => setTerm(''),
    placeholder: 'Search user... (e.g.: Ana)',
    value: term,
  }
  return <AutocompleteInput input={input} options={options} />
}

;<UsersAutocomplete />
```

#### Show search history

```jsx
import { uniq } from 'lodash'
import { useState, useRef } from 'react'

const allUsers = [
  'Ana Clara',
  'Ana Luiza',
  { value: 1, label: 'Bruno' },
  'Carlos',
  'Daniela',
]

const UsersAutocomplete = () => {
  const [term, setTerm] = useState('')
  const [loading, setLoading] = useState(false)
  const [lastSearched, setLastSearched] = useState([])
  const timeoutRef = useRef(null)

  const options = {
    onSelect: (...args) => console.log('onSelect: ', ...args),
    loading,
    value: !term.length
      ? []
      : allUsers.filter(user =>
          typeof user === 'string'
            ? user.toLowerCase().includes(term.toLowerCase())
            : user.label.toLowerCase().includes(term.toLowerCase())
        ),
    // --- This is what makes the Last Searched Terms work!
    // This can be stored anywhere the dev wants. To be persistent, for example.
    lastSearched: {
      value: lastSearched,
      label: 'Last searched users',
      onChange: option =>
        option && setLastSearched(uniq([...lastSearched, option])),
    },
  }

  const input = {
    onChange: term => {
      if (term) {
        setLoading(true)
        if (timeoutRef.current) {
          clearTimeout(timeoutRef.current)
        }
        timeoutRef.current = setTimeout(() => {
          setLoading(false)
          setTerm(term)
          timeoutRef.current = null
        }, 1000)
      } else {
        setTerm(term)
      }
    },
    onSearch: (...args) => console.log('onSearch:', ...args),
    onClear: () => setTerm(''),
    placeholder: 'Search user... (e.g.: Ana)',
    value: term,
  }
  return <AutocompleteInput input={input} options={options} />
}

;<UsersAutocomplete />
```

#### Custom option rendering

```jsx
import { uniq } from 'lodash'
import { useState, useRef } from 'react'

import User from '../icon/User'
import Search from '../icon/Search'

const allUsers = [
  'Ana',
  { value: 1, label: 'Ana Clara' },
  { value: 2, label: 'Ana Luiza', caption: 'VTEX' },
  { value: 3, label: 'Bruno' },
]

const CustomOption = props => {
  const { roundedBottom, searchTerm, value, key, selected, onClick } = props
  const [highlightOption, setHighlightOption] = useState(false)

  const renderOptionHighlightedText = () => {
    const highlightableText = typeof value === 'string' ? value : value.label
    const index = highlightableText
      .toLowerCase()
      .indexOf(searchTerm.toLowerCase())
    if (index === -1) {
      return highlightableText
    }
    const prefix = highlightableText.substring(0, index)
    const match = highlightableText.substr(index, searchTerm.length)
    const suffix = highlightableText.substring(index + match.length)
    return (

        {prefix}
        {match}
        {suffix}

    )
  }

  const buttonClasses = `bn w-100 tl pointer pa4 f6 ${
    roundedBottom ? 'br2 br--bottom' : ''
  } ${highlightOption || selected ? 'bg-muted-5' : 'bg-base'}`

  const icon = typeof value === 'string' ? <Search size={14} /> : <User size={14} />

  // --- This is a good practice. Use <button />.
  return (
    <button
      key={key}
      className={buttonClasses}
      onFocus={() => setHighlightOption(true)}
      onMouseEnter={() => setHighlightOption(true)}
      onMouseLeave={() => setHighlightOption(false)}
      onClick={onClick}>

        {icon}
        {renderOptionHighlightedText()}
        {typeof value !== 'string' && (

{value.caption}

        )}

    </button>
  )
}

const UsersAutocomplete = () => {
  const [term, setTerm] = useState('')
  const [loading, setLoading] = useState(false)
  const [lastSearched, setLastSearched] = useState([])
  const timeoutRef = useRef(null)

  const options = {
    onSelect: (...args) => console.log('onSelect: ', ...args),
    loading,
    value: !term.length
      ? []
      : allUsers.filter(user =>
          typeof user === 'string'
            ? user.toLowerCase().includes(term.toLowerCase())
            : user.label.toLowerCase().includes(term.toLowerCase())
        ),
    lastSearched: {
      value: lastSearched,
      label: 'Last searched users',
      onChange: option =>
        option && setLastSearched(uniq([...lastSearched, option])),
    },
    // --- This is what makes the custom option work!
    renderOption: props => <CustomOption {...props} />,
  }

  const input = {
    onChange: term => {
      if (term) {
        setLoading(true)
        if (timeoutRef.current) {
          clearTimeout(timeoutRef.current)
        }
        timeoutRef.current = setTimeout(() => {
          setLoading(false)
          setTerm(term)
          timeoutRef.current = null
        }, 1000)
      } else {
        setTerm(term)
      }
    },
    onSearch: (...args) => console.log('onSearch:', ...args),
    onClear: () => setTerm(''),
    placeholder: 'Search user... (e.g.: Ana)',
    value: term,
  }
  return <AutocompleteInput input={input} options={options} />
}

;<UsersAutocomplete />
```

```


[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/Styleguide/components/AutocompleteInput/hooks.ts from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { useState, useEffect } from 'react'

export const useClickOutside = (
  ref: React.RefObject<HTMLElement> | null,
  onClickOutside: (e: Event) => void
) => {
  const handleClickOutside = (e: Event) => {
    if (
      ref &&
      ref.current &&
      e.target instanceof Node &&
      !ref.current.contains(e.target)
    ) {
      onClickOutside(e)
    }
  }

  useEffect(() => {
    // Bind the event listener
    document.addEventListener('mousedown', handleClickOutside)
    return () => {
      // Unbind the event listener on clean up
      document.removeEventListener('mousedown', handleClickOutside)
    }
  })
}

export const useArrowNavigation = (
  ref: React.RefObject<HTMLElement> | null,
  optionsLength: number,
  initialSelectedOptionIndex: number
): [number, (index: number) => void] => {
  const [selectedOptionIndex, setSelectedOptionIndex] = useState(
    initialSelectedOptionIndex
  )

  const handleKeyDown = (e: KeyboardEvent) => {
    if (
      ref &&
      ref.current &&
      e.target instanceof Node &&
      ref.current.contains(e.target)
    ) {
      let index
      switch (e.key) {
        case 'ArrowUp':
          e.preventDefault()
          index = Math.max(selectedOptionIndex - 1, initialSelectedOptionIndex)
          return setSelectedOptionIndex(index)
        case 'ArrowDown':
          e.preventDefault()
          index = Math.min(selectedOptionIndex + 1, optionsLength - 1)
          return setSelectedOptionIndex(index)
        default:
          return
      }
    }
  }

  useEffect(() => {
    // Bind the event listener
    document.addEventListener('keydown', handleKeyDown)
    return () => {
      // Unbind the event listener on clean up
      document.removeEventListener('keydown', handleKeyDown)
    }
  })

  return [selectedOptionIndex, setSelectedOptionIndex]
}

```


[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/Styleguide/components/EmptyState/index.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'

class EmptyState extends PureComponent {
  render() {
    const { title, children, testId } = this.props

    return (
      <div
        className="MAIN br3 flex c-muted-2 justify-center pv9 ph6 ph9-l tc"
        data-testid={testId}>
        <div className="w-80 w-50-l">
          {title && <span className="t-heading-3 mt0 mt0">{title}</span>}
          {children && <div className="t-body lh-copy">{children}</div>}
        </div>
      </div>
    )
  }
}

EmptyState.propTypes = {
  /** Title of the component (String) */
  title: (props, propName, componentName) => {
    if (!props.title && !props.children) {
      return new Error(
        `Prop 'title' or 'children' was not specified in '${componentName}'.`
      )
    }
  },
  /** node */
  children: (props, propName, componentName) => {
    if (!props.title && !props.children) {
      return new Error(
        `Prop 'title' or 'children' was not specified in '${componentName}'.`
      )
    }
  },
  /** Data attribute */
  testId: PropTypes.string,
}

export default EmptyState

```


[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/Styleguide/components/EmptyState/README.md from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```markdown
#### An Empty State shows _something_ when there's nothing to show. Instead of leaving the user with a blank space, it explains what should be there and encourage to take an appropriate action.

### 👍 Dos
- Guide the user to what should be done to populate that screen, either if it's an empty search result or onboarding of a new product feature.
- Although its parts (heading, body and call-to-action) are all optional, do try to use most of them.
- You may use as a call-to-action whatever makes more sense to you: a button, a link, etc.
- Do use an illustration or icon if it's very important for your product to delight the user at this step.

### 👎 Don'ts
- Don't use informal language. An empty state might be a break in the user expectations, so it's not the time to be funny. But do try to be friendly and instructive.
- Don't reuse the same copy for empty search results and empty application states.

```js
const Button = require('../Button').default

;

  <EmptyState title="A big headline">

      A longer explanation of what should be here, and why should I care about
      what should be here.

      <Button variation="secondary" size="small">
        Suggested action
      </Button>

  </EmptyState>

```

```


[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/Styleguide/components/Textarea/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'

class Textarea extends Component {
  constructor(props) {
    super(props)

    this.state = {
      active: false,
    }
  }

  static CharacterCountdown = props => {
    let classes = 't-small mt2 lh-title '
    if (props.value <= 10) {
      classes += 'c-danger'
    } else {
      classes += 'c-muted-1'
    }
    return (
      <div className={classes}>
        {props.value} {props.text}
      </div>
    )
  }

  handleChange = event => {
    this.props.onChange && this.props.onChange(event)
  }

  handleFocus = event => {
    this.setState({ active: true })
    this.props.onFocus && this.props.onFocus(event)
  }

  handleBlur = event => {
    this.setState({ active: false })
    this.props.onBlur && this.props.onBlur(event)
  }

  render() {
    const {
      errorMessage,
      error,
      label,
      helpText,
      dataAttributes,
      children,
      maxLength,
      resize,
      size,
    } = this.props
    const { active } = this.state

    const dataAttrs = {}
    for (const key of Object.keys(dataAttributes)) {
      dataAttrs[`data-${key}`] = dataAttributes[key]
    }

    const widthClass = 'w-100'
    const box = 'ma0 border-box'
    const border = 'bw1 br2 b--solid outline-0'
    const typography = 'c-on-base t-small'
    const padding = 'pv3 ph5'

    let classes = `${widthClass} ${box} ${padding} ${border} ${typography} `
    let labelClasses = `vtex-textarea__label db mb3 w-100 `

    if (active) {
      classes += 'b--muted-2 '
    } else if (!error && !errorMessage) {
      classes += 'b--muted-4 '
      if (!this.props.disabled) {
        classes += 'hover-b--muted-3 '
      }
    }

    if (error || errorMessage) {
      classes += 'b--danger hover-b--danger '
    }

    if (this.props.disabled) {
      classes += 'bg-disabled b--disabled c-disabled '
    } else {
      classes += 'bg-base '
    }

    switch (size) {
      case 'small':
        classes += 't-small '
        labelClasses += 't-small '
        break

      case 'large':
        classes += 't-body '
        labelClasses += 't-body '
        break

      default:
        classes += 't-body '
        labelClasses += 't-body '
        break
    }

    return (
      <label className="vtex-textarea">
        {label && <span className={labelClasses}>{label}</span>}
        <textarea
          {...dataAttrs}
          onBlur={this.handleBlur}
          onFocus={this.handleFocus}
          onChange={this.handleChange}
          className={classes}
          autoComplete={this.props.autoComplete}
          autoFocus={this.props.autoFocus}
          disabled={this.props.disabled}
          maxLength={this.props.maxLength}
          minLength={this.props.minLength}
          name={this.props.name}
          placeholder={this.props.placeholder}
          readOnly={this.props.readOnly}
          required={this.props.required}
          spellCheck={this.props.spellCheck}
          id={this.props.id}
          rows={this.props.rows}
          defaultValue={this.props.defaultValue}
          value={this.props.value}
          style={{ resize, WebkitAppearance: 'none' }}>
          {children}
        </textarea>

        <div className="flex justify-between">
          <div>
            {errorMessage && (
              <div className="c-danger t-small mt2 lh-title">
                {errorMessage}
              </div>
            )}
            {helpText && (
              <div className="c-muted-1 t-small mt2 lh-title">{helpText}</div>
            )}
          </div>
          {maxLength && (
            <Textarea.CharacterCountdown
              value={this.props.maxLength - this.props.value.length}
              text={this.props.characterCountdownText}
            />
          )}
        </div>
      </label>
    )
  }
}

Textarea.defaultProps = {
  autoFocus: false,
  dataAttributes: {},
  disabled: false,
  label: '',
  readOnly: false,
  resize: 'both',
  size: 'regular',
  error: false,
  characterCountdownText: 'characters left',
  rows: 5,
}

Textarea.propTypes = {
  /** Content of the textarea */
  children: PropTypes.string,
  /* Size of the textarea */
  size: PropTypes.oneOf(['small', 'regular', 'large']),
  /** Controlled content of the textarea */
  value: PropTypes.string,
  /** Default content of the textarea */
  defaultValue: PropTypes.string,
  /** Error highlight */
  error: PropTypes.bool,
  /** Error message */
  errorMessage: PropTypes.string,
  /** Help text */
  helpText: PropTypes.node,
  /** Label */
  label: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
  /** Spec attribute */
  autoComplete: PropTypes.string,
  /** Spec attribute */
  autoFocus: PropTypes.bool,
  /** Spec attribute */
  disabled: PropTypes.bool,
  /** Spec attribute */
  id: PropTypes.string,
  /** If defined, the textarea will have a character countdown at the bottom right */
  maxLength: PropTypes.string,
  /** Spec attribute */
  minLength: PropTypes.string,
  /** Spec attribute */
  name: PropTypes.string,
  /** Spec attribute */
  placeholder: PropTypes.string,
  /** Spec attribute */
  readOnly: PropTypes.bool,
  /** Spec attribute */
  required: PropTypes.string,
  /** Controls if Textarea is resizable and the resize direction. */
  resize: PropTypes.oneOf(['both', 'horizontal', 'none', 'vertical']),
  /** Spec attribute */
  rows: PropTypes.number,
  /** Spec attribute */
  spellCheck: PropTypes.string,
  /** Spec attribute */
  wrap: PropTypes.string,
  /** List of data attributes as a object like `{'locale': 'en-US'}` */
  dataAttributes: PropTypes.object,
  /** onChange event */
  onChange: PropTypes.func,
  /** onFocus event */
  onFocus: PropTypes.func,
  /** onBlur event */
  onBlur: PropTypes.func,
  /** Helper text for character countdown (X characters left) */
  characterCountdownText: PropTypes.string,
}

export default Textarea

```


[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/Styleguide/components/Textarea/README.md from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```markdown
```js
initialState = {
  value: '',
}
;

    <Textarea label="With a label">I haz content</Textarea>

    <Textarea disabled label="Disabled">
      Cant touch this!
    </Textarea>

    <Textarea
      label="With helper"
      helpText={Your help text goes here!}
    />

    <Textarea label="With error" error errorMessage="Somehow wrong" />

    <Textarea
      label="Controlling text (no spaces) with character countdown"
      onChange={e => setState({ value: e.target.value.trim() })}
      value={state.value}
      maxLength="100"
      helpText="You can have helper text alongside the countdown."
    />

```
```


[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/Styleguide/components/FilterOptions/index.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import find from 'lodash/find'
import head from 'lodash/head'

import FilterColapsible from './FilterColapsible'

class FilterOptions extends PureComponent {
  handleStatementChange = statement => {
    const { statements } = this.props
    const { subject } = statement
    const filteredStatements = statements.filter(st => st.subject !== subject)
    this.props.onChangeStatements([...filteredStatements, statement])
  }

  extractStatement = (statements, subject) =>
    find(statements, st => st.subject === subject)

  createEmptyStatement = (subject, options) => {
    const availableVerbs =
      options && options[subject] ? options[subject].verbs : []
    const verb = head(availableVerbs) ? head(availableVerbs).value : null
    return {
      subject,
      verb,
      object: null,
      error: null,
    }
  }

  render() {
    const { options, statements } = this.props
    const optionsKeys = Object.keys(options)
    return (
      optionsKeys.length > 0 && (
        <div className={'flex flex-column'}>
          {optionsKeys.map(subject => {
            const statement =
              this.extractStatement(statements, subject) ||
              this.createEmptyStatement(subject, options)
            return (
              <div key={subject} className="ma2">
                <FilterColapsible
                  subject={subject}
                  options={options}
                  statement={statement}
                  onChangeStatement={this.handleStatementChange}
                  beginWithOpenCollapsibles={optionsKeys.length <= 3}
                />
              </div>
            )
          })}
        </div>
      )
    )
  }
}

FilterOptions.defaultProps = {
  options: [],
}

FilterOptions.propTypes = {
  /** filter options (mirroring statements from Conditions component) */
  options: PropTypes.objectOf(
    PropTypes.shape({
      label: PropTypes.string,
      verbs: PropTypes.array.isRequired,
    })
  ).isRequired,
  /** filter statements (mirroring statements from Conditions component) */
  statements: PropTypes.arrayOf(
    PropTypes.shape({
      subject: PropTypes.string,
      verb: PropTypes.string.isRequired,
      object: PropTypes.any,
      error: PropTypes.any,
    })
  ),
  /** Filters change callback: returns array of statement definitions */
  onChangeStatements: PropTypes.func.isRequired,
}

export default FilterOptions

```