[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 slider/react/SliderContainer.js from the slider VTEX app.

[Assistant]
Here's the implementation:

```javascript
import SliderContainer from './components/SliderContainer'

export default SliderContainer

```


[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 slider/react/Slider.js from the slider VTEX app.

[Assistant]
Here's the implementation:

```javascript
import Slider from './components/Slider'

export default Slider

```


[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 slider/react/utils/resolveSlidesNumber.js from the slider VTEX app.

[Assistant]
Here's the implementation:

```javascript
/**
 * This function returns the number of slides to show depending on the size of the window.
 * If you pass a number it just returns that number.
 * If you pass an object it will return the number of slides of the closest breakpoint to the size of the window.
 * If you pass for example
 * perPage = {
 *   400: 2,
 *   1000: 3
 * }
 *
 * If the size of the window is something between 400px and 999px if will return 2,
 * if it is 1000px or bigger, it will return 3, and if it is smaller than 400px it
 * will return the default value; that is, 1.
 * @param {number|object} perPage
 * @param {number|undefined} minPerPage
 */
function resolveSlidesNumber(minPerPage, perPage, isMobile) {
  let result = minPerPage || 1
  if (typeof perPage === 'number') {
    result = perPage
  } else if (typeof perPage === 'object') {
    const innerWidth = window && window.innerWidth

    /** If it's on SSR, use placeholder screen sizes to get an approximate
     * guess of how many items are displayed per page */
    const windowSize = innerWidth || (isMobile ? 320 : 1024)

    for (const viewport in perPage) {
      if (windowSize >= viewport) {
        result = perPage[viewport]
      }
    }
  }
  return result < minPerPage ? minPerPage : result
}

export default resolveSlidesNumber

```


[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 slider/react/utils/index.js from the slider VTEX app.

[Assistant]
Here's the implementation:

```javascript
export function setStyle(target, styles) {
  Object.keys(styles).forEach(attr => {
    target.style[attr] = styles[attr]
  })
}

function getZeroOrString(num = 0) {
  return num === 0 ? num : `${num}%`
}

export function getTranslateProperty(x = 0, y = 0, z = 0) {
  return {
    transform: `translate3d(${getZeroOrString(x)}, ${getZeroOrString(
      y
    )}, ${getZeroOrString(z)})`,
    WebkitTransform: `translate3d(${getZeroOrString(x)}, ${getZeroOrString(
      y
    )}, ${getZeroOrString(z)})`,
  }
}

export function getStylingTransition(easing, duration = 0) {
  return {
    WebkitTransition: `all ${duration}ms ${easing}`,
    transition: `all ${duration}ms ${easing}`,
  }
}

export const constants = {
  defaultResizeDebounce: 250,
  defaultTransitionDuration: 250,
  NAVIGATION_PAGE: 'page',
}

```


[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 slider/react/components/styles.css from the slider VTEX app.

[Assistant]
Here's the implementation:

```css
.slideImg {
  margin-right: -50%;
  transform: translate(-50%, -50%);
  left: 50%;
  top: 50%;
}

.dotsContainer {
  margin-right: -50%;
  transform: translate(-50%, 0);
  left: 50%;
}

.arrowContainer {
  top: 50%;
  transform: translate(0, -50%);
}

.sliderFrame {
  will-change: transform;
}

```


[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 slider/react/components/Dots.js from the slider VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
import debounce from 'debounce'
import EventListener from 'react-event-listener'
import { constants } from '../utils'
import resolveSlidesNumber from '../utils/resolveSlidesNumber'
import styles from './styles.css'

class Dots extends PureComponent {
  static propTypes = {
    /** Classes to style the elements fo the component */
    classes: PropTypes.shape({
      root: PropTypes.string,
      dot: PropTypes.string,
      activeDot: PropTypes.string,
      notActiveDot: PropTypes.string,
    }),
    /** Current slide on the screen, if you have perPage > 1, then the current slide is the most left slide on the screen */
    currentSlide: PropTypes.number,
    /** Extra props to be applied to the dot element */
    dotProps: PropTypes.object,
    /** The size of the dots, can be a number (in this case it will use px unit), or a string (you have to pass the number with the unit e.g '3rem') */
    dotSize: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    /** Tag to be rendered in the dot element */
    dotTag: PropTypes.string,
    /** If the slides should be looping */
    loop: PropTypes.bool,
    /** Function to change the currentSlide */
    onChangeSlide: PropTypes.func.isRequired,
    /** This prop works the same way the minPerPage of Slider and this component should receive the same value of Slider */
    minPerPage: PropTypes.number,
    /** This prop works the same way the perPage of Slider and this component should receive the same value of Slider */
    perPage: PropTypes.oneOfType([PropTypes.number, PropTypes.object]),
    /** Debounce time in milliseconds. */
    resizeDebounce: PropTypes.number,
    /** Tag of root element of the component to be rendered */
    rootTag: PropTypes.string,
    /** Total value of sliders that will be rendered */
    totalSlides: PropTypes.number.isRequired,
    /** If this flag is true, then every dot represent a page of slides (e.g. if perPage = 2 and you have 4 elements,
     * then you have 2 dots), if false, then it will render a dot to every slide */
    showDotsPerPage: PropTypes.bool,
  }

  static defaultProps = {
    classes: {
      root: '',
      dot: '',
      activeDot: '',
      notActiveDot: '',
    },
    dotTag: 'li',
    loop: false,
    perPage: 1,
    rootTag: 'ul',
    showDotsPerPage: false,
    resizeDebounce: constants.defaultResizeDebounce,
  }

  constructor(props) {
    super(props)

    this.handleResize = debounce(this._setPerPageOnResize, props.resizeDebounce)
  }

  get slideIndeces() {
    const { showDotsPerPage, totalSlides } = this.props
    return this.perPage
      ? [
          ...Array(
            showDotsPerPage
              ? Math.ceil(totalSlides / this.perPage)
              : totalSlides
          ).keys(),
        ]
      : []
  }

  get selectedDot() {
    const { showDotsPerPage, currentSlide, loop } = this.props
    const realCurrentSlide = loop ? currentSlide - this.perPage : currentSlide
    return showDotsPerPage
      ? Math.floor(realCurrentSlide / this.perPage)
      : realCurrentSlide
  }

  handleDotClick = index => {
    const { showDotsPerPage, onChangeSlide, loop } = this.props
    const slideToGo = showDotsPerPage ? index * this.perPage : index
    onChangeSlide(loop ? slideToGo + this.perPage : slideToGo)
  }

  componentWillUnmount() {
    this.handleResize.clear()
  }

  _setPerPageOnResize = () => {
    const { minPerPage, perPage } = this.props
    this.perPage = resolveSlidesNumber(minPerPage, perPage)
    this.forceUpdate()
  }

  render() {
    const {
      rootTag: RootTag,
      dotTag: DotTag,
      classes: classesProp,
      dotProps,
      minPerPage,
      perPage,
      totalSlides,
      dotSize,
    } = this.props

    const classes = {
      ...Dots.defaultProps.classes,
      ...classesProp,
    }

    if (totalSlides < 2) {
      return null
    }

    if (!this.perPage) {
      this.perPage = resolveSlidesNumber(minPerPage, perPage)
    }

    return (
      <RootTag
        className={classnames(
          styles.dotsContainer,
          classes.root,
          'absolute ma0 pa0 dib list'
        )}
      >
        <EventListener target="window" onResize={this.handleResize} />
        {this.slideIndeces.map(i => {
          const dotClasses = classnames(classes.dot, 'dib', {
            [classes.activeDot]: i === this.selectedDot,
            [classes.notActiveDot]: i !== this.selectedDot,
          })

          return (
            <DotTag
              className={dotClasses}
              key={i}
              onClick={() => this.handleDotClick(i)}
              {...{ style: { height: dotSize, width: dotSize } }}
              {...dotProps}
            />
          )
        })}
      </RootTag>
    )
  }
}

export default Dots

```


[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 slider/react/components/Slide.js from the slider VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { PureComponent } from 'react'
import EventListener from 'react-event-listener'
import classnames from 'classnames'
import PropTypes from 'prop-types'
import debounce from 'debounce'
import styles from './styles.css'
import { constants } from '../utils'

class SlideComponent extends PureComponent {
  constructor(props) {
    super(props)
    this.imgRef = React.createRef()
    this.handleResize = debounce(() => {
      setTimeout(() => {
        this.fit()
      }, props.sliderTransitionDuration)
    }, props.resizeDebounce)

    this.state = {
      firstRender: true
    }
  }

  componentDidMount() {
    this.ensureImageCover()
    this.setState({ firstRender: false })
  }

  componentDidUpdate() {
    this.ensureImageCover()
  }

  componentWillUnmount() {
    this.handleResize.clear()
  }

  fit = () => {
    const { current: imgElement } = this.imgRef

    if (!imgElement || !imgElement.complete) {
      return
    }

    const imgAspectRatio = imgElement.width / imgElement.height
    const parentAspectRatio = imgElement.parentNode.offsetWidth / imgElement.parentNode.offsetHeight

    if (imgAspectRatio > parentAspectRatio) {
      imgElement.classList.remove('w-100')
      imgElement.classList.add('h-100')
    } else {
      imgElement.classList.remove('h-100')
      imgElement.classList.add('w-100')
    }
    imgElement.removeEventListener('load', this.fit)
  }

  ensureImageCover = () => {
    const { current: imgElement } = this.imgRef
    if (!imgElement || !this.props.fitImg) {
      return
    }

    if (imgElement.complete) {
      this.fit()
    } else {
      imgElement.addEventListener('load', this.fit)
    }
  }

  render() {
    const {
      children,
      className,
      tag: RootComponent,
      fitImg,
      innerRef,
      resizeDebounce,
      defaultWidth,
      style,
      sliderTransitionDuration,
      ...rootProps
    } = this.props

    return (
      <RootComponent
        ref={innerRef}
        className={classnames(className, 'inline-flex h-100 relative overflow-hidden')}
        style={{ ...style }}
        {...rootProps}
      >
        <EventListener target="window" onResize={this.handleResize} />
        {React.Children.map(children, child => {
          if (!React.isValidElement(child)) {
            return null
          }
          if (fitImg && child.type === 'img') {
            return React.cloneElement(child, {
              ref: this.imgRef,
              className: classnames(styles.slideImg, child.props.className, 'absolute')
            })
          }

          return child
        })}
      </RootComponent>
    )
  }
}

const renderForwardRef = (props, ref) => <SlideComponent innerRef={ref} {...props} />

renderForwardRef.displayName = 'Slide'

const Slide = React.forwardRef(renderForwardRef)

Slide.propTypes = {
  /** Node to render */
  children: PropTypes.node.isRequired,
  /** Classes to pass to root of slider */
  className: PropTypes.string,
  /** Default width of root in px */
  defaultWidth: PropTypes.number,
  /** Tag to be rendered in root element */
  tag: PropTypes.string,
  /** If the slide component should try to fit the img (only works if children is an img element) */
  fitImg: PropTypes.bool,
  /** Time of debounce of resize event listener */
  resizeDebounce: PropTypes.number,
  /** Duration of transition passed to Slider (must be the same), if nothing is passed to any of the components
   * it will apply the same default value
   */
  sliderTransitionDuration: PropTypes.number
}

Slide.defaultProps = {
  tag: 'li',
  fitImg: true,
  resizeDebounce: constants.defaultResizeDebounce,
  sliderTransitionDuration: constants.defaultTransitionDuration
}

export default Slide

```


[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 slider/react/components/SliderContainer.js from the slider VTEX app.

[Assistant]
Here's the implementation:

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

class SliderContainerComponent extends PureComponent {
  timeoutRef = null

  setNewTimeout = () => {
    const { autoplay, autoplayInterval, onNextSlide } = this.props

    if (
      !autoplay ||
      typeof autoplayInterval !== 'number' ||
      autoplayInterval === 0
    ) {
      return
    }

    if (this.timeoutRef) {
      clearTimeout(this.timeoutRef)
    }

    this.timeoutRef = setTimeout(() => {
      if (onNextSlide) {
        onNextSlide()
      }

      this.setNewTimeout()
    }, autoplayInterval)
  }

  componentDidMount() {
    if (this.props.autoplay && this.props.autoplayInterval > 0) {
      this.setNewTimeout()
    }
  }

  componentWillUnmount() {
    clearTimeout(this.timeoutRef)
  }

  eventProcedure = (e, eventCallback, clearOnPause = true) => {
    const { pauseOnHover } = this.props
    if (pauseOnHover) {
      clearOnPause ? clearTimeout(this.timeoutRef) : this.setNewTimeout()
    }
    if (eventCallback) {
      eventCallback(e)
    }
  }

  handleTouchStart = e => {
    this.eventProcedure(e, this.props.onTouchStart)
  }

  handleTouchEnd = e => {
    this.eventProcedure(e, this.props.onTouchEnd, false)
  }

  handleMouseEnter = e => {
    this.eventProcedure(e, this.props.onMouseEnter)
  }

  handleMouseLeave = e => {
    this.eventProcedure(e, this.props.onMouseLeave, false)
  }

  render() {
    const {
      className,
      children,
      tag: RootTag,
      innerRef,
      ...otherProps
    } = this.props

    return (
      <RootTag
        ref={innerRef}
        className={classnames(className, 'relative')}
        onMouseEnter={this.handleMouseEnter}
        onMouseLeave={this.handleMouseLeave}
        onTouchStart={this.handleTouchStart}
        onTouchEnd={this.handleTouchEnd}
        {...otherProps}
      >
        {children}
      </RootTag>
    )
  }
}

const renderForwardRef = (props, ref) => (
  <SliderContainerComponent innerRef={ref} {...props} />
)
renderForwardRef.displayName = 'SliderContainer'
const SliderContainer = React.forwardRef(renderForwardRef)

SliderContainer.propsTypes = {
  /** If the slider should be passing automatically */
  autoplay: PropTypes.boolean,
  /** Time in milliseconds of the interval to pass from a slider to the next one */
  autoplayInterval: PropTypes.number,
  /** Children of the component to render */
  children: PropTypes.node.isRequired,
  /** Classes to be applied to the root element */
  className: PropTypes.string,
  /** Function to go to the next slide */
  onNextSlide: PropTypes.func,
  /** If the interval should not be executed if the mouse is on the component */
  pauseOnHover: PropTypes.boolean,
  /** Tag to render the component */
  tag: PropTypes.string,
}

SliderContainer.defaultProps = {
  autoplay: false,
  autoplayInterval: 5000,
  pauseOnHover: true,
  tag: 'div',
}

export default SliderContainer

```


[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 slider/react/components/Slider.js from the slider VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { PureComponent, Fragment } from 'react'
import debounce from 'debounce'
import classnames from 'classnames'
import PropTypes from 'prop-types'
import EventListener from 'react-event-listener'
import styles from './styles.css'
import resolveSlidesNumber from '../utils/resolveSlidesNumber'
import { withDevice } from 'vtex.device-detector'

import {
  getStylingTransition,
  getTranslateProperty,
  setStyle,
  constants,
} from '../utils'

class Slider extends PureComponent {
  static propTypes = {
    /** A render function that will receive as props an orientation prop
     * and a onClick callback */
    arrowRender: PropTypes.func,
    /** The component used to contain both arrows.
     * Either a string to use a DOM element or a component.
     */
    arrowsContainerComponent: PropTypes.oneOfType([
      PropTypes.func,
      PropTypes.string,
    ]),
    /** The slides to render */
    children: PropTypes.oneOfType([
      PropTypes.element,
      PropTypes.arrayOf(PropTypes.element),
    ]),
    /** Classes to apply to the Slider elements */
    classes: PropTypes.shape({
      root: PropTypes.string,
      sliderFrame: PropTypes.string,
    }),
    /** Current slide on the screen (if you have perPage > 1, then the current slide is the most left slide on the screen) */
    currentSlide: PropTypes.number,
    /** Css value of cursor when mouse is hovering the slider frame */
    cursor: PropTypes.string,
    /** Css value of cursos when mouse is down */
    cursorOnMouseDown: PropTypes.string,
    // TODO draggable: PropTypes.bool,
    /** Duration of transitions */
    duration: PropTypes.number,
    /** Transition function */
    easing: PropTypes.string,
    /** If the slides should be looping */
    loop: PropTypes.bool,
    /** Function to change the value of currentSlide */
    onChangeSlide: PropTypes.func.isRequired,
    /** Minimum amount of slides to be on the screen */
    minPerPage: PropTypes.number,
    /** Amount of slides to be on the screen, if a number is passed, then thats the slides that will be shown,
     * if an object with breakpoints is passed, then the component will check the size of the screen to see how
     * many elements will be on the screen
     */
    perPage: PropTypes.oneOfType([PropTypes.number, PropTypes.object]),
    /** Resize debounce timer in milliseconds */
    resizeDebounce: PropTypes.number,
    /** Tag to be rendered in the root element of the page */
    rootTag: PropTypes.string,
    /** Tag to be rendered in the slider frame */
    sliderFrameTag: PropTypes.string,
    /** Threshold of pixels to drag to the slider let it go to the next/prev slide */
    threshold: PropTypes.number,
    /** If should scroll by page or one item at a time */
    scrollByPage: PropTypes.bool,
    /** Check if on mobile using vtex.device-detector */
    isMobile: PropTypes.bool,
    draggable: PropTypes.bool,
    navigationStep: PropTypes.oneOfType([
      PropTypes.oneOf([constants.NAVIGATION_PAGE]),
      PropTypes.number,
    ]),
  }

  static defaultProps = {
    classes: {
      root: '',
      sliderFrame: '',
    },
    currentSlide: 0,
    cursor: 'default',
    cursorOnMouseDown: 'default',
    draggable: false,
    duration: 250,
    easing: 'ease-out',
    loop: false,
    perPage: 1,
    resizeDebounce: constants.defaultResizeDebounce,
    rootTag: 'div',
    showArrows: false,
    sliderFrameTag: 'ul',
    threshold: 50,
    scrollByPage: false,
    navigationStep: 'page',
  }

  static events = [
    'onTouchStart',
    'onTouchEnd',
    'onTouchMove',
    'onMouseUp',
    'onMouseDown',
    'onMouseLeave',
    'onMouseMove',
  ]

  static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.currentSlide !== prevState.currentSlide) {
      const { currentSlide, children } = nextProps
      const perPage = resolveSlidesNumber(
        nextProps.minPerPage,
        nextProps.perPage,
        nextProps.isMobile
      )
      const currentSlideIsClone =
        currentSlide < perPage ||
        currentSlide >= React.Children.count(children) + perPage
      return {
        currentSlide: currentSlideIsClone
          ? prevState.currentSlide
          : currentSlide,
        enableTransition: !currentSlideIsClone,
      }
    }

    return null
  }

  constructor(props) {
    super(props)

    this.drag = {
      startX: 0,
      endX: 0,
      startY: 0,
      letItGo: null,
    }

    this._selector = React.createRef()
    this._sliderFrame = React.createRef()
    this._sliderFrameWidth = null
    this._selectorWidth = null
    this.handleResize = debounce(this.fit, props.resizeDebounce)
    this.perPage = resolveSlidesNumber(
      props.minPerPage,
      props.perPage,
      props.isMobile
    )

    this.state = {
      firstRender: true,
      currentSlide: props.currentSlide,
      enableTransition: false,
      dragDistance: 0,
    }
  }

  componentDidMount() {
    const { onChangeSlide, currentSlide, loop } = this.props
    let stateCurrentSlide = currentSlide
    if (loop) {
      if (this.isNegativeClone(currentSlide)) {
        onChangeSlide(currentSlide + this.perPage)
        stateCurrentSlide += this.perPage
      } else if (this.isPositiveClone(currentSlide)) {
        const mirrorIndex =
          this.childrenLength + this.perPage - currentSlide - 1
        onChangeSlide(mirrorIndex)
      }
    }
    this.setState({
      firstRender: false,
      currentSlide: stateCurrentSlide,
    })
  }

  componentWillUnmount() {
    this.handleResize.clear()
  }

  componentDidUpdate() {
    const newState = {
      currentSlide: this.state.currentSlide,
      dragDistance: 0,
      enableTransition: true,
    }

    if (this.props.currentSlide !== this.state.currentSlide) {
      const { currentSlide } = this.state
      const { onChangeSlide } = this.props
      if (this.isNegativeClone(currentSlide)) {
        newState.currentSlide = currentSlide + this.perPage
        onChangeSlide(newState.currentSlide)
      } else if (this.isPositiveClone(currentSlide)) {
        newState.currentSlide = this.totalSlides - currentSlide
        onChangeSlide(newState.currentSlide)
      } else {
        onChangeSlide(currentSlide)
      }
      this.setState(newState)
    } else if (this.state.dragDistance) {
      this.setState(newState)
    }

    this.setInnerElements()
    this.perPage = resolveSlidesNumber(
      this.props.minPerPage,
      this.props.perPage,
      this.props.isMobile
    )
    this.resetWidthCalculation()
  }

  /** Marks _selectorWidth and _sliderFrameWidth as "dirty", in order
   * to let the getters know that they need to be recalculated.
   * This is done for performance, to avoid triggering a layout
   * recalculation before needed.
   */
  resetWidthCalculation = () => {
    this._selectorWidth = null
    this._sliderFrameWidth = null
  }

  getSliderFrameWidth = () => {
    if (!this._sliderFrameWidth) {
      this._sliderFrameWidth = this._sliderFrame.current.getBoundingClientRect().width
    }
    return this._sliderFrameWidth
  }

  getSelectorWidth = () => {
    if (!this._selectorWidth) {
      this._selectorWidth = this._selector.current.getBoundingClientRect().width
    }
    return this._selectorWidth
  }

  isNegativeClone = index => {
    return index < this.perPage
  }

  isPositiveClone = index => {
    return index >= this.childrenLength + this.perPage
  }

  getNegativeClone = index => {
    return index - this.childrenLength
  }

  getPositiveClone = index => {
    return index + this.childrenLength
  }

  fit = () => {
    const { minPerPage, perPage, currentSlide, onChangeSlide } = this.props
    this.perPage = resolveSlidesNumber(minPerPage, perPage, this.props.isMobile)
    const newCurrentSlide =
      Math.floor(currentSlide / this.perPage) * this.perPage

    this.resetWidthCalculation()

    if (currentSlide !== newCurrentSlide) {
      this.setState({
        currentSlide: newCurrentSlide,
        enableTransition: false,
      })
      onChangeSlide(newCurrentSlide)
    }
    this.forceUpdate()
  }

  setInnerElements = () => {
    this.innerElements = Array.prototype.slice.call(
      this._sliderFrame.current.children
    )
  }

  get totalSlides() {
    const { children } = this.props

    if (children) {
      const totalChildren = React.Children.count(children)
      return totalChildren + (this.shouldAddClones ? 2 * this.perPage : 0)
    }

    return 0
  }

  get childrenLength() {
    return this.props.children ? React.Children.count(this.props.children) : 0
  }

  prev = (howManySlides = 1, dragDistance = 0) => {
    const howManyInt = Number.parseInt(howManySlides)
    const { onChangeSlide, currentSlide, loop } = this.props
    let newCurrentSlide = Number.parseInt(currentSlide)
    let stateCurrentSlide
    let enableTransition = true

    if (this.totalSlides <= this.perPage) {
      return
    }

    if (loop) {
      if (this.isNegativeClone(currentSlide - howManyInt)) {
        newCurrentSlide = this.getPositiveClone(currentSlide)
        enableTransition = false
        stateCurrentSlide = newCurrentSlide - howManyInt
      } else {
        newCurrentSlide = currentSlide - howManyInt
        stateCurrentSlide = newCurrentSlide
      }
    } else {
      newCurrentSlide = Math.max(currentSlide - howManyInt, 0)
      stateCurrentSlide = newCurrentSlide
    }

    if (newCurrentSlide !== currentSlide) {
      this.setState({
        enableTransition,
        currentSlide: stateCurrentSlide,
        dragDistance,
      })
      onChangeSlide(newCurrentSlide)
    }
  }

  next = (howManySlides = 1, dragDistance = 0) => {
    const howManyInt = Number.parseInt(howManySlides)
    const { onChangeSlide, currentSlide, loop } = this.props
    let newCurrentSlide = Number.parseInt(currentSlide)
    let stateCurrentSlide
    let enableTransition = true

    if (this.totalSlides <= this.perPage) {
      return
    }

    if (loop) {
      if (this.isPositiveClone(currentSlide + howManyInt)) {
        newCurrentSlide = this.getNegativeClone(currentSlide)
        enableTransition = false
        stateCurrentSlide = newCurrentSlide + howManyInt
      } else {
        newCurrentSlide = currentSlide + howManyInt
        stateCurrentSlide = newCurrentSlide
      }
    } else {
      newCurrentSlide = Math.min(
        currentSlide + howManyInt,
        this.totalSlides - this.perPage
      )
      stateCurrentSlide = newCurrentSlide
    }

    if (newCurrentSlide !== currentSlide) {
      this.setState({
        enableTransition,
        currentSlide: stateCurrentSlide,
        dragDistance,
      })
      onChangeSlide(newCurrentSlide)
    }
  }

  prevPage = () => {
    this.prev(this.perPage)
  }

  nextPage = () => {
    this.next(this.perPage)
  }

  updateAfterDrag = () => {
    const { threshold } = this.props
    const movement = this.drag.endX - this.drag.startX
    const movementDistance = Math.abs(movement)
    const howManySlidesToSlide = Math.ceil(
      movementDistance / (this.getSelectorWidth() / this.perPage)
    )
    const dragDistance = (movement / this.getSliderFrameWidth()) * 100
    if (
      movement > 0 &&
      movementDistance > threshold &&
      this.totalSlides > this.perPage
    ) {
      this.prev(howManySlidesToSlide, dragDistance)
    } else if (
      movement < 0 &&
      movementDistance > threshold &&
      this.totalSlides > this.perPage
    ) {
      this.next(howManySlidesToSlide, dragDistance)
    } else {
      const { easing, duration, currentSlide } = this.props

      this.setState({ enableTransition: true, dragDistance: 0 })
      setStyle(this._sliderFrame.current, {
        ...getStylingTransition(easing, duration),
        ...getTranslateProperty((currentSlide / this.totalSlides) * -100),
      })
    }
  }

  _clearDrag = () => {
    this.drag = {
      startX: 0,
      endX: 0,
      startY: 0,
      letItGo: null,
    }
  }

  onTouchStart = e => {
    this.pointerDown = true
    this.drag.startX = e.touches[0].pageX
    this.drag.startY = e.touches[0].pageY
    this.setState({ enableTransition: false })
  }

  onTouchEnd = () => {
    this.pointerDown = false
    if (this.drag.endX) {
      this.updateAfterDrag()
    }
    this._clearDrag()
  }

  onTouchMove = e => {
    if (this.drag.letItGo === null) {
      this.drag.letItGo =
        Math.abs(this.drag.startY - e.touches[0].pageY) <
        Math.abs(this.drag.startX - e.touches[0].pageX)
    }

    if (this.pointerDown && this.drag.letItGo) {
      const { currentSlide } = this.props

      this.drag.endX = e.touches[0].pageX

      const currentOffset =
        currentSlide * (this.getSelectorWidth() / this.perPage)
      const dragOffset = this.drag.endX - this.drag.startX
      const offset =
        ((currentOffset - dragOffset) / this.getSliderFrameWidth()) * -100

      setStyle(this._sliderFrame.current, {
        ...getTranslateProperty(offset),
      })
    }
  }

  onMouseDown = e => {
    const { cursorOnMouseDown } = this.props

    /**
     * This check avoids calling the preventDefault when the event was triggered by SKU-selector with mode selector inside a product-summary.
     * Further details at https://github.com/vtex-apps/store-components/pull/958.
     */
    if (e.target.name !== 'product-summary-sku-selector') {
      e.preventDefault()
    }

    this.pointerDown = true
    this.drag.startX = e.pageX

    setStyle(this._sliderFrame.current, {
      cursor: cursorOnMouseDown,
    })

    this.setState({ enableTransition: false })
  }

  onMouseUp = () => {
    const { cursor } = this.props

    this.pointerDown = false
    setStyle(this._sliderFrame.current, { cursor })
    if (this.drag.endX) {
      this.updateAfterDrag()
    }

    this._clearDrag()
  }

  onMouseMove = e => {
    const { currentSlide, draggable, cursorOnMouseDown } = this.props
    e.preventDefault()

    if (this.pointerDown && draggable) {
      // TODO prevent link clicks
      this.drag.endX = e.pageX

      const currentOffset =
        currentSlide * (this.getSelectorWidth() / this.perPage)
      const dragOffset = this.drag.endX - this.drag.startX
      const offset =
        ((currentOffset - dragOffset) / this.getSliderFrameWidth()) * -100
      setStyle(this._sliderFrame.current, {
        cursor: cursorOnMouseDown,
        ...getTranslateProperty(offset),
      })
    }
  }

  onMouseLeave = e => {
    if (this.pointerDown) {
      const { cursor, draggable } = this.props
      this.pointerDown = false
      this.drag.endX = e.pageX

      if (draggable) {
        setStyle(this._sliderFrame.current, { cursor })
      }
      this.updateAfterDrag()
      this._clearDrag()
    }
  }

  getSlidesToSlide = () => {
    const { navigationStep, scrollByPage } = this.props

    if (typeof navigationStep === 'number') {
      return navigationStep
    }

    if (navigationStep === constants.NAVIGATION_PAGE || scrollByPage) {
      return this.perPage
    }

    return 1
  }

  renderArrows = () => {
    const {
      arrowsContainerComponent: ArrowsContainerComponent,
      arrowRender,
    } = this.props

    if (!arrowRender) {
      return null
    }

    const slidesToSlide = this.getSlidesToSlide()

    const arrows = (
      <Fragment>
        {arrowRender({
          orientation: 'left',
          onClick: () => this.prev(slidesToSlide),
        })}
        {arrowRender({
          orientation: 'right',
          onClick: () => this.next(slidesToSlide),
        })}
      </Fragment>
    )
    return ArrowsContainerComponent ? (
      <ArrowsContainerComponent>{arrows}</ArrowsContainerComponent>
    ) : (
      arrows
    )
  }

  renderChild = child => {
    return React.cloneElement(child, {
      style: {
        ...(child.props.style ? child.props.style : {}),
        width: this.isMultiPage
          ? `${100 / this.totalSlides}%`
          : `${100 / this.perPage}%`,
      },
    })
  }

  get isMultiPage() {
    return this.childrenLength > this.perPage
  }

  get shouldAddClones() {
    const { loop } = this.props
    const { firstRender } = this.state
    return !firstRender && loop && this.isMultiPage
  }

  render() {
    const {
      children,
      sliderFrameTag: SliderFrameTag,
      rootTag: RootTag,
      classes: classesProp,
      currentSlide,
      easing,
      duration,
      cursor,
      isMobile,
      minPerPage,
    } = this.props
    const { enableTransition, dragDistance, firstRender } = this.state
    const shouldCenterSlideOnMobile =
      minPerPage && !Number.isInteger(minPerPage)
    const CURRENT_SLIDE_CENTER_SHIFT =
      isMobile && shouldCenterSlideOnMobile ? 0.75 : 0

    const classes = {
      ...Slider.defaultProps.classes,
      ...classesProp,
    }

    const arrayChildren = React.Children.toArray(children)
    const sliderFrameWidth =
      this.perPage < this.childrenLength || firstRender
        ? (100 * this.totalSlides) / this.perPage
        : 100
    const sliderFrameStyle = {
      width: `${sliderFrameWidth}%`,
      ...(this.isMultiPage &&
        getTranslateProperty(
          ((currentSlide + CURRENT_SLIDE_CENTER_SHIFT) / this.totalSlides) *
            -100 +
            dragDistance
        )),
      ...getStylingTransition(easing, enableTransition ? duration : 0),
      ...(this.isMultiPage && { cursor }),
    }

    return (
      <Fragment>
        <div className={this.isMultiPage && !firstRender ? 'db' : 'dn'}>
          {this.renderArrows()}
        </div>
        <RootTag
          className={classnames(classes.root, 'overflow-hidden h-100')}
          ref={this._selector}
          {...(this.isMultiPage &&
            Slider.events.reduce(
              (props, event) => ({ ...props, [event]: this[event] }),
              {}
            ))}
        >
          <EventListener target="window" onResize={this.handleResize} />
          <SliderFrameTag
            className={classnames(
              classes.sliderFrame,
              styles.sliderFrame,
              { 'justify-center': !this.isMultiPage },
              'list pa0 h-100 ma0 flex'
            )}
            style={sliderFrameStyle}
            ref={this._sliderFrame}
          >
            {this.shouldAddClones &&
              React.Children.map(
                arrayChildren.slice(
                  children.length - this.perPage,
                  children.length
                ),
                this.renderChild
              )}
            {React.Children.map(arrayChildren, this.renderChild)}
            {this.shouldAddClones &&
              React.Children.map(
                arrayChildren.slice(0, this.perPage),
                this.renderChild
              )}
          </SliderFrameTag>
        </RootTag>
      </Fragment>
    )
  }
}

export default withDevice(Slider)

```


[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 slider/react/__tests__/Slider.test.js from the slider VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { render } from '@vtex/test-tools/react'

import Slider from '../components/Slider.js'
import Slide from '../components/Slide.js'

describe('<Slider /> component', () => {
  const renderComponent = customProps => {
    const props = {
      loop: true,
      arrowRender: ({ orientation }) => {
        return <div>arrow {orientation}</div>
      },
      onChangeSlide: () => {},
      ...customProps,
    }

    const comp = (
      <Slider {...props}>
        <Slide>
          <div>
            <p>Slide 1</p>
          </div>
        </Slide>
        <Slide>
          <div>
            <p>Slide 2</p>
          </div>
        </Slide>
      </Slider>
    )

    return render(comp)
  }

  it('should be rendered', () => {
    const { asFragment } = renderComponent()
    expect(asFragment()).toBeTruthy()
  })

  it('should match snapshot', () => {
    const { asFragment } = renderComponent()
    expect(asFragment()).toMatchSnapshot()
  })
})

```


[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 slider/react/__tests__/SliderContainer.test.js from the slider VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { render } from '@vtex/test-tools/react'

import Slider from '../components/Slider.js'
import Slide from '../components/Slide.js'
import SliderContainer from '../components/SliderContainer.js'

describe('<SliderContainer /> component', () => {
  const renderComponent = customProps => {
    const props = {
      ...customProps,
    }

    const comp = (
      <SliderContainer {...props}>
        <Slider onChangeSlide={() => {}}>
          <Slide>
            <div>
              <p>Slide 1</p>
            </div>
          </Slide>
          <Slide>
            <div>
              <p>Slide 2</p>
            </div>
          </Slide>
        </Slider>
      </SliderContainer>
    )

    return render(comp)
  }

  it('should be rendered', () => {
    const { asFragment } = renderComponent()
    expect(asFragment()).toBeTruthy()
  })

  it('should match snapshot', () => {
    const { asFragment } = renderComponent()
    expect(asFragment()).toMatchSnapshot()
  })

  it('should match snapshot with another tag', () => {
    const { asFragment } = renderComponent({ tag: 'span' })
    expect(asFragment()).toMatchSnapshot()
  })

  it('should generate with tag', () => {
    const { container } = renderComponent({ tag: 'span' })
    expect(container.querySelector('span')).toBeTruthy()
  })
})

```


[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 slider/react/__tests__/Dots.test.js from the slider VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { render, fireEvent } from '@vtex/test-tools/react'

import Dots from '../components/Dots.js'

describe('<Dots /> component', () => {
  const renderComponent = customProps => {
    const props = {
      totalSlides: 10,
      onChangeSlide: () => {},
      ...customProps,
    }

    const comp = <Dots {...props} />

    return render(comp)
  }

  it('should be rendered', () => {
    const { asFragment } = renderComponent()
    expect(asFragment()).toBeTruthy()
  })

  it('should match snapshot', () => {
    const { asFragment } = renderComponent()
    expect(asFragment()).toMatchSnapshot()
  })

  it('should be active when clicked', () => {
    const { container } = renderComponent({
      classes: { dot: 'dot', activeDot: 'active', notActiveDot: 'inactive' },
    })

    const dot = container.querySelector('.dot')
    fireEvent.click(dot)

    expect(container.querySelector('.inactive')).toBeTruthy()
  })
})

```


[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 slider/react/__tests__/Utils.test.js from the slider VTEX app.

[Assistant]
Here's the implementation:

```javascript
import { JSDOM } from 'jsdom'

import resolveSlidesNumber from '../utils/resolveSlidesNumber'
import { setStyle, getTranslateProperty, getStylingTransition } from '../utils'

describe('Util functions', () => {
  beforeEach(() => {
    const dom = new JSDOM(
      '<!DOCTYPE html><html><head></head><body></body></html>'
    )

    global.window = dom.window
    global.document = dom.window.document

    const resizeEvent = document.createEvent('Event')
    resizeEvent.initEvent('resize', true, true)

    global.window.resizeTo = (width, height) => {
      global.window.innerWidth = width || global.window.innerWidth
      global.window.innerHeight = height || global.window.innerHeight
      global.window.dispatchEvent(resizeEvent)
    }
  })

  it('should resolve slides number correctly', () => {
    expect(resolveSlidesNumber(5)).toEqual(5)

    window.resizeTo(400, 1000)
    expect(resolveSlidesNumber(1, { 400: 2, 1000: 3 })).toEqual(2)

    window.resizeTo(1000, 1000)
    expect(resolveSlidesNumber(1, { 400: 2, 1000: 3 })).toEqual(3)

    // Testing for minimum values
    window.resizeTo(320, 1000)
    expect(resolveSlidesNumber(2, { 320: 1, 500: 2, 750: 3 })).toEqual(2)
  })

  it('should set style correctly', () => {
    const target = {
      style: {},
    }
    const styles = {
      backgroundColor: 'pink',
      color: 'black',
    }
    setStyle(target, styles)
    expect(target.style).toEqual(styles)
  })

  it('should get translate property correctly', () => {
    expect(getTranslateProperty(0, 5, -70)).toEqual({
      transform: 'translate3d(0, 5%, -70%)',
      WebkitTransform: 'translate3d(0, 5%, -70%)',
    })
  })

  it('should get styling transition correctly', () => {
    expect(
      getStylingTransition('cubic-bezier(0.215, 0.61, 0.355, 1)', 500)
    ).toEqual({
      WebkitTransition: 'all 500ms cubic-bezier(0.215, 0.61, 0.355, 1)',
      transition: 'all 500ms cubic-bezier(0.215, 0.61, 0.355, 1)',
    })
  })
})

```


[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 slider/react/__tests__/Slide.test.js from the slider VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { render } from '@vtex/test-tools/react'

import Slide from '../components/Slide.js'

describe('<Slide /> component', () => {
  const renderComponent = customProps => {
    const props = {
      ...customProps,
    }

    const comp = (
      <Slide {...props}>
        <div>
          <p>Testing</p>
        </div>
      </Slide>
    )

    return render(comp)
  }

  it('should be rendered', () => {
    const { asFragment } = renderComponent()
    expect(asFragment()).toBeTruthy()
  })

  it('should match snapshot', () => {
    const { asFragment } = renderComponent()
    expect(asFragment()).toMatchSnapshot()
  })

  it('should generate with the correct tag', () => {
    const { container, rerender } = renderComponent({ tag: 'span' })
    expect(container.querySelector('span')).toBeTruthy()

    rerender(<Slide tag="main" />)
    expect(container.querySelector('main')).toBeTruthy()

    rerender(<Slide tag="section" />)
    expect(container.querySelector('section')).toBeTruthy()
  })

  it('should math snapshot with tag', () => {
    const { asFragment } = renderComponent({ tag: 'span' })
    expect(asFragment()).toMatchSnapshot()
  })
})

```


[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 std/app/app.ts from the std VTEX app.

[Assistant]
Here's the implementation:

```typescript
export type App = {
  name: string;
  vendor: string;
  release: ReleaseDate;
};

export type ReleaseDate = {
  year: number;
  month: number;
  day: number;
  build: number;
  toString: () => string
};

export type BuildConfig = {

}

export type RuntimeConfig = {

}

export type BuildData = {

}

export type RouteData = {

}

export type EventData = {

}

export type BuildResult = {

}

export type RouteResult = {

}

export type EventResult = {

} | void

```


[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 disclosure-layout/docs/README.md from the disclosure-layout VTEX app.

[Assistant]
Here's the implementation:

```markdown
📢 Use this project, [contribute](https://github.com/vtex-apps/disclosure-layout) to it or open issues to help evolve it using [Store Discussion](https://github.com/vtex-apps/store-discussion).

# Disclosure Layout

<!-- DOCS-IGNORE:start -->
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->

[![All Contributors](https://img.shields.io/badge/all_contributors-0-orange.svg?style=flat-square)](#contributors-)

<!-- ALL-CONTRIBUTORS-BADGE:END -->
<!-- DOCS-IGNORE:end -->

The Disclosure Layout app creates a layout structure based on disclosure indicators.

![Disclosure Example](https://cdn.jsdelivr.net/gh/vtexdocs/dev-portal-content@main/images/vtex-disclosure-layout-0.gif) [Check this example](https://github.com/vtex-apps/store-theme/pull/226)

## Configuration

### Step 1 - Adding the Disclosure Layout app to your theme dependencies

In the `manifest.json` file of your theme, add the Disclosure Layout app as a dependency:

```diff
  "dependencies": {
+   "vtex.disclosure-layout": "1.x"
  }
```

Now, you can use all the blocks exported by the `disclosure-layout` app. See the full list below:

| Block name | Description |
| - | - |
| `disclosure-layout` | ![https://img.shields.io/badge/-Mandatory-red](https://img.shields.io/badge/-Mandatory-red) Parent block that enables you to build the disclosure layout using its three children blocks: `disclosure-trigger`, `disclosure-content`, and `disclosure-state-indicator`. |
| `disclosure-trigger` | Declares the blocks that will be rendered as disclosure triggers, i.e., the blocks that, when clicked, will open or close the disclosure content (defined by the `disclosure-content` block). |
| `disclosure-content` | Declares the blocks displaying the desired content when the disclosure trigger is clicked. |
| `disclosure-state-indicator` | Optional block that renders the chevron or other UI elements that change when the disclosure is opened or closed. |
| `disclosure-layout-group` | Wraps many `disclosure-layouts` blocks at once. You can use this block to control when each should be displayed, allowing only one `disclosure-layout` open at a time. |
| `disclosure-trigger-group` | Wraps many `disclosure-trigger` blocks at once. You can use this block to control when and how the `disclosure-layouts` blocks declared inside the `disclosure-layout-group` should be displayed. |

### Step 2 - Adding the Disclosure Layout blocks to your theme templates

Copy one of the examples below and paste it into your desired theme template, changing as necessary. If needed, add the `disclosure-layout` block to the block list of the template.

- Simple example:

```json
{
  "disclosure-layout#simple": {
    "children": ["disclosure-trigger#simple", "disclosure-content#simple"]
  },
  "disclosure-trigger#simple": {
    "children": ["rich-text#question"]
  },
  "disclosure-content#simple": {
    "children": ["rich-text#answer"]
  },
  "rich-text#question": {
    "props": {
      "text": "How can I change my shipping address?"
    }
  },
  "rich-text#answer": {
    "props": {
      "text": "Call us at (212) 123-1234"
    }
  }
}
```

- Example using the `disclosure-layout-group` block:

```json
{
  "disclosure-layout-group#group": {
    "children": ["disclosure-layout#first", "disclosure-layout#second"]
  },

  "disclosure-layout#first": {
    "children": ["disclosure-trigger#first", "disclosure-content#first"]
  },
  "disclosure-trigger#first": {
    "children": ["rich-text#question1"]
  },
  "disclosure-content#first": {
    "children": ["rich-text#answer1"]
  },
  "rich-text#question1": {
    "props": {
      "text": "How can I change my shipping address?"
    }
  },
  "rich-text#answer1": {
    "props": {
      "text": "Call us at (212) 123-1234."
    }
  },

  "disclosure-layout#second": {
    "children": ["disclosure-trigger#first", "disclosure-content#first"]
  },
  "disclosure-trigger#second": {
    "children": ["rich-text#question1"]
  },
  "disclosure-content#second": {
    "children": ["rich-text#answer1"]
  },
  "rich-text#question2": {
    "props": {
      "text": "How can I track my order?"
    }
  },
  "rich-text#answer2": {
    "props": {
      "text": "After logging in to your account, you can find this information in the Orders link."
    }
  }
}
```

- Example using the `disclosure-state-indicator` block:

```json
{
  "disclosure-state-indicator": {
    "props": {
      "Show": "icon-angle--down",
      "Hide": "icon-angle--up"
    }
  }
}
```

#### `disclosure-layout` props

| Prop name | Type | Description | Default value |
| - | - | - | - |
| `initialVisibility` | `enum` | Defines the initial visibility of the layout content. Possible values are: `visible` (content initially open) or `hidden` (content is only displayed with user interaction). | `hidden` |
| `animated` | `boolean` | Defines if the layout content should have animations. When set as `true`, this prop will enable additional `data-\*` attributes on the content, which you can use as selectors in CSS. It will also ensure that the element will be hidden once the transition has ended. | `false` |

#### `disclosure-trigger` props

| Prop name | Type | Description | Default value |
| - | - | - | - |
| `Show` | `block` | Name of the block that will be rendered when prompted to show the content. | `undefined` |
| `Hide` | `block` | Name of the block that will be rendered when prompted to hide the content. | `undefined` |
| `as` | `string` | HTML tag to be applied to the component when rendered on the UI. | `button` |
| `children` | `block`  | Name of the block that will be rendered if no blocks are declared in the `Show` or `Hide` props. | `undefined` |
| `blockClass` | `string` | Block ID defined by you that will be used in [CSS customizations](https://developers.vtex.com/docs/guides/vtex-io-documentation-using-css-handles-for-store-customization#using-the-blockclass-property). | `undefined` |

#### `disclosure-content` props

| Prop name | Type | Description | Default value |
| - | - | - | - |
| `blockClass` | `string` | Block ID defined by you that will be used in [CSS customizations](https://developers.vtex.com/docs/guides/vtex-io-documentation-using-css-handles-for-store-customization#using-the-blockclass-property). | `undefined` |
| `children`   | `[block]` | List of blocks that will render the desired disclosure content. | `undefined` |

#### `disclosure-state-indicator` props

| Prop name | Type | Description | Default value |
| - | - | - | - |
| `Show` | `block` | Name of the block that will be rendered when prompted to show the content. | `undefined` |
| `Hide` | `block` | Name of the block that will be rendered when prompted to hide the content. | `undefined` |

#### `disclosure-layout-group` props

| Prop name | Type | Description | Default value |
| - | - | - | - |
| `maxVisible` | `enum` | Defines how many `disclosure-layout` blocks should be displayed at a time. Possible values are: `one` (only one `disclosure-layout` block should have its content displayed at time) or `many` (different `disclosure-layout` block content can be displayed at time). | `one` |

#### `disclosure-trigger-group` props

| Prop name | Type | Description | Default value |
| - | - | - | - |
| `Show` | `block`  | Name of the block that will be rendered when prompted to show the content. | `undefined` |
| `Hide` | `block`  | Name of the block that will be rendered when prompted to hide the content. | `undefined` |
| `as` | `string` | HTML tag to be applied to the component when rendered on the UI. | `button`      |
| `children` | `block`  | Name of the block that will be rendered if no blocks are declared in the `Show` or `Hide` props. | `undefined` |
| `blockClass` | `string` | Block ID defined by you that will be used in [CSS customizations](https://developers.vtex.com/docs/guides/vtex-io-documentation-using-css-handles-for-store-customization#using-the-blockclass-property). | `undefined` |

## Customization

To apply CSS customizations in this and other blocks, follow the instructions given in the recipe on [Using CSS handles for store customization](https://developers.vtex.com/docs/guides/vtex-io-documentation-using-css-handles-for-store-customization).

| CSS handles             |
| ----------------------- |
| `content`               |
| `content--visible`      |
| `content--hidden`       |
| `trigger`               |
| `trigger--visible`      |
| `trigger--hidden`       |
| `triggerGroup`          |
| `triggerGroup--visible` |
| `triggerGroup--hidden`  |

<!-- DOCS-IGNORE:start -->

## Contributors ✨

Thanks goes to these wonderful people:

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind are welcome!

<!-- DOCS-IGNORE:end -->

```


[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 disclosure-layout/react/DisclosureLayoutGroup.tsx from the disclosure-layout VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC } from 'react'
import {
  DisclosureLayoutGroup,
  DisclosureLayoutGroupProps,
} from '@vtex/disclosure'

const Group: FC<DisclosureLayoutGroupProps> = ({ maxVisible, children }) => {
  return (
    <DisclosureLayoutGroup maxVisible={maxVisible}>
      {children}
    </DisclosureLayoutGroup>
  )
}

Group.displayName = 'DisclosureLayoutGroup'

export default Group

```


[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 disclosure-layout/react/DisclosureLayout.tsx from the disclosure-layout VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC } from 'react'
import { DisclosureLayout, DisclosureLayoutProps } from '@vtex/disclosure'

const Layout: FC<DisclosureLayoutProps> = ({
  initialVisibility,
  animated,
  children,
}) => {
  return (
    <DisclosureLayout initialVisibility={initialVisibility} animated={animated}>
      {children}
    </DisclosureLayout>
  )
}

Layout.displayName = 'DisclosureLayout'

export default Layout

```


[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 disclosure-layout/react/DisclosureTrigger.tsx from the disclosure-layout VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC, useMemo, ComponentType } from 'react'
import {
  DisclosureTrigger,
  DisclosureTriggerProps,
  useDisclosure,
} from '@vtex/disclosure'
import { useCssHandles, applyModifiers } from 'vtex.css-handles'

interface Props
  extends Omit<DisclosureTriggerProps, 'htmlProps' | 'show' | 'hide'> {
  blockClass?: string
  Show?: ComponentType
  Hide?: ComponentType
}

const CSS_HANDLES = ['trigger'] as const

const Trigger: FC<Props> = ({ as, children, Show, Hide }) => {
  const handles = useCssHandles(CSS_HANDLES)
  const { state } = useDisclosure()
  const visible = state?.visible

  const htmlProps = useMemo(
    () => ({
      className: applyModifiers(
        handles.trigger,
        visible ? 'visible' : 'hidden'
      ),
    }),
    [handles, visible]
  )

  return (
    <DisclosureTrigger
      as={as}
      htmlProps={htmlProps}
      show={Show ? <Show /> : undefined}
      hide={Hide ? <Hide /> : undefined}
    >
      {children}
    </DisclosureTrigger>
  )
}

Trigger.displayName = 'DisclosureTrigger'

export default Trigger

```


[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 disclosure-layout/react/DisclosureContent.tsx from the disclosure-layout VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC, useMemo } from 'react'
import {
  DisclosureContent,
  DisclosureContentProps,
  useDisclosure,
} from '@vtex/disclosure'
import { useCssHandles, applyModifiers } from 'vtex.css-handles'

interface Props extends Omit<DisclosureContentProps, 'htmlProps'> {
  blockClass?: string
}

const CSS_HANDLES = ['content'] as const

const Content: FC<Props> = ({ as, children }) => {
  const handles = useCssHandles(CSS_HANDLES)
  const { state } = useDisclosure()
  const visible = state?.visible

  const htmlProps = useMemo(
    () => ({
      className: applyModifiers(
        handles.content,
        visible ? 'visible' : 'hidden'
      ),
    }),
    [handles, visible]
  )

  return (
    <DisclosureContent as={as} htmlProps={htmlProps}>
      {children}
    </DisclosureContent>
  )
}

Content.displayName = 'DisclosureContent'

export default Content

```


[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 disclosure-layout/react/package.json from the disclosure-layout VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "name": "disclosure-layout",
  "version": "1.0.4",
  "scripts": {
    "test": "vtex-test-tools test"
  },
  "dependencies": {
    "@vtex/disclosure": "^0.1.5",
    "apollo-client": "^2.6.8",
    "react": "^16.12.0",
    "react-apollo": "^3.1.3",
    "react-dom": "^16.12.0",
    "react-intl": "^3.12.0"
  },
  "devDependencies": {
    "@apollo/react-testing": "^3.1.3",
    "@types/jest": "^25.1.4",
    "@types/node": "^13.9.8",
    "@types/react": "^16.9.31",
    "@vtex/test-tools": "^3.2.1",
    "@vtex/tsconfig": "^0.4.4",
    "apollo-cache-inmemory": "^1.6.5",
    "graphql": "^14.6.0",
    "typescript": "3.8.3",
    "vtex.css-handles": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.css-handles@0.4.2/public/@types/vtex.css-handles",
    "vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.111.1/public/@types/vtex.render-runtime"
  }
}

```


[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 disclosure-layout/react/DisclosureTriggerGroup.tsx from the disclosure-layout VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC, useMemo, ComponentType } from 'react'
import {
  DisclosureTriggerGroup,
  DisclosureTriggerGroupProps,
  useDisclosureGroup,
} from '@vtex/disclosure'
import { useCssHandles, applyModifiers } from 'vtex.css-handles'

interface Props
  extends Omit<DisclosureTriggerGroupProps, 'htmlProps' | 'show' | 'hide'> {
  blockClass?: string
  Show?: ComponentType
  Hide?: ComponentType
}

const CSS_HANDLES = ['triggerGroup'] as const

const TriggerGroup: FC<Props> = ({ as, Show, Hide, children }) => {
  const handles = useCssHandles(CSS_HANDLES)
  const { state } = useDisclosureGroup()
  const visible = state?.allVisibility

  const htmlProps = useMemo(
    () => ({
      className: applyModifiers(
        handles.triggerGroup,
        visible === 'shown' ? 'visible' : 'hidden'
      ),
    }),
    [handles, visible]
  )

  return (
    <DisclosureTriggerGroup
      as={as}
      htmlProps={htmlProps}
      show={Show ? <Show /> : undefined}
      hide={Hide ? <Hide /> : undefined}
    >
      {children}
    </DisclosureTriggerGroup>
  )
}

TriggerGroup.displayName = 'DisclosureTriggerGroup'

export default TriggerGroup

```


[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 disclosure-layout/react/DisclosureStateIndicator.tsx from the disclosure-layout VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC, ComponentType } from 'react'
import { DisclosureStateIndicator } from '@vtex/disclosure'

interface Props {
  Show?: ComponentType
  Hide?: ComponentType
}

const StateIndicator: FC<Props> = ({ Show, Hide }) => {
  return (
    <DisclosureStateIndicator
      show={Show ? <Show /> : undefined}
      hide={Hide ? <Hide /> : undefined}
    />
  )
}

StateIndicator.displayName = 'DisclosureStateIndicator'

export default StateIndicator

```


[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 disclosure-layout/store/interfaces.json from the disclosure-layout VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "disclosure-layout": {
    "component": "DisclosureLayout",
    "composition": "children"
  },
  "disclosure-layout-group": {
    "component": "DisclosureLayoutGroup",
    "composition": "children"
  },
  "disclosure-trigger": {
    "component": "DisclosureTrigger",
    "composition": "children"
  },
  "disclosure-trigger-group": {
    "component": "DisclosureTriggerGroup",
    "composition": "children"
  },
  "disclosure-state-indicator": {
    "component": "DisclosureStateIndicator",
    "composition": "children"
  },
  "disclosure-content": {
    "component": "DisclosureContent",
    "composition": "children"
  }
}

```


[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 disclosure-layout/react/__tests__/DisclosureLayout.test.tsx from the disclosure-layout VTEX app.

[Assistant]
Here's the implementation:

```tsx
import * as React from 'react'
import { render, waitFor } from '@vtex/test-tools/react'

import DisclosureLayout from '../DisclosureLayout'
import DisclosureContent from '../DisclosureContent'
import DisclosureTrigger from '../DisclosureTrigger'

test('should change the CSS Handles', async () => {
  const { getByText } = render(
    <DisclosureLayout>
      <DisclosureTrigger>Trigger</DisclosureTrigger>
      <DisclosureContent>Content</DisclosureContent>
    </DisclosureLayout>
  )

  const content = getByText('Content')

  expect(content).toHaveClass('content--hidden')

  const trigger = getByText('Trigger')

  expect(trigger).toHaveClass('trigger--hidden')

  trigger.click()

  expect(content).toHaveClass('content--visible')
  expect(trigger).toHaveClass('trigger--visible')
})

test('should render hide and show props', async () => {
  const Show = () => <>Show</>
  const Hide = () => <>Hide</>

  const { getByText } = render(
    <DisclosureLayout>
      <DisclosureTrigger Show={Show} Hide={Hide} />
      <DisclosureContent>Content</DisclosureContent>
    </DisclosureLayout>
  )

  const content = getByText('Content')

  expect(content).not.toBeVisible()

  getByText('Show').click()
  expect(content).toBeVisible()

  getByText('Hide').click()
  await waitFor(() => expect(content).not.toBeVisible())
})

test('should show if initialVisibility is visible', async () => {
  const { getByText } = render(
    <DisclosureLayout initialVisibility="visible">
      <DisclosureTrigger>Trigger</DisclosureTrigger>
      <DisclosureContent>Content</DisclosureContent>
    </DisclosureLayout>
  )

  const content = getByText('Content')

  expect(content).toBeVisible()

  getByText('Trigger').click()
  expect(content).not.toBeVisible()
})

```


[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 disclosure-layout/react/__tests__/DisclosureLayoutGroup.test.tsx from the disclosure-layout VTEX app.

[Assistant]
Here's the implementation:

```tsx
import * as React from 'react'
import { render, waitFor } from '@vtex/test-tools/react'

import DisclosureLayoutGroup from '../DisclosureLayoutGroup'
import DisclosureTriggerGroup from '../DisclosureTriggerGroup'
import DisclosureLayout from '../DisclosureLayout'
import DisclosureContent from '../DisclosureContent'
import DisclosureTrigger from '../DisclosureTrigger'

test('trigger group', async () => {
  const { getByText } = render(
    <DisclosureLayoutGroup>
      <DisclosureLayout>
        <DisclosureTrigger>Trigger 1</DisclosureTrigger>
        <DisclosureContent>Content 1</DisclosureContent>
      </DisclosureLayout>
      <DisclosureLayout>
        <DisclosureTrigger>Trigger 2</DisclosureTrigger>
        <DisclosureContent>Content 2</DisclosureContent>
      </DisclosureLayout>
      <DisclosureLayout>
        <DisclosureTrigger>Trigger 3</DisclosureTrigger>
        <DisclosureContent>Content 3</DisclosureContent>
      </DisclosureLayout>

      <DisclosureTriggerGroup>Trigger Group</DisclosureTriggerGroup>
    </DisclosureLayoutGroup>
  )

  const content1 = getByText('Content 1')
  const triggerGroup = getByText('Trigger Group')

  expect(content1).toHaveClass('content--hidden')
  expect(triggerGroup).toHaveClass('triggerGroup--hidden')

  triggerGroup.click()
  await waitFor(() =>
    expect(triggerGroup).toHaveAttribute('aria-expanded', 'true')
  )

  expect(content1).toHaveClass('content--visible')
  expect(triggerGroup).toHaveClass('triggerGroup--visible')
})

test('trigger with show and hide', async () => {
  const Show = () => <>SHOW ALL</>
  const Hide = () => <>HIDE ALL</>

  const { getByText } = render(
    <DisclosureLayoutGroup>
      <DisclosureLayout>
        <DisclosureTrigger>Trigger 1</DisclosureTrigger>
        <DisclosureContent>Content 1</DisclosureContent>
      </DisclosureLayout>
      <DisclosureLayout>
        <DisclosureTrigger>Trigger 2</DisclosureTrigger>
        <DisclosureContent>Content 2</DisclosureContent>
      </DisclosureLayout>
      <DisclosureLayout>
        <DisclosureTrigger>Trigger 3</DisclosureTrigger>
        <DisclosureContent>Content 3</DisclosureContent>
      </DisclosureLayout>

      <DisclosureTriggerGroup Show={Show} Hide={Hide} />
    </DisclosureLayoutGroup>
  )

  const content1 = getByText('Content 1')
  const content2 = getByText('Content 2')
  const content3 = getByText('Content 3')

  getByText('SHOW ALL').click()
  await waitFor(() => expect(content1).toBeVisible())
  expect(content2).toBeVisible()
  expect(content3).toBeVisible()

  getByText('HIDE ALL').click()
  expect(content1).not.toBeVisible()
  expect(content2).not.toBeVisible()
  expect(content3).not.toBeVisible()
})

```


[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 admin-graphql-ide/messages/nl.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
{
    "admin/error.state": "Probeer het opnieuw",
    "admin/error.title": "Er is iets misgegaan",
    "admin/no-app-selected.title": "Kies een app",
    "admin/no-app-selected.state": "Kies een app om vragen te stellen",
    "admin/layout.title": "GraphQL IDE",
    "admin/controller.app-picker": "Kies een app"
}
```


[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 admin-graphql-ide/messages/ja.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
{
    "admin/error.state": "もう一度やり直す",
    "admin/error.title": "エラーあり",
    "admin/no-app-selected.title": "アプリを選ぶ",
    "admin/no-app-selected.state": "クエリを作成するアプリを選ぶ",
    "admin/layout.title": "GraphQL IDE",
    "admin/controller.app-picker": "アプリを選ぶ"
}
```


[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 admin-graphql-ide/messages/de.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
{
    "admin/error.state": "Versuchen Sie es erneut",
    "admin/error.title": "Ein Problem ist aufgetreten",
    "admin/no-app-selected.title": "Wählen Sie eine App aus",
    "admin/no-app-selected.state": "Wählen Sie eine App für Abfragen",
    "admin/layout.title": "GraphQL IDE",
    "admin/controller.app-picker": "Wählen Sie eine App aus"
}
```


[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 admin-graphql-ide/messages/pl.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/error.state": "Spróbuj ponownie",
  "admin/error.title": "Coś poszło nie tak",
  "admin/no-app-selected.title": "Wybierz aplikację",
  "admin/no-app-selected.state": "Wybierz aplikację do zapytań",
  "admin/layout.title": "GraphQL IDE",
  "admin/controller.app-picker": "Wybierz aplikację"
}
```


[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 admin-graphql-ide/messages/pt.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/error.state": "Tente novamente",
  "admin/error.title": "Alguma deu errado",
  "admin/no-app-selected.title": "Selecione um app",
  "admin/no-app-selected.state": "Escolha um app para realizar queries",
  "admin/layout.title": "GraphQL IDE",
  "admin/controller.app-picker": "Selecione um app"
}
```


[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 admin-graphql-ide/messages/en.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
{
    "admin/error.state": "Try again",
    "admin/error.title": "Something went wrong",
    "admin/no-app-selected.title": "Choose an app",
    "admin/no-app-selected.state": "Choose an app to make queries",
    "admin/layout.title": "GraphQL IDE",
    "admin/controller.app-picker": "Choose an app"
}
```


[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 admin-graphql-ide/messages/it.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
{
    "admin/error.state": "Riprova",
    "admin/error.title": "Si è verificato un errore",
    "admin/no-app-selected.title": "Scegli un'app",
    "admin/no-app-selected.state": "Scegli un'app per realizzare query",
    "admin/layout.title": "Ambiente di sviluppo integrato GraphQL",
    "admin/controller.app-picker": "Scegli un'app"
}
```


[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 admin-graphql-ide/messages/bs.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
{
    "admin/error.state": "crwdns105188:0crwdne105188:0",
    "admin/error.title": "crwdns105190:0crwdne105190:0",
    "admin/no-app-selected.title": "crwdns105192:0crwdne105192:0",
    "admin/no-app-selected.state": "crwdns105194:0crwdne105194:0",
    "admin/layout.title": "crwdns105196:0crwdne105196:0",
    "admin/controller.app-picker": "crwdns105198:0crwdne105198:0"
}
```


[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 admin-graphql-ide/messages/fr.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
{
    "admin/error.state": "Réessayez",
    "admin/error.title": "Un problème est survenu",
    "admin/no-app-selected.title": "Choisir une application",
    "admin/no-app-selected.state": "Choisissez une application pour effectuer des recherches",
    "admin/layout.title": "GraphQL IDE",
    "admin/controller.app-picker": "Choisir une application"
}
```


[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 admin-graphql-ide/messages/bg.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
{
    "admin/error.state": "Опитайте отново",
    "admin/error.title": "Нещо се обърка",
    "admin/no-app-selected.title": "Изберете приложение",
    "admin/no-app-selected.state": "Изберете приложение, за да отправите заявка",
    "admin/layout.title": "GraphQL IDE",
    "admin/controller.app-picker": "Изберете приложение"
}
```


[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 admin-graphql-ide/messages/ro.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
{
    "admin/error.state": "Încearcă din nou",
    "admin/error.title": "A apărut o eroare",
    "admin/no-app-selected.title": "Alege o aplicație",
    "admin/no-app-selected.state": "Alege o aplicație pentru a face căutări",
    "admin/layout.title": "GraphQL IDE",
    "admin/controller.app-picker": "Alege o aplicație"
}
```


[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 admin-graphql-ide/messages/context.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
{
    "admin/error.state": "admin/error.state",
    "admin/error.title": "admin/error.title",
    "admin/no-app-selected.title": "admin/no-app-selected.title",
    "admin/no-app-selected.state": "admin/no-app-selected.state",
    "admin/layout.title": "admin/layout.title",
    "admin/controller.app-picker": "admin/controller.app-picker"
}
```


[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 admin-graphql-ide/messages/ko.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
{
    "admin/error.state": "다시 시도",
    "admin/error.title": "문제가 발생했습니다",
    "admin/no-app-selected.title": "앱 선택",
    "admin/no-app-selected.state": "쿼리를 만들 앱 선택",
    "admin/layout.title": "GraphQL IDE",
    "admin/controller.app-picker": "앱 선택"
}
```


[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 admin-graphql-ide/messages/es.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/error.state": "Reintentar",
  "admin/error.title": "Se produjo un error",
  "admin/no-app-selected.title": "Selecciona una aplicación",
  "admin/no-app-selected.state": "Selecciona una aplicación para realizar consultas",
  "admin/layout.title": "IDE de GraphQL",
  "admin/controller.app-picker": "Selecciona una aplicación"
}
```


[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 admin-graphql-ide/messages/ar.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
{
    "admin/error.state": "حاول من جديد",
    "admin/error.title": "شيء ما لا يعمل جيدًا",
    "admin/no-app-selected.title": "اختر تطبيقًا",
    "admin/no-app-selected.state": "اختر تطبيقًا لإجراء البحوثات",
    "admin/layout.title": "GraphQL IDE",
    "admin/controller.app-picker": "اختر تطبيقًا"
}
```


[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 admin-graphql-ide/admin/navigation.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
[
  {
    "section": "storeSetup",
    "titleId": "admin/layout.title",
    "path": "/admin/graphql-ide"
  },
  {
    "adminVersion": 4,
    "section": "storeSettings",
    "titleId": "admin/layout.title",
    "subSection": "storeFront",
    "subSectionItems": [
      {
        "labelId": "admin/layout.title",
        "path": "/admin/graphql-ide"
      }
    ]
  }
]

```


[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 admin-graphql-ide/admin/routes.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
{
    "admin.app.admin-graphql-ide": {
        "component": "GraphiQL",
        "path": "/admin/app/graphql-ide",
        "around": ["layout"]
    },
    "layout": {
        "component": "PageLayout"
    }
}
```


[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 admin-graphql-ide/docs/README.md from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```markdown
  # Admin GraphQL IDE - VTEX IO

  Select your app and start **writing**, **simulating** and **testing requests** to validate your GraphQL API using `GraphiQL` (a graphical interactive in-browser GraphQL IDE).

  To install this app, just go to your VTEX IO workspace and run:

  ```
  vtex install vtex.admin-graphql-ide
  ```

  As soon as the app is installed the button `GraphQL IDE` will already appear in the section "Store Setup" of your `admin` menu (left side of your screen in the admin page).

  The URL path is `<your-website>/admin/graphql-ide`. Have fun!

  > Obs: The `vtex install` command above will install the latest version of `Admin GraphQL IDE`, that is compatible with vtex.admin@3.x. If you need to keep using `vtex.admin@2.x` in your workspace and cannot upgrade it to `vtex.admin@3.x`, you can run `vtex install vtex.admin-graphql-ide@2.x` that is compatible with this prior `admin` major version.
```


[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 admin-graphql-ide/node/service.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "memory": 256,
  "ttl": 43200,
  "timeout": 30,
  "minReplicas": 2,
  "maxReplicas": 4,
  "routes": {
    "graphqlProxy": {
      "path": "/_v/private/admin-graphql-ide/v0/:appId",
      "public": true
    }
  }
}

```


[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 admin-graphql-ide/node/package.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "dependencies": {
    "bluebird": "^3.5.4",
    "co-body": "^6.0.0",
    "ramda": "^0.26.1"
  },
  "devDependencies": {
    "@types/bluebird": "^3.5.26",
    "@types/co-body": "^0.0.3",
    "@types/node": "12.x",
    "@types/ramda": "^0.26.8",
    "@vtex/api": "^3.16.0",
    "vtex.admin-graphql-ide": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.admin-graphql-ide@3.6.0/public/@types/vtex.admin-graphql-ide",
    "vtex.graphql-server": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.graphql-server@1.67.4/public/_types/react",
    "vtex.styleguide": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.146.1/public/@types/vtex.styleguide"
  },
  "scripts": {
    "check": "tsc --noEmit && tslint -c tslint.json './**/*.ts'"
  },
  "version": "3.8.0"
}

```


[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 admin-graphql-ide/node/typings.ts from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { ServiceContext } from '@vtex/api'

import type { Clients } from './clients'

declare global {
  type Context = ServiceContext<Clients>
}

```


[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 admin-graphql-ide/node/index.ts from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { LRUCache, Service } from '@vtex/api'

import { Clients } from './clients'
import { graphqlProxy } from './middlewares/graphqlProxy'
import { apps } from './resolvers/apps'

const appsCacheStorage = new LRUCache<string, any>({
  max: 10000,
})

const SHORT_TIMEOUT_MS = 1 * 500
const THIRTY_SECONDS_MS = 30 * 1000

metrics.trackCache('apps', appsCacheStorage)

export default new Service<Clients>({
  clients: {
    implementation: Clients,
    options: {
      default: {
        timeout: THIRTY_SECONDS_MS,
      },
      apps: {
        memoryCache: appsCacheStorage,
        retries: 1,
        timeout: SHORT_TIMEOUT_MS,
      },
    },
  },
  graphql: {
    resolvers: {
      Query: {
        apps,
      },
    },
  },
  routes: {
    graphqlProxy,
  },
})

```


[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 admin-graphql-ide/react/PageLayout.tsx from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FunctionComponent } from 'react'
import { defineMessages, InjectedIntlProps, injectIntl } from 'react-intl'
import { Layout, PageBlock, PageHeader } from 'vtex.styleguide'

const messages = defineMessages({
  title: {
    id: 'admin/layout.title',
    defaultMessage: 'GraphQL IDE'
  }
})

// This component generates the base layout for this app.
const PageLayout: FunctionComponent<InjectedIntlProps> = ({ children, intl }) => (
  <Layout fullWidth pageHeader={<PageHeader title={intl.formatMessage(messages.title)} />}>
    <PageBlock>
      {children}
    </PageBlock>
  </Layout>
)

export default injectIntl(PageLayout)

```


[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 admin-graphql-ide/react/package.json from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "dependencies": {
    "apollo-client": "^2.5.1",
    "graphiql": "^0.13.0",
    "graphql": "^14.3.0",
    "punycode": "^2.1.1",
    "ramda": "^0.26.1",
    "react": "^16.6.3",
    "react-apollo": "^2.5.5",
    "react-dom": "^16.0.0",
    "react-intl": "^2.9.0"
  },
  "resolutions": {
    "graphql-language-service-parser": "1.2.2",
    "graphql-language-service-types": "1.2.2"
  },
  "devDependencies": {
    "@types/jest": "^24.0.11",
    "@types/node": "12.x",
    "@types/ramda": "^0.26.8",
    "@types/react": "^16.7.17",
    "@types/react-intl": "^2.3.17",
    "vtex.admin-graphql-ide": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.admin-graphql-ide@3.6.0/public/@types/vtex.admin-graphql-ide",
    "vtex.graphql-server": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.graphql-server@1.67.4/public/_types/react",
    "vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.132.4/public/@types/vtex.render-runtime",
    "vtex.styleguide": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.146.1/public/@types/vtex.styleguide"
  },
  "scripts": {
    "lint": "tsc --noEmit && tslint -c tslint.json './**/*.ts'"
  },
  "version": "3.8.0"
}

```


[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 admin-graphql-ide/react/GraphiQL.tsx from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FunctionComponent } from 'react'
import { Helmet, NoSSR } from 'vtex.render-runtime'

import { GraphiQLController } from './components/Controller'
import { GetApps } from './graphql/getApps'

const Index: FunctionComponent = () => (
  <div className="vh-100 flex flex-column flex-grow-1">
    <NoSSR>
      <Helmet>
        <link href="//cdn.jsdelivr.net/npm/graphiql@0.11.11/graphiql.css" rel="stylesheet" />
      </Helmet>
      <GetApps>
        {({apps}) => <GraphiQLController apps={apps} />}
      </GetApps>
    </NoSSR>
  </div>
)

export default Index
```


[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 admin-graphql-ide/node/clients/graphqlServer.ts from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { InstanceOptions, IOContext } from '@vtex/api'
import { AppClient } from '@vtex/api'

export class GraphQLServer extends AppClient {
  constructor(ctx: IOContext, opts?: InstanceOptions) {
    super('vtex.graphql-server@1.x', ctx, opts)
  }

  public proxyGraphiQL = (
    body: any,
    appId: string,
    headers: Record<string, string | string[] | undefined>
  ) =>
    this.http.post('/graphiql', body, {
      headers: {
        ...headers,
        'x-colossus-declarer-id': appId,
      },
    })
}

```


[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 admin-graphql-ide/node/clients/vtexid.ts from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { InstanceOptions, IOContext } from '@vtex/api'
import { ExternalClient } from '@vtex/api'

export class VtexID extends ExternalClient {
  constructor(ctx: IOContext, opts?: InstanceOptions) {
    super('http://vtexid.vtex.com.br/api/vtexid', ctx, opts)
  }

  public getIdUser = (token: string) =>
    this.http.get(`pub/authenticated/user?authToken=${token}`, {
      headers: {
        Accept: 'application/json',
        Authorization: this.context.authToken,
        'Content-Type': 'application/json',
        'User-Agent': process.env.VTEX_APP_ID!,
        'X-VTEX-Proxy-To': 'https://vtexid.vtex.com.br',
      },
    })
}

```


[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 admin-graphql-ide/node/clients/index.ts from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { IOClients, Sphinx } from '@vtex/api'

import { GraphQLServer } from './graphqlServer'
import { VtexID } from './vtexid'

export class Clients extends IOClients {
  public get graphqlServer() {
    return this.getOrSet('graphqlServer', GraphQLServer)
  }

  public get sphinx() {
    return this.getOrSet('sphinx', Sphinx)
  }

  public get vtexID() {
    return this.getOrSet('vtexID', VtexID)
  }
}

```


[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 admin-graphql-ide/node/middlewares/graphqlProxy.ts from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ForbiddenError } from '@vtex/api'
import bodyParser from 'co-body'
import { path, pick } from 'ramda'

import type { Clients } from '../clients'

const EMPTY_OBJECT = {}

export const ensureAdminUser = async (
  clients: Pick<Clients, 'sphinx' | 'vtexID'>,
  idToken: string | undefined
) => {
  const { sphinx, vtexID } = clients

  if (!idToken) {
    throw new ForbiddenError('No VtexIdclientAutCookie provided')
  }

  const { user: email } =
    (await vtexID.getIdUser(idToken)) || (EMPTY_OBJECT as any)

  if (!email) {
    throw new ForbiddenError(
      'User must have a valid email to use admin-graphql-ide'
    )
  }

  const isAdminUser = await sphinx.isAdmin(email)

  if (!isAdminUser) {
    throw new ForbiddenError('User must be admin to use admin-graphql-ide')
  }
}

export async function graphqlProxy(ctx: Context) {
  const {
    clients: { graphqlServer },
    vtex: {
      route: {
        params: { appId: paramAppId },
      },
    },
  } = ctx

  const idToken = ctx.cookies.get('VtexIdclientAutCookie')

  await ensureAdminUser(ctx.clients, idToken)

  const body = await bodyParser(ctx.req)

  const appId = paramAppId as string

  const headersToSend = [
    'accept',
    'accept-language',
    'authorization',
    'content-length',
    'content-type',
    'cookie',
    'rest-range',
    'user-agent',
    'vtexidclientautcookie',
    'x-forwarded-host',
  ]

  const headers = pick(headersToSend, ctx.request.headers)

  ctx.body = await graphqlServer
    .proxyGraphiQL(body, appId, headers)
    .catch(path(['response', 'data']))
  ctx.status = 200
}

```


[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 admin-graphql-ide/node/resolvers/apps.ts from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { AppMetaInfo, Apps } from '@vtex/api'
import { filter as filterP } from 'bluebird'
import { filter, pluck } from 'ramda'

import type { Query } from '../../typedql/schema'

const TARGET_APP_NAME = 'vtex.graphql-server'
const TARGET_APP_MAJOR = '1'
const SCHEMA_GRAPHQL = 'public/schema.graphql'

const filterGraphQLApps = (metaInfos: AppMetaInfo[]) =>
  filter(({ _resolvedDependencies }) => {
    const graphqlServerVersion = _resolvedDependencies[TARGET_APP_NAME]

    if (graphqlServerVersion) {
      const [major] = graphqlServerVersion.split('.')

      return major === TARGET_APP_MAJOR
    }

    return false
  }, metaInfos)

const filterAppWithSchema = (appsClient: Apps, metaInfos: AppMetaInfo[]) =>
  filterP(metaInfos, async ({ id }) => {
    try {
      const schema = await appsClient.getAppFile(id, SCHEMA_GRAPHQL)

      return !!schema
    } catch (_) {
      return false
    }
  })

export const apps = async (
  _: any,
  __: any,
  ctx: Context
): Promise<Query['apps']> => {
  const {
    clients: { apps: appsClient },
  } = ctx

  const metaInfos = await appsClient.getAppsMetaInfos()

  const graphqlApps = filterGraphQLApps(metaInfos)
  const appsWithSchema = await filterAppWithSchema(appsClient, graphqlApps)

  return pluck('id', appsWithSchema)
}

```


[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 admin-graphql-ide/react/typings/vtex.render-runtime.d.ts from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* Typings for `render-runtime` */
declare module 'vtex.render-runtime' {
  import { Component, ComponentType, ReactElement } from 'react'

  export interface NavigationOptions {
    page: string
    params?: any
  }

  export interface RenderContextProps {
    runtime: {
      navigate: (options: NavigationOptions) => void
    }
  }

  export const ExtensionPoint: ReactElement
  export const Helmet: ComponentType<any>
  export const Link: ReactElement
  export const NoSSR: ComponentType<any>
  export const RenderContextConsumer: ReactElement
  export const canUseDOM: boolean
  export const withRuntimeContext: <TOriginalProps extends {}>(
    Component: ComponentType<TOriginalProps & RenderContextProps>
  ) => ComponentType<TOriginalProps>

  export const buildCacheLocator = (app: string, type: string, cacheId: string) => string

  interface RenderComponent<P = {}, S = {}> extends Component<P, S> {
    getCustomMessages?: (locale: string) => any
    schema: ComponentSchema
    getSchema?: (a: any, b: any?) => ComponentSchema
    uiSchema: UISchema
  }

  export interface ComponentsRegistry {
    [component: string]: RenderComponent<any, any>
  }

  export interface Window extends Window {
    __RENDER_7_COMPONENTS__: ComponentsRegistry
  }

  let global: Window
}

```


[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 admin-graphql-ide/react/typings/graphiql.d.ts from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'graphiql' {
  const value: any
  export default 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 admin-graphql-ide/react/typings/graphqlQueries.d.ts from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module '*.graphql' {
  import { DocumentNode } from 'graphql'

  const value: DocumentNode
  export default 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 admin-graphql-ide/react/typings/vtex.styleguide.d.ts from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'vtex.styleguide' {
  import { ComponentType } from 'react'

  export const Alert: ComponentType<any>
  export const Checkbox: ComponentType<any>
  export const Badge: ComponentType<any>
  export const Box: ComponentType<any>
  export const Button: ComponentType<any>
  export const Card: ComponentType<any>
  export const Dropdown: ComponentType<any>
  export const EmptyState: ComponentType<any>
  export const IconArrowBack: ComponentType<any>
  export const IconEdit: ComponentType<any>
  export const Input: ComponentType<any>
  export const Modal: ComponentType<any>
  export const PageHeader: ComponentType<any>
  export const Pagination: ComponentType<any>
  export const Radio: ComponentType<any>
  export const Spinner: ComponentType<any>
  export const Tab: ComponentType<any>
  export const Table: ComponentType<any>
  export const Tabs: ComponentType<any>
  export const Toggle: ComponentType<any>
  export const Layout: ComponentType<any>
  export const PageBlock: ComponentType<any>
}

```


[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 admin-graphql-ide/react/utils/storage.ts from the admin-graphql-ide VTEX app.

[Assistant]
Here's the implementation:

```typescript
class ScopedStorage implements Storage {
  private keys: Set<string>

  constructor(
    private namespace: string
  ) {
    this.keys = new Set<string>()
  }

  public get length(): number {
    return this.keys.size
  }

  public setItem = (key: string, value: string) => {
    const scopedKey = this.addScope(key)
    this.keys.add(scopedKey)
    window.localStorage.setItem(scopedKey, value)
  }

  public clear = () => {
    this.keys.forEach(window.localStorage.removeItem)
  }

  public removeItem = (key: string) => window.localStorage.removeItem(this.addScope(key))

  public key = (index: number ) => window.localStorage.key(index)

  public getItem = (key: string) => window.localStorage.getItem(this.addScope(key))

  private addScope = (key: string) => `${this.namespace}::${key}`
}

const storage: Record<string, Storage> = {}

export const getOrCreateScopedStorage = (namespace: string) => {
  if (!storage[namespace]) {
    storage[namespace] = new ScopedStorage(namespace)
  }
  return storage[namespace]
}
```