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

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/Styleguide/components/Tooltip/TooltipPopup.tsx from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

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

import Portal from './Portal'
import { useRect } from './hooks'
import zIndex from '../utils/zIndex'
import style from './tooltip.css'

export type Position = 'top' | 'right' | 'bottom' | 'left'
export type Size = 'mini' | 'small'

const OFFSET = 8
const hasComputedDimensions = rect => rect && rect.width && rect.height

function getChildRefPropType() {
  if (typeof HTMLElement !== 'undefined') {
    return PropTypes.shape({ current: PropTypes.instanceOf(HTMLElement) })
  }
  return PropTypes.shape({ current: PropTypes.elementType })
}

const propTypes = {
  /** Tooltip content */
  label: PropTypes.node.isRequired,
  /** Tooltip position */
  position: PropTypes.oneOf<Position>(['top', 'bottom', 'left', 'right']),
  /** Tooltip font size */
  size: PropTypes.oneOf<Size>(['mini', 'small']),
  /** Fallback position (when the tooltip cannot appear in the original position) */
  fallbackPosition: PropTypes.oneOf<Position>([
    'top',
    'bottom',
    'left',
    'right',
  ]),
  /** Boolean to see if the popup should appear */
  visible: PropTypes.bool,
  /** Delay to show the tooltip */
  delay: PropTypes.number,
  /** Tooltip animation duration */
  duration: PropTypes.number,
  /** Tooltip timming function used to animate the tooltip */
  timmingFn: PropTypes.string,
  /** Child ref. Used to correctly position the tooltip */
  childRef: getChildRefPropType(),
}

const defaultProps = {
  visible: false,
}

const TooltipPopup: FC<PropTypes.InferProps<typeof propTypes>> = ({
  position,
  size,
  fallbackPosition,
  label,
  visible,
  delay,
  duration,
  timmingFn,
  childRef,
}) => {
  const [showPopup, setShowPopup] = useState(visible)
  const popupRef = useRef<HTMLDivElement>()
  const childRect = useRect(childRef, visible)
  const popupRect = useRect(popupRef, visible)

  useEffect(() => {
    if (visible) {
      setShowPopup(true)
    }
  }, [visible])

  const popupClasses = classNames(
    'absolute pv3 ph4 bg-base--inverted c-on-base--inverted br2 shadow-4 mw5 overflow-hidden',
    style.popup,
    {
      dn: !visible || !showPopup || !childRect || !popupRect,
      'o-0': !visible || !hasComputedDimensions(popupRect),
      'o-100': visible && hasComputedDimensions(popupRect),
      't-mini': size === 'mini',
      't-small': size === 'small',
    }
  )

  const positionStyle = getStyles(
    childRect,
    popupRect,
    position,
    fallbackPosition
  )

  return (
    <Portal>
      <div
        role="tooltip"
        className={popupClasses}
        style={{
          ...positionStyle,
          zIndex: zIndex.tooltip,
          transition: `opacity ${duration}ms ${timmingFn} ${delay}ms`,
        }}
        ref={popupRef}
        onTransitionEnd={() => setShowPopup(visible)}>
        {label}
      </div>
    </Portal>
  )
}

const getStyles = (childRect, popupRect, position, fallbackPosition) => {
  return childRect && popupRect && window && hasComputedDimensions(popupRect)
    ? getPopupPosition(childRect, popupRect, position, fallbackPosition)
    : { top: 0, left: 0 }
}

const FALLBACK_POSITION = {
  top: 'right',
  right: 'bottom',
  bottom: 'left',
  left: 'top',
}

const getFallbackPosition = (position, fallback) =>
  fallback || FALLBACK_POSITION[position]

const getPopupPosition = (childRect, popupRect, position, fallbackPosition) =>
  getPopupPositionRecursively(
    childRect,
    popupRect,
    position,
    fallbackPosition,
    position
  )
const getPopupPositionRecursively = (
  childRect,
  popupRect,
  position,
  fallbackPosition,
  originalPosition
) => {
  const horizontalMax = window.innerWidth + window.pageXOffset
  const verticalMax = window.innerHeight + window.pageYOffset
  const styles = {
    left:
      childRect.left +
      window.pageXOffset +
      (childRect.width - popupRect.width) / 2 +
      (position === 'right'
        ? (childRect.width + popupRect.width) / 2 + OFFSET
        : 0) -
      (position === 'left'
        ? (childRect.width + popupRect.width) / 2 + OFFSET
        : 0),
    top:
      childRect.top +
      window.pageYOffset -
      (position === 'top' ? popupRect.height + OFFSET : 0) +
      (position === 'bottom' ? childRect.height + OFFSET : 0) +
      (position === 'right' || position === 'left'
        ? (childRect.height - popupRect.height) / 2
        : 0),
  }

  const collisions = {
    top: styles.top < window.pageYOffset,
    right: styles.left + popupRect.width > horizontalMax,
    bottom: styles.top + popupRect.height > verticalMax,
    left: styles.left < window.pageXOffset,
  }

  if (collisions[position]) {
    fallbackPosition = getFallbackPosition(position, fallbackPosition)
    // If there is no place without collisions, it will not be shown
    return fallbackPosition === originalPosition
      ? null
      : getPopupPositionRecursively(
          childRect,
          popupRect,
          fallbackPosition,
          null,
          originalPosition
        )
  }

  const top = Math.max(
    window.pageYOffset + 1,
    Math.min(styles.top, verticalMax - popupRect.height - 1)
  )
  const left = Math.max(
    window.pageXOffset + 1,
    Math.min(styles.left, horizontalMax - popupRect.width - 1)
  )

  const transform = `translate3d(${Math.round(left)}px, ${Math.round(
    top - document.body.offsetHeight
  )}px, 0)`

  return {
    transform,
    WebkitTransform: transform,
  }
}

TooltipPopup.propTypes = propTypes
TooltipPopup.defaultProps = defaultProps

export default TooltipPopup

```


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

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/Styleguide/components/Tooltip/README.md from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```markdown
#### Tooltips are a small informative text that appear when an item is being, hovered, focused or touched.

### 👍 Dos

- Do use tooltips when you want to add a label to an specific icon.
- Do use tooltips when you want to add an informative text in situations where more clarification may be needed.

### 👎 Don'ts

- Don't change the tooltip colors.
- Don't use long texts in tooltips - a good character limit is 220.

#### Positioning tooltip

The position where the tooltip appears can be set and its fallback position too. By default the tooltip appears at the top and follows clockwise.

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

;

  <Tooltip label="Tooltip text">
    <Button variation="tertiary">Top</Button>
  </Tooltip>
  <Tooltip label="Tooltip text" position="left">
    <Button variation="tertiary">Left</Button>
  </Tooltip>
  <Tooltip label="Tooltip text" position="right">
    <Button variation="tertiary">Right</Button>
  </Tooltip>
  <Tooltip label="Tooltip text" position="bottom">
    <Button variation="tertiary">Bottom</Button>
  </Tooltip>

```

#### Label and Informative text

```jsx
const Edit = require('../icon/Edit').default
const Info = require('../icon/Info').default

;

    <Tooltip label="Edit">

        <Edit />

    </Tooltip>

    <Tooltip label="Lorem ipsum dolor sit amet, consectetur adipiscing elit.">

        <Info />

    </Tooltip>

```

#### Hover vs Focused

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

;

    <Tooltip label="Tooltip text">
      <Button variation="tertiary">Hover</Button>
    </Tooltip>

    <Tooltip label="Tooltip text" trigger="focus">
      <Button variation="tertiary">Focused</Button>
    </Tooltip>

```

```


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

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/Styleguide/components/Tooltip/Portal.tsx from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```tsx
import PropTypes from 'prop-types'
import React from 'react'
import ReactDOM from 'react-dom'

import { setRef } from '../utils/react'

function getContainer(container: any) {
  container = typeof container === 'function' ? container() : container
  // eslint-disable-next-line react/no-find-dom-node
  return ReactDOM.findDOMNode(container)
}

const useEnhancedEffect =
  typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect

const propTypes = {
  /**
   * The children to render into the `container`.
   */
  children: PropTypes.node,
  /**
   * A node, component instance, or function that returns either.
   * The `container` will have the portal children appended to it.
   * By default, it uses the body of the top-level document object,
   * so it's simply `document.body` most of the time.
   */
  container: PropTypes.oneOfType([
    PropTypes.func,
    PropTypes.instanceOf(React.Component),
    PropTypes.instanceOf(typeof Element === 'undefined' ? Object : Element),
  ]),
  /**
   * Callback fired once the children has been mounted into the `container`.
   */
  onRendered: PropTypes.func,
}

/**
 * Portals provide a first-class way to render children into a DOM node
 * that exists outside the DOM hierarchy of the parent component.
 */
const Portal = (props: PropTypes.InferProps<typeof propTypes>, ref) => {
  const { children, container, onRendered } = props
  const [mountNode, setMountNode] = React.useState(null)

  useEnhancedEffect(() => {
    setMountNode(getContainer(container) || document.body)
  }, [container])

  useEnhancedEffect(() => {
    if (mountNode) {
      setRef(ref, mountNode)
      return () => {
        setRef(ref, null)
      }
    }

    return undefined
  }, [ref, mountNode])

  useEnhancedEffect(() => {
    if (onRendered && mountNode) {
      onRendered()
    }
  }, [onRendered, mountNode])

  return mountNode ? ReactDOM.createPortal(children, mountNode) : mountNode
}

Portal.propTypes = propTypes

export default React.forwardRef<
  HTMLElement,
  PropTypes.InferProps<typeof propTypes>
>(Portal as 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 store-on-localhost/src/monobloco/components/new/Styleguide/components/Tooltip/hooks.ts from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```typescript
import get from 'lodash/get'
import { RefObject, useState, useRef, useLayoutEffect } from 'react'

import observeRect from './utils/dom'
import { setRef } from '../utils/react'

export type Trigger = 'click' | 'hover' | 'focus'

export function useRect(nodeRef, observe = true) {
  const [rect, setRect] = useState(null)
  const observerRef = useRef(null)
  useLayoutEffect(() => {
    if (!observerRef.current && nodeRef.current) {
      observerRef.current = observeRect(nodeRef.current, setRect)
    }
    if (observerRef.current && observe) {
      observerRef.current.observe()
    }
    return () => observerRef.current && observerRef.current.unobserve()
  }, [observe, nodeRef])
  return rect
}

export function useTooltip({
  trigger,
}: {
  trigger?: Trigger
} = {}): [
  (c: React.ReactElement) => object,
  { childRef: RefObject<HTMLElement>; visible: boolean }
] {
  const childRef = useRef<HTMLElement>()
  const [visible, setVisible] = useState(false)
  const handleTooltip = (
    child: React.ReactElement & { ref?: RefObject<HTMLElement> }
  ) => {
    return {
      ref: node => {
        // Keep your own reference
        if (node) {
          setRef(childRef, node)
        }
        // Call the original ref, if any
        setRef(child.ref, node)
      },
      ...(trigger === 'hover'
        ? {
            onMouseEnter: (...args) => {
              setVisible(true)
              const onMouseEnter = get(child, 'props.onMouseEnter')
              if (onMouseEnter) {
                return onMouseEnter.call(child.props, ...args)
              }
            },
            onMouseLeave: (...args) => {
              setVisible(false)
              const onMouseLeave = get(child, 'props.onMouseLeave')
              if (onMouseLeave) {
                return onMouseLeave.call(child.props, ...args)
              }
            },
          }
        : {}),
      ...(trigger === 'click' || trigger === 'focus'
        ? {
            onClick: (...args) => {
              // Firefox and Safari, both on Mac OS, doesn't focus on click, like
              // Google Chrome does, so...
              if (childRef.current) {
                childRef.current.focus()
              }
              const onClick = get(child, 'props.onClick')
              if (onClick) {
                return onClick.call(child.props, ...args)
              }
            },
            onFocus: (...args) => {
              setVisible(true)
              const onFocus = get(child, 'props.onFocus')
              if (onFocus) {
                return onFocus.call(child.props, ...args)
              }
            },
            onBlur: (...args) => {
              setVisible(false)
              const onBlur = get(child, 'props.onBlur')
              if (onBlur) {
                return onBlur.call(child.props, ...args)
              }
            },
          }
        : {}),
    }
  }
  return [handleTooltip, { childRef, visible }]
}

```


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

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

[Assistant]
Here's the implementation:

```tsx
import { useMemo, useCallback, useEffect, useReducer, useState } from 'react'
import PropTypes from 'prop-types'
import isEmpty from 'lodash/isEmpty'

import { getFlat } from './util'
import { defaultComparatorCurry, ROOT_KEY, ROOT_VALUE } from './constants'
import { useCheckboxesInput, Tree } from './types'
import reducer, { ActionType } from './reducer'

export default function useCheckboxTree<T>({
  items,
  onToggle,
  nodesKey = 'children',
  checked = [],
  comparator = defaultComparatorCurry,
  isDisabled = (_: T | Tree<T>) => false,
}: useCheckboxesInput<T>) {
  const [checkedItems, dispatch] = useReducer(reducer, checked)
  const [lastToggledItem, setLastToggledItem] = useState(null)

  const itemTree = useMemo(() => {
    return { [ROOT_KEY]: ROOT_VALUE, [nodesKey]: items }
  }, [items, nodesKey])

  const disabledItems = useMemo(() => {
    return getFlat(itemTree).filter(isDisabled)
  }, [isDisabled, itemTree])

  const toggle = useCallback(
    (item: T | Tree<T>): void => {
      if (!isDisabled(item)) {
        dispatch({
          type: ActionType.Toggle,
          itemToToggle: { item, nodesKey, comparator },
          isDisabled,
        })
        setLastToggledItem(item)
      }
    },
    [comparator, isDisabled, nodesKey]
  )

  useEffect(() => {
    onToggle && onToggle({ checkedItems, disabledItems, item: lastToggledItem })
  }, [checkedItems, disabledItems, lastToggledItem, onToggle, toggle])

  const toggleAll = useCallback(() => {
    toggle(itemTree)
  }, [itemTree, toggle])

  useEffect(() => {
    const shake = (tree: Tree<T>) => {
      const childNodes = tree[nodesKey] as Array<T>

      if (!childNodes || isEmpty(childNodes)) return

      const childrenChecked = childNodes
        .filter(childNode => !isDisabled(childNode))
        .every(childNode => checkedItems.some(comparator(childNode)))

      const rootChecked = checkedItems.some(comparator(tree))

      if (childrenChecked && !rootChecked && !isDisabled(tree))
        dispatch({ type: ActionType.Check, item: tree })

      if (!childrenChecked && rootChecked)
        dispatch({
          type: ActionType.Uncheck,
          itemToToggle: { item: tree, comparator },
        })

      childNodes.forEach(shake)
    }
    shake(itemTree)
  }, [checkedItems, toggle, itemTree, nodesKey, comparator, isDisabled])

  const isChecked = useCallback(
    (item: T | Tree<T>) => {
      const children = item[nodesKey]
      const onCheckedList = (item: T | Tree<T>) =>
        checkedItems.some(comparator(item))
      const notDisabled = (item: T | Tree<T>) => !isDisabled(item)

      const notDisabledChildren = children && children.filter(notDisabled)
      const notEmpty = !!notDisabledChildren && !isEmpty(notDisabledChildren)

      return notEmpty
        ? notDisabledChildren.every(onCheckedList)
        : checkedItems.some(comparator(item))
    },
    [checkedItems, comparator, isDisabled, nodesKey]
  )

  const isPartiallyChecked = useCallback(
    (item: T | Tree<T>) => {
      return (
        !isDisabled(item) &&
        item[nodesKey] &&
        getFlat(item, [], nodesKey)
          .slice(1)
          .some(child => checkedItems.some(comparator(child)))
      )
    },
    [checkedItems, comparator, isDisabled, nodesKey]
  )

  const allChecked = useMemo(() => {
    return isChecked(itemTree)
  }, [isChecked, itemTree])

  const someChecked = useMemo(() => {
    return checkedItems.length > 0
  }, [checkedItems])

  const allDisabled = useMemo(() => {
    return isDisabled(itemTree)
  }, [isDisabled, itemTree])

  const check = (item: T | Tree<T>) => {
    if (!isDisabled(item))
      dispatch({
        type: ActionType.BulkCheck,
        itemToToggle: { item, comparator, nodesKey },
        isDisabled,
      })
  }

  const checkAll = () => check(itemTree)

  const uncheck = useCallback(
    (item: T | Tree<T>) => {
      if (!isDisabled(item))
        dispatch({
          type: ActionType.BulkUncheck,
          itemToToggle: { item, comparator, nodesKey },
        })
    },
    [comparator, isDisabled, nodesKey]
  )

  const uncheckAll = useCallback(() => {
    uncheck(itemTree)
  }, [itemTree, uncheck])

  const setChecked = (checked: Array<T>) => {
    dispatch({ type: ActionType.SetChecked, checked })
  }

  return {
    checkedItems,
    isChecked,
    allChecked,
    allDisabled,
    someChecked,
    isPartiallyChecked,
    itemTree,
    toggle,
    toggleAll,
    check,
    checkAll,
    uncheck,
    uncheckAll,
    isDisabled,
    disabledItems,
    setChecked,
    lastToggledItem,
  }
}

export const checkboxesPropTypes = {
  checkboxes: PropTypes.shape({
    checkedItems: PropTypes.arrayOf(
      PropTypes.shape({
        id: PropTypes.string,
      })
    ),
    itemTree: PropTypes.shape({
      id: PropTypes.string,
    }),
    toggle: PropTypes.func,
    isChecked: PropTypes.func,
    isPartiallyChecked: PropTypes.func,
  }),
}

```


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

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/Styleguide/components/EXPERIMENTAL_useCheckboxTree/README.md from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```markdown
💡 If you want a detailed explanation of each input/output, proceed to the `Detailed Props` section.

The `EXPERIMENTAL_useChecbokTree` is a hook to helps to hold state the state of checkboxes lists or trees. The following documentation exposes some examples of usage to give you an overview of how it works. To better structure our examples, let's imagine that we have a collection of clothes featuring the props `id`, `name`, `color` and `qtd` (for quantity). It is desired to select each one separately or all of them with a single checkbox (root):

```js
const useCheckboxTree = require('./index.tsx').default
const Checkbox = require('../Checkbox/index.js').default

const ID_PREFIX = 'simple-example'

function SimpleExample() {
  const items = [
    { id: 'one', name: 'jacket', color: 'red', qtd: 12 },
    { id: 'two', name: 'shirt', color: 'pink', qtd: 0 },
    { id: 'three', name: 'sweater', color: 'blue', qtd: 8 },
    { id: 'four', name: 'hat', color: 'purple', qtd: 0 },
  ]

  const checkboxes = useCheckboxTree({
    items,
  })

  return (
    <>

        <Checkbox
          id={`${ID_PREFIX}-${checkboxes.itemTree.id}`}
          checked={checkboxes.allChecked}
          partial={checkboxes.someChecked}
          onChange={checkboxes.toggleAll}
          label="Clothes"
        />

        {checkboxes.itemTree.children.map(item => {
          const id = `${ID_PREFIX}-${item.id}`
          const label = `${item.qtd} ${item.color} ${item.name}${
            item.qtd > 1 ? 's' : ''
          } left`
          return (
            <Checkbox
              key={id}
              id={id}
              label={label}
              checked={checkboxes.isChecked(item)}
              partial={checkboxes.isPartiallyChecked(item)}
              disabled={checkboxes.isDisabled(item)}
              onChange={() => checkboxes.toggle(item)}
            />
          )
        })}

    </>
  )
}
;<SimpleExample />
```

### Handling disabled items

The disabled items are controlled by the `isDisabled` function, that receives an item as param. In the following example, an item should be disabled if the quantity is below 1.

```js
const useCheckboxTree = require('./index.tsx').default
const Checkbox = require('../Checkbox/index.js').default

const ID_PREFIX = 'disabled-example'

function DisabledExample() {
  const items = [
    { id: 'one', name: 'jacket', color: 'red', qtd: 12 },
    { id: 'two', name: 'shirt', color: 'pink', qtd: 0 },
    { id: 'three', name: 'sweater', color: 'blue', qtd: 8 },
    { id: 'four', name: 'hat', color: 'purple', qtd: 0 },
  ]

  const checkboxes = useCheckboxTree({
    items,
    isDisabled: item => item.qtd < 1,
  })

  return (
    <>

        <Checkbox
          id={`${ID_PREFIX}-${checkboxes.itemTree.id}`}
          checked={checkboxes.allChecked}
          partial={checkboxes.someChecked}
          onChange={checkboxes.toggleAll}
          label="Clothes"
        />

        {checkboxes.itemTree.children.map(item => {
          const id = `${ID_PREFIX}-${item.id}`
          const label = `${item.qtd} ${item.color} ${item.name}${
            item.qtd > 1 ? 's' : ''
          } left`
          return (
            <Checkbox
              key={id}
              id={id}
              label={label}
              checked={checkboxes.isChecked(item)}
              partial={checkboxes.isPartiallyChecked(item)}
              disabled={checkboxes.isDisabled(item)}
              onChange={() => checkboxes.toggle(item)}
            />
          )
        })}

    </>
  )
}
;<DisabledExample />
```

### Granting unicity

Unicity should be granted by the `comparator` curry, in which the curried parameters are two items and must return true if items are equal. In the example above there are some items with repeated `id`s, so we define a comparator that compares `id` and `color`.

⚠If you encounter a collection that contains deep equal items, a good solution is to map it into a new collection adding a prop to grants unicity, and then use the comparator function.

```js
const useCheckboxTree = require('./index.tsx').default
const Checkbox = require('../Checkbox/index.js').default

const ID_PREFIX = 'comparator-example'

function ComparatorExample() {
  const items = [
    { id: 'one', name: 'jacket', color: 'red', qtd: 12 },
    { id: 'one', name: 'shirt', color: 'pink', qtd: 0 },
    { id: 'one', name: 'sweater', color: 'blue', qtd: 8 },
    { id: 'four', name: 'hat', color: 'purple', qtd: 0 },
  ]

  const checkboxes = useCheckboxTree({
    items,
    comparator: item => candidate =>
      item.id === candidate.id && item.color === candidate.color,
  })

  return (
    <>

        <Checkbox
          id={`${ID_PREFIX}-${checkboxes.itemTree.id}`}
          checked={checkboxes.allChecked}
          partial={checkboxes.someChecked}
          onChange={checkboxes.toggleAll}
          label="Clothes"
        />

        {checkboxes.itemTree.children.map(item => {
          const id = `${ID_PREFIX}-${item.id}-${item.color}`
          const label = `${item.qtd} ${item.color} ${item.name}${
            item.qtd > 1 ? 's' : ''
          } left`
          return (
            <Checkbox
              key={id}
              id={id}
              label={label}
              checked={checkboxes.isChecked(item)}
              partial={checkboxes.isPartiallyChecked(item)}
              onChange={() => checkboxes.toggle(item)}
            />
          )
        })}

    </>
  )
}
;<ComparatorExample />
```

### Nested Items

Your items can be trees of any depth as well. To control which prop contains the nested items ('related' in our example) use the `nodesKey` input. You can also define default checked items with the `checked` input.

```js
const useCheckboxTree = require('./index.tsx').default
const Checkbox = require('../Checkbox/index.js').default

const ID_PREFIX = 'tree-example'

function TreeExample() {
  const items = [
    {
      id: '1',
      name: 'jacket',
      color: 'red',
      qtd: 12,
      related: [
        { id: '1.1', name: 'sweater', color: 'blue', qtd: 8 },
        {
          id: '1.2',
          name: 'shirt',
          color: 'pink',
          qtd: 1,
          related: [
            { id: '1.2.1', name: 't-shirt', color: 'lime', qtd: 2 },
            { id: '1.2.2', name: 'shirt', color: 'pink', qtd: 2 },
          ],
        },
      ],
    },
    {
      id: '2',
      name: 'hat',
      color: 'purple',
      qtd: 10,
      related: [
        { id: '2.1', name: 'cap', color: 'black', qtd: 17 },
        { id: '2.2', name: 'bandana', color: 'green', qtd: 6 },
      ],
    },
  ]

  const checkboxes = useCheckboxTree({
    items,
    nodesKey: 'related',
    checked: [
      { id: '1.2.2', name: 'shirt', color: 'pink', qtd: 2 },
      { id: '2.2', name: 'bandana', color: 'green', qtd: 6 },
    ],
  })

  function recursiveRender(item, depth = 0) {
    const id = `${ID_PREFIX}-${item.id}`
    const label = `${item.qtd} ${item.color} ${item.name}${
      item.qtd > 1 ? 's' : ''
    } left`

    const containerProps = {
      className: 'mt3',
      style: { marginLeft: 18 * depth },
    }

    return item.related ? (

        <Checkbox
          key={id}
          id={id}
          label={label}
          checked={checkboxes.isChecked(item)}
          partial={checkboxes.isPartiallyChecked(item)}
          onChange={() => checkboxes.toggle(item)}
        />
        {item.related.map(related => recursiveRender(related, depth + 1))}

    ) : (

        <Checkbox
          key={id}
          id={id}
          label={label}
          checked={checkboxes.isChecked(item)}
          partial={checkboxes.isPartiallyChecked(item)}
          onChange={() => checkboxes.toggle(item)}
        />

    )
  }

  return (
    <>

        <Checkbox
          id={`${ID_PREFIX}-${checkboxes.itemTree.id}`}
          checked={checkboxes.allChecked}
          partial={checkboxes.someChecked}
          onChange={checkboxes.toggleAll}
          label="Clothes - Select All"
        />

        {checkboxes.itemTree.related.map(item => recursiveRender(item))}

    </>
  )
}
;<TreeExample />
```

## Detailed props

#### Input

The `useCheckboxTree` hook receives a single object as a parameter, which contains the following props:

##### items

- Represents the items of your collection. Each one will be related to a single checkbox and may be toggled by parents.
- **Type**: `Array<T>`
- ⚠This property is required!

##### nodesKey

- Name of the property that contains the nested items, which is children by default.
- Type: `string`
- **Default**: `'children'`

##### checked

- List of items that are checked by default.
- Type: `Array<T>`
- **Default**: `[]`

##### comparator

- The curry that defines the condition that makes an item unique in the collection. You MUST grant item unicity! If the comparator condition is ambiguous the toggle algorithm will not work as it supposed to.
- **Type**: `(item: T) => (candidante: T) => boolean`
- **Default**: `(item: T) => (candidante: T) => item.id === candidate.id`

##### onToggle

- Funtion that is called on every item toggle.
- **Type**: `({ checkedItems: T[], disabledItems: T[] }) => void`
- **Default**: `undefined`

##### isDisabled

- Function that defines a item disabled or not. Returns `true` for a disabled item
- **Type**: `(item: T | Tree<T>) => boolean`
- **Default**: `() => false`

#### Output

Similarly to input, the output is also a single object. All the exported properties are either states, memos or callbacks - meaning that you can safely include then as dependencies of your custom effects. They are so many to support a large number of use cases, and normally you will not need all of them to reach your solution.

##### itemTree

- Parsed tree that has the shape:

```ts
type Tree<T>{
  id: 'VTEX_CheckboxTreeRoot' //id of the root
  [nodesKey]: T[] //Your items will be here
}
```

- **Type**: `Tree<T>`.

##### checkedItems

- Current list of items that are checked (including the root).
- **Type**: `Array<T>`.

##### disabledItems

- List of items that are disabled
- **Type**: `Array<T>`

##### isChecked

- If a item is checked or not
- **Type**: `(item: T | Tree<T>) => boolean`

##### isPartiallyChecked

- Return if an item or a tree is checked partially
- **Type**: `(item: T | Tree<T>) => boolean`

##### allChecked

- Returns true if all the items are checked
- **Type**: `boolean`

##### someChecked

- Returns true if one some item is checked
- **Type**: `boolean`

##### toggle

- Bulk toggle one item or a tree
- **Type**: `(item: T | Tree<T>) => void`

##### check

- Bulk checks one item or tree
- **Type**: `(item: T | Tree<T>) => void`

##### uncheck

- Bulk unchecks one item or tree
- **Type**: `(item: T | Tree<T>) => void`

##### toggleAll

- Toggle the root
- **Type**: `() => void`

##### checkAll

- Check the root
- **Type**: `() => void`

##### uncheckAll

- Uncheck the root
- **Type**: `() => void`

##### setChecked

- Sets the current `checkedItems`
- **Type**: `(checked: Array<T>) => 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 store-on-localhost/src/monobloco/components/new/Styleguide/components/EXPERIMENTAL_useCheckboxTree/types.ts from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ROOT_KEY } from './constants'
import useCheckboxTree from '.'

export type ChildKey<T> = { [key: string]: Array<T> }

export type comparatorCurry<T> = (item: T) => (candidate: T) => boolean

export type Checkboxes<T> = ReturnType<typeof useCheckboxTree>

export type Tree<T> = { [x: string]: string | T[]; [ROOT_KEY]: string } | T

export type toggleCallback<T> = {
  checkedItems: Array<unknown>
  disabledItems: Array<T>
  item: T | Tree<T>
}

export type useCheckboxesInput<T> = {
  items: Array<T>
  onToggle?: (callback: toggleCallback<T>) => void
  nodesKey?: string
  checked?: Array<T>
  comparator?: comparatorCurry<Tree<T>>
  isDisabled?: (item: T | Tree<T>) => boolean
}

```


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

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/Styleguide/components/EXPERIMENTAL_useCheckboxTree/reducer.ts from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { getBulkChecked, getBulkUnchecked, getToggledState } from './util'
import { comparatorCurry, Tree } from './types'

export default function reducer<T>(state: Array<T>, action: Action<T>) {
  switch (action.type) {
    case ActionType.Check: {
      const { item } = action
      return [...state, item]
    }
    case ActionType.Uncheck: {
      const {
        itemToToggle: { item, comparator },
      } = action
      const rowFilter = (row: T) => !comparator(row)(item)
      return state.filter(rowFilter)
    }
    case ActionType.BulkCheck: {
      const { itemToToggle, isDisabled } = action
      if (!itemToToggle) return state
      const { item, nodesKey, comparator } = itemToToggle
      return getBulkChecked(state, item, nodesKey, comparator, isDisabled)
    }
    case ActionType.BulkUncheck: {
      const { itemToToggle } = action
      if (!itemToToggle) return state
      const { item, nodesKey, comparator } = itemToToggle
      return getBulkUnchecked(state, item, nodesKey, comparator)
    }
    case ActionType.Toggle: {
      const { itemToToggle, isDisabled } = action
      if (!itemToToggle) return state
      const { item, nodesKey, comparator } = itemToToggle
      return getToggledState(state, item, nodesKey, comparator, isDisabled)
    }
    case ActionType.SetChecked: {
      const { checked } = action
      return checked || state
    }
    default: {
      return state
    }
  }
}

export enum ActionType {
  Check,
  Uncheck,
  Toggle,
  BulkCheck,
  BulkUncheck,
  SetChecked,
}

export type Action<T> = {
  type: ActionType
  item?: T
  checked?: Array<T>
  itemToToggle?: {
    item: T
    nodesKey?: string
    comparator?: comparatorCurry<T>
  }
  isDisabled?: (item: T | Tree<T>) => boolean
}

```


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

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/Styleguide/components/EXPERIMENTAL_useCheckboxTree/constants.ts from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```typescript
type ItemWithID = {
  id: string
}

export const defaultComparatorCurry = (item: ItemWithID) => (
  candidate: ItemWithID
) => item.id === candidate.id

export const ROOT_KEY = 'id'
export const ROOT_VALUE = 'VTEX_CheckboxTreeRoot'

```


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

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/Styleguide/components/EXPERIMENTAL_useCheckboxTree/util.ts from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { comparatorCurry, Tree } from './types'

/**
 * Checks nested items
 * @param checked
 * @param item
 * @param nodesKey
 * @param comparator
 */
export function getBulkChecked<T>(
  checked: Array<Tree<T>>,
  item: T,
  nodesKey = 'children',
  comparator: comparatorCurry<Tree<T>>,
  isDisabled: (item: T | Tree<T>) => boolean
): Array<Tree<T>> {
  const notDisabled = (item: T | Tree<T>) => !isDisabled(item)
  return [...checked, ...getFlat(item, [], nodesKey)]
    .filter(notDisabled)
    .reduce(
      (acc: Array<Tree<T>>, item: T) =>
        acc.some(comparator(item)) ? acc : [...acc, item],
      []
    ) as Array<Tree<T>>
}

/**
 * Unchecks nested items
 * @param checked
 * @param item
 * @param nodesKey
 * @param comparator
 */
export function getBulkUnchecked<T>(
  checked: Array<Tree<T>>,
  item: T,
  nodesKey = 'children',
  comparator: comparatorCurry<Tree<T>>
): Array<Tree<T>> {
  const flatCurry = (item: T, nodesKey: string) => getFlat(item, [], nodesKey)
  const flat = flatCurry(item, nodesKey)
  const bulkFilter = (row: T) => !flat.some(comparator(row))
  return checked.filter(bulkFilter)
}

/**
 * Return new state with items toggled
 * @param state
 * @param item
 */
export function getToggledState<T>(
  state: Array<Tree<T>>,
  item: T,
  nodesKey = 'children',
  comparator: comparatorCurry<Tree<T>>,
  isDisabled: (item: T | Tree<T>) => boolean
): Array<Tree<T>> {
  const stateIncludesItem = state.some(comparator(item))
  const filter = (row: T) => !comparator(row)(item)

  if (stateIncludesItem) {
    return item[nodesKey]
      ? getBulkUnchecked<T>(state, item, nodesKey, comparator)
      : state.filter(filter)
  }
  return item[nodesKey]
    ? getBulkChecked<T>(state, item, nodesKey, comparator, isDisabled)
    : ([...state, item] as Array<Tree<T>>)
}

/**
 * Represents a tree section on a single array.
 */
export function getFlat<T>(
  tree: Tree<T>,
  arr: Array<Tree<T>> = [],
  nodesKey = 'children'
): Array<T> {
  arr.push(tree)
  if (tree[nodesKey])
    (tree[nodesKey] as Array<Tree<T>>).forEach(child =>
      getFlat(child, arr, nodesKey)
    )
  return arr as T[]
}

```


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

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

[Assistant]
Here's the implementation:

```tsx
import React, { FC } from 'react'
import PropTypes, { InferProps } from 'prop-types'

const propTypes = {
  /** Content of the box */
  children: PropTypes.node.isRequired,
  /** Use the full size of the box. */
  noPadding: PropTypes.bool,
  /** Title to the box */
  title: PropTypes.string,
}

type Props = InferProps<typeof propTypes>

const Box: FC<Props> = ({ children, noPadding, title }) => {
  const padding = noPadding ? '' : 'pa7'
  return (
    <div
      className={`styleguide__box bg-base t-body c-on-base ${padding} br3 b--muted-4 ba`}>
      {title && <h3 className="t-heading-4 mt0">{title}</h3>}
      {children}
    </div>
  )
}

Box.propTypes = propTypes

export default Box

```


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

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/Styleguide/components/Box/README.md from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```markdown
#### A simple container for organizing stuff of any sizes or hierarchies.

### 👎 Don'ts

- Don't make the whole box as a big interactable area, use a <a href="#/Components/Containers/Card">Card</a> for that.

```
<div className="bg-muted-5 pa8">
  <Box title="Lorem ipsum">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse convallis leo id tellus commodo tincidunt. Pellentesque et blandit risus. Duis rhoncus neque odio, quis suscipit lectus venenatis non. Vivamus ornare aliquet facilisis. Nullam eu lacinia felis. Proin dapibus consequat erat, vel aliquam urna commodo a.
  </Box>
</div>
```
```


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

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

[Assistant]
Here's the implementation:

```javascript
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import NumberFormat from 'react-number-format'

import Input from '../Input'
import { withForwardedRef, refShape } from '../../modules/withForwardedRef'

/** WORKAROUND incoming!
 * BaseInput is a wrapper for the Input component for being able to use the
 * prefix prop with the NumberFormat component.
 * We can remove this as soon as the following issue is resolved:
 * https://github.com/s-yadav/react-number-format/issues/276
 *
 */
const BaseInput = props => {
  const { inputPrefix: prefix, inputSuffix: suffix, inputRef: ref } = props

  return <Input {...props} prefix={prefix} suffix={suffix} ref={ref} />
}

BaseInput.propTypes = {
  inputPrefix: PropTypes.string,
  inputSuffix: PropTypes.string,
  inputRef: refShape,
}

const baseNumber = 9999999999.9999999999

class InputCurrency extends Component {
  handleChange = ({ floatValue }) => {
    const { onChange } = this.props
    onChange &&
      onChange({
        ...event,
        target: {
          ...event.target,
          value: floatValue,
        },
      })
  }

  render() {
    const {
      locale,
      currencyCode,
      forwardedRef,
      /** We exclude the onChange event because
       * NumberFormat uses onValueChange instead */
      /* eslint-disable-next-line no-unused-vars */
      onChange,
      ...props
    } = this.props

    const formatter = new Intl.NumberFormat(locale, {
      style: 'currency',
      currency: currencyCode,
    })

    const formattedParts = formatter.formatToParts
      ? formatter.formatToParts(baseNumber)
      : null
    const prefix = formattedParts
      ? !formattedParts.map(part => part.type).indexOf('currency')
      : true
    const [currencySymbol] = formattedParts
      ? formattedParts
          .filter(part => part.type === 'currency')
          .map(part => part.value)
      : ['$']
    const [decimalSeparator] = formattedParts
      ? formattedParts
          .filter(part => part.type === 'decimal')
          .map(part => part.value)
      : ['.']
    const [thousandSeparator] = formattedParts
      ? formattedParts
          .filter(part => part.type === 'group')
          .map(part => part.value)
      : [',']
    const [fraction] = formattedParts
      ? formattedParts
          .filter(part => part.type === 'fraction')
          .map(part => part.value)
      : ['99']

    return (
      <div>
        <NumberFormat
          {...props}
          inputRef={forwardedRef}
          inputPrefix={prefix ? currencySymbol : null}
          inputSuffix={prefix ? null : currencySymbol}
          decimalSeparator={decimalSeparator || false}
          decimalScale={fraction ? fraction.length : 0}
          fixedDecimalScale={!!decimalSeparator}
          thousandSeparator={thousandSeparator}
          onValueChange={this.handleChange}
          customInput={BaseInput}
        />
      </div>
    )
  }
}

InputCurrency.propTypes = {
  /** @ignore Forwarded Ref */
  forwardedRef: refShape,
  /** _onChange event. You can get the numeric value of the input from the event
   * as _event.target.floatValue_ */
  onChange: PropTypes.func,
  onClear: PropTypes.func,
  size: PropTypes.string,
  defaultValue: PropTypes.number,
  value: PropTypes.number,
  /** Locale ISO string ('en-US', 'pt-BR', etc.)*/
  locale: PropTypes.string.isRequired,
  /** Currency code in ISO 4217 ('USD', 'BRL', etc.) */
  currencyCode: PropTypes.string.isRequired,
}

export default withForwardedRef(InputCurrency)

```


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

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/Styleguide/components/InputCurrency/README.md from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```markdown
#### InputCurrency lets an user easily enter monetary values. The component understands currency codes and locales, so it can automatically format the input with the correct combination of commas, periods, etc.

Sizes

```js
initialState = { value: undefined }
;

    <InputCurrency
      label="Small"
      size="small"
      placeholder="Type a monetary value"
      locale="pt-BR"
      currencyCode="BRL"
      value={state.value}
      onChange={e => setState({ value: e.target.value })}
    />

    <InputCurrency
      label="Regular"
      placeholder="Type a monetary value"
      locale="pt-BR"
      currencyCode="BRL"
      value={state.value}
      onChange={e => setState({ value: e.target.value })}
    />

    <InputCurrency
      label="Large"
      size="large"
      placeholder="Type a monetary value"
      locale="pt-BR"
      currencyCode="BRL"
      value={state.value}
      onChange={e => setState({ value: e.target.value })}
    />

```

Currency variations

```js
const Dropdown = require('../Dropdown/index.js').default
class InputExamples extends React.Component {
  constructor() {
    super()
    this.state = {
      value: undefined,
      selectedCurrency: 'USD',
      currencyOptions: [
        {
          label: 'Real',
          value: 'BRL',
        },
        {
          label: 'US Dollar',
          value: 'USD',
        },
        {
          label: 'Euro',
          value: 'EUR',
        },
        {
          label: 'Yen',
          value: 'JPY',
        },
      ],
    }
  }

  render() {
    const { currencyOptions, selectedCurrency, value } = this.state

    return (

          <Dropdown
            label="Currency"
            options={currencyOptions}
            value={selectedCurrency}
            onChange={(e, value) => this.setState({ selectedCurrency: value })}
          />

          <InputCurrency
            label="Product value"
            placeholder="Type a monetary value"
            locale="pt-BR"
            currencyCode={selectedCurrency}
            value={value}
            onChange={e => this.setState({ value: e.target.value })}
          />

    )
  }
}
;<InputExamples />
```

```


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

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/Styleguide/components/EXPERIMENTAL_Conditions/Statement.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

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

import Button from '../Button'
import IconClose from '../icon/Close'
import SubjectAtom from './Atoms/SubjectAtom'
import VerbAtom from './Atoms/VerbAtom'
import ObjectAtom from './Atoms/ObjectAtom'

class Statement extends React.Component {
  constructor(props) {
    super(props)
    this.handleChangeStatement(
      {
        subject: React.createRef(),
        verb: React.createRef(),
        object: React.createRef(),
      },
      'refs'
    )
  }

  handleChangeStatement = (newValue, structure) => {
    this.props.onChangeStatement(newValue, structure)
  }

  handleRemoveStatement = () => {
    this.props.onRemoveStatement()
  }

  getChoiceBySubject = subject => {
    const { options } = this.props
    return options[subject]
  }

  resetPredicate = subjectValue => {
    const { options } = this.props

    this.handleChangeStatement(
      options[subjectValue].verbs[0].value ||
        Statement.defaultProps.statements[0].verb,
      'verb'
    )

    this.handleChangeStatement(
      Statement.defaultProps.statements[0].object,
      'object'
    )

    this.handleChangeStatement(null, 'error')
  }

  clearObjects = () => {
    this.handleChangeStatement(
      Statement.defaultProps.statements[0].object,
      'object'
    )
    this.handleChangeStatement(null, 'error')
  }

  render() {
    const {
      canDelete,
      options,
      subjectPlaceholder,
      isRtl,
      isFullWidth,
      statements,
      statementIndex,
      labels,
      onChangeObjectCallback,
    } = this.props
    const condition = statements[statementIndex]
    const atomProps = {
      statements: statements,
      options: options,
      isFullWidth: isFullWidth,
      statementIndex: statementIndex,
      onChangeObjectCallback,
    }

    const statementAtoms = [
      <SubjectAtom
        ref={condition.refs.subject}
        key="subject"
        {...atomProps}
        placeholder={subjectPlaceholder}
        onChangeStatement={(value, structure) => {
          this.handleChangeStatement(value, structure)
          this.resetPredicate(value)
        }}
      />,
      <VerbAtom
        ref={condition.refs.verb}
        key="verb"
        {...atomProps}
        onChangeStatement={(value, structure) => {
          this.handleChangeStatement(value, structure)
        }}
      />,
      <ObjectAtom key="object" {...atomProps} />,
    ]

    return (
      <div>
        <div className="flex-column w-100 mv3">
          <div
            className={`flex w-100 items-start ${
              isFullWidth ? 'flex-column items-stretch' : ''
            }`}>
            {canDelete && !isFullWidth && isRtl && (
              <div
                className="ma3 c-muted-2 pointer hover-c-danger"
                onClick={this.handleRemoveStatement}>
                <IconClose size={25} />
              </div>
            )}
            {isRtl ? [...statementAtoms].reverse() : statementAtoms}
            {canDelete && !isFullWidth && !isRtl && (
              <div
                className="ma3 c-muted-2 pointer hover-c-danger"
                onClick={this.handleRemoveStatement}>
                <IconClose size={25} />
              </div>
            )}
            {canDelete && isFullWidth && (
              <div className="tr">
                <Button
                  variation="tertiary"
                  size="small"
                  onClick={this.handleRemoveStatement}>
                  <div className="dib">
                    <IconClose className="c-on-action-primary" />
                  </div>

                  <div className="dib mb1 v-mid" style={{ lineHeight: '10px' }}>
                    {labels.delete}
                  </div>
                </Button>
              </div>
            )}
          </div>
          {condition.error && condition.error.message && (
            <div className="red t-small mh3 mt2 lh-title">
              {condition.error.message}
            </div>
          )}
        </div>
      </div>
    )
  }
}

Statement.defaultProps = {
  onRemoveStatement: () => {},
  onChangeStatement: () => {},
  onChangeObjectCallback: () => {},
  canDelete: true,
  statements: [{ subject: '', verb: '', object: null }],
  isRtl: false,
  isFullWidth: false,
  statementIndex: 0,
  labels: { delete: 'DELETE' },
}

Statement.propTypes = {
  /** Shows or hides the delete button */
  canDelete: PropTypes.bool,
  /** Current selected options for this Statement */
  statements: PropTypes.arrayOf(
    PropTypes.shape({
      refs: PropTypes.shape({
        subject: PropTypes.string,
        verb: PropTypes.string,
        object: PropTypes.any,
      }),
      error: PropTypes.string,
    })
  ),
  /** Possible options and respective data types, verb options */
  options: PropTypes.object.isRequired,
  /** Placeholder for subject dropdown */
  subjectPlaceholder: PropTypes.string.isRequired,
  /** Stretch component to 100% of the width */
  isFullWidth: PropTypes.bool,
  /** Whether the order of elements and text if right to left */
  isRtl: PropTypes.bool,
  /** Statement change callback */
  onChangeStatement: PropTypes.func,
  /** Statement remove callback */
  onRemoveStatement: PropTypes.func,
  /** To which row does this Statement belong to?  */
  statementIndex: PropTypes.number,
  /** Labels for the controls and texts, default is english */
  labels: PropTypes.shape({
    delete: PropTypes.string,
  }),
  /** Please use the following one with caution, I did not test it, so it can break everything */
  onChangeObjectCallback: PropTypes.func,
}

export default Statement

```


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

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/Styleguide/components/EXPERIMENTAL_Conditions/StrategySelector.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

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

import IconCaretDown from '../icon/CaretDown'

class StrategySelector extends React.Component {
  handleOperatorChange = event => {
    const newOperator = event.target.value
    const { operator } = this.props
    if (operator !== newOperator) {
      this.props.onChangeOperator(newOperator)
    }
  }

  render() {
    const { labels } = this.props

    return (
      <div className="flex flex-row nowrap">
        <span>{labels.headerPrefix}</span>
        <div className="c-link relative">
          <span className="mh3 b">
            {this.props.operator === 'all'
              ? labels.operatorAll
              : labels.operatorAny}
          </span>
          <select
            className="o-0 absolute top-0 left-0 w-100 bottom-0 pointer t-small"
            onChange={this.handleOperatorChange}
            value={this.props.operator}
            style={{
              // safari select height fix
              WebkitAppearance: 'menulist-button',
            }}>
            <option value="all">{labels.operatorAll}</option>
            <option value="any">{labels.operatorAny}</option>
          </select>
          <IconCaretDown size={14} />
        </div>
        <span className="ml3">{labels.headerSufix}</span>
      </div>
    )
  }
}

StrategySelector.propTypes = {
  /** Operator indicates whether all the conditions should be met or any of them */
  operator: PropTypes.oneOf(['all', 'any']),
  /** Operator change callback: one of 'any', 'all' */
  onChangeOperator: PropTypes.func,
  /** Labels for the controls and texts, default is english */
  labels: PropTypes.shape({
    operatorAll: PropTypes.string,
    operatorAny: PropTypes.string,
    headerPrefix: PropTypes.string,
    headerSufix: PropTypes.string,
  }),
}

export default StrategySelector

```


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

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/Styleguide/components/EXPERIMENTAL_Conditions/Separator.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

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

class Separator extends React.Component {
  render() {
    const { label } = this.props

    return (
      <div>
        <div
          style={{
            marginLeft: -17,
            width: 'calc(100% + 34px)',
          }}
          className="flex flex-row w-100 nowrap items-center mv3">
          <hr className="ma0 b--black-10 bb bb-0 w-100" />
        </div>
        <div className="w-100 tc" style={{ marginTop: -18 }}>
          <span className="gray ph3 dib bg-white">{label}</span>
        </div>
      </div>
    )
  }
}

Separator.propTypes = {
  /** `and` or `or` label */
  label: PropTypes.string,
}

export default Separator

```


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

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

[Assistant]
Here's the implementation:

```javascript
/* eslint-disable camelcase */
import React from 'react'
import PropTypes from 'prop-types'

import Button from '../Button'
import IconPlus from '../icon/Plus'
import Separator from './Separator'
import StrategySelector from './StrategySelector'
import Statement from './Statement'

/**
 * @visibleName Conditions
 */
class EXPERIMENTAL_Conditions extends React.Component {
  static defaultProps = {
    operator: 'any',
    showOperator: true,
    statements: [],
    onChangeOperator: () => {},
    onChangeStatements: () => {},
    labels: {
      operatorAll: 'all',
      operatorAnd: 'and',
      operatorAny: 'any',
      operatorOr: 'or',
      headerPrefix: 'Matching',
      headerSufix: 'following conditions:',
      addConditionBtn: 'add condition',
      noConditions: 'No conditions selected.',
      addNewCondition: 'add new condition',
    },
  }

  objectIsEmpty = object => {
    if (object === undefined) return true
    if (object === null) return true
    if (object === '') return true
    if (Array.isArray(object) && object.length === 0) return true
    return false
  }

  canAddNewCondition = () => {
    const { statements } = this.props
    if (statements.length === 0) return true

    const hasIncompleteCondition = statements.some(
      condition =>
        condition.subject === '' ||
        condition.verb === '' ||
        this.objectIsEmpty(condition.object)
    )
    return !hasIncompleteCondition
  }

  handleAddNewCondition = () => {
    const emptyStatement = {
      subject: '',
      verb: '',
      object: null,
    }

    this.props.onChangeStatements([...this.props.statements, emptyStatement])
  }

  handleRemoveStatement = index => {
    const currentStatements = this.props.statements
    const updatedStatements = currentStatements
      .slice(0, index)
      .concat(currentStatements.slice(index + 1))

    this.props.onChangeStatements(updatedStatements)
  }

  handleChangeStatement = (statementIndex, newValue, structure) => {
    const updatedCurrentStatements = [...this.props.statements]
    if (structure === 'verb') {
      updatedCurrentStatements[statementIndex].object = null
    }
    updatedCurrentStatements[statementIndex][structure] = newValue
    this.props.onChangeStatements(updatedCurrentStatements)
  }

  componentDidMount() {
    console.warn(
      `Experimental component warning:

       Conditions component is in an experimental state.
       This component may suffer breaking changes in a near future, even in minor or patch versions.
       It may even cease to exist without further notice 👻`
    )
  }
  render() {
    const {
      canDelete,
      statements,
      options,
      subjectPlaceholder,
      isFullWidth,
      isRtl,
      labels,
      showOperator,
      operator,
    } = this.props

    return (
      <div>
        {showOperator && (
          <div className="mh6">
            <StrategySelector
              operator={operator}
              labels={labels}
              onChangeOperator={operator =>
                this.props.onChangeOperator({ operator })
              }
            />
          </div>
        )}

        <div className="t-body c-on-base ph5 mt4 br3 b--muted-4 ba">
          {this.props.statements.length === 0 ? (
            <div className="mv6 mh3">
              <span className="light-gray">{labels.noConditions}</span>
            </div>
          ) : (
            <div className="mv5">
              {statements.map((statement, statementIndex) => {
                return (
                  <div
                    className="flex flex-column w-100 mv3"
                    key={statementIndex}>
                    <Statement
                      canDelete={canDelete}
                      isRtl={isRtl}
                      isFullWidth={isFullWidth}
                      onChangeStatement={(newValue, structure) => {
                        this.handleChangeStatement(
                          statementIndex,
                          newValue,
                          structure
                        )
                      }}
                      onRemoveStatement={() =>
                        this.handleRemoveStatement(statementIndex)
                      }
                      options={options}
                      subjectPlaceholder={subjectPlaceholder}
                      statements={statements}
                      statementIndex={statementIndex}
                      labels={labels}
                    />

                    {statementIndex !== statements.length - 1 && (
                      <Separator
                        label={
                          operator === 'all'
                            ? labels.operatorAnd
                            : labels.operatorOr
                        }
                      />
                    )}
                  </div>
                )
              })}
            </div>
          )}

          <div
            style={{
              marginLeft: -17,
              width: 'calc(100% + 34px)',
            }}
            className="flex flex-row w-100 nowrap items-center mv3">
            <hr className="ma0 b--black-10 bb bb-0 w-100" />
          </div>

          <div style={{ marginLeft: -10 }} className="mv5">
            <Button
              variation="tertiary"
              size="small"
              disabled={!this.canAddNewCondition()}
              onClick={this.handleAddNewCondition}>
              <span className="flex align-baseline">
                <span className="mr2">
                  <IconPlus solid size={16} color="currentColor" />
                </span>
                {labels.addNewCondition}
              </span>
            </Button>
          </div>
        </div>
      </div>
    )
  }
}

EXPERIMENTAL_Conditions.propTypes = {
  /** Shows or hides the delete button */
  canDelete: PropTypes.bool,
  /** Operator indicates whether all the statements should be met or any of them */
  operator: PropTypes.oneOf(['all', 'any']),
  /** Current selected options for all statements */
  statements: PropTypes.arrayOf(
    PropTypes.shape({
      subject: PropTypes.string,
      verb: PropTypes.string,
      object: PropTypes.any,
      error: PropTypes.any,
    })
  ),
  /** Possible options and respective data types, verb options */
  options: PropTypes.object.isRequired,
  /** Placeholder for subject dropdown */
  subjectPlaceholder: PropTypes.string.isRequired,
  /** Wether to show this component stretched to the width */
  isFullWidth: PropTypes.bool,
  /** Conditions change callback: array of statement definitions */
  onChangeStatements: PropTypes.func,
  /** Operator (any, all) change callback  */
  onChangeOperator: PropTypes.func,
  /** Whether the order of elements and text if right to left */
  isRtl: PropTypes.bool,
  /** Show or hide the header that selects the operator (any vs all) */
  showOperator: PropTypes.bool,
  /** Labels for the controls and texts, default is english */
  labels: PropTypes.shape({
    addNewCondition: PropTypes.string,
    addConditionBtn: PropTypes.string,
    delete: PropTypes.string,
    noConditions: PropTypes.string,
    operatorAll: PropTypes.string,
    operatorAnd: PropTypes.string,
    operatorAny: PropTypes.string,
    operatorOr: PropTypes.string,
    headerPrefix: PropTypes.string,
    headerSufix: PropTypes.string,
  }),
}

export default EXPERIMENTAL_Conditions

```


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

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/Styleguide/components/EXPERIMENTAL_Conditions/README.md from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```markdown
#### Conditions works like a filter

- Conditions component is based on creating statements.

### Statements

- Statements are composed of 3 basic atoms (subject, verb and object), here are some use cases if you are filtering user data for example:

- Filtering a specific user by name

  - subject: User Name
  - verb: is
  - object: John Doe

- Filtering gmail users

  - subject: Email
  - verb: contains
  - object: @gmail.com

### 👍 Dos

- Use clear verbs and subjects, which should be intuitive and provide sufficient context for the user take that decision.
- Initialize it with a default value that makes sense to your needs. (example: initial render already with an active filter)

### 👎 Don'ts

- Don't use too complex components as objects for a statement. If your statement object is too complex, maybe you should break it in simpler statements options and the complex case can be contemplated by using multiple simpler statements.

Simple

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

class SimpleConditionsCase extends React.Component {
  constructor() {
    super()

    this.state = {
      simpleStatements: [],
      operator: 'all',
    }

    this.handleToggleOperator = this.handleToggleOperator.bind(this)
    this.simpleInputObject = this.simpleInputObject.bind(this)
  }

  handleToggleOperator(operator) {
    this.setState({ operator: this.state.operator === 'all' ? 'any' : 'all' })
  }

  simpleInputObject({
    statements,
    values,
    statementIndex,
    error,
    extraParams,
  }) {
    return (
      <Input
        value={values}
        onChange={e => {
          statements[statementIndex].object = e.target.value
          this.setState({ simpleStatements: statements })
        }}
      />
    )
  }

  render() {
    const options = {
      name: {
        label: 'User name',
        verbs: [
          {
            label: 'is',
            value: '=',
            object: {
              renderFn: this.simpleInputObject,
              extraParams: {},
            },
          },
          {
            label: 'is not',
            value: '!=',
            object: {
              renderFn: this.simpleInputObject,
              extraParams: {},
            },
          },
        ],
      },
      email: {
        label: 'Email',
        verbs: [
          {
            label: 'contains',
            value: 'contains',
            object: {
              renderFn: this.simpleInputObject,
              extraParams: {},
            },
          },
          {
            label: 'is',
            value: '=',
            object: {
              renderFn: this.simpleInputObject,
              extraParams: {},
            },
          },
          {
            label: 'is not',
            value: '!=',
            object: {
              renderFn: this.simpleInputObject,
              extraParams: {},
            },
          },
        ],
      },
    }

    return (
      <EXPERIMENTAL_Conditions
        options={options}
        subjectPlaceholder="Select subject"
        statements={this.state.simpleStatements}
        operator={this.state.operator}
        onChangeOperator={this.handleToggleOperator}
        onChangeStatements={statements => {
          this.setState({ simpleStatements: statements })
        }}
      />
    )
  }
}
;<SimpleConditionsCase />
```

Complex

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

const possibleColors = [
  { label: 'White', value: 'white' },
  { label: 'Black', value: 'black' },
  { label: 'Grey', value: 'grey' },
  { label: 'Yellow', value: 'yellow' },
  { label: 'Red', value: 'red' },
  { label: 'Blue', value: 'blue' },
  { label: 'Green', value: 'green' },
  { label: 'Brown', value: 'brown' },
  { label: 'Pink', value: 'pink' },
  { label: 'Orange', value: 'orange' },
  { label: 'Purple', value: 'purple' },
  { label: 'Dark-blue', value: 'dark-blue' },
  { label: 'Dark-red', value: 'dark-red' },
  { label: 'Light-blue', value: 'light-blue' },
]

class ComplexConditionsCase extends React.Component {
  constructor() {
    super()

    this.state = {
      statements: [],
      operator: 'all',
    }

    this.handleToggleOperator = this.handleToggleOperator.bind(this)
    this.complexDropdownObject = this.complexDropdownObject.bind(this)
    this.complexMultiselectObject = this.complexMultiselectObject.bind(this)
    this.complexDatePickerObject = this.complexDatePickerObject.bind(this)
    this.complexDatePickerRangeObject = this.complexDatePickerRangeObject.bind(
      this
    )
    this.complexNumericInputObject = this.complexNumericInputObject.bind(this)
    this.complexNumericInputRangeObject = this.complexNumericInputRangeObject.bind(
      this
    )
  }

  handleToggleOperator(operator) {
    this.setState({ operator: this.state.operator === 'all' ? 'any' : 'all' })
  }

  complexDropdownObject({
    statements,
    values,
    statementIndex,
    error,
    extraParams,
  }) {
    return (
      <Dropdown
        value={values}
        options={possibleColors}
        onChange={(e, value) => {
          statements[statementIndex].object = value

          this.setState({ statements })
        }}
      />
    )
  }

  complexMultiselectObject({
    statements,
    values,
    statementIndex,
    error,
    extraParams,
  }) {
    return (

        <MultiSelect
          emptyState={term => {
            return `Your search for the color "${term}" did not find any results.`
          }}
          options={possibleColors}
          onChange={selected => {
            statements[statementIndex].object = selected

            this.setState({ statements })
          }}
          selected={values || []}
        />

    )
  }

  complexDatePickerObject({
    statements,
    values,
    statementIndex,
    error,
    extraParams,
  }) {
    return (
      <DatePicker
        value={values || new Date()}
        onChange={date => {
          statements[statementIndex].object = date
          this.setState({ statements })
        }}
        locale="en-US"
      />
    )
  }

  complexDatePickerRangeObject({
    statements,
    values,
    statementIndex,
    error,
    extraParams,
  }) {
    return (

          <DatePicker
            style={{ maxWidth: 140 }}
            value={values && values.from}
            errorMessage={
              statements[statementIndex].object &&
              statements[statementIndex].object.from >=
                statements[statementIndex].object.to
                ? 'Must be before end date'
                : ''
            }
            onChange={date => {
              statements[statementIndex].object = {
                ...(statements[statementIndex].object || {}),
                from: date,
              }

              this.setState({ statements })
            }}
            locale="en-US"
          />

and

          <DatePicker
            value={values && values.to}
            onChange={date => {
              statements[statementIndex].object = {
                ...(statements[statementIndex].object || {}),
                to: date,
              }

              this.setState({ statements })
            }}
            locale="en-US"
          />

    )
  }

  complexNumericInputObject({ statements, values, statementIndex, error }) {
    return (
      <Input
        placeholder="Insert age..."
        type="number"
        min={0}
        value={values}
        onChange={e => {
          statements[statementIndex].object = e.target.value.replace(/\D/g, '')
          this.setState({ statements })
        }}
      />
    )
  }

  complexNumericInputRangeObject({
    statements,
    values,
    statementIndex,
    error,
    extraParams,
  }) {
    return (

        <Input
          placeholder="Age from..."
          errorMessage={
            statements[statementIndex].object &&
            parseInt(statements[statementIndex].object.first) >=
              parseInt(statements[statementIndex].object.last)
              ? 'Must be smaller than other input'
              : ''
          }
          value={values && values.first ? values.first : ''}
          onChange={e => {
            const currentObject = statements[statementIndex].object || {}
            currentObject.first = e.target.value.replace(/\D/g, '')

            statements[statementIndex].object = currentObject

            this.setState({ statements })
          }}
        />

and

        <Input
          placeholder="Age to..."
          value={values && values.last ? values.last : ''}
          onChange={e => {
            const currentObject = statements[statementIndex].object || {}
            currentObject.last = e.target.value.replace(/\D/g, '')

            statements[statementIndex].object = currentObject

            this.setState({ statements })
          }}
        />

    )
  }

  render() {
    const options = {
      age: {
        unique: true,
        label: 'User age',
        verbs: [
          {
            label: 'is',
            value: '=',
            object: {
              renderFn: this.complexNumericInputObject,
              extraParams: {},
            },
          },
          {
            label: 'is between',
            value: 'between',
            object: {
              renderFn: this.complexNumericInputRangeObject,
              extraParams: {},
            },
          },
        ],
      },
      color: {
        unique: true,
        label: 'User favorite color',
        verbs: [
          {
            label: 'is',
            value: '=',
            object: {
              renderFn: this.complexDropdownObject,
              extraParams: {},
            },
          },
          {
            label: 'is any of',
            value: 'any',
            object: {
              renderFn: this.complexMultiselectObject,
              extraParams: {},
            },
          },
        ],
      },
      birthday: {
        unique: true,
        label: 'User birthday',
        verbs: [
          {
            label: 'is',
            value: '=',
            object: {
              renderFn: this.complexDatePickerObject,
              extraParams: {},
            },
          },
          {
            label: 'is between',
            value: 'between',
            object: {
              renderFn: this.complexDatePickerRangeObject,
              extraParams: {},
            },
          },
        ],
      },
    }

    return (
      <EXPERIMENTAL_Conditions
        options={options}
        subjectPlaceholder="Select subject"
        statements={this.state.statements}
        operator={this.state.operator}
        onChangeOperator={this.handleToggleOperator}
        onChangeStatements={statements => {
          this.setState({ statements })
        }}
      />
    )
  }
}
;<ComplexConditionsCase />
```

Using ref

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

class SimpleConditionsCase extends React.Component {
  constructor() {
    super()

    this.state = {
      simpleStatements: [
        { subject: 'name', verb: '=', object: 'a', error: null },
        { subject: 'name', verb: '=', object: 'b', error: null },
        { subject: 'name', verb: '=', object: 'c', error: null },
      ],
      operator: 'all',
    }

    this.handleToggleOperator = this.handleToggleOperator.bind(this)
    this.simpleInputObject = this.simpleInputObject.bind(this)
  }

  handleToggleOperator(operator) {
    this.setState({ operator: this.state.operator === 'all' ? 'any' : 'all' })
  }

  simpleInputObject({
    statements,
    values,
    statementIndex,
    error,
    extraParams,
  }) {
    return (
      <Input
        ref={statements[statementIndex].refs.object}
        value={values}
        onChange={e => {
          statements[statementIndex].object = e.target.value
          this.setState({ simpleStatements: statements })
        }}
      />
    )
  }

  render() {
    const options = {
      name: {
        label: 'User name',
        verbs: [
          {
            label: 'is',
            value: '=',
            object: {
              renderFn: this.simpleInputObject,
              extraParams: {},
            },
          },
        ],
      },
    }

    return (

        <EXPERIMENTAL_Conditions
          options={options}
          subjectPlaceholder="Select subject"
          statements={this.state.simpleStatements}
          operator={this.state.operator}
          onChangeOperator={this.handleToggleOperator}
          onChangeStatements={statements => {
            this.setState({ simpleStatements: statements })
          }}
        />

            <Button
              onClick={() =>
                this.state.simpleStatements[0].refs.subject.current.focus()
              }>
              Focus on first subject
            </Button>

            <Button
              onClick={() =>
                this.state.simpleStatements[0].refs.verb.current.focus()
              }>
              Focus on first verb
            </Button>

            <Button
              onClick={() =>
                this.state.simpleStatements[0].refs.object.current.focus()
              }>
              Focus on first object
            </Button>

    )
  }
}
;<SimpleConditionsCase />
```

```


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

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

[Assistant]
Here's the implementation:

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

class Radio extends PureComponent {
  constructor(props) {
    super(props)
    this.radio = React.createRef()
    this.container = React.createRef()
  }

  handleContainerClick = e => {
    const { disabled } = this.props
    if (!disabled && e.target === this.container.current) {
      this.radio.current.click()
    }
  }

  render() {
    const {
      checked,
      disabled,
      id,
      isLast,
      label,
      name,
      onChange,
      required,
      value,
    } = this.props

    return (
      <div
        className={classNames('flex items-start relative', {
          pointer: !disabled,
          mb3: !isLast,
        })}
        ref={this.container}
        onClick={this.handleContainerClick}>
        {/* This empty div is used so that the radio circle is not a direct child of
         * a flex element, and thus can set a fixed width. Otherwise, the width would
         * be used as flex-basis, and would not be set directly */}
        <div>
          <div
            className={classNames(
              'fake-radio relative ba br-100 mr3 flex justify-center items-center',
              {
                'b--muted-4 pointer': !disabled && !checked,
                'b--action-primary pointer': !disabled && checked,
                'b--muted-4 bg-muted-5': disabled,
              }
            )}
            style={{
              borderWidth: '3px',
              height: '1.25rem',
              width: '1.25rem',
              transition: 'border 100ms ease-in-out',
            }}>
            <div
              className={classNames('br-100', {
                'bg-action-primary': !disabled,
                'bg-muted-3': disabled,
              })}
              style={{
                height: '0.5rem',
                width: '0.5rem',
                transform: `scale(${checked ? 1 : 0})`,
                transition: `transform 80ms ${
                  checked ? 'ease-out' : 'ease-in'
                }`,
              }}
            />
          </div>
        </div>
        <input
          checked={checked}
          className={classNames('absolute o-0', {
            pointer: !disabled,
          })}
          disabled={disabled}
          required={required}
          id={id}
          name={name}
          onChange={onChange}
          type="radio"
          value={value}
          style={{
            height: '1.5rem',
            width: '1.5rem',
          }}
          ref={this.radio}
        />
        <label
          style={{ wordBreak: 'break-word' }}
          className={classNames(
            { 'c-disabled': disabled },
            { 'c-on-base pointer': !disabled },
            'flex flex-auto'
          )}
          htmlFor={id}>
          {label}
        </label>
      </div>
    )
  }
}

Radio.defaultProps = {
  checked: false,
  disabled: false,
  required: false,
  isLast: false,
}

Radio.propTypes = {
  /** (Radio spec attribute) */
  checked: PropTypes.bool,
  /** (Radio spec attribute) */
  disabled: PropTypes.bool,
  /** (Radio spec attribute) */
  id: PropTypes.string.isRequired,
  /** (Radio spec attribute) */
  isLast: PropTypes.bool,
  /** Radio label */
  label: PropTypes.node.isRequired,
  /** (Radio spec attribute) */
  name: PropTypes.string.isRequired,
  /** onChange event */
  onChange: PropTypes.func.isRequired,
  /** (Radio spec attribute) */
  required: PropTypes.bool,
  /** (Radio spec attribute) */
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
}

export default Radio

```


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

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

[Assistant]
Here's the implementation:

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

class Card extends PureComponent {
  render() {
    const { children, noPadding } = this.props
    const padding = noPadding ? '' : 'pa6'

    return (
      <div
        style={{ boxShadow: '0 3px 9px 0 rgba(61, 62, 64, 0.2)' }}
        className={`vtex-card card w-100 b2 br2 bg-base c-on-base ${padding}`}>
        {children}
      </div>
    )
  }
}

Card.propTypes = {
  /** Content of the card */
  children: PropTypes.node.isRequired,
  /** Use the full size of the card. */
  noPadding: PropTypes.bool,
}

export default Card

```


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

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/Styleguide/components/Card/README.md from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```markdown
#### A Card like any container improves scannability of a design when well used. What sets the Card apart is that it has higher visual prominence and invites interactivity with its fancy drop shadow.

### 👍 Dos

- It works best when used as a big button.
- Do use buttons inside it if you need, but keep it simple.

### 👎 Don'ts

- Don't nest cards.
- Avoid using it to encompass the entirety of a page.

### Related components

- In doubt prefer using a simple <a href="#/Components/Containers/Box">Box</a>.

Default

```js

  <Card>

Lorem Ipsum

      It is simply dummy text of the printing and typesetting industry. Lorem
      Ipsum has been the industry's standard dummy text ever since the 1500s,
      when an unknown printer took a galley of type and scrambled it to make a
      type specimen book.

      It has survived not only five centuries, but also the leap into electronic
      typesetting, remaining essentially unchanged. It was popularised in the
      1960s with the release of Letraset sheets containing Lorem Ipsum passages,
      and more recently with desktop publishing software like Aldus PageMaker
      including versions of Lorem Ipsum.

  </Card>

```

Full width

```js

  <Card noPadding>

Spider

      It is simply dummy text of the printing and typesetting industry. Lorem
      Ipsum has been the industry's standard dummy text ever since the 1500s,
      when an unknown printer took a galley of type and scrambled it to make a
      type specimen book.

  </Card>

```

```


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

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

[Assistant]
Here's the implementation:

```javascript
import React, { Component } from 'react'

import Button from '../Button'
import ButtonWithIcon from '../ButtonWithIcon'
import ActionMenu from '../ActionMenu'
import { childrenOf } from '../utils'

class ButtonGroup extends Component {
  render() {
    const { buttons } = this.props

    return (
      <div className="button_group flex flex-row">
        {buttons.map((btn, i) => {
          const TagName = btn.type

          return i === 0 ? (
            // First button
            <span key={i} className="mr1 isFirstOfGroup">
              <TagName {...btn.props} isGrouped isFirstOfGroup />
            </span>
          ) : buttons.length - 1 === i ? (
            // Last button
            <TagName key={i} {...btn.props} isGrouped isLastOfGroup />
          ) : (
            // Others
            <span key={i} className="mr1">
              <TagName {...btn.props} isGrouped />
            </span>
          )
        })}
      </div>
    )
  }
}

ButtonGroup.defaultProps = {}

ButtonGroup.propTypes = {
  buttons: childrenOf(Button, ButtonWithIcon, ActionMenu),
}

export default ButtonGroup

```


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

[User] Show me the implementation of store-on-localhost/src/monobloco/components/new/Styleguide/components/ButtonGroup/README.md from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```markdown
Button group receives a list of button components with an extra available prop `isActiveOfGroup` as a boolean to display an active state. This has to be handled on the app side.

### Related components

- <a href="#/Components/Navigation/Tabs">tabs</a>

Default

```js
const Button = require('../Button').default
initialState = { active: 1 }
;

  <ButtonGroup
    buttons={[
      <Button
        isActiveOfGroup={state.active === 1}
        onClick={() => setState({ active: 1 })}>
        one
      </Button>,
      <Button
        isActiveOfGroup={state.active === 2}
        onClick={() => setState({ active: 2 })}>
        two
      </Button>,
      <Button
        isActiveOfGroup={state.active === 3}
        onClick={() => setState({ active: 3 })}>
        three
      </Button>,
    ]}
  />

```

Sizes

```js
const Button = require('../Button').default
initialState = { active: 1 }
;

  <ButtonGroup
    buttons={[
      <Button
        size="small"
        isActiveOfGroup={state.active === 1}
        onClick={() => setState({ active: 1 })}>
        {state.active === 1 ? 'loading' : 'load'}
      </Button>,
      <Button
        size="small"
        isActiveOfGroup={state.active === 2}
        onClick={() => setState({ active: 2 })}>
        two
      </Button>,
      <Button
        size="small"
        isActiveOfGroup={state.active === 3}
        onClick={() => setState({ active: 3 })}>
        three
      </Button>,
      <Button
        size="small"
        isActiveOfGroup={state.active === 4}
        onClick={() => setState({ active: 4 })}>
        four
      </Button>,
      <Button
        size="small"
        isActiveOfGroup={state.active === 5}
        onClick={() => setState({ active: 5 })}>
        five
      </Button>,
      <Button
        size="small"
        isActiveOfGroup={state.active === 6}
        onClick={() => setState({ active: 6 })}
        isLoading={state.active === 1}>
        Load?
      </Button>,
    ]}
  />

```

Misc

```js
const Button = require('../Button').default
initialState = { active: 1 }
;

  <ButtonGroup
    buttons={[
      <Button
        disabled
        isActiveOfGroup={state.active === 1}
        onClick={() => setState({ active: 1 })}>
        disabled
      </Button>,
      <Button
        variation="secondary"
        isActiveOfGroup={state.active === 2}
        onClick={() => setState({ active: 2 })}>
        secondary
      </Button>,
      <Button
        variation="tertiary"
        isActiveOfGroup={state.active === 3}
        onClick={() => setState({ active: 3 })}>
        tertiary
      </Button>,
      <Button
        variation="danger"
        isActiveOfGroup={state.active === 4}
        onClick={() => setState({ active: 4 })}>
        danger
      </Button>,
      <Button
        variation="danger-tertiary"
        isActiveOfGroup={state.active === 5}
        onClick={() => setState({ active: 5 })}>
        danger-tertiary
      </Button>,
    ]}
  />

```

Buttons with icon

```js
const ArrowBack = require('../icon/ArrowBack').default
const Delete = require('../icon/Delete').default
const Edit = require('../icon/Edit').default
const PlusLines = require('../icon/PlusLines').default
const ButtonWithIcon = require('../ButtonWithIcon').default

const arrow = <ArrowBack />
const remove = <Delete />
const edit = <Edit />
const plus = <PlusLines />

initialState = { active: 1 }
;

  <ButtonGroup
    buttons={[
      <ButtonWithIcon
        isActiveOfGroup={state.active === 1}
        onClick={() => setState({ active: 1 })}
        icon={arrow}>
        Back
      </ButtonWithIcon>,
      <ButtonWithIcon
        isActiveOfGroup={state.active === 2}
        onClick={() => setState({ active: 2 })}
        icon={edit}
      />,
      <ButtonWithIcon
        isActiveOfGroup={state.active === 3}
        onClick={() => setState({ active: 3 })}
        icon={plus}
        iconPosition="right"
      />,
      <ButtonWithIcon
        isActiveOfGroup={state.active === 4}
        onClick={() => setState({ active: 4 })}
        icon={remove}
      />,
    ]}
  />

```

Split Button

```js
const Button = require('../Button').default
const ActionMenu = require('../ActionMenu').default
const CaretDown = require('../icon/CaretDown').default
const caretDown = <CaretDown />

const options = [
  'General',
  'Desktop & Screen Saver',
  'Dock',
  'Language & Region',
].map(label => ({
  label,
  onClick: () => {},
}))

initialState = { active: 1 }
;

  <ButtonGroup
    buttons={[
      <Button isActiveOfGroup>new</Button>,
      <ActionMenu
        isActiveOfGroup
        hideCaretIcon
        buttonProps={{
          variation: 'primary',
          icon: <CaretDown color="currentColor" />,
          iconPosition: 'right',
        }}
        options={options}
      />,
    ]}
  />

```

```


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

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

[Assistant]
Here's the implementation:

```tsx
import React, { FunctionComponent, Fragment, useEffect } from 'react'
import PropTypes, { InferProps } from 'prop-types'
import classNames from 'classnames'

import Spinner from '../Spinner'
import { withForwardedRef, refShape } from '../../modules/withForwardedRef'

const SIZE = {
  SMALL: 'small',
  REGULAR: 'regular',
  LARGE: 'large',
}

const VARIATION = {
  PLAIN: 'plain',
  INVERTED: 'inverted',
  DANGER: 'danger',
}

const loaderSize = {
  [SIZE.SMALL]: 15,
  [SIZE.REGULAR]: 20,
  [SIZE.LARGE]: 25,
}

const propTypes = {
  /** Button size  */
  size: PropTypes.oneOf(Object.values(SIZE)),
  /** Button prominence variation */
  variation: PropTypes.oneOf(Object.values(VARIATION)),
  /** [DEPRECATED] If you are using just an Icon component inside, use this as true */
  icon: PropTypes.bool,
  /** Loading state */
  isLoading: PropTypes.bool,
  /** @ignore For internal use
   * Sets reduced paddings in order to keep the button squareish if it
   * only has an icon  */
  iconOnly: PropTypes.bool,
  /** (Button spec attribute) */
  id: PropTypes.string,
  /** Data attribute */
  testId: PropTypes.string,
  /** (Button spec attribute) */
  autoFocus: PropTypes.bool,
  /** (Button spec attribute) */
  autoComplete: PropTypes.string,
  /** (Button spec attribute) */
  disabled: PropTypes.bool,
  /** @ignore Forwarded Ref */
  forwardedRef: refShape,
  /** (Button spec attribute) */
  name: PropTypes.string,
  /** (Button spec attribute) */
  type: PropTypes.string,
  /** (Button spec attribute) */
  value: PropTypes.string,
  /** Label of the Button */
  children: PropTypes.node.isRequired,
  /** onClick event. */
  onClick: PropTypes.func,
  /** URL for link mode. Converts the button internally to a link. */
  href: PropTypes.string,
  /** onMouseEnter event */
  onMouseEnter: PropTypes.func,
  /** onMouseLeave event */
  onMouseLeave: PropTypes.func,
  /** onMouseOver event */
  onMouseOver: PropTypes.func,
  /** onMouseOut event */
  onMouseOut: PropTypes.func,
  /** onMouseUp event */
  onMouseUp: PropTypes.func,
  /** onMouseDown event */
  onMouseDown: PropTypes.func,
  /** onFocus event */
  onFocus: PropTypes.func,
  /** onBlur event */
  onBlur: PropTypes.func,
  /** Link spec */
  target: PropTypes.string,
  /** Link spec */
  rel: PropTypes.string,
  /** Link spec */
  referrerPolicy: PropTypes.string,
  /** Link spec */
  download: PropTypes.string,
  /** Disables label wrapping */
  noWrap: PropTypes.bool,
}

type Props = InferProps<typeof propTypes>

const ButtonPlain: FunctionComponent<Props> = props => {
  const handleClick = (event: React.MouseEvent) => {
    !props.disabled && !props.isLoading && props.onClick && props.onClick(event)
  }

  useEffect(() => {
    if (props.icon) {
      console.warn(
        'Button: The prop "icon" of the "Button" component has been deprecated, and will be removed in a future version. Please use the component "ButtonWithIcon" instead'
      )
    }
  }, [props.icon])

  const {
    size,
    variation,
    children,
    icon,
    isLoading,
    href,
    target,
    rel,
    referrerPolicy,
    download,
    noWrap,
  } = props

  const disabled = props.disabled || isLoading
  const iconOnly = icon || props.iconOnly
  const horizontalPadding = iconOnly ? 1 : 2
  const horizontalCompensation = `nr${horizontalPadding} nl${horizontalPadding} `

  const classes = classNames(
    'vtex-button bw1 ba fw5 v-mid relative pa0 br2 bn',
    horizontalCompensation,
    {
      't-action--small': size === SIZE.SMALL,
      't-action': size === SIZE.REGULAR,
      't-action--large': size === SIZE.LARGE,
    },
    { 'icon-button dib': iconOnly },
    {
      'bg-transparent b--transparent c-disabled': disabled,
      'bg-transparent b--transparent c-action-primary hover-b--transparent hover-bg-action-secondary hover-b--action-secondary':
        !disabled && variation === VARIATION.PLAIN,
      'bg-transparent b--transparent c-on-base--inverted':
        !disabled && variation === VARIATION.INVERTED,
      'bg-transparent b--transparent c-danger hover-bg-danger--faded hover-b--danger--faded':
        !disabled && variation === VARIATION.DANGER,
    },
    { pointer: !disabled },
    { 'inline-flex items-center no-underline': href }
  )

  const labelClasses = classNames(
    'flex items-center justify-center h-100 pv1 ttn ',
    `ph${horizontalPadding}`,
    { nowrap: noWrap }
  )

  const style: { fontSize?: number } = {}

  if (iconOnly) {
    style.fontSize = 0
  }

  const linkModeProps = {
    target,
    rel,
    referrerPolicy,
    download,
  }

  const Element = href ? 'a' : 'button'

  return (
    <Element
      id={props.id}
      data-testid={props.testId}
      autoFocus={iconOnly ? undefined : props.autoFocus}
      disabled={iconOnly ? undefined : props.disabled}
      name={iconOnly ? undefined : props.name}
      value={iconOnly ? undefined : props.value}
      tabIndex={0}
      className={classes}
      href={href}
      onClick={handleClick}
      onMouseEnter={props.onMouseEnter}
      onMouseLeave={props.onMouseLeave}
      onMouseOver={props.onMouseOver}
      onMouseOut={props.onMouseOut}
      onMouseUp={props.onMouseUp}
      onMouseDown={props.onMouseDown}
      onFocus={props.onFocus}
      onBlur={props.onBlur}
      ref={props.forwardedRef as any}
      style={style}
      // Button-mode exclusive props
      type={href ? undefined : (props.type as 'button' | 'submit' | 'reset')}
      // Link-mode exclusive props
      {...(href && linkModeProps)}>
      {isLoading ? (
        <Fragment>
          <span className="top-0 left-0 w-100 h-100 absolute flex justify-center items-center">
            <Spinner
              secondary={variation === VARIATION.DANGER}
              size={loaderSize[size]}
            />
          </span>
          <span className={`${labelClasses} o-0`}>{children}</span>
        </Fragment>
      ) : (
        <div className={labelClasses}>{children}</div>
      )}
    </Element>
  )
}

ButtonPlain.defaultProps = {
  size: SIZE.REGULAR,
  variation: VARIATION.PLAIN,
  disabled: false,
  autoFocus: false,
  icon: false,
  type: 'button',
  isLoading: false,
}

ButtonPlain.propTypes = propTypes

export default withForwardedRef(ButtonPlain)

```