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

[Assistant]
Here's the implementation:

```markdown
#### Collapsibles are containers that allows an toggling the display of an initially hidden content. Its main objective is to hide from view detailed information that might not be necessarily.

### 👍 Dos

- Do make your header as complex as you want, but avoid nesting interactive elements.
- Do nest collapsibles if needed, but avoid too many levels.

### 👎 Don'ts

- Don't hide information that you consider critical for the user in that given moment. For the same reason, it doesn't make sense to initialize a collapsible in the expanded state.
- Avoid using the right-aligned variation with widths larger than around 600px or if affordance might be at stake.
- Avoid using the muted variation if affordance is not well secured.

Usage

```js
initialState = { isOpen1: false, isOpen2: false }
;

  <Collapsible
    header={Here goes your header}
    onClick={e => setState({ isOpen1: e.target.isOpen })}
    isOpen={state.isOpen1}
    >

        Here goes your content

  </Collapsible>

```

"Read-more-like" example

```js
const Input = require('../Input').default
initialState = { isOpen: false }
;

    <Input label="Name" />

    <Input label="Email" prefix={@} />

    <Collapsible
      header={

          Advanced settings

      }
      onClick={e => setState({ isOpen: e.target.isOpen })}
      isOpen={state.isOpen}
      >

            <Input label="Surname" />

            <Input label="Nickname" />

    </Collapsible>

```

Custom Caret Color Example

```js
initialState = { isOpen1: false, isOpen2: false, isOpen3: false }
;

  <Collapsible
    header={Here goes your base header}
    onClick={e => setState({ isOpen1: e.target.isOpen })}
    isOpen={state.isOpen1}
    caretColor="base"
    >

        Here goes your content

  </Collapsible>
  <Collapsible
    header={Here goes your primary header}
    onClick={e => setState({ isOpen2: e.target.isOpen })}
    isOpen={state.isOpen2}
    caretColor="primary"
    >

        Here goes your content

  </Collapsible>
  <Collapsible
    header={Here goes your muted header}
    onClick={e => setState({ isOpen3: e.target.isOpen })}
    isOpen={state.isOpen3}
    caretColor="muted"
    >

        Here goes your content

  </Collapsible>

```

Navigation bar example

```js
const PageBlock = require('../PageBlock').default
initialState = { isOpen1: false, isOpen2: false, isOpen3: false }

;

      <Collapsible
          header={

                <svg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'>
                  <path d='M7 8H1C0.4 8 0 8.4 0 9V15C0 15.6 0.4 16 1 16H7C7.6 16 8 15.6 8 15V9C8 8.4 7.6 8 7 8Z'
                  fill='currentColor' />
                  <path d='M11 4H2V6H10V14H12V5C12 4.4 11.6 4 11 4Z' fill='currentColor' />
                  <path d='M15 0H6V2H14V10H16V1C16 0.4 15.6 0 15 0Z' fill='currentColor' />
                </svg>

                Catalog

          }
          align="right"
          onClick={e => setState({ isOpen1: e.target.isOpen })}
          isOpen={state.isOpen1}
          caretColor="muted"
          >

              Products and SKUs
              Categories
              Brands
              Import and export
              Reports

        </Collapsible>

        <Collapsible
          header={

                <svg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'>
                    <path d='M16 5V3C16 2.4 15.6 2 15 2H1C0.4 2 0 2.4 0 3V5H16Z' fill='currentColor'
                    />
                    <path fillRule='evenodd' clipRule='evenodd' d='M0 7V13C0 13.6 0.4 14 1 14H15C15.6 14 16 13.6 16 13V7H0ZM6 11H2V10H6V11ZM12 11H14V10H12V11Z'
                    fill='currentColor' />
                </svg>

                Payments

          }
          align="right"
          onClick={e => setState({ isOpen2: e.target.isOpen })}
          isOpen={state.isOpen2}
          caretColor="muted"
          >

              Transactions
              Bank conciliation
              Gift card
              Settings

        </Collapsible>

        <Collapsible
          header={

                <svg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'>
                  <path d='M16 12H5.8C5.5 11.2 4.8 10.5 4 10.2V1C4 0.4 3.6 0 3 0H0V2H2V10.2C0.8 10.6 0 11.7 0 13C0 14.7 1.3 16 3 16C4.3 16 5.4 15.2 5.8 14H16V12Z'
                  fill='currentColor' />
                  <path d='M7 10H14C14.6 10 15 9.6 15 9V4C15 3.4 14.6 3 14 3H7C6.4 3 6 3.4 6 4V9C6 9.6 6.4 10 7 10Z'
                  fill='currentColor' />
              </svg>

                Inventory & shipping

          }
          align="right"
          onClick={e => setState({ isOpen3: e.target.isOpen })}
          isOpen={state.isOpen3}
          caretColor="muted"
          >

              Dashboard
              Shipping
              Inventory
              Pickup points
              Settings

        </Collapsible>

```

FAQ accordion example

```js
const PageBlock = require('../PageBlock').default
const Box = require('../Box').default

initialState = { openQuestion: null }

function toggleAccordion(questionNbr) {
  return e => setState(
    { openQuestion: state.openQuestion !== questionNbr ? questionNbr : null }
  );
}

;

      <Box>
        <Collapsible
          header={

              What is your name?

          }
          onClick={toggleAccordion(1)}
          isOpen={ state.openQuestion===1 }
          >

              Arthur, King of the Britons.

        </Collapsible>

        <Collapsible
          header={

              What is your quest?

          }
          onClick={toggleAccordion(2)}
          isOpen={ state.openQuestion===2 }
          >

              To seek the Holy Grail.

        </Collapsible>

        <Collapsible
          header={

              What is your favorite color?

          }
          onClick={toggleAccordion(3)}
          isOpen={ state.openQuestion===3 }
          >

              Pink.

        </Collapsible>

        <Collapsible
          header={

              What is the air-speed velocity of an unladen swallow?

          }
          onClick={toggleAccordion(4)}
          isOpen={ state.openQuestion===4 }
          >

              What do you mean? An African or European swallow?

        </Collapsible>
      </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/Divider/index.tsx from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

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

const propTypes = {
  orientation: PropTypes.oneOf(['vertical', 'horizontal']),
}

const Divider: React.FC<PropTypes.InferProps<typeof propTypes>> = props => {
  const size = {
    [props.orientation === 'horizontal' ? 'height' : 'width']: 1,
  }
  return <div className="bg-light-gray" style={size} />
}

Divider.propTypes = propTypes
Divider.defaultProps = {
  orientation: 'horizontal',
}

export default Divider

```


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

[Assistant]
Here's the implementation:

```markdown
# Horizontal

```jsx

  text 1
  <Divider orientation="horizontal" />
  text 2

```

# Vertical

```jsx

  text 1
  <Divider orientation="vertical" />
  text 2

```

```


[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/Menu/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 { Overlay } from 'react-overlays'

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

const DEFAULT_WIDTH = 292
const CONTAINER_MARGIN = 6
const WINDOW_MARGIN = 10
const DEFAULT_DOCUMENT_ELEMENT = {
  scrollTop: 0,
  scrollLeft: 0,
  clientWidth: 0,
  clientHeight: 0,
}

class Menu extends Component {
  constructor(props) {
    super(props)
    this.containerElement = React.createRef()
    this.menuElement = props.forwardedRef || React.createRef()
  }

  state = {
    hasCalculatedSize: false, // hides the menu while calculating its size and position
    isUpwards: false, // opens the menu from bottom to top, if it doesn't fit on the screen otherwise
    isVisible: false, // triggers the opening animation
    menuHeight: 0,
    containerHeight: 0,
  }

  onWindowResize = () => this.forceUpdate()

  componentDidMount() {
    if (window) window.addEventListener('resize', this.onWindowResize)
  }

  componentWillUnmount() {
    if (window) window.removeEventListener('resize', this.onWindowResize)
  }

  getMenuBounds = () =>
    this.menuElement.current &&
    this.menuElement.current.getBoundingClientRect &&
    this.menuElement.current.getBoundingClientRect()

  getContainerBounds = () =>
    this.containerElement.current &&
    this.containerElement.current.getBoundingClientRect &&
    this.containerElement.current.getBoundingClientRect()

  updateMenu() {
    const menuBounds = this.getMenuBounds()
    const containerBounds = this.getContainerBounds()

    if (!menuBounds || !containerBounds) return

    const containerHeight = containerBounds.height

    const initialMenuHeight = menuBounds.height

    const itemHeight = initialMenuHeight / this.props.options.length

    const isOutOfBounds =
      menuBounds.top + initialMenuHeight + containerHeight > window.innerHeight

    const isUpwards =
      isOutOfBounds && containerBounds.top > window.innerHeight / 2

    const maxMenuHeight = isUpwards
      ? menuBounds.top - CONTAINER_MARGIN - WINDOW_MARGIN - containerHeight
      : window.innerHeight - menuBounds.top - CONTAINER_MARGIN - WINDOW_MARGIN

    // Makes the height of the menu, if it doesn't entirely fit on the screen,
    // fall in the middle of an item, to hint that the menu scrolls
    const visibleItemsNum = Math.round(maxMenuHeight / itemHeight)
    const adjustedMenuHeight = visibleItemsNum * itemHeight - itemHeight / 2

    const menuHeight =
      maxMenuHeight < initialMenuHeight ? adjustedMenuHeight : 0

    this.setState(
      {
        containerHeight,
        menuHeight,
        isUpwards,
        hasCalculatedSize: true,
      },
      () => {
        // triggers the menu opening animation
        setTimeout(() => {
          this.setState({ isVisible: true })
        }, 1)
      }
    )
  }

  componentDidUpdate(prevProps) {
    if (!prevProps.open && this.props.open) {
      this.updateMenu()
    }

    if (prevProps.open && !this.props.open) {
      this.setState({
        hasCalculatedSize: false,
        isUpwards: false,
        isVisible: false,
        menuHeight: 0,
        containerHeight: 0,
      })
    }
  }

  render() {
    const { options, align, open, onClose, children, width } = this.props
    const { hasCalculatedSize, isUpwards, isVisible, menuHeight } = this.state

    const isRight = align === 'right'

    return (
      <div className="relative">
        <div ref={this.containerElement}>{children}</div>
        <Overlay show={open}>
          {() => {
            const { top, left, right, height } = this.getContainerBounds()

            const {
              scrollTop,
              scrollLeft,
              clientWidth,
              clientHeight,
            } = document ? document.documentElement : DEFAULT_DOCUMENT_ELEMENT

            return (
              <div
                ref={this.menuElement}
                style={{
                  transform:
                    !hasCalculatedSize || isVisible
                      ? 'scale(1)'
                      : 'scale(0.9, 0.6)',
                  transformOrigin: `${isRight ? '75%' : '25%'} ${
                    isUpwards ? '100%' : '0'
                  }`,
                  transition: isVisible
                    ? 'transform 50ms ease-out, opacity 25ms'
                    : 'none',
                  [isUpwards ? 'bottom' : 'top']: isUpwards
                    ? clientHeight - (top + scrollTop - CONTAINER_MARGIN)
                    : top + scrollTop + height + CONTAINER_MARGIN,
                  [isRight ? 'right' : 'left']: isRight
                    ? clientWidth - right
                    : left + scrollLeft,
                  width: width || DEFAULT_WIDTH,
                }}
                className={`absolute z-999 ba b--muted-4 br2 shadow-5 ${
                  isRight ? 'right-0' : 'left-0'
                }
              ${isVisible ? 'o-100' : 'o-0'}`}>
                <div className="b2 br2 bg-base">
                  <div
                    style={{ height: menuHeight || 'auto' }}
                    className={menuHeight ? 'overflow-auto' : ''}>
                    {options.map((option, index) => (
                      <button
                        key={index}
                        className="flex justify-between items-center t-body ph6 h-regular pointer hover-bg-muted-5 ma0 bg-transparent bn w-100 tl"
                        onClick={() => {
                          option.onClick(option)
                          if (onClose) {
                            onClose()
                          }
                        }}>
                        <span
                          className={`${
                            option.toggle ? 'w-70 truncate' : 'w-100 truncate'
                          } ${option.isDangerous ? 'c-danger' : ''}`}>
                          {option.label}
                        </span>
                        {option.toggle && (
                          <div style={{ pointerEvents: 'none' }}>
                            <Toggle
                              size="regular"
                              semantic={option.toggle.semantic}
                              checked={option.toggle.checked}
                            />
                          </div>
                        )}
                      </button>
                    ))}
                  </div>
                </div>
              </div>
            )
          }}
        </Overlay>
      </div>
    )
  }
}

Menu.defaultProps = {
  options: [],
  align: 'right',
  open: false,
}

Menu.propTypes = {
  /** The element which will open the menu--the menu will
   * be positioned around this element */
  children: PropTypes.node,
  /** @ignore Forwarded Ref */
  forwardedRef: refShape,
  /** Menu visibility (default is false) */
  open: PropTypes.bool,
  /** Menu Box width (default is 292px) */
  width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  /** Menu options */
  options: PropTypes.arrayOf(
    PropTypes.shape({
      label: PropTypes.node,
      onClick: PropTypes.func,
      /** whether option has inline toggle */
      toggle: PropTypes.shape({
        checked: PropTypes.bool,
        semantic: PropTypes.bool,
      }),
    })
  ),
  /** function to close the menu after clicking an option */
  onClose: PropTypes.func,
  /** Menu Box align (default is right) */
  align: PropTypes.oneOf(['right', 'left']),
}

export default withForwardedRef(Menu)

```


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

[Assistant]
Here's the implementation:

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

import ButtonWithIcon from '../ButtonWithIcon/index'
import IconPlus from '../icon/Plus/index'
import IconClose from '../icon/Close/index'
import Separator from './Separator'
import StrategySelector from './StrategySelector'
import Statement from '../Statement/index'
import { Labels, Operator } from './typings'
import { DEFAULT_LABELS, MEDIUM_ICON_SIZE } from './constants'
import { SubjectOptions } from '../Statement/Atoms/SubjectAtom'

type Props = {
  canDelete?: boolean
  isFullWidth?: boolean
  isRtl?: boolean
  labels?: Labels
  onChangeStatements: (statement: Props['statements']) => void
  onChangeOperator: (operator: Props['operator']) => void
  operator: Operator
  options: SubjectOptions
  hideOperator?: boolean
  statements: {
    subject: string
    verb: string
    object?: unknown
    error?: string
  }[]
  subjectPlaceholder: string
}

const Conditions: React.FC<Props> = ({
  canDelete,
  statements,
  options,
  subjectPlaceholder,
  isFullWidth,
  isRtl,
  labels = {} as Props['labels'],
  hideOperator,
  operator,
  onChangeOperator,
  onChangeStatements,
}) => {
  const 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
  }

  const canAddNewCondition = () => {
    if (statements.length === 0) return false

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

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

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

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

    onChangeStatements(updatedStatements)
  }

  const handleUpdatestatement = (newStatement, statementIndex) => {
    const newStatements = statements.map((statement, idx) =>
      idx === statementIndex ? newStatement : statement
    )
    onChangeStatements(newStatements)
  }

  return (
    <div>
      {!hideOperator && (
        <div className={`mh6 ${isRtl ? 'flex justify-end' : ''}`}>
          <StrategySelector
            isRtl={isRtl}
            operator={operator}
            labels={labels}
            onChangeOperator={operator => onChangeOperator(operator)}
          />
        </div>
      )}

      <div className="t-body c-on-base ph5 mt4 br3 b--muted-4 ba">
        {statements.length === 0 ? (
          <div className="flex-grow-1 mv6">
            <Statement
              isRtl={isRtl}
              isFullWidth={isFullWidth}
              onChangeStatement={newStatement =>
                onChangeStatements([newStatement])
              }
              options={options}
              subjectPlaceholder={subjectPlaceholder}
            />
          </div>
        ) : (
          <div className="mv5">
            {statements.map((statement, statementIndex) => {
              // if statement is configured as unique we should filter subject
              // options that were already selected in other statements.
              const uniqueBasedSubjects = Object.keys(options).filter(
                subject =>
                  !options[subject].unique ||
                  !statements.some(
                    (stmt, idx) =>
                      stmt.subject === subject && idx !== statementIndex
                  )
              )

              const uniqueBasedOptions = uniqueBasedSubjects.reduce(
                (uniqueOptions, subject) => ({
                  ...uniqueOptions,
                  [subject]: options[subject],
                }),
                {}
              )

              const statementContent = [
                <div key="1" className="flex-grow-1">
                  <Statement
                    isRtl={isRtl}
                    isFullWidth={isFullWidth}
                    onChangeStatement={newStatement => {
                      handleUpdatestatement(newStatement, statementIndex)
                    }}
                    options={uniqueBasedOptions}
                    subjectPlaceholder={subjectPlaceholder}
                    statement={statement}
                  />
                </div>,
                canDelete &&
                  (!isFullWidth ? (
                    <div
                      key="2"
                      className="ma3 c-muted-2 pointer hover-c-danger"
                      onClick={() => handleRemoveStatement(statementIndex)}>
                      <IconClose size={25} />
                    </div>
                  ) : (
                    <div key="3" className="tr mh3">
                      <ButtonWithIcon
                        variation="tertiary"
                        collapseRight
                        size="small"
                        icon={<IconClose className="c-on-action-primary" />}
                        onClick={() => handleRemoveStatement(statementIndex)}
                      >
                        {labels.delete || DEFAULT_LABELS.delete}
                      </ButtonWithIcon>
                    </div>
                  )),
              ]

              return (
                <div
                  className="flex flex-column w-100 mv3"
                  key={statementIndex}>
                  <div
                    className={`flex ${
                      isFullWidth
                        ? 'flex-column items-strech'
                        : 'flex-row items-center'
                    }`}>
                    {isRtl ? statementContent.reverse() : statementContent}
                  </div>

                  {statementIndex !== statements.length - 1 && (
                    <Separator
                      label={
                        operator === 'all'
                          ? labels.operatorAnd || DEFAULT_LABELS.operatorAnd
                          : labels.operatorOr || DEFAULT_LABELS.operatorOr
                      }
                    />
                  )}
                </div>
              )
            })}
          </div>
        )}
        <Separator />
        <div className={`mv5 mh3 ${isRtl ? 'flex justify-end' : ''}`}>
          <ButtonWithIcon
            variation="tertiary"
            collapseLeft
            size="small"
            icon={<IconPlus solid size={MEDIUM_ICON_SIZE} />}
            iconPosition={isRtl ? 'right' : 'left'}
            disabled={!canAddNewCondition()}
            onClick={handleAddNewCondition}>
            {labels.addNewCondition || DEFAULT_LABELS.addNewCondition}
          </ButtonWithIcon>
        </div>
      </div>
    </div>
  )
}

// this is so styleguidist can pick the prop types reference
Conditions.propTypes = {
  /** Shows or hides the delete button */
  canDelete: PropTypes.bool,
  /** Wether to show this component stretched to the width */
  isFullWidth: PropTypes.bool,
  /** Whether the order of elements and text if right to left */
  isRtl: 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,
  }),
  /** Conditions change callback: array of statement definitions */
  onChangeStatements: PropTypes.func.isRequired,
  /** Operator (any, all) change callback  */
  onChangeOperator: PropTypes.func,
  /** Operator indicates whether all the statements should be met or any of them */
  operator: PropTypes.oneOf(['all', 'any']),
  /** Possible options and respective data types, verb options */
  options: PropTypes.any.isRequired,
  /** Show or hide the header that selects the operator (any vs all) */
  hideOperator: PropTypes.bool,
  /** one statement = {subject: string, verb: string, object: unknown, error: string} */
  statements: PropTypes.array,
  /** Placeholder for subject dropdown */
  subjectPlaceholder: PropTypes.string.isRequired,
}

Conditions.defaultProps = {
  operator: 'any',
  hideOperator: false,
  statements: [],
  onChangeOperator: () => {},
  onChangeStatements: () => {},
  labels: {
    addNewCondition: 'add new condition',
    delete: 'Remove',
    headerPrefix: 'Matching',
    headerSufix: 'following conditions:',
    operatorAll: 'all',
    operatorAnd: 'and',
    operatorAny: 'any',
    operatorOr: 'or',
  },
}

export default 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/Conditions/typings.d.ts from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```typescript
export type Labels = {
  addNewCondition?: string
  delete?: string
  operatorAll?: string
  operatorAnd?: string
  operatorAny?: string
  operatorOr?: string
  headerPrefix?: string
  headerSufix?: string
}

export type Operator = 'all' | '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/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

function SimpleInputObject({ value, onChange }) {
  return <Input value={value || ''} onChange={e => onChange(e.target.value)} />
}

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

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

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

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

  render() {
    const options = {
      name: {
        label: 'User name',
        verbs: [
          {
            label: 'is',
            value: '=',
            object: props => <SimpleInputObject {...props} />,
          },
          {
            label: 'is not',
            value: '!=',
            object: props => <SimpleInputObject {...props} />,
          },
        ],
      },
      email: {
        label: 'Email',
        verbs: [
          {
            label: 'contains',
            value: 'contains',
            object: props => <SimpleInputObject {...props} />,
          },
          {
            label: 'is',
            value: '=',
            object: props => <SimpleInputObject {...props} />,
          },
          {
            label: 'is not',
            value: '!=',
            object: props => <SimpleInputObject {...props} />,
          },
        ],
      },
    }

    return (
      <Conditions
        canDelete
        onChangeOperator={this.handleToggleOperator}
        onChangeStatements={statements => {
          console.log('Changed statements to:', statements)
          this.setState({ simpleStatements: statements })
        }}
        operator={this.state.operator}
        options={options}
        subjectPlaceholder="Select subject"
        statements={this.state.simpleStatements}
      />
    )
  }
}
;<SimpleConditionsCase />
```

Unique

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

function SimpleInputObject({ value, onChange }) {
  return <Input value={value || ''} onChange={e => onChange(e.target.value)} />
}

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

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

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

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

  render() {
    const options = {
      name: {
        label: 'User name',
        verbs: [
          {
            label: 'is',
            value: '=',
            object: props => <SimpleInputObject {...props} />,
          },
          {
            label: 'is not',
            value: '!=',
            object: props => <SimpleInputObject {...props} />,
          },
        ],
        unique: true,
      },
      surname: {
        label: 'Last name',
        verbs: [
          {
            label: 'is',
            value: '=',
            object: props => <SimpleInputObject {...props} />,
          },
          {
            label: 'is not',
            value: '!=',
            object: props => <SimpleInputObject {...props} />,
          },
        ],
        unique: true,
      },
      country: {
        label: 'Country of residence',
        verbs: [
          {
            label: 'is',
            value: '=',
            object: props => <SimpleInputObject {...props} />,
          },
          {
            label: 'is not',
            value: '!=',
            object: props => <SimpleInputObject {...props} />,
          },
        ],
        unique: true,
      },
      email: {
        label: 'Email',
        verbs: [
          {
            label: 'contains',
            value: 'contains',
            object: props => <SimpleInputObject {...props} />,
          },
          {
            label: 'is',
            value: '=',
            object: props => <SimpleInputObject {...props} />,
          },
          {
            label: 'is not',
            value: '!=',
            object: props => <SimpleInputObject {...props} />,
          },
        ],
      },
    }

    return (
      <Conditions
        canDelete
        onChangeOperator={this.handleToggleOperator}
        onChangeStatements={statements => {
          console.log('Changed statements to:', statements)
          this.setState({ simpleStatements: statements })
        }}
        operator={this.state.operator}
        options={options}
        subjectPlaceholder="Select subject"
        statements={this.state.simpleStatements}
      />
    )
  }
}
;<SimpleConditionsCase />
```

Mobile

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

function SimpleInputObject({ value, onChange }) {
  return <Input value={value || ''} onChange={e => onChange(e.target.value)} />
}

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

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

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

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

  render() {
    const options = {
      name: {
        label: 'User name',
        verbs: [
          {
            label: 'is',
            value: '=',
            object: props => <SimpleInputObject {...props} />,
          },
          {
            label: 'is not',
            value: '!=',
            object: props => <SimpleInputObject {...props} />,
          },
        ],
      },
      email: {
        label: 'Email',
        verbs: [
          {
            label: 'contains',
            value: 'contains',
            object: props => <SimpleInputObject {...props} />,
          },
          {
            label: 'is',
            value: '=',
            object: props => <SimpleInputObject {...props} />,
          },
          {
            label: 'is not',
            value: '!=',
            object: props => <SimpleInputObject {...props} />,
          },
        ],
      },
    }

    return (
      <Conditions
        canDelete
        isFullWidth
        onChangeOperator={this.handleToggleOperator}
        onChangeStatements={statements => {
          console.log('Changed statements to:', statements)
          this.setState({ simpleStatements: statements })
        }}
        operator={this.state.operator}
        options={options}
        subjectPlaceholder="Select subject"
        statements={this.state.simpleStatements}
      />
    )
  }
}
;<SimpleConditionsCase />
```

Complex

```js
const DatePicker = require('../DatePicker').default
const Dropdown = require('../Dropdown').default
const Input = require('../Input').default
const Select = require('../EXPERIMENTAL_Select').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' },
]

function SimpleInputObject({ value, onChange }) {
  return <Input value={value || ''} onChange={e => onChange(e.target.value)} />
}

function ComplexDropdownObject({ value, onChange }) {
  return (
    <Dropdown
      value={value}
      options={possibleColors}
      onChange={(e, value) => {
        onChange(value)
      }}
    />
  )
}

function ComplexSelectObject({ value, onChange }) {
  return (
    <Select
      multi
      value={value}
      onChange={values => onChange(values)}
      options={possibleColors}
    />
  )
}

function ComplexNumericInputObject({ value, onChange }) {
  return (
    <Input
      min="0"
      onChange={e => onChange(e.target.value.replace(/\D/g, ''))}
      placeholder="Insert age..."
      type="number"
      value={value || ''}
    />
  )
}

function ComplexNumericInputRangeObject({ value, onChange }) {
  return (

      <Input
        type="number"
        min="0"
        placeholder="Age from..."
        errorMessage={
          value && parseInt(value.first) >= parseInt(value.last)
            ? 'Must be smaller than other input'
            : ''
        }
        value={value && value.first ? value.first : ''}
        onChange={e =>
          onChange({
            ...value,
            first: e.target.value.replace(/\D/g, ''),
          })
        }
      />

and

      <Input
        type="number"
        min={(value && `${parseInt(value.first) + 1}`) || '0'}
        placeholder="Age to..."
        value={value && value.last ? value.last : ''}
        onChange={e =>
          onChange({
            ...value,
            last: e.target.value.replace(/\D/g, ''),
          })
        }
      />

  )
}

function ComplexDatePickerObject({ value, onChange }) {
  return (
    <DatePicker
      locale="en-US"
      onChange={date => onChange(date)}
      value={value}
    />
  )
}

function ComplexDatePickerRangeObject({ value, onChange }) {
  return (

        <DatePicker
          errorMessage={
            value && value.from >= value.to ? 'Must be before end date' : ''
          }
          locale="en-US"
          onChange={date =>
            onChange({
              ...value,
              from: date,
            })
          }
          value={value && value.from}
        />

and

        <DatePicker
          locale="en-US"
          onChange={date =>
            onChange({
              ...value,
              to: date,
            })
          }
          value={value && value.to}
        />

  )
}

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

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

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

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

  render() {
    const options = {
      age: {
        unique: true,
        label: 'User age',
        verbs: [
          {
            label: 'is',
            value: '=',
            object: props => <ComplexNumericInputObject {...props} />,
          },
          {
            label: 'is between',
            value: 'between',
            object: props => <ComplexNumericInputRangeObject {...props} />,
          },
        ],
      },
      color: {
        unique: true,
        label: 'User favorite color',
        verbs: [
          {
            label: 'is',
            value: '=',
            object: props => <ComplexDropdownObject {...props} />,
          },
          {
            label: 'is any of',
            value: 'any',
            object: props => <ComplexSelectObject {...props} />,
          },
        ],
      },
      birthday: {
        unique: true,
        label: 'User birthday',
        verbs: [
          {
            label: 'is',
            value: '=',
            object: props => <ComplexDatePickerObject {...props} />,
          },
          {
            label: 'is between',
            value: 'between',
            object: props => <ComplexDatePickerRangeObject {...props} />,
          },
        ],
      },
    }

    return (
      <Conditions
        onChangeStatements={statements => {
          console.log('Changed statements to:', statements)
          this.setState({ statements })
        }}
        onChangeOperator={this.handleToggleOperator}
        operator={this.state.operator}
        options={options}
        statements={this.state.statements}
        subjectPlaceholder="Select subject"
      />
    )
  }
}
;<ComplexConditionsCase />
```

Grouped

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

function SimpleInputObject({ value, onChange }) {
  return <Input value={value || ''} onChange={e => onChange(e.target.value)} />
}

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

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

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

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

  render() {
    const options = {
      name: {
        label: 'User name',
        group: 'Group 1',
        unique: true,
        verbs: [
          {
            label: 'is',
            value: '=',
            object: props => <SimpleInputObject {...props} />,
          },
        ],
      },
      lastname: {
        label: 'Last name',
        group: 'Group 1',
        unique: true,
        verbs: [
          {
            label: 'is',
            value: '=',
            object: props => <SimpleInputObject {...props} />,
          },
        ],
      },
      email: {
        label: 'Email',
        group: 'Group 2',
        unique: true,
        verbs: [
          {
            label: 'contains',
            value: 'contains',
            object: props => <SimpleInputObject {...props} />,
          },
        ],
      },
    }

    return (
      <Conditions
        canDelete
        onChangeOperator={this.handleToggleOperator}
        onChangeStatements={statements => {
          console.log('Changed statements to:', statements)
          this.setState({ simpleStatements: statements })
        }}
        operator={this.state.operator}
        options={options}
        subjectPlaceholder="Select subject"
        statements={this.state.simpleStatements}
      />
    )
  }
}
;<GroupedConditionsCase />
```

RTL example

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

function SimpleInputObject({ value, onChange }) {
  return <Input value={value || ''} onChange={e => onChange(e.target.value)} />
}

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

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

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

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

  render() {
    const options = {
      name: {
        label: 'שם משתמש',
        verbs: [
          {
            label: 'הוא',
            value: '=',
            object: props => <SimpleInputObject {...props} />,
          },
          {
            label: 'לא',
            value: '!=',
            object: props => <SimpleInputObject {...props} />,
          },
        ],
      },
      email: {
        label: 'דוא"ל',
        verbs: [
          {
            label: 'מכיל',
            value: 'contains',
            object: props => <SimpleInputObject {...props} />,
          },
          {
            label: 'הוא',
            value: '=',
            object: props => <SimpleInputObject {...props} />,
          },
          {
            label: 'לא',
            value: '!=',
            object: props => <SimpleInputObject {...props} />,
          },
        ],
      },
    }

    return (
      <Conditions
        canDelete
        isRtl={true}
        onChangeOperator={this.handleToggleOperator}
        onChangeStatements={statements => {
          console.log('Changed statements to:', statements)
          this.setState({ simpleStatements: statements })
        }}
        operator={this.state.operator}
        options={options}
        subjectPlaceholder="בחר נושא"
        statements={this.state.simpleStatements}
        labels={{
          headerPrefix: 'מהתנאים הבאים',
          operatorAll: 'כל',
          operatorAny: 'לכל אחד',
          headerSufix: 'תואם',
          addNewCondition: 'הוסף תנאי חדש',
          operatorAnd: 'ו',
          operatorOr: 'או',
        }}
      />
    )
  }
}
;<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/Conditions/StrategySelector.tsx from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'

import IconCaretDown from '../icon/CaretDown/index.js'
import { Labels, Operator } from './typings'
import { DEFAULT_LABELS, SMALL_ICON_SIZE } from './constants'

type Props = {
  isRtl?: boolean
  labels: Pick<
    Labels,
    'headerPrefix' | 'headerSufix' | 'operatorAll' | 'operatorAny'
  >
  onChangeOperator: (operator: Props['operator']) => void
  operator: Operator
}

const StrategySelector: React.FC<Props> = ({
  isRtl,
  operator,
  onChangeOperator,
  labels,
}) => {
  const handleOperatorChange = event => {
    const newOperator = event.target.value
    if (operator !== newOperator) {
      onChangeOperator(newOperator)
    }
  }

  const seletorContent = [
    <span key="seletorContent-operator" className="mh3 b">
      {operator === 'all'
        ? labels.operatorAll || DEFAULT_LABELS.operatorAll
        : labels.operatorAny || DEFAULT_LABELS.operatorAny}
    </span>,
    <select
      key="seletorContent-select"
      className="o-0 absolute top-0 left-0 w-100 bottom-0 pointer t-small"
      onChange={handleOperatorChange}
      value={operator}
      style={{
        // safari select height fix
        WebkitAppearance: 'menulist-button',
      }}>
      <option value="all">
        {labels.operatorAll || DEFAULT_LABELS.operatorAll}
      </option>
      <option value="any">
        {labels.operatorAny || DEFAULT_LABELS.operatorAny}
      </option>
    </select>,
    <IconCaretDown key="seletorContent-icon" size={SMALL_ICON_SIZE} />,
  ]

  return (
    <div className="flex flex-row nowrap">
      <span className={isRtl ? 'mr3' : ''}>
        {labels.headerPrefix || DEFAULT_LABELS.headerPrefix}
      </span>
      <div className="c-link relative">
        {isRtl ? seletorContent.reverse() : seletorContent}
      </div>
      <span className={isRtl ? '' : 'ml3'}>
        {labels.headerSufix || DEFAULT_LABELS.headerSufix}
      </span>
    </div>
  )
}

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/Conditions/constants.ts from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Labels } from './typings'

export const DEFAULT_LABELS: Labels = {
  addNewCondition: 'add new condition',
  delete: 'Remove',
  headerPrefix: 'Matching',
  headerSufix: 'following conditions:',
  operatorAll: 'all',
  operatorAnd: 'and',
  operatorAny: 'any',
  operatorOr: 'or',
}

export const SMALL_ICON_SIZE = 14
export const MEDIUM_ICON_SIZE = 16

```


[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/Conditions/Separator.tsx from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'

const SEPARATOR_LINE_OPTICAL_COMPENSATION = '32px'

type Props = {
  label?: string
}

const Separator: React.FC<Props> = ({ label }) => {
  return (
    <div
      style={{ width: `calc(100% + ${SEPARATOR_LINE_OPTICAL_COMPENSATION})` }}
      className="flex flex-row w-100 nowrap items-center mv3 nl5">
      <hr className="ma0 b--black-10 bb bb-0 w-50" />
      {label && <span className="gray ph3 dib bg-white">{label}</span>}
      <hr className="ma0 b--black-10 bb bb-0 w-50" />
    </div>
  )
}

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/ColorPicker/Gradient.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import PropTypes from 'prop-types'
import { CustomPicker } from 'react-color'
import { Hue } from 'react-color/lib/components/common'

/**
 * Gradient Component
 */
class Gradient extends React.Component {
  render() {
    return (
      <div className="gradient-container relative w-100 mv6">
        <Hue
          {...this.props}
          onChange={this.props.onChange}
          pointer={() => (
            <div
              className="pointer-gradient"
              style={{ background: this.props.hex }}
            />
          )}
          direction="horizontal"
        />
      </div>
    )
  }
}

Gradient.propTypes = {
  /** onChange event */
  onChange: PropTypes.func,
  /** Pointer Hex Color */
  hex: PropTypes.string,
}

export default CustomPicker(Gradient)

```


[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/ColorPicker/ColorOptions.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

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

import Gradient from './Gradient'
import Saturation from './Saturation'
import Alpha from './Alpha'
import RGBInput from './RGBInput'
import HSVInput from './HSVInput'
import Dropdown from '../Dropdown'
import ColorHistory from './ColorHistory'

/** HSV Key to Dropdown */
const HSV_INPUT = 'HSV_KEY'
/** RGB Key to Dropdown */
const RGB_INPUT = 'RGB_KEY'

/**
 * ColorOptions Component
 */
export default class ColorOptions extends React.Component {
  /** Initial State */
  state = {
    currentInput: RGB_INPUT,
  }

  /**
   * Handle input changes
   */
  handleOnChangeInput = e => {
    this.setState({
      currentInput: e.target.value,
    })
  }

  /**
   * Render ColorOptions Component
   */
  render() {
    return (
      <div className="absolute pa3 w-100 z-5 bg-base options-container br2">
        <div className="mv3 relative items-end flex w-100">
          <div className="w-75">
            {this.state.currentInput === RGB_INPUT ? (
              <RGBInput
                color={this.props.color.rgba}
                onChange={this.props.onColorChange}
              />
            ) : (
              <HSVInput
                color={this.props.color.hsva}
                onChange={this.props.onColorChange}
              />
            )}
          </div>
          <div className="w-25 mb3">
            <Dropdown
              size="small"
              options={[
                { value: RGB_INPUT, label: 'RGB' },
                { value: HSV_INPUT, label: 'HSV' },
              ]}
              value={this.state.currentInput}
              onChange={this.handleOnChangeInput}
            />
          </div>
        </div>
        <Saturation
          color={this.props.color.rgba}
          onChangeComplete={this.props.onColorChange}
        />
        <Gradient
          color={this.props.color.rgba}
          onChangeComplete={this.props.onColorChange}
        />
        <Alpha
          color={this.props.color.rgba}
          onChangeComplete={this.props.onColorChange}
        />
        <ColorHistory {...this.props} />
      </div>
    )
  }
}

ColorOptions.propTypes = {
  /** Color input */
  color: PropTypes.object.isRequired,
  /** ColorChange event */
  onColorChange: 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/ColorPicker/color-picker.global.css from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```css
/**
* ColorPicker
*/

/** Gradient container style */
.gradient-container {
  height: 0.25rem;
}

/** Saturation container style */
.saturation-container {
  min-height: 12rem;
}

/** Gradient container inner's div style */
.gradient-container div {
  border-radius: 0.25rem;
}

/** Saturation container inner's div style */
.saturation-container div {
  border-radius: 0.25rem;
}

/** Default Pointer styles */
.pointer-gradient, .pointer-saturation {
  border-radius: 1rem !important;
  cursor: pointer;
  transform: translate(-50%, -0.4375rem);
  box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
}

/** Gradient Point style */
.pointer-gradient {
  width: 1rem;
  height: 1rem;
  border: 0.125rem solid #ffffff;
}

/** Saturation Pointer style */
.pointer-saturation {
  width: 0.625rem;
  height: 0.625rem;
  border: 0.125rem solid #ffffff;
}

/** Options Container Style */
.options-container {
  box-shadow: 0px 4px 8px rgba(15, 54, 102, 0.15);
  min-width: 20rem;
}

/** Remove input number spinners */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
```


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

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

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { CustomPicker } from 'react-color'
import { PropTypes } from 'prop-types'
import { Saturation } from 'react-color/lib/components/common'

/** SaturationCustom Component */
class SaturationCustom extends React.Component {
  render() {
    const { hex } = this.props
    return (
      <div className="saturation-container relative w-100">
        <Saturation
          {...this.props}
          pointer={() => (
            <div className="pointer-saturation" style={{ background: hex }} />
          )}
        />
      </div>
    )
  }
}

SaturationCustom.propTypes = {
  /** onChenge event */
  onChange: PropTypes.func,
  /** Pointer hex color  */
  hex: PropTypes.string,
}

export default CustomPicker(SaturationCustom)

```


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

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import OutsideClickHandler from 'react-outside-click-handler'
import PropTypes from 'prop-types'

import colorutil from './colorUtil'
import HexInput from './HexInput'
import ColorOptions from './ColorOptions'

import './color-picker.global.css'

/**
 * ColorPicker Component
 */
class ColorPicker extends React.Component {
  state = {
    showOptions: false,
  }

  validColor() {
    const { rgba, hsva, hex } = this.props.color
    const color = rgba || hsva || hex
    const hsvaAux = color && (hsva || colorutil.any.to.hsv(color))
    const hexAux = color && (hex || colorutil.any.to.hex(color))
    const rgbaAux = color && (rgba || colorutil.any.to.rgb(color))

    return {
      rgba: rgbaAux,
      hsva: hsvaAux,
      hex: hexAux,
    }
  }

  handleColorChange = color => {
    const { onChange } = this.props
    onChange &&
      onChange({
        rgba: color.rgb || color.rgba,
        hsva: color.hsv || color.hsva,
        hex: color.hex,
      })
  }

  handleOutsideClick = () => {
    this.setState({ showOptions: false })
  }

  handleShowOptions = () => {
    this.setState({ showOptions: !this.state.showOptions })
  }

  render() {
    const { title, disabled } = this.props
    const { rgba, hsva, hex } = this.validColor()

    const styleColorBox = {
      backgroundColor: `rgba(${rgba.r},${rgba.g},${rgba.b},${rgba.a})`,
      height: '1.5rem',
    }

    return (
      <OutsideClickHandler onOutsideClick={this.handleOutsideClick}>
        <div className="relative dib w-100">
          {title && (
            <div className="bb b--muted-4 mb3 t-heading-5 pv5">{title}</div>
          )}
          <div className="flex w-100">
            <div className="w-25 pa1">
              <div className="t-small w-100 c-on-base db mb3">
                {this.props.label}
              </div>
              <div
                className={`ba bw1 b--muted-4 br2 pa1 ${
                  disabled ? '' : 'hover-b--action-primary pointer'
                }`}
                onClick={this.handleShowOptions}>
                <div className="br1" style={styleColorBox} />
              </div>
            </div>
            <div className="w-75 pa1">
              <HexInput
                rgb={rgba}
                onChange={this.handleColorChange}
                disabled={disabled}
              />
            </div>
          </div>
          <div>
            {this.state.showOptions && !disabled && (
              <ColorOptions
                {...this.props}
                color={{ rgba, hex, hsva }}
                onColorChange={this.handleColorChange}
              />
            )}
          </div>
        </div>
      </OutsideClickHandler>
    )
  }
}

/** Default props values */
ColorPicker.defaultProps = {
  label: 'Default',
}

ColorPicker.propTypes = {
  /** onChange event */
  onChange: PropTypes.func,
  /** Color Label */
  label: PropTypes.string,
  /** ColorPicker Title */
  title: PropTypes.string,
  /** Color format */
  color: PropTypes.shape({
    /** RGBA color format */
    rgba: PropTypes.object,
    /** HSVA color format */
    hsva: PropTypes.object,
    /** HEX color format */
    hex: PropTypes.string,
  }).isRequired,
  /** Color history */
  colorHistory: PropTypes.array.isRequired,
  /** Disable component */
  disabled: PropTypes.bool,
}

export default ColorPicker

```


[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/ColorPicker/RGBInput.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

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

import colorutil from './colorUtil'
import Input from '../Input'

/**
 * RGBInput Component
 */
class RGBInput extends React.Component {
  getValue = event => {
    const max = Number(event.target.max)
    const min = Number(event.target.min)
    let value = Number(event.target.value)

    if (value > max) value = max
    if (value < min) value = min

    return value
  }
  handleChange = (event, key) => {
    const value = this.getValue(event)

    const rgb = { ...this.props.color, [key]: value }
    const hsv = colorutil.rgb.to.hsv(rgb)
    const hex = colorutil.rgb.to.hex(rgb)

    this.props.onChange({
      hsv,
      hex,
      rgb,
    })
  }
  render() {
    return (
      <div className="relative flex mv3">
        <div className="ph2 w-25">
          <Input
            label="R"
            size="small"
            type="number"
            min="0"
            max="255"
            value={this.props.color.r}
            onChange={e => this.handleChange(e, 'r')}
          />
        </div>
        <div className="ph2 w-25">
          <Input
            label="G"
            size="small"
            type="number"
            min="0"
            max="255"
            value={this.props.color.g}
            onChange={e => this.handleChange(e, 'g')}
          />
        </div>
        <div className="ph2 w-25">
          <Input
            label="B"
            size="small"
            type="number"
            min="0"
            max="255"
            value={this.props.color.b}
            onChange={e => this.handleChange(e, 'b')}
          />
        </div>
        <div className="ph2 w-25">
          <Input
            label="A"
            size="small"
            type="number"
            min="0"
            max="1"
            step="0.01"
            value={this.props.color.a}
            onChange={e => this.handleChange(e, 'a')}
          />
        </div>
      </div>
    )
  }
}

RGBInput.propTypes = {
  /** inChange event */
  onChange: PropTypes.func.isRequired,
  /** Color Input */
  color: PropTypes.object.isRequired,
}

export default RGBInput

```


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

[Assistant]
Here's the implementation:

```markdown
Color Picker lets users select a color value using three differenets way: RGBA (Red, green, blue and alpha properties), [HSVA](https://en.wikipedia.org/wiki/HSL_and_HSV) (Hue, saturation, value and alpha properties) or hexadecimal (color code abstraction to rgb values).

### 👍 Dos
- Use color picker in cenarios that user needs to choose an specific color value.
- You can use multiples color picker components, if you need more than one color to be setted.

### 👎 Don'ts
- Don’t use color picker in cenarios that users must only reference a color name.

#### Simple ColorPicker

```js
class ColorPickerExample extends React.Component {
  constructor() {
    super()
    this.state = { color:{ hex: '#141E7A' }, history: [] }

    this.handleChange = this.handleChange.bind(this)
  }

  handleChange(color) {
    const { history } = this.state
    history.push(color)
    this.setState({
      history,
      color,
    })
  }

  render() {
    return (

          <ColorPicker
            color={this.state.color}
            colorHistory={this.state.history}
            onChange={ this.handleChange }
          />

    )
  }
}

;<ColorPickerExample />
```

#### ColorPicker with Title

```js
class ColorPickerExample extends React.Component {
  constructor() {
    super()
    this.state = { color:{ hex: '#141E7A' }, history: [] }

    this.handleChange = this.handleChange.bind(this)
  }

  handleChange(color) {
    const { history } = this.state
    history.push(color)
    this.setState({
      history
    })
  }

  render() {
    return (

          <ColorPicker
            color={this.state.color}
            title="Color Title"
            colorHistory={this.state.history}
            onChange={ this.handleChange }
          />

    )
  }
}

;<ColorPickerExample />
```
#### Multiples ColorPickers

```js
const black = require('./index.js').COLOR

class ColorPickerExample extends React.Component {
  constructor() {
    super()
    this.handleChange = this.handleChange.bind(this)
    this.state = {
        colorDefault: { hex: '#141E7A' },
        colorActive: { hex: '#141E7A' },
        colorHover:{ hex: '#141E7A' },
        history: [],
      }
  }

  render() {
    return (

          <ColorPicker
            color={this.state.colorDefault}
            colorHistory={this.state.history}
            onChange={ (color) => this.handleChange(color, 'colorDefault') }
          />

          <ColorPicker
            color={this.state.colorActive}
            colorLabel="Active"
            colorHistory={this.state.history}
            onChange={ (color) => this.handleChange(color, 'colorActive') }
          />

          <ColorPicker
            color={this.state.colorHover}
            colorLabel="Hover"
            colorHistory={this.state.history}
            onChange={ (color) => this.handleChange(color, 'colorHover') }
          />

    )
  }

  handleChange(color, picker) {
    const { history } = this.state
    history.push(color)
    this.setState({
      history,
      [picker]: color,
    })
  }
}

;<ColorPickerExample />
```

#### ColorPicker Disabled

```js
class ColorPickerExample extends React.Component {
  constructor() {
    super()
    this.state = { color:{ hex: '#141E7A' }, history: [] }

    this.handleChange = this.handleChange.bind(this)
  }

  handleChange(color) {
    const { history } = this.state
    history.push(color)
    this.setState({
      history
    })
  }

  render() {
    return (

          <ColorPicker
            color={this.state.color}
            disabled
            colorHistory={this.state.history}
            onChange={ this.handleChange }
          />

    )
  }
}

;<ColorPickerExample />
```

```


[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/ColorPicker/colorUtil.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
const COLOR_CONSTS = {
  RGB_MAX_VALUE: 255,
}

const COLOR_FORMAT = {
  HSV: 'hsv',
  RGB: 'rgb',
  HEX: 'hex',
}

/** Convert RGB to HSV format */
const rgbTohsv = rgb => {
  const { r, g, b, a } = rgb
  const rAux = r / COLOR_CONSTS.RGB_MAX_VALUE
  const gAux = g / COLOR_CONSTS.RGB_MAX_VALUE
  const bAux = b / COLOR_CONSTS.RGB_MAX_VALUE
  const cMax = Math.max(rAux, gAux, bAux)
  const cMin = Math.min(rAux, gAux, bAux)
  const theta = cMax - cMin

  let h, s
  // Calcule Hue
  if (theta === 0) {
    h = 0
  } else {
    if (cMax === rAux) h = ((gAux - bAux) / theta) % 6
    else if (cMax === gAux) h = (bAux - rAux) / theta + 2
    else h = (rAux - gAux) / theta + 4
  }

  h = Math.round(h * 60)

  // Calcule Saturation
  if (cMax === 0) {
    s = 0
  } else {
    s = parseFloat((theta / cMax).toFixed(2))
  }

  // Calcule Value
  const v = parseFloat(cMax.toFixed(2))

  return {
    h,
    s,
    v,
    a,
  }
}

/** Convert RGB to Hex*/
const rgbTohex = rgb => {
  const { r, g, b } = rgb
  let rString = r.toString(16).toUpperCase()
  let gString = g.toString(16).toUpperCase()
  let bString = b.toString(16).toUpperCase()

  if (rString.length < 2) {
    rString = `0${rString}`
  }

  if (gString.length < 2) {
    gString = `0${gString}`
  }

  if (bString.length < 2) {
    bString = `0${bString}`
  }

  const hex = `#${rString}${gString}${bString}`

  return hex
}

/** Convert HSV to RGB */
const hsvToRgb = hsv => {
  const { h, s, v, a } = hsv
  const c = v * s
  const x = c * (1 - Math.abs(((h / 60) % 2) - 1))
  const m = v - c

  let rAux, gAux, bAux

  if (h >= 0 && h < 60) {
    rAux = c
    gAux = x
    bAux = 0
  } else if (h >= 60 && h < 120) {
    rAux = x
    gAux = c
    bAux = 0
  } else if (h >= 120 && h < 180) {
    rAux = 0
    gAux = c
    bAux = x
  } else if (h >= 180 && h < 240) {
    rAux = 0
    gAux = x
    bAux = c
  } else if (h >= 240 && h < 300) {
    rAux = x
    gAux = 0
    bAux = c
  } else {
    rAux = c
    gAux = 0
    bAux = x
  }

  const r = Math.round((rAux + m) * COLOR_CONSTS.RGB_MAX_VALUE)
  const g = Math.round((gAux + m) * COLOR_CONSTS.RGB_MAX_VALUE)
  const b = Math.round((bAux + m) * COLOR_CONSTS.RGB_MAX_VALUE)

  return {
    r,
    g,
    b,
    a,
  }
}

/** Convert HSV to Hex */
const hsvTohex = hsv => {
  const rgb = hsvToRgb(hsv)
  return rgbTohex(rgb)
}

/** Convert Hex to RGB */
const hexTorgb = hex => {
  const r = parseInt(hex.substring(1, 3), 16)
  const g = parseInt(hex.substring(3, 5), 16)
  const b = parseInt(hex.substring(5, 7), 16)
  return {
    r,
    g,
    b,
    a: 1,
  }
}

/** Convert Hex to HSV */
const hexTohsv = hex => {
  const rgb = hexTorgb(hex)
  return rgbTohsv(rgb)
}

const validHex = hex => {
  return /(^#[0-9A-F]{6}$)/i.test(hex)
}

/** Get color format */
const colorFormat = color => {
  if (validHex(color)) return COLOR_FORMAT.HEX
  else if ('h' in color && 's' in color && 'v' in color) return COLOR_FORMAT.HSV
  else if ('r' in color && 'g' in color && 'b' in color) return COLOR_FORMAT.RGB
}

/** Convert Any format suported(RGB, HSV and HEX) to RGB */
const anyTorgb = color => {
  const format = colorFormat(color)
  switch (format) {
    case COLOR_FORMAT.HEX:
      return hexTorgb(color)
    case COLOR_FORMAT.HSV:
      return hsvToRgb(color)
    case COLOR_FORMAT.RGB:
      return color
    default:
      return
  }
}

/** Convert Any format suported(RGB, HSV and HEX) to HSV */
const anyTohsv = color => {
  const format = colorFormat(color)
  switch (format) {
    case COLOR_FORMAT.HEX:
      return hexTohsv(color)
    case COLOR_FORMAT.HSV:
      return color
    case COLOR_FORMAT.RGB:
      return rgbTohsv(color)
    default:
      return
  }
}

/** Convert Any format suported(RGB, HSV and HEX) to HEX */
const anyTohex = color => {
  const format = colorFormat(color)
  switch (format) {
    case COLOR_FORMAT.HEX:
      return color
    case COLOR_FORMAT.HSV:
      return hsvTohex(color)
    case COLOR_FORMAT.RGB:
      return rgbTohex(color)
    default:
      return
  }
}

export default {
  rgb: {
    to: {
      hsv: rgbTohsv,
      hex: rgbTohex,
    },
  },
  hsv: {
    to: {
      rgb: hsvToRgb,
      hex: hsvTohex,
    },
  },
  hex: {
    to: {
      rgb: hexTorgb,
      hsv: hexTohsv,
    },
  },
  any: {
    to: {
      rgb: anyTorgb,
      hsv: anyTohsv,
      hex: anyTohex,
    },
  },
  validateHex: validHex,
}

```


[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/ColorPicker/ColorHistory.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

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

import colorutil from './colorUtil'

/**
 * ColorHistory Component
 */
class ColorHistory extends React.Component {
  /**
   * Render sigle color block
   */
  renderColorBlock = colorInput => {
    const { rgba, hsva, hex } = colorInput
    const color = rgba || hsva || hex || '#FFFFFF'
    const colorInRGB = colorutil.any.to.rgb(color)
    const styleColorBox = {
      backgroundColor: `rgba(${colorInRGB.r},${colorInRGB.g},${colorInRGB.b},${colorInRGB.a})`,
      height: '1.5rem',
    }
    const output = {
      rgba: colorInRGB,
      hsva: colorutil.any.to.hsv(color),
      hex: colorutil.any.to.hex(color),
    }

    return (
      <div
        onClick={() => this.props.onColorChange(output)}
        className="br2 ba b--muted-4 w-100 ma1 hover-b--action-primary pointer"
        style={styleColorBox}
      />
    )
  }

  /**
   * Render a list of color blocks
   */
  renderColorList = colorList => {
    const blocks = []
    const appendColor = color =>
      color
        ? blocks.push(this.renderColorBlock(color))
        : blocks.push(this.renderColorBlock(this.props.defaultColor))
    for (let i = 0; i < this.props.historyLength; i++) {
      appendColor(colorList && colorList[i])
    }
    return blocks
  }

  /**
   * Render ColorHistory component
   */
  render() {
    const { colorHistory } = this.props
    return (
      <div className="flex">{this.renderColorList(colorHistory.reverse())}</div>
    )
  }
}

/**
 * ColorHistory default props
 */
ColorHistory.defaultProps = {
  /** Default historyLength */
  historyLength: 9,
  /** Default color to empty blocks */
  defaultColor: { hex: '#FFFFFF' },
}

/** ColorHistory Props */
ColorHistory.propTypes = {
  /** Color history list */
  colorHistory: PropTypes.array,
  /** Color history length */
  historyLength: PropTypes.number,
  /** Default color to empty blocks */
  defaultColor: PropTypes.object,
  /** onColorChange event */
  onColorChange: PropTypes.func,
}

export default ColorHistory

```


[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/ColorPicker/HexInput.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

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

import colorutil from './colorUtil'
import Input from '../Input'

/** HexInput Component */
class HexInput extends React.Component {
  state = {
    inputValue: '#000000',
    error: false,
  }
  handleChange = e => {
    e.preventDefault()
    const inputValue = e.target.value
    this.setState({ inputValue: inputValue })
    if (this.validation(inputValue)) {
      const { onChange } = this.props
      const rgb = colorutil.hex.to.rgb(inputValue)
      const hsv = colorutil.rgb.to.hsv(rgb)
      onChange({
        rgb,
        hsv,
        hex: inputValue,
      })
    }
  }
  validation = color => {
    const validColor = colorutil.validateHex(color)
    this.setState({
      error: !validColor,
    })
    return validColor
  }

  componentDidMount() {
    this.updateInputValue()
  }

  componentDidUpdate(prevProps) {
    if (prevProps.rgb !== this.props.rgb) {
      this.updateInputValue()
    }
  }

  updateInputValue() {
    const { rgb } = this.props
    const color = colorutil.rgb.to.hex(rgb)
    this.setState({ inputValue: color })
  }

  render() {
    const { disabled, errorMessage } = this.props
    const { error, inputValue } = this.state
    return (
      <div className="mb5">
        <Input
          error={error}
          label="Hex"
          value={inputValue}
          size="small"
          onChange={this.handleChange}
          errorMessage={error && errorMessage}
          disabled={disabled}
        />
      </div>
    )
  }
}

/** Default props values */
HexInput.defaultProps = {
  errorMessage: 'Invalid Hex Color',
  disable: false,
}

HexInput.propTypes = {
  /** onChange event */
  onChange: PropTypes.func,
  /** RGB color input */
  rgb: PropTypes.object,
  /** Erro message */
  errorMessage: PropTypes.string,
  /** Disable component */
  disabled: PropTypes.bool,
}

export default HexInput

```


[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/ColorPicker/Alpha.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { CustomPicker } from 'react-color'
import PropTypes from 'prop-types'
import { Alpha } from 'react-color/lib/components/common'

/**
 * AlphaComponent to control alpha level
 */
class AlphaCustom extends React.Component {
  render() {
    const { rgb, hsl, hex, onChange } = this.props
    return (
      <div className="gradient-container relative w-100 mv6 alpha">
        <Alpha
          rgb={rgb}
          hsl={hsl}
          onChange={onChange}
          pointer={() => (
            <div className="pointer-gradient" style={{ background: hex }} />
          )}
        />
      </div>
    )
  }
}

AlphaCustom.propTypes = {
  /** onChange event */
  onChange: PropTypes.func.isRequired,
  /** Hex Color string */
  hex: PropTypes.string.isRequired,
  /** RGB color object */
  rgb: PropTypes.object.isRequired,
  /** HSL color object */
  hsl: PropTypes.object.isRequired,
}

export default CustomPicker(AlphaCustom)

```


[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/ColorPicker/HSVInput.js from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

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

import colorutil from './colorUtil'
import Input from '../Input'

/** HSVInput component */
class HSVInput extends React.Component {
  getValue = event => {
    const max = Number(event.target.max)
    const min = Number(event.target.min)
    let value = Number(event.target.value)

    if (value > max) value = max
    if (value < min) value = min

    return value
  }

  handleChange = (event, key) => {
    const value = this.getValue(event)

    const hsv = { ...this.props.color, [key]: value }
    const rgb = colorutil.hsv.to.rgb(hsv)
    const hex = colorutil.rgb.to.hex(rgb)

    this.props.onChange({
      rgb,
      hex,
      hsv,
    })
  }
  render() {
    return (
      <div className="mv3">
        <div className="relative flex">
          <div className="ph2 w-25">
            <Input
              label="H"
              size="small"
              type="number"
              min="0"
              max="360"
              step="0.000000000001"
              value={this.props.color.h}
              onChange={e => this.handleChange(e, 'h')}
            />
          </div>
          <div className="ph2 w-25">
            <Input
              label="S"
              size="small"
              type="number"
              min="0"
              max="1"
              step="0.000000000001"
              value={this.props.color.s}
              onChange={e => this.handleChange(e, 's')}
            />
          </div>
          <div className="ph2 w-25">
            <Input
              label="V"
              size="small"
              type="number"
              min="0"
              max="1"
              step="0.000000000001"
              value={this.props.color.v}
              onChange={e => this.handleChange(e, 'v')}
            />
          </div>
          <div className="ph2 w-25">
            <Input
              label="A"
              size="small"
              type="number"
              min="0"
              max="1"
              step="0.01"
              value={this.props.color.a}
              onChange={e => this.handleChange(e, 'a')}
            />
          </div>
        </div>
      </div>
    )
  }
}

HSVInput.propTypes = {
  /** onChange event */
  onChange: PropTypes.func.isRequired,
  /** Color input */
  color: PropTypes.object,
}

export default HSVInput

```


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

[Assistant]
Here's the implementation:

```javascript
import InputPassword from '../InputPassword'
import deprecated from '../../modules/deprecated'

export default deprecated({
  useNewComponent: {
    old: 'PasswordInput',
    new: 'InputPassword',
  },
})(InputPassword)

```


[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_TableTree/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'

import Toolbar from '../EXPERIMENTAL_Table/Toolbar'
import DataTable from '../EXPERIMENTAL_Table/DataTable'
import Tree from './Tree'
import { tablePropTypes, TableComposites } from '../EXPERIMENTAL_Table'
import Pagination from '../EXPERIMENTAL_Table/Pagination'
import FilterBar from '../EXPERIMENTAL_Table/FilterBar'
import { Checkboxes } from '../EXPERIMENTAL_useCheckboxTree/types'
import { defaultComparatorCurry } from '../EXPERIMENTAL_useCheckboxTree/constants'
import Headings from '../EXPERIMENTAL_Table/DataTable/Headings'
import useTableMotion from '../EXPERIMENTAL_Table/hooks/useTableMotion'

const CONTAINER_TRANSITIONS = [
  {
    prop: 'minHeight',
    duration: 200,
    func: 'ease-in-out',
    delay: 0,
    optimize: true,
  },
]

const TableTree: FC<Props> & TableComposites = ({
  children,
  columns,
  items,
  checkboxes,
  nodesKey,
  comparator,
  measures,
  loading,
  empty,
  emptyState,
  onRowClick,
}) => {
  if (!measures) {
    throw new Error('Provide measures to the TableTree')
  }

  const { tableHeight, rowHeight, currentDensity } = measures
  const motion = useTableMotion(CONTAINER_TRANSITIONS)

  return (
    <div style={{ minHeight: tableHeight }} className="flex flex-column">
      {children}
      <DataTable
        loading={loading}
        emptyState={emptyState}
        empty={empty}
        motion={motion}
        height={tableHeight}>
        <thead className="w-100 ph4 truncate overflow-x-hidden c-muted-2 f6">
          <Headings checkboxes={checkboxes} columns={columns} />
        </thead>
        {!empty && !loading && (
          <tbody>
            <Tree
              currentDensity={currentDensity}
              checkboxes={checkboxes}
              columns={columns}
              items={items}
              onRowClick={onRowClick}
              comparator={comparator}
              nodesKey={nodesKey}
              rowHeight={rowHeight}
            />
          </tbody>
        )}
      </DataTable>
    </div>
  )
}

TableTree.defaultProps = {
  nodesKey: 'children',
  comparator: defaultComparatorCurry,
}

const treePropTypes = {
  nodesKey: PropTypes.string,
  comparator: PropTypes.func,
}

const propTypes = {
  ...treePropTypes,
  ...tablePropTypes,
}

type Props = InferProps<typeof propTypes> & {
  checkboxes?: Checkboxes<unknown>
}

TableTree.Toolbar = Toolbar
TableTree.FilterBar = FilterBar
TableTree.Pagination = Pagination
TableTree.propTypes = propTypes

export type TreeState = {
  collapsedItems: Array<string>
  toggleCollapsed: (id: string) => void
  isCollapsed: (id: string) => boolean
}

export default TableTree

```


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

[Assistant]
Here's the implementation:

```markdown
#### NodesKey Prop

```js
const useTableMeasures = require('../EXPERIMENTAL_Table/hooks/useTableMeasures.tsx')
  .default
const sampleData = require('./sampleData.ts').default

// Define the columns
const columns = [
  {
    id: 'name',
    title: 'Name',
    width: 300,
  },
  {
    id: 'email',
    title: 'Email',
  },
  {
    id: 'number',
    title: 'Number',
  },
  {
    id: 'country',
    title: 'Country',
  },
]

// Define the items
const items = sampleData

function ToolbarExample() {
  const measures = useTableMeasures({
    size: items.length,
  })

  const comparator = item => candidate => {
    return item.email === candidate.email
  }

  const onRowClick = ({ rowData }) => {
    console.log(rowData)
  }

  return (
    <TableTree
      onRowClick={onRowClick}
      comparator={comparator}
      measures={measures}
      columns={columns}
      items={items}
      nodesKey="children"
    />
  )
}
;<ToolbarExample />
```

#### Checkboxes

```js
const useTableMeasures = require('../EXPERIMENTAL_Table/hooks/useTableMeasures.tsx')
  .default
const sampleData = require('./sampleData.ts').default
const useCheckboxTree = require('../EXPERIMENTAL_useCheckboxTree').default

// Define the columns
const columns = [
  {
    id: 'name',
    title: 'name',
    width: 300,
  },
  {
    id: 'email',
    title: 'Email',
  },
  {
    id: 'number',
    title: 'Number',
  },
  {
    id: 'country',
    title: 'Country',
  },
]

const items = [
  {
    name: "T'Chala",
    email: 'black.panther@gmail.com',
    number: 1.88191,
    country: '🇰🇪Wakanda',
  },
  {
    name: 'Shang-Chi',
    email: 'kungfu.master@gmail.com',
    number: 39.09222,
    country: '🇨🇳China',
    children: [],
  },
  {
    name: 'Natasha Romanoff',
    email: 'black.widow@gmail.com',
    number: 5.09291,
    country: '🇷🇺Russia',
  },
  {
    name: 'Peter Parker',
    email: 'spider.man@gmail.com',
    country: '🇺🇸USA',
    children: [
      {
        name: 'Aunt May',
        email: 'may.parker@gmail.com',
        country: '🇺🇸USA',
      },
    ],
  },
]

function Example() {
  const [inputValue, setInputValue] = React.useState('')

  const comparator = item => candidate => {
    return item.email === candidate.email
  }

  const onToggle = ({ checkedItems }) => {
    console.log(checkedItems)
  }

  const checkboxes = useCheckboxTree({
    comparator,
    items,
    onToggle,
  })

  const measures = useTableMeasures({
    size: items.length,
  })

  return (
    <TableTree
      comparator={comparator}
      checkboxes={checkboxes}
      columns={columns}
      items={checkboxes.itemTree}
      measures={measures}
    />
  )
}
;<Example />
```

#### Full Example

```js
const useTableMeasures = require('../EXPERIMENTAL_Table/hooks/useTableMeasures.tsx')
  .default
const useTableVisibility = require('../EXPERIMENTAL_Table/hooks/useTableVisibility.ts')
  .default
const sampleData = require('./sampleData.ts').default
const useCheckboxTree = require('../EXPERIMENTAL_useCheckboxTree').default

// Define the columns
const columns = [
  {
    id: 'name',
    title: 'Description',
    width: 350,
    cellRenderer: ({ rowHeight, data }) => (

        <Image size={rowHeight - 10} />
        {data}

    ),
  },
  {
    id: 'email',
    title: 'Email',
  },
  {
    id: 'number',
    title: 'Number',
  },
  {
    id: 'country',
    title: 'Country',
  },
]

// Define the items
const items = sampleData

function Image({ size }) {
  return (

      <svg
        width={size}
        height={size}
        fill="none"
        xmlns="http://www.w3.org/2000/svg">
        <rect width={size} height={size} rx="4" fill="#AAAAAA" />
      </svg>

  )
}

function ToolbarExample() {
  const [inputValue, setInputValue] = React.useState('')
  const [displayItems, setDisplayItems] = React.useState(items)

  const onToggle = ({ checkedItems }) => {
    console.log(checkedItems)
  }

  const comparator = item => candidate => {
    return item.email === candidate.email
  }

  const checkboxes = useCheckboxTree({
    items,
    onToggle,
    comparator,
    checked: [
      {
        name: "T'Chala",
        email: 'black.panther@gmail.com',
        number: 1.88191,
        country: '🇰🇪Wakanda',
      },
      {
        name: 'Harry Osbourne',
        email: 'harry@gmail.com',
        country: '🇺🇸USA',
      },
      {
        name: 'Green Goblin',
        email: 'norman.green@gmail.com',
        country: '🇺🇸USA',
      },
      {
        name: 'Aunt May',
        email: 'may.parker@gmail.com',
        country: '🇺🇸USA',
      },
      {
        name: 'Uncle Ben',
        email: 'ben.parker@gmail.com',
        country: '🇺🇸USA',
      },
    ],
  })

  const measures = useTableMeasures({
    size: items.length,
  })

  const visibility = useTableVisibility({
    columns,
  })

  const emptyState = {
    label: 'The table is empty',
  }

  const inputSearch = {
    value: inputValue,
    placeholder: 'Search stuff...',
    onChange: e => setInputValue(e.currentTarget.value),
    onClear: () => {
      setInputValue('')
      setDisplayItems(items)
    },
    onSubmit: e => {
      e.preventDefault()
      const isInputClear = inputValue === ''
      const filterFn = item =>
        item.name.toLowerCase().includes(inputValue.toLowerCase())
      setDisplayItems(isInputClear ? items : items.filter(filterFn))
    },
  }

  const buttonColumns = {
    label: 'Toggle visible fields',
    showAllLabel: 'Show All',
    hideAllLabel: 'Hide All',
  }

  const density = {
    label: 'Line density',
    compactLabel: 'Compact',
    regularLabel: 'Regular',
    comfortableLabel: 'Comfortable',
  }

  const download = {
    label: 'Export',
    onClick: () => alert('Clicked EXPORT'),
  }

  const upload = {
    label: 'Import',
    onClick: () => alert('Clicked IMPORT'),
  }

  const extraActions = {
    label: 'More options',
    actions: [
      {
        label: 'An action',
        onClick: () => alert('An action'),
      },
      {
        label: 'Another action',
        onClick: () => alert('Another action'),
      },
      {
        label: 'A third action',
        onClick: () => alert('A third action'),
      },
    ],
  }

  const newLine = {
    label: 'New',
    onClick: () => alert('handle new line callback'),
    actions: [
      'General',
      'Desktop & Screen Saver',
      'Dock',
      'Language & Region',
    ].map(label => ({
      label,
      onClick: () => alert(`Clicked ${label}`),
    })),
  }

  const empty = React.useMemo(
    () =>
      displayItems.length === 0 ||
      Object.keys(visibility.visibleColumns).length === 0,
    [visibility.visibleColumns, displayItems]
  )

  return (
    <TableTree
      comparator={comparator}
      checkboxes={checkboxes}
      columns={visibility.visibleColumns}
      items={checkboxes.itemTree}
      empty={empty}
      emptyState={emptyState}
      measures={measures}>
      <TableTree.Toolbar>
        <TableTree.Toolbar.InputSearch {...inputSearch} />
        <TableTree.Toolbar.ButtonGroup>
          <TableTree.Toolbar.ButtonGroup.Columns
            visibility={visibility}
            {...buttonColumns}
          />
          <TableTree.Toolbar.ButtonGroup.Density
            density={measures}
            {...density}
          />
          <TableTree.Toolbar.ButtonGroup.Download {...download} />
          <TableTree.Toolbar.ButtonGroup.Upload {...upload} />
          <TableTree.Toolbar.ButtonGroup.ExtraActions {...extraActions} />
          <TableTree.Toolbar.ButtonGroup.NewLine {...newLine} />
        </TableTree.Toolbar.ButtonGroup>
      </TableTree.Toolbar>
    </TableTree>
  )
}
;<ToolbarExample />
```

```


[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_TableTree/sampleData.ts from the store-on-localhost VTEX app.

[Assistant]
Here's the implementation:

```typescript
export default [
  {
    name: "T'Chala",
    email: 'black.panther@gmail.com',
    number: 1.88191,
    country: '🇰🇪Wakanda',
  },
  {
    name: 'Shang-Chi',
    email: 'kungfu.master@gmail.com',
    number: 39.09222,
    country: '🇨🇳China',
  },
  {
    name: 'Natasha Romanoff',
    email: 'black.widow@gmail.com',
    number: 5.09291,
    country: '🇷🇺Russia',
  },
  {
    name: 'Peter Parker',
    email: 'spider.man@gmail.com',
    country: '🇺🇸USA',
    children: [
      {
        name: 'Aunt May',
        email: 'may.parker@gmail.com',
        country: '🇺🇸USA',
      },
      {
        name: 'Uncle Ben',
        email: 'ben.parker@gmail.com',
        country: '🇺🇸USA',
      },
      {
        name: 'Marry Jane',
        email: 'mjaaay@gmail.com',
        country: '🇺🇸USA',
        children: [
          {
            name: 'Harry Osbourne',
            email: 'harry@gmail.com',
            country: '🇺🇸USA',
          },
          {
            name: 'Normal Osbourne',
            email: 'norman@gmail.com',
            country: '🇺🇸USA',
            children: [
              {
                name: 'Green Goblin',
                email: 'norman.green@gmail.com',
                country: '🇺🇸USA',
              },
            ],
          },
        ],
      },
    ],
  },
  {
    name: 'Stephen Strange',
    country: '🇺🇸USA',
    number: 121.414,
    email: 'dr.strange@marvel.com',
  },
  {
    name: 'Steve Rogers',
    country: '🇺🇸USA',
    number: 133.313,
    email: 'capitain.america@marvel.com',
  },
  {
    name: 'Abdul Alhazred',
    country: '🇸🇦Saudi Arabia',
    number: 221.553,
    email: 'abdul@marvel.com',
  },
  {
    name: 'Carol Danvers',
    country: '🇺🇸USA',
    number: 8850.414,
    email: 'cap@marvel.com',
  },
  {
    name: 'Scott Lang',
    country: '🇺🇸USA',
    number: 313.777,
    email: 'ant.man@gmail.com',
  },
  {
    name: 'En Sabah Nuh',
    country: '🇨🇺Cuba',
    number: 471.3131,
    email: 'sabah.nuh@marvel.com',
  },
  {
    name: 'Abdul Qamar',
    country: '🇸🇦Saudi Arabia',
    number: 959.533,
    email: 'qamar@hotmail.com',
  },
  {
    name: 'Goose the Cat',
    country: '🇺🇸USA',
    number: 884.2121,
    email: 'dangerous@marvel.com',
  },
  {
    name: 'Brian Braddock',
    country: '🇬🇧Great Britain',
    number: 18841.3131,
    email: 'cap.britain@marvel.com',
  },
  {
    name: 'Marc Spector',
    country: '🇺🇸USA',
    number: 991.313,
    email: 'spector@gmail.com',
  },
  {
    name: 'John Walker',
    country: '🇺🇸USA',
    number: 9193.1313,
    email: 'im.faded@gmail.com',
  },
  {
    name: 'Dane Whitman',
    country: '🇺🇸USA',
    number: 9819.333,
    email: 'dane@marvel.com',
  },
]

```


[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/ActionMenu/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 ButtonWithIcon from '../ButtonWithIcon'
import IconCaretDown from '../icon/CaretDown'
import Menu from '../Menu'

class ActionMenu extends Component {
  constructor(props) {
    super(props)
    this.container = React.createRef()
    this.menu = React.createRef()
    this.state = {
      isMenuOpen: false,
    }
  }

  openMenu = () => {
    if (this.state.isMenuOpen) return

    document.addEventListener('mousedown', this.handleClickOutside)
    this.setState({ isMenuOpen: true })
  }

  closeMenu = () => {
    if (!this.state.isMenuOpen) return

    document.removeEventListener('mousedown', this.handleClickOutside)
    this.setState({ isMenuOpen: false })
  }

  handleClick = () => {
    if (!this.state.isMenuOpen) {
      this.openMenu()
    } else {
      this.closeMenu()
    }
  }

  isClickOutsideMenu = target =>
    this.menu && this.menu.current && !this.menu.current.contains(target)

  isClickOutsideContainer = target =>
    this.container &&
    this.container.current &&
    !this.container.current.contains(target)

  isClickOutside = target =>
    this.isClickOutsideContainer(target) && this.isClickOutsideMenu(target)

  handleClickOutside = e => {
    if (this.isClickOutside(e.target) && this.state.isMenuOpen) {
      this.closeMenu()
    }
  }

  componentWillUnmount() {
    if (this.state.isMenuOpen) {
      this.closeMenu()
    }
  }

  render() {
    const {
      icon,
      label,
      options,
      menuWidth,
      align,
      buttonProps,
      hideCaretIcon,
      shouldCloseOnClick,
      isGrouped,
      isFirstOfGroup,
      isLastOfGroup,
      isActiveOfGroup,
    } = this.props

    const { isMenuOpen } = this.state

    const iconCaret = <IconCaretDown size={12} color="currentColor" />

    return (
      <div ref={this.container}>
        <Menu
          ref={this.menu}
          open={isMenuOpen}
          align={align}
          width={menuWidth}
          options={options}
          onClose={shouldCloseOnClick ? this.closeMenu : null}>
          <ButtonWithIcon
            {...{
              icon:
                icon ||
                (!label && !hideCaretIcon ? iconCaret : <React.Fragment />),
            }}
            {...buttonProps}
            isGrouped={isGrouped}
            isFirstOfGroup={isFirstOfGroup}
            isLastOfGroup={isLastOfGroup}
            isActiveOfGroup={isActiveOfGroup}
            onClick={this.handleClick}>
            {label && (
              <span className="flex align-baseline items-center">
                <span className={`${hideCaretIcon ? '' : 'mr3'}`}>{label}</span>
                {!hideCaretIcon && <span>{iconCaret}</span>}
              </span>
            )}
          </ButtonWithIcon>
        </Menu>
      </div>
    )
  }
}

ActionMenu.defaultProps = {
  options: [],
  align: 'right',
  hideCaretIcon: false,
  menuWidth: 292,
  shouldCloseOnClick: true,
  isGrouped: false,
  isFirstOfGroup: false,
  isLastOfGroup: false,
  isActiveOfGroup: false,
}

ActionMenu.propTypes = {
  /** Menu alignment in relation to the button*/
  align: PropTypes.oneOf(['right', 'left']),
  /** If should close the menu after clicking an option */
  shouldCloseOnClick: PropTypes.bool,
  /** Respecting ButtonWithIcon props contract. For more info, see:
   * https://styleguide.vtex.com/#/Components/Forms/Button
   */
  // TODO: match ButtonWithIcon prop types
  buttonProps: PropTypes.object,
  /** @deprecated Button icon: use buttonProps instead */
  icon: PropTypes.element,
  /** Button text label */
  label: PropTypes.node,
  /** Hide the automatic caret icon */
  hideCaretIcon: PropTypes.bool,
  /** Menu width*/
  menuWidth: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  /** Menu options */
  options: PropTypes.arrayOf(
    PropTypes.shape({
      label: PropTypes.node,
      handleCallback: PropTypes.func,
      /** whether option has inline toggle */
      toggle: PropTypes.shape({
        checked: PropTypes.bool,
        semantic: PropTypes.bool,
      }),
    })
  ).isRequired,
  /** */
  isGrouped: PropTypes.bool,
  /** */
  isFirstOfGroup: PropTypes.bool,
  /** */
  isLastOfGroup: PropTypes.bool,
  /** */
  isActiveOfGroup: PropTypes.bool,
}

export default ActionMenu

```