[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 pixel-manager/react/__tests__/usePixelEventCallback.test.ts from the pixel-manager VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { shouldCallEventHandler } from '../usePixelEventCallback'
import type { PixelData } from '../PixelEventTypes'

const mockPixelEventData: PixelData = {
  id: 'test',
  event: 'addToCart',
}

describe('shouldCallEventHandler function', () => {
  describe('Should not call the event handler', () => {
    it("If eventName from input matches 'event' property but eventId doesn't match 'id' property", () => {
      const eventNameFromInput = 'addToCart'
      const eventIdFromInput = 'not-test'

      expect(
        shouldCallEventHandler(
          mockPixelEventData,
          eventIdFromInput,
          eventNameFromInput
        )
      ).toBe(false)
    })

    it("If id from input matches 'id' property but eventName doesn't match 'event' property", () => {
      const eventNameFromInput = 'openDrawer'
      const eventIdFromInput = 'test'

      expect(
        shouldCallEventHandler(
          mockPixelEventData,
          eventIdFromInput,
          eventNameFromInput
        )
      ).toBe(false)
    })

    it("If eventName doesn't match 'event' property and no eventId is passed", () => {
      const eventNameFromInput = 'openDrawer'
      const eventIdFromInput = undefined

      expect(
        shouldCallEventHandler(
          mockPixelEventData,
          eventIdFromInput,
          eventNameFromInput
        )
      ).toBe(false)
    })

    it("If eventId doesn't match 'id' property and no eventName is passed", () => {
      const eventNameFromInput = undefined
      const eventIdFromInput = 'not-test'

      expect(
        shouldCallEventHandler(
          mockPixelEventData,
          eventIdFromInput,
          eventNameFromInput
        )
      ).toBe(false)
    })
  })

  describe('Should call the event handler', () => {
    it("If eventId and eventName from input match the event's 'id' and 'event' properties", () => {
      const eventIdFromInput = 'test'
      const eventNameFromInput = 'addToCart'

      expect(
        shouldCallEventHandler(
          mockPixelEventData,
          eventIdFromInput,
          eventNameFromInput
        )
      ).toBe(true)
    })

    it("If eventName from input matches the event's 'event' property and eventId from input is undefined", () => {
      const eventIdFromInput = undefined
      const eventNameFromInput = 'addToCart'

      expect(
        shouldCallEventHandler(
          mockPixelEventData,
          eventIdFromInput,
          eventNameFromInput
        )
      ).toBe(true)
    })

    it("If eventId from input matches the event's 'id' property and eventName from input is undefined", () => {
      const eventIdFromInput = 'test'
      const eventNameFromInput = undefined

      expect(
        shouldCallEventHandler(
          mockPixelEventData,
          eventIdFromInput,
          eventNameFromInput
        )
      ).toBe(true)
    })
  })
})

```


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

[User] Show me the implementation of zendesk-chat/docs/README.md from the zendesk-chat VTEX app.

[Assistant]
Here's the implementation:

```markdown
# Zendesk Chat

This app provides a storefront widget for the [Zendesk](https://zendesk.com/) chat functionality to comunicate with your store's customers while they navigate your store.

## Before you start

To use the chat you need to have an active [Zendesk](https://zendesk.com/) account. Some features are only available for specific plans.

## Installation

1. Open the VTEX App Store and install the [Zendesk Chat](https://apps.vtex.com/vtex-zendesk-chat/p) app on your store.
2. On VTEX Admin, go to **Extensions Hub > App Management** and click the Zendesk Chat app settings.
3. Fill in your Zendesk Chat's Account Key, which you can find on Zendesk following [these instructions](https://support.zendesk.com/hc/en-us/articles/4408825772698-How-do-I-find-my-Chat-Account-Key-).
4. Click `Save`.
5. Copy the following script and insert it into your website's HTML source code between the `<head>` tags. This code must be inserted into every page where you want to display the Web Widget.

   ```html
   <script id="ze-snippet" src="https://static.zdassets.com/ekr/snippet.js?key=xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx> </script>
   ```
> Replace the key value, i.e. `xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`, according to your scenario.

```


[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 zendesk-chat/react/index.tsx from the zendesk-chat VTEX app.

[Assistant]
Here's the implementation:

```tsx
/* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable no-restricted-globals */
import { canUseDOM } from 'vtex.render-runtime'

let fakeBtn: HTMLButtonElement

function updateWidgetSettings(o: Record<string, unknown>) {
  window.zE('webWidget', 'updateSettings', o)
}

function setWidgetLocale(locale: string) {
  window.zE('webWidget', 'setLocale', locale)
}

function waitChatToLoad(fn: Function) {
  window.zE(() => window.$zopim(fn))
}

function onWidgetClosed(fn: Function) {
  window.zE('webWidget:on', 'close', fn)
}

function openWidget() {
  window.zE.activate()
}

function shouldOpenChat() {
  const zdStore = JSON.parse(localStorage.getItem('ZD-store') || 'null')

  if (zdStore) {
    return zdStore.widgetShown
  }

  return localStorage.getItem('zdChatOpen') === 'true'
}

function identifySession() {
  const sessionPromise = window?.__RENDER_8_SESSION__?.sessionPromise

  if (!sessionPromise) return

  sessionPromise.then((session) => {
    const userEmail: string =
      session?.response?.namespaces?.profile?.email?.value || ''

    const firstName: string =
      session?.response?.namespaces?.profile?.firstName?.value || ''

    const lastName: string =
      session?.response?.namespaces?.profile?.lastName?.value || ''

    const userName = `${firstName} ${lastName}`.trim()

    if (userEmail || userName) {
      window.zE.identify({
        name: userName,
        email: userEmail,
      })
    }
  })
}

function bootstrap() {
  const {
    widget: widgetSettings,
    titlePathPreffix = '',
    useAnalytics = false,
    accountKey = null,
  } = window.__zendeskPixel

  const IS_MOBILE = window.__RUNTIME__.hints.mobile

  const chatTheme = widgetSettings.theme?.theme || widgetSettings.color?.theme
  const btnLabel = widgetSettings.theme?.launcherLabel || 'Chat'
  const btnBgColor = widgetSettings.theme?.launcherColor || chatTheme
  const btnTextColor = widgetSettings.theme?.launcherTextColor
  const btnPosition = widgetSettings.theme?.launcherPosition || 'right'
  const widgetZindex = widgetSettings.theme?.widgetZindex || '999998'

  function configureSnippetForVTEX() {
    window.zESettings = window.zESettings || {}
    window.zESettings.analytics = useAnalytics

    waitChatToLoad(() => {
      const curLocale = document.documentElement.lang

      setWidgetLocale(curLocale)

      const titlePath = `${titlePathPreffix}${document.title}`

      window.$zopim.livechat.sendVisitorPath({
        url: document.URL,
        title: titlePath,
      })

      onWidgetClosed(() => localStorage.setItem('zdChatOpen', 'false'))

      identifySession()
    })

    const helpCenterSuppress = widgetSettings.helpCenter.suppress
    const { departments } = widgetSettings.chat
    const enabled =
      departments.enabled?.map((value) => {
        const intValue = parseInt(value, 10)

        return !isNaN(intValue) ? intValue : value
      }) || []

    const select = isNaN(parseInt(departments.select, 10))
      ? departments.select
      : parseInt(departments.select, 10)

    const { tags } = departments

    updateWidgetSettings({
      webWidget: {
        color: {
          theme: chatTheme,
          launcher: btnBgColor,
          launcherText: btnTextColor,
        },
        position: { horizontal: btnPosition, vertical: 'bottom' },
        zIndex: widgetZindex,
        launcher: {
          label: { '*': btnLabel },
          chatLabel: { '*': btnLabel },
        },
        helpCenter: {
          suppress: helpCenterSuppress,
        },
        chat: {
          departments: {
            enabled,
            select,
            tags,
          },
        },
      },
    })
  }

  function addZDSnippet() {
    const script = document.createElement('script')

    if (fakeBtn) fakeBtn.disabled = true

    script.id = 'ze-snippet'
    script.async = true
    script.src = `https://static.zdassets.com/ekr/snippet.js?key=${accountKey}`
    script.onload = () => {
      const intervalId = setInterval(() => {
        if (window?.zE?.activate == null) {
          return
        }

        clearInterval(intervalId)

        configureSnippetForVTEX()

        openWidget()

        if (fakeBtn) {
          document.body.removeChild(fakeBtn)
        }
      }, 400)
    }

    document.head.appendChild(script)
  }

  function addFakeButton() {
    fakeBtn = document.createElement('button')

    fakeBtn.id = 'zendesk-fake-btn'
    fakeBtn.innerHTML = `<svg id="zendesk-fake-icon" x="0" y="0" viewBox="0 0 15 16" xml:space="preserve" aria-hidden="true"><path d="M1.3,16c-0.7,0-1.1-0.3-1.2-0.8c-0.3-0.8,0.5-1.3,0.8-1.5c0.6-0.4,0.9-0.7,1-1c0-0.2-0.1-0.4-0.3-0.7c0,0,0-0.1-0.1-0.1 C0.5,10.6,0,9,0,7.4C0,3.3,3.4,0,7.5,0C11.6,0,15,3.3,15,7.4s-3.4,7.4-7.5,7.4c-0.5,0-1-0.1-1.5-0.2C3.4,15.9,1.5,16,1.5,16 C1.4,16,1.4,16,1.3,16z M3.3,10.9c0.5,0.7,0.7,1.5,0.6,2.2c0,0.1-0.1,0.3-0.1,0.4c0.5-0.2,1-0.4,1.6-0.7c0.2-0.1,0.4-0.2,0.6-0.1 c0,0,0.1,0,0.1,0c0.4,0.1,0.9,0.2,1.4,0.2c3,0,5.5-2.4,5.5-5.4S10.5,2,7.5,2C4.5,2,2,4.4,2,7.4c0,1.2,0.4,2.4,1.2,3.3 C3.2,10.8,3.3,10.8,3.3,10.9z"></path></svg><span>${btnLabel}</span>`

    fakeBtn.className =
      'flex items-center justify-center b br-pill bg-base--inverted c-on-base--inverted pointer'

    if (btnTextColor) fakeBtn.style.color = btnTextColor
    if (btnBgColor) fakeBtn.style.backgroundColor = btnBgColor

    fakeBtn.addEventListener('click', () => {
      localStorage.setItem('zdChatOpen', 'true')
      addZDSnippet()
    })

    document.head.insertAdjacentHTML(
      'beforeend',
      `<style>
        #zendesk-fake-btn {
          position: fixed;
          ${btnPosition}: 0;
          bottom: 0;
          margin: 15px 20px;
          ${IS_MOBILE ? 'padding: .9em;' : 'padding: .9em 1.5em;'}
          opacity: 1;
          border: 0px;
          z-index: ${widgetZindex};
          font-size: 15px;
          -webkit-appearance: none;
        }
        #zendesk-fake-icon {
          ${!IS_MOBILE ? 'padding-right: 0.57143em;' : ''}
          fill: currentColor;
          width: 1.42em;
          height: 1.42em;
        }
        #zendesk-fake-btn span {
          font-size: 1.1em;
          ${IS_MOBILE ? `display: none;` : ''}
        }
      </style>`
    )

    document.body.appendChild(fakeBtn)
  }

  if (shouldOpenChat()) {
    addZDSnippet()
  } else {
    addFakeButton()
  }
}

if (canUseDOM && window.__zendeskPixel) {
  bootstrap()
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "scripts": {
    "test": "vtex-test-tools test"
  },
  "devDependencies": {
    "@apollo/react-testing": "^3.1.3",
    "@types/jest": "^25.1.5",
    "@types/node": "^13.11.0",
    "@types/react": "^16.9.31",
    "@vtex/test-tools": "^3.1.0",
    "apollo-cache-inmemory": "^1.6.5",
    "apollo-client": "^2.6.8",
    "graphql": "^14.5.4",
    "react-intl": "^3.11.0",
    "typescript": "3.9.7",
    "vtex.pixel-interfaces": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-interfaces@1.1.1/public/_types/react",
    "vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.124.2/public/@types/vtex.render-runtime"
  },
  "version": "1.4.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 zendesk-chat/store/interfaces.json from the zendesk-chat VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "pixel.zendesk-chat": {
    "component": "index"
  }
}

```


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

[User] Show me the implementation of zendesk-chat/react/typings/zendesk.d.ts from the zendesk-chat VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable @typescript-eslint/no-explicit-any */

// modified from https://gist.github.com/vsaarinen/b0e2dcaf4f7c522d4ff1f672eb996f73
interface ZendeskWidget {
  (
    type: 'webWidget:on' | 'webWidget' | 'webWidget:get',
    command: string,
    payload?: any
  ): void
  (type: 'webWidget', command: 'updateSettings', payload: ZendeskSettings): void
  (fn: Function): void

  activate: Function
  identify: Function
}

interface ZendeskUIString {
  [locale: string]: string
}

interface ZendeskField {
  id: string | number
  prefill: ZendeskUIString
}

interface ZendeskSettings {
  analytics?: boolean
  cookies?: boolean
  errorReporting?: boolean
  webWidget?: {
    answerBot?: {
      avatar?: {
        url: string
        name: ZendeskUIString
      }
      suppress?: boolean
      title?: ZendeskUIString
      contactOnlyAfterQuery?: boolean
      search?: {
        labels: string[]
      }
    }
    authenticate?: {
      chat?: {
        jwtFn: (callback: (jwtToken: string) => void) => void
      }
      jwtFn?: (callback: (jwtToken: string) => void) => void
    }
    contactForm?: {
      attachments?: boolean
      fields?: ZendeskField[]
      selectTicketForm?: ZendeskUIString
      subject?: boolean
      suppress?: boolean
      title?: ZendeskUIString
      ticketForms?: Array<{ id: number; fields?: ZendeskField[] }>
    }
    contactOptions?: {
      enabled?: boolean
      contactButton?: ZendeskUIString
      contactFormLabel?: ZendeskUIString
      chatLabelOnline?: ZendeskUIString
      chatLabelOffline?: ZendeskUIString
    }
    chat?: {
      concierge?: {
        avatarPath: string
        name: string
        title: ZendeskUIString
      }
      departments?: {
        enabled: string[]
        select?: string
      }
      hideWhenOffline?: boolean
      menuOptions?: {
        emailTranscript?: boolean
      }
      notifications?: {
        mobile?: {
          disable?: boolean
        }
      }
      offlineForm?: {
        greeting?: ZendeskUIString
      }
      prechatForm?: {
        greeting?: ZendeskUIString
        departmentLabel?: ZendeskUIString
      }
      profileCard?: {
        avatar?: boolean
        rating?: boolean
        title?: boolean
      }
      suppress?: boolean
      tags?: string
      title?: ZendeskUIString
    }
    color?: {
      theme?: string
      launcher?: string
      launcherText?: string
      button?: string
      resultLists?: string
      header?: string
      articleLinks?: string
    }
    helpCenter?: {
      messageButton?: ZendeskUIString
      originalArticleButton?: boolean
      searchPlaceholder?: ZendeskUIString
      suppress?: boolean
      title?: ZendeskUIString
      chatButton?: ZendeskUIString
      filter?: {
        category?: string
        section?: string
        label_names?: string
      }
    }
    launcher?: {
      label?: ZendeskUIString
      mobile?: {
        labelVisible?: boolean
      }
      badge?: {
        label?: ZendeskUIString
        image?: string
        layout?: 'image_right' | 'image_left' | 'image_only' | 'text_only'
      }
      chatLabel?: ZendeskUIString
    }
    navigation?: {
      popoutButton?: {
        enabled?: boolean
      }
    }
    offset?: {
      horizontal?: string
      vertical?: string
      mobile?: {
        horizontal?: string
        vertical?: string
      }
    }
    position?: {
      horizontal: 'left' | 'right'
      vertical: 'top' | 'bottom'
    }
    talk?: {
      nickname?: string
      suppress?: boolean
      title?: ZendeskUIString
    }
    zIndex?: number
  }
}

```


[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 zendesk-chat/react/typings/global.d.ts from the zendesk-chat VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable @typescript-eslint/naming-convention */
import type { useRuntime } from 'vtex.render-runtime'

export {}

declare global {
  interface Window {
    __RUNTIME__: ReturnType<typeof useRuntime>

    __RENDER_8_SESSION__: {
      sessionPromise: Promise<{ response: any }>
    }

    __zendeskPixel: {
      widget: {
        // @deprecated. Use `theme`
        color?: {
          theme: string
        }
        theme: {
          launcherLabel: string
          launcherColor: string
          launcherTextColor: string
          launcherPosition: string
          theme: string
          widgetZindex: string
        }
        helpCenter: {
          suppress: unknown
        }
        chat: {
          departments: {
            enabled: string[]
            select: string
            tags: string[]
          }
        }
      }
      titlePathPreffix: string
      useAnalytics: boolean
      accountKey: string
    }

    zESettings: ZendeskSettings
    zE: ZendeskWidget

    $zopim: {
      (arg: Function): unknown
      livechat: {
        sendVisitorPath: Function
      }
    }
  }
}

```


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

[Assistant]
Here's the implementation:

```markdown
# VTEX Buybox Resolver

> ⚠ This app is no longer maintained by VTEX. This means support and maintenance are no longer provided.

This app is an implementation of the VTEX Buybox protocol to sort sellers, that is defined by the schema GraphQL [buybox-graphql](https://github.com/vtex-apps/buybox-graphql).

```


[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 buybox-resolver/graphql/schema.graphql from the buybox-resolver VTEX app.

[Assistant]
Here's the implementation:

```graphql
# To really understand GraphQL, go to https://graphql.org/learn/

type Book {
  authors: [String!]
  cacheId: ID!
  id: ID!
  name: String
}

# It is necessary to generate input types for creating books
# ref: http://graphql.org/graphql-js/mutations-and-input-types/
input BookInput {
  authors: [String!]
  cacheId: ID
  id: ID
  name: String
}

type Query {
  # Cache control can only be set at root fields
  book(id: ID!): Book
  books(from: Int = 0, to: Int = 4): [Book] @cacheControl(scope: PUBLIC, maxAge: SHORT)
  total: Int

  """
  Returns a markdown source given an id
  """
  source(id: ID!): String
}

type Mutation {
  # You should always return the whole object in a mutation, not only a boolean. This will help in browser caching
  delete(id: String): Boolean
  editBook(id: ID!, book: BookInput!): Book
  newBook(book: BookInput!): Book
}

```


[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 buybox-resolver/node/service.json from the buybox-resolver VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "memory": 256,
  "ttl": 10,
  "timeout": 1,
  "minReplicas": 2,
  "maxReplicas": 5
}

```


[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 buybox-resolver/node/package.json from the buybox-resolver VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "dependencies": {
    "@gocommerce/utils": "^0.6.11",
    "atob": "^2.1.2",
    "axios": "^0.23.0",
    "graphql": "^14.5.8",
    "graphql-tools": "^4.0.6",
    "qs": "^6.6.0",
    "vtex.buybox-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.buybox-graphql@0.1.0/public",
    "ramda": "^0.26.1"
  },
  "devDependencies": {
    "@types/atob": "^2.1.2",
    "@types/graphql": "^14.5.0",
    "@types/node": "^12.0.0",
    "@types/qs": "^6.5.1",
    "@types/ramda": "types/npm-ramda#dist",
    "@vtex/api": "6.45.4",
    "@vtex/tsconfig": "^0.5.6",
    "typescript": "3.9.7",
    "vtex.buybox-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.buybox-graphql@0.1.0/public/@types/vtex.buybox-graphql",
    "vtex.catalog-api-proxy": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.catalog-api-proxy@0.10.2/public/_types/react"
  },
  "scripts": {
    "lint": "tsc --noEmit && tslint -c tslint.json './**/*.ts'"
  },
  "version": "0.1.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 buybox-resolver/node/globals.ts from the buybox-resolver VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type {
  IOContext,
  ParamsContext,
  RecorderState,
  SegmentData,
  ServiceContext,
  MessagesLoaderV2,
} from '@vtex/api'
import { MetricsAccumulator } from '@vtex/api'

import type { Clients } from './clients'

if (!global.metrics) {
  console.error('No global.metrics at require time')
  global.metrics = new MetricsAccumulator()
}

declare global {
  type Context = ServiceContext<Clients, State, CustomContext>

  interface State extends RecorderState {
    messagesTenantLanguage?: MessagesLoaderV2
    messagesBindingLanguage?: MessagesLoaderV2
  }

  interface CustomContext extends ParamsContext {
    cookie: string
    originalPath: string
    vtex: CustomIOContext
  }

  interface CustomIOContext extends IOContext {
    segment?: SegmentData
  }
}

```


[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 buybox-resolver/node/index.ts from the buybox-resolver VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { Cached, RecorderState } from '@vtex/api'
import { LRUCache, Service } from '@vtex/api'
import schema from 'vtex.buybox-graphql/graphql'

import { Clients } from './clients'
import { schemaDirectives } from './directives'
import { resolvers } from './resolvers'

const THREE_SECONDS_MS = 3 * 1000

const searchCache = new LRUCache<string, Cached>({ max: THREE_SECONDS_MS })

metrics.trackCache('search', searchCache)

export default new Service<Clients, RecorderState, CustomContext>({
  clients: {
    implementation: Clients,
    options: {
      default: {
        retries: 2,
        timeout: THREE_SECONDS_MS,
      },
    },
  },
  graphql: {
    resolvers,
    schema,
    schemaDirectives,
  },
})

```


[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 buybox-resolver/node/directives/withSegment.ts from the buybox-resolver VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { GraphQLField } from 'graphql'
import { defaultFieldResolver } from 'graphql'
import { SchemaDirectiveVisitor } from 'graphql-tools'
import atob from 'atob'

/**
 * Warning: we stopped using the segment client to decode the segment token for us because it added unnecessary overhead for now.
 * If the getSegment API evolves to do more than a decode we must stop decoding it here and start calling the API once again.
 */
export class WithSegment extends SchemaDirectiveVisitor {
  public visitFieldDefinition(field: GraphQLField<any, any>) {
    const { resolve = defaultFieldResolver } = field

    field.resolve = async (root, args, ctx: Context, info) => {
      const {
        vtex: { segmentToken },
        clients: { segment },
      } = ctx

      ctx.vtex.segment = segmentToken
        ? JSON.parse(atob(segmentToken))
        : await segment.getSegment()

      return resolve(root, args, ctx, info)
    }
  }
}

```


[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 buybox-resolver/node/directives/index.ts from the buybox-resolver VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { WithSegment } from './withSegment'

export const schemaDirectives = {
  withSegment: WithSegment,
}

```


[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 buybox-resolver/node/clients/search.ts from the buybox-resolver VTEX app.

[Assistant]
Here's the implementation:

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

const inflightKey = ({ baseURL, url, params, headers }: RequestConfig) => {
  return `${
    baseURL! +
    url! +
    stringify(params, { arrayFormat: 'repeat', addQueryPrefix: true })
  }&segmentToken=${headers['x-vtex-segment']}`
}

export class Search extends AppClient {
  private basePath: string

  private addSalesChannel = (url: string, salesChannel?: string | number) => {
    if (!salesChannel) {
      return url
    }

    return url.concat(`&sc=${salesChannel}`)
  }

  private addCompleteSpecifications = (url: string) => {
    if (!url.includes('?')) {
      return `${url}?compSpecs=true`
    }

    return `${url}&compSpecs=true`
  }

  constructor(ctx: IOContext, opts?: InstanceOptions) {
    super('vtex.catalog-api-proxy@0.x', ctx, opts)

    this.basePath = ctx.sessionToken
      ? '/proxy/authenticated/catalog'
      : '/proxy/catalog'
  }

  public productBySku = (skuId: string, salesChannel?: string | number) =>
    this.get<SearchProduct[]>(
      this.addCompleteSpecifications(
        this.addSalesChannel(
          `/pub/products/search?fq=skuId:${skuId}`,
          salesChannel
        )
      ),
      {
        metric: 'search-productBySku',
      }
    )

  private get = <T = any>(url: string, config: RequestConfig = {}) => {
    const segmentData: SegmentData | undefined = (
      this.context as CustomIOContext
    ).segment

    const { channel: salesChannel = '' } = segmentData ?? {}

    config.params = {
      ...config.params,
      ...(!!salesChannel && { sc: salesChannel }),
    }
    config.inflightKey = inflightKey

    return this.http.get<T>(`${this.basePath}${url}`, config)
  }
}

```


[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 buybox-resolver/node/clients/checkout.ts from the buybox-resolver VTEX app.

[Assistant]
Here's the implementation:

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

import { statusToError } from '../utils'

export class Checkout extends JanusClient {
  constructor(ctx: IOContext, options?: InstanceOptions) {
    super(ctx, {
      ...options,
      headers: {
        ...options?.headers,
      },
    })
  }

  private getChannelQueryString = () => {
    const { segment } = this.context as CustomIOContext
    const channel = segment?.channel
    const queryString = channel ? `?sc=${channel}` : ''

    return queryString
  }

  public simulation = (simulation: SimulationPayload) =>
    this.post<OrderForm>(
      this.routes.simulation(this.getChannelQueryString()),
      simulation,
      {
        metric: 'checkout-simulation',
      }
    )

  protected post = <T>(url: string, data?: any, config: RequestConfig = {}) => {
    return this.http
      .post<T>(url, data, config)
      .catch(statusToError) as Promise<T>
  }

  private get routes() {
    const base = '/api/checkout/pub'

    return {
      simulation: (queryString: string) =>
        `${base}/orderForms/simulation${queryString}`,
    }
  }
}

```


[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 buybox-resolver/node/clients/index.ts from the buybox-resolver VTEX app.

[Assistant]
Here's the implementation:

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

import { Search } from './search'
import { Checkout } from './checkout'

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

  public get checkout() {
    return this.getOrSet('checkout', Checkout)
  }
}

```


[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 buybox-resolver/node/typings/Checkout.ts from the buybox-resolver VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface OrderFormMarketingData {
  utmCampaign?: string
  utmMedium?: string
  utmSource?: string
  utmiCampaign?: string
  utmiPart?: string
  utmipage?: string
  marketingTags?: string
}

interface CheckoutAddress {
  addressType: string
  receiverName: string
  addressId: string
  postalCode: string
  city: string
  state: string
  country: string
  street: string
  number: string
  neighborhood: string
  complement: string
  reference: string | null
  geoCoordinates: [number, number]
}

interface OrderFormItem {
  id: string
  name: string
  detailUrl: string
  imageUrl: string
  productRefId: string
  skuName: string
  quantity: number
  uniqueId: string
  productId: string
  refId: string
  ean: string
  priceValidUntil: string
  price: number
  tax: number
  listPrice: number
  sellingPrice: number
  rewardValue: number
  isGift: boolean
  parentItemIndex: number | null
  parentAssemblyBinding: string | null
  productCategoryIds: string
  priceTags: string[]
  measurementUnit: string
  additionalInfo: {
    brandName: string
    brandId: string
    offeringInfo: any | null
    offeringType: any | null
    offeringTypeId: any | null
  }
  productCategories: Record<string, string>
  seller: string
  sellerChain: string[]
  availability: string
  unitMultiplier: number
}

interface LogisticsInfo {
  itemIndex: number
  selectedSla: string
  selectedDeliveryChannel: string
  addressId: string
  slas: Array<{
    id: string
    deliveryChannel: string
    name: string
    deliveryIds: Array<{
      courierId: string
      warehouseId: string
      dockId: string
      courierName: string
      quantity: number
    }>
    shippingEstimate: string
    shippingEstimateDate: string | null
    lockTTL: string | null
    availableDeliveryWindows: any[]
    deliveryWindow: string | null
    price: number
    listPrice: number
    tax: number
    pickupStoreInfo: {
      isPickupStore: boolean
      friendlyName: string | null

      address: CheckoutAddress | null
      additionalInfo: any | null
      dockId: string | null
    }
    pickupPointId: string | null
    pickupDistance: number
    polygonName: string | null
  }>
  shipsTo: string[]
  itemId: string
  deliveryChannels: Array<{ id: string }>
}

interface OrderForm {
  items: OrderFormItem[]
  ratesAndBenefitsData: {
    rateAndBenefitsIdentifiers: any[]
    teaser: any[]
  }
  paymentData: {
    installmentOptions: Array<{
      paymentSystem: string
      bin: string | null
      paymentName: string | null
      paymentGroupName: string | null
      value: number
      installments: Array<{
        count: number
        hasInterestRate: false
        interestRate: number
        value: number
        total: number
        sellerMerchantInstallments: Array<{
          count: number
          hasInterestRate: false
          interestRate: number
          value: number
          total: number
        }>
      }>
    }>
    paymentSystems: Array<{
      id: string
      name: string
      groupName: string
      validator: {
        regex: string
        mask: string
        cardCodeRegex: string
        cardCodeMask: string
        weights: number[]
        useCvv: boolean
        useExpirationDate: boolean
        useCardHolderName: boolean
        useBillingAddress: boolean
      }
      stringId: string
      template: string
      requiresDocument: boolean
      isCustom: boolean
      description: string | null
      requiresAuthentication: boolean
      dueDate: string
      availablePayments: any | null
    }>
    payments: any[]
    giftCards: any[]
    giftCardMessages: any[]
    availableAccounts: any[]
    availableTokens: any[]
  }
  selectableGifts: any[]
  logisticsInfo: LogisticsInfo[]
  marketingData: OrderFormMarketingData | null
  postalCode: string
  country: string
  messages: any[]
  subscriptionData: any | null
  itemMetadata: {
    items: MetadataItem[]
  }
}

interface PayloadItem {
  id: string
  quantity: number
  seller: string
  parentItemIndex?: number | null
  parentAssemblyBinding?: string | null
}

interface SimulationPayload {
  country?: string
  items: PayloadItem[]
  postalCode?: string
  isCheckedIn?: boolean
  priceTables?: string[]
  marketingData?: Record<string, string>
}

```


[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 buybox-resolver/node/typings/ItemMetadata.ts from the buybox-resolver VTEX app.

[Assistant]
Here's the implementation:

```typescript
/**
 * Assembly options related types
 */

interface CompositionItem {
  id: string
  minQuantity: number
  maxQuantity: number
  initialQuantity: number
  priceTable: string
  seller: string
}

interface Composition {
  minQuantity: number
  maxQuantity: number
  items: CompositionItem[]
}

interface AssemblyOption {
  id: string
  name: string
  composition: Composition | null
  inputValues: InputValues
}

interface InputValues {
  [key: string]: RawInputValue
}

interface RawInputValue {
  maximumNumberOfCharacters: number
  domain: string[]
}

interface SearchMetadataItem {
  Name: string
  NameComplete: string
  MainImage: string
  BrandName: string
  CategoryId: number
  ProductId: number
  id: string
  seller: string
  assemblyOptions: AssemblyOption[]
}

interface MetadataItem {
  id: string
  name: string
  imageUrl: string
  detailUrl: string
  seller: string
  assemblyOptions: AssemblyOption[]
  skuName: string
  productId: string
  refId: string
  ean: string | null
}

```


[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 buybox-resolver/node/typings/Catalog.ts from the buybox-resolver VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface SearchProduct {
  productId: string
  productName: string
  brand: string
  brandId: number
  linkText: string
  productReference: string
  categoryId: string
  productTitle: string
  metaTagDescription: string
  clusterHighlights: Record<string, string>
  productClusters: Record<string, string>
  searchableClusters: Record<string, string>
  categories: string[]
  categoriesIds: string[]
  link: string
  description: string
  items: SearchItem[]
  itemMetadata: {
    items: SearchMetadataItem[]
  }
  titleTag: string
  Specifications?: string[]
  allSpecifications?: string[]
  allSpecificationsGroups?: string[]
  completeSpecifications?: CompleteSpecification[]
  skuSpecifications?: SkuSpecification[]
}

interface SearchItem {
  itemId: string
  name: string
  nameComplete: string
  complementName: string
  ean: string
  referenceId: Array<{ Key: string; Value: string }>
  measurementUnit: string
  unitMultiplier: number
  modalType: any | null
  images: SearchImage[]
  Videos: string[]
  variations: string[]
  sellers: Seller[]
  attachments: Array<{
    id: number
    name: string
    required: boolean
    domainValues: string
  }>
  isKit: boolean
  kitItems?: Array<{
    itemId: string
    amount: number
  }>
}

interface CompleteSpecification {
  Values: Array<{
    Id: string
    Position: number
    Value: string
  }>
  Name: string
  Position: number
  IsOnProductDetails: boolean
  FieldId: string
}

interface SkuSpecification {
  field: SKUSpecificationField
  values: SKUSpecificationValue[]
}

interface SKUSpecificationField {
  name: string
  id: string
}

interface SKUSpecificationValue {
  name: string
  id: string
  fieldId: string
}

interface SearchImage {
  imageId: string
  imageLabel: string | null
  imageTag: string
  imageUrl: string
  imageText: string
}

interface SearchInstallment {
  Value: number
  InterestRate: number
  TotalValuePlusInterestRate: number
  NumberOfInstallments: number
  PaymentSystemName: string
  PaymentSystemGroupName: string
  Name: string
}

interface CommertialOffer {
  DeliverySlaSamplesPerRegion: Record<
    string,
    { DeliverySlaPerTypes: any[]; Region: any | null }
  >
  Installments: SearchInstallment[]
  DiscountHighLight: any[]
  GiftSkuIds: string[]
  Teasers: any[]
  BuyTogether: any[]
  ItemMetadataAttachment: any[]
  Price: number
  ListPrice: number
  PriceWithoutDiscount: number
  RewardValue: number
  PriceValidUntil: string
  AvailableQuantity: number
  Tax: number
  DeliverySlaSamples: Array<{
    DeliverySlaPerTypes: any[]
    Region: any | null
  }>
  GetInfoErrorMessage: any | null
  CacheVersionUsedToCallCheckout: string
}

interface Seller {
  sellerId: string
  sellerName: string
  addToCartLink: string
  sellerDefault: boolean
  commertialOffer: CommertialOffer
}

```


[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 buybox-resolver/node/utils/index.ts from the buybox-resolver VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { AxiosError } from 'axios'
import { AuthenticationError, ForbiddenError, UserInputError } from '@vtex/api'

export function statusToError(e: AxiosError) {
  if (!e.response) {
    throw e
  }

  const { response } = e
  const { status } = response

  if (status === 401) {
    throw new AuthenticationError(e)
  }

  if (status === 403) {
    throw new ForbiddenError(e)
  }

  if (status === 400) {
    throw new UserInputError(e)
  }

  throw e
}

```


[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 buybox-resolver/node/resolvers/index.ts from the buybox-resolver VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { queries as sellersQueries } from './search'

export const resolvers = {
  Query: {
    ...sellersQueries,
  },
}

```


[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 buybox-resolver/node/resolvers/search/index.ts from the buybox-resolver VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { NotFoundError, UserInputError } from '@vtex/api'
import { head } from 'ramda'

interface ProductArgs {
  skuId?: string
  salesChannel?: number
  country?: string
  postalCode?: string
}

export const queries = {
  sortSellers: async (_: unknown, rawArgs: ProductArgs, ctx: Context) => {
    const {
      clients: { search, checkout },
      vtex: { segment },
    } = ctx

    const { skuId, country, postalCode } = rawArgs
    const salesChannel = rawArgs.salesChannel ?? segment?.channel

    if (!skuId) {
      throw new UserInputError('No product identifier provided')
    }

    const products = await search.productBySku(skuId, salesChannel)

    let product: SearchProduct | undefined

    if (products.length > 0) {
      product = head(products)
    } else {
      throw new NotFoundError(
        `No product was found with requested ${skuId} ${JSON.stringify(
          rawArgs
        )}`
      )
    }

    const item = product?.items.find((i) => i.itemId === skuId)

    const requestBody = {
      country,
      postalCode,
      items: item?.sellers.map((s) => {
        return {
          id: item.itemId,
          quantity: 1,
          seller: s.sellerId,
        }
      }),
    } as SimulationPayload

    const { logisticsInfo } = await checkout.simulation(requestBody)

    const sellerLogisticsInfo = item?.sellers.map((seller, index) => {
      return {
        seller,
        logisticsInfo: logisticsInfo[index],
      }
    })

    sellerLogisticsInfo?.sort(
      (a, b) => a.seller.commertialOffer.Price - b.seller.commertialOffer.Price
    )

    return { sellers: sellerLogisticsInfo?.map((sli) => sli.seller.sellerId) }
  },
}

```


[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 flex-layout/messages/it-IT.json from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.row.title": "Riga",
  "admin/editor.column.title": "Colonna",
  "admin/editor.row.description": "Componente a riga della struttura di Flex Layout",
  "admin/editor.column.description": "Componente a colonna della struttura di Flex Layout"
}
```


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

[User] Show me the implementation of flex-layout/messages/bs-BA.json from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.row.title": "crwdns90648:0crwdne90648:0",
  "admin/editor.column.title": "crwdns90650:0crwdne90650:0",
  "admin/editor.row.description": "crwdns90652:0crwdne90652:0",
  "admin/editor.column.description": "crwdns90654:0crwdne90654: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 flex-layout/messages/ko-KR.json from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.row.title": "행",
  "admin/editor.column.title": "열",
  "admin/editor.row.description": "플렉스 레이아웃 구조의 행 구성 요소",
  "admin/editor.column.description": "플렉스 레이아웃 구조의 열 구성 요소"
}
```


[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 flex-layout/messages/ja-JP.json from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.row.title": "行",
  "admin/editor.column.title": "列",
  "admin/editor.row.description": "フレックスレイアウト構造の行コンポーネント",
  "admin/editor.column.description": "フレックスレイアウト構造の列コンポーネント"
}
```


[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 flex-layout/messages/bg-BG.json from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.row.title": "Ред",
  "admin/editor.column.title": "Колона",
  "admin/editor.row.description": "Редови компонент от гъвкава структура на оформление",
  "admin/editor.column.description": "Компонент от колона от гъвкава структура на оформление"
}
```


[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 flex-layout/messages/pt.json from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.row.title": "Linha",
  "admin/editor.column.title": "Coluna",
  "admin/editor.row.description": "Componente de Linha para estrutura de layout flex",
  "admin/editor.column.description": "Componente de Coluna para estrutura de layout flex",
  "store/flex-layout.flexLayout-row.aria-label": "Linha {sectionId, select, row {de sessão} other {#}}"
}
```


[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 flex-layout/messages/en.json from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.row.title": "Row",
  "admin/editor.column.title": "Column",
  "admin/editor.row.description": "Row component of flex layout structure",
  "admin/editor.column.description": "Column component of flex layout structure",
  "store/flex-layout.flexLayout-row.aria-label": "Section {sectionId, select, row {row} other {#}}"
}
```


[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 flex-layout/messages/ro-RO.json from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.row.title": "Rând",
  "admin/editor.column.title": "Coloană",
  "admin/editor.row.description": "Componenta de rânduri a structurii modului de afișare flexibil",
  "admin/editor.column.description": "Componenta de coloane a structurii modului de afișare flexibil"
}
```


[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 flex-layout/messages/context.json from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.row.title": "Row",
  "admin/editor.column.title": "Column",
  "admin/editor.row.description": "Row component of flex layout structure",
  "admin/editor.column.description": "Column component of flex layout structure",
  "store/flex-layout.flexLayout-row.aria-label": "Section {sectionId, select, row {row} other {#}}"
}
```


[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 flex-layout/messages/de-DE.json from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.row.title": "Zeile",
  "admin/editor.column.title": "Spalte",
  "admin/editor.row.description": "Zeilenkomponente der Flex-Layoutstruktur",
  "admin/editor.column.description": "Spaltenkomponente der Flex-Layoutstruktur"
}
```


[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 flex-layout/messages/fr-FR.json from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.row.title": "Ligne",
  "admin/editor.column.title": "Colonne",
  "admin/editor.row.description": "Composant de la ligne pour l’aménagement de la mise en page flexible",
  "admin/editor.column.description": "Composant de la colonne pour l’aménagement de la mise en page flexible"
}
```


[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 flex-layout/messages/nl-NL.json from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.row.title": "Rij",
  "admin/editor.column.title": "Kolom",
  "admin/editor.row.description": "Rijcomponent van flex layoutstructuur",
  "admin/editor.column.description": "Kolomcomponent van flex layoutstructuur"
}
```


[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 flex-layout/messages/es.json from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.row.title": "Fila",
  "admin/editor.column.title": "Columna",
  "admin/editor.row.description": "Componente de Fila para la estructura de layout flex",
  "admin/editor.column.description": "Componente de Columna para la estructura de layout flex"
}
```


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

[Assistant]
Here's the implementation:

```markdown
📢 Don't fork this project. Use, [contribute](https://github.com/vtex-apps/flex-layout), or open issues through [Store Discussion](https://github.com/vtex-apps/store-discussion).

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

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

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

# Flex Layout

Flex Layout is a **layout structure** built within VTEX IO Store Framework. It allows building complex custom layouts using the concept of **rows** and **columns**, setting the desired block structure and positioning in a page.

![Screen Shot 2019-08-21 at 4 05 19 PM](https://cdn.jsdelivr.net/gh/vtexdocs/dev-portal-content@main/images/vtex-flex-layout-0.png) _Example of a page layout built using Flex Layout, following the one row with two columns model_

## Configuration

**Flex Layout has two basic building blocks**: `flex-layout.row` and `flex-layout.col`. You should **never** use `flex-layout`.

If you are already familiar with the [`flexbox`](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) layout used in CSS, Flex Layout should be easy to grasp since this is what `flex-layout.row` and `flex-layout.col` are using under the hood.

You can use **any** array of blocks as children for `flex-layout.row` and `flex-layout.col`.

The props below support [`responsive-values`](https://github.com/vtex-apps/responsive-values), meaning that you can define different values for the same prop based on device screen size, such as mobile and desktop.

### `flex-layout.row`

| Prop name                  | Type                                                           | Description                                                                                | Default value |
| -------------------------- | -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `blockClass`               | `String`                                                       | Block container class. The set value of this prop functions as a block identifier for CSS customizations. (                                                                                | `""`          |
| `borderColor`              | `String`                                                       | The color of the border.                                                                                | `undefined`   |
| `borderWidth`              | `0...5`                                                        | A `number` or `string` magnitude for applying the `bw` Tachyons token to the row.                                                                                | `undefined`   |
| `border`                   | `String \| String[]`                                          | An array to define on which sides of the row a border should apply (`top`, `right`, `bottom`, `left`, or `all`).                                                                                | `undefined`   |
| `colGap`                   | `0...10`                                                       | A `number` or `string` magnitude for applying the `pr` Tachyons token to the columns in the `flex-layout.row`.                                                                                | `undefined`   |
| `colSizing`                | `equal`|`auto`                                            | Controls the width of the columns in the `flex-layout.row`.                                                                                | `equal`       |
| `fullWidth`                | `Boolean`                                                      | Whether the component should occupy all the available width from its parent.                                                                                | `false`       |
| `horizontalAlign`          | `left`|`right`|`center`|`between`|`around` | Controls horizontal alignment for the items in the `flex-layout.row`. It defaults to `between` if `colSizing` is `auto` and to `left` otherwise.                                                                              | `left`        |
| `colJustify`               | `enum`                                                         | Controls the space between columns and borders of the `flex-layout.row`, following the `justify-content` CSS property. Possible values are `between` (no space added between borders and columns) and `around` (space added). | `between`     |
| `marginBottom`             | `0...10`                                                       | A `number` or `string` magnitude for applying the `mb` Tachyons token to the row.                                                                                | `undefined`   |
| `marginTop`                | `0...10`                                                       | A `number` or `string` magnitude for applying the `mt` Tachyons token to the row.                                                                                | `undefined`   |
| `paddingBottom`            | `0...10`                                                       | A `number` or `string` magnitude for applying the `pb` Tachyons token to the row.                                                                                | `undefined`   |
| `paddingTop`               | `0...10`                                                       | A `number` or `string` magnitude for applying the `pt` Tachyons token to the row.                                                                                | `undefined`   |
| `preserveLayoutOnMobile`   | `Boolean`                                                      | Whether the `flex-layout.row` should break into a column layout on mobile.                                                                                | `false`       |
| `preventHorizontalStretch` | `Boolean`                                                      | Prevents the row from stretching horizontally to fill its parent's width.                                                                                | `false`       |
| `preventVerticalStretch`   | `Boolean`                                                      | Prevents the row from stretching vertically to fill its parent's height with the `items-stretch` token.                                                                                | `false`       |
| `rowGap`                   | `0...10`                                                       | A `number` or `string` magnitude for applying the `pb` Tachyons token to columns in the `flex-layout.row`.                                                                                | `undefined`   |
| `htmlId`                   | `String`                                                       | This prop adds an HTML id to `flexRow`. This allows accessing a page section using links.                                                                                | `undefined`   |
| `arialabel` | `string` | Aria-label to be included for accessibility purposes |  `undefined` |

### `flex-layout.col`

| Prop name                | Type                              | Description                                                                                | Default value |
| ------------------------ | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `blockClass`             | `String`                          | Block container class. The set value of this prop functions as a block identifier for CSS customizations                     | `""`          |
| `borderColor`            | `String`                          | The color of the border.                                                                                | `undefined`   |
| `borderWidth`            | `0...5`                           | A `number` or `string` magnitude for applying the `bw` Tachyons token to the column.                                         | `undefined`   |
| `border`                 | `String \| String[]`             | An array to define on which sides of the row a border should apply (`top`, `right`, `bottom`, `left`, or `all`).             | `undefined`   |
| `horizontalAlign`        | `left`|`right`|`center` | Controls horizontal alignment for the items in the `flex-layout.col`.                                                        | `left`        |
| `marginLeft`             | `0...10`                          | A `number` or `string` magnitude for applying the `ml` Tachyons token to the column.                                         | `undefined`   |
| `marginRight`            | `0...10`                          | A `number` or `string` magnitude for applying the `mr` Tachyons token to the column.                                         | `undefined`   |
| `paddingLeft`            | `0...10`                          | A `number` or `string` magnitude for applying the `pl` Tachyons token to the column.                                         | `undefined`   |
| `paddingRight`           | `0...10`                          | A `number` or `string` magnitude for applying the `pr` Tachyons token to the column.                                         | `undefined`   |
| `preventVerticalStretch` | `Boolean`                         | Prevents the row from stretching vertically to fill its parent's height with `height: 100%`, using `height: "auto"` instead. | `false`       |
| `rowGap`                 | `0...10`                          | A `number` or `string` magnitude for applying the `pb` Tachyons token to rows in the `flex-layout.col`.                      | `undefined`   |
| `verticalAlign`          | `top`|`middle`|`bottom` | Controls vertical alignment for the items in the `flex-layout.col`.                                                          | `top`         |
| `width`                  | `"0...100%"`|`"grow"`        | Sets the width of the column. Accepts either a percentage or `"grow"`.                                                       | `undefined`   |
| `arialabel` | `string` | Aria-label to be included for accessibility purposes |  `undefined` |

## App behavior

- The highest level in a flex layout is **always** a row. Therefore, you can only add a `flex-layout.col` inside a `flex-layout.row` — never as a first-level block.
- Every row and column can have as **many levels as needed**.
- When creating levels, you have to **alternate between rows and columns**. You can only place columns within a row and rows within a column.
- Keep in mind that the structure that you set in your flex layout does not only affect your code organization, but will also reflect in the way that blocks will be shown and managed through the Site Editor admin. Therefore, it is always important to **take the organization of both code and Site Editor into account when planning to apply the flex layout** to a page.

To better understand Flex Layout's practical operation, you can access the recipe for [Using Flex Layout](https://developers.vtex.com/docs/guides/vtex-io-documentation-using-flex-layout)

## Customization

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

| CSS Handles      |
| ---------------- |
| `flexColChild`   |
| `flexCol`        |
| `flexRowContent` |
| `flexRow`        |

## Contributors ✨

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

```


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

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { defineMessages } from 'react-intl'
import { useResponsiveValues } from 'vtex.responsive-values'
import { useCssHandles } from 'vtex.css-handles'

import {
  FlexLayoutTypes,
  useFlexLayoutContext,
  FlexLayoutContextProvider,
} from './components/FlexLayoutContext'
import {
  TachyonsScaleInput,
  parseTachyonsGroup,
  parseMargins,
  parsePaddings,
  parseBorders,
} from './modules/valuesParser'

enum VerticalAlign {
  top = 'top',
  middle = 'middle',
  bottom = 'bottom',
}

enum HorizontalAlign {
  left = 'left',
  right = 'right',
  center = 'center',
}

interface Props extends Flex, Gap, Border {
  blockClass?: string
  height?: string
  marginLeft: TachyonsScaleInput
  marginRight: TachyonsScaleInput
  paddingLeft: TachyonsScaleInput
  paddingRight: TachyonsScaleInput
  preventVerticalStretch?: boolean
  verticalAlign?: VerticalAlign
  horizontalAlign?: HorizontalAlign
}

const parseVerticalAlign = (input?: string) => {
  switch (input) {
    case VerticalAlign.middle:
      return 'justify-center'
    case VerticalAlign.bottom:
      return 'justify-end'
  }
  return ''
}

const parseHorizontalAlign = (input?: string) => {
  switch (input) {
    case HorizontalAlign.center:
      return 'items-center'
    case HorizontalAlign.right:
      return 'items-end'
  }
  return ''
}

const CSS_HANDLES = ['flexCol', 'flexColChild'] as const

const Col: StorefrontFunctionComponent<Props> = ({ children, ...props }) => {
  const {
    colGap,
    rowGap,
    marginLeft,
    marginRight,
    paddingLeft,
    paddingRight,
    border,
    borderWidth,
    borderColor,
    grow,
    preventVerticalStretch,
    verticalAlign,
    horizontalAlign
  } = useResponsiveValues(props) as Props

  const context = useFlexLayoutContext()
  const handles = useCssHandles(CSS_HANDLES)

  const gaps = parseTachyonsGroup({
    colGap: colGap != null ? colGap : context.colGap,
    rowGap: rowGap != null ? rowGap : context.rowGap,
  })

  const margins = parseMargins({
    marginLeft,
    marginRight,
  })

  const paddings = parsePaddings({
    paddingLeft,
    paddingRight,
  })

  const borders = parseBorders({
    border,
    borderWidth,
    borderColor,
  })

  if (context.parent === FlexLayoutTypes.NONE) {
    return null
  }

  const vertical = parseVerticalAlign(verticalAlign)
  const horizontal = parseHorizontalAlign(horizontalAlign)

  const rowsNum = React.Children.count(children)

  return (
    <FlexLayoutContextProvider parent={FlexLayoutTypes.COL} {...gaps}>
      <div
        className={`${handles.flexCol} ${
          grow ? 'flex-grow-1' : ''
        } ${margins} ${paddings} ${borders} ${vertical} ${horizontal} flex flex-column h-100 w-100`}
      >
        {React.Children.map(children, (row, i) => {
          const isLast = i === rowsNum - 1
          const rowGap = isLast ? 0 : gaps.rowGap

          return (
            <div
              key={i}
              className={`${handles.flexColChild} pb${rowGap}`}
              style={{
                height:
                  preventVerticalStretch || verticalAlign ? 'auto' : '100%',
              }}
            >
              {row}
            </div>
          )
        })}
      </div>
    </FlexLayoutContextProvider>
  )
}

const messages = defineMessages({
  title: {
    defaultMessage: '',
    id: 'admin/editor.column.title',
  },
  description: {
    defaultMessage: '',
    id: 'admin/editor.column.description',
  },
})

Col.schema = {
  title: messages.title.id,
  description: messages.description.id,
}

export default Col

```


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

[Assistant]
Here's the implementation:

```json
{
  "dependencies": {
    "@vtex/css-handles": "^1.1.3",
    "ramda": "^0.26.1",
    "react": "^16.8.6",
    "react-intl": "^3.12.1"
  },
  "devDependencies": {
    "@types/jest": "^24.0.11",
    "@types/node": "^11.13.2",
    "@types/ramda": "^0.26.8",
    "@types/react": "^16.8.13",
    "@types/react-intl": "^2.3.17",
    "@vtex/test-tools": "^1.2.0",
    "eslint": "^6.5.1",
    "eslint-config-vtex-react": "^5.0.1",
    "prettier": "^1.18.2",
    "tslint-eslint-rules": "^5.4.0",
    "typescript": "3.9.7"
  },
  "resolutions": {
    "@types/graphql": "14.0.7"
  },
  "version": "0.21.5"
}

```


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

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { defineMessages } from 'react-intl'
import { useCssHandles } from 'vtex.css-handles'

import {
  FlexLayoutTypes,
  FlexLayoutContextProvider,
  useFlexLayoutContext,
} from './components/FlexLayoutContext'

import { useResponsiveWidth } from './hooks/responsiveWidth'
import {
  parseTachyonsGroup,
  TachyonsScaleInput,
  parseMargins,
  parsePaddings,
  parseBorders,
} from './modules/valuesParser'

import styles from './Row.css'

enum ColSizing {
  equal = 'equal',
  auto = 'auto',
}

enum ColJustify {
  between = 'between',
  around = 'around',
  left = 'left',
  right = 'right',
  center = 'center',
}

const HorizontalAlignments = {
  [ColJustify.between]: 'justify-between',
  [ColJustify.around]: 'justify-around',
  [ColJustify.left]: 'justify-start',
  [ColJustify.center]: 'justify-center',
  [ColJustify.right]: 'justify-end',
}

const CSS_HANDLES = ['flexRowContent'] as const

export interface Props extends Flex, Gap, Border {
  blockClass?: string
  marginTop: TachyonsScaleInput
  marginBottom: TachyonsScaleInput
  paddingTop: TachyonsScaleInput
  paddingBottom: TachyonsScaleInput
  preserveLayoutOnMobile?: boolean
  preventHorizontalStretch?: boolean
  preventVerticalStretch?: boolean
  colSizing?: ColSizing
  horizontalAlign?: ColJustify
  colJustify?: ColJustify
  experimentalHideEmptyCols?: boolean
  htmlId?: string
}

const Row: StorefrontFunctionComponent<Props> = ({
  children,
  colGap,
  rowGap,
  marginTop,
  marginBottom,
  paddingTop,
  paddingBottom,
  border,
  borderWidth,
  borderColor,
  preserveLayoutOnMobile,
  preventHorizontalStretch,
  preventVerticalStretch,
  horizontalAlign,
  colSizing,
  colJustify = ColJustify.between,
  experimentalHideEmptyCols = false,
}) => {
  const context = useFlexLayoutContext()
  const handles = useCssHandles(CSS_HANDLES)

  const gaps = parseTachyonsGroup({
    colGap: colGap != null ? colGap : context.colGap,
    rowGap: rowGap != null ? rowGap : context.rowGap,
  })

  const margins = parseMargins({
    marginTop,
    marginBottom,
  })

  const paddings = parsePaddings({
    paddingTop,
    paddingBottom,
  })

  const borders = parseBorders({
    border,
    borderWidth,
    borderColor,
  })

  const { cols, breakOnMobile } = useResponsiveWidth(children, {
    preserveLayoutOnMobile,
    hideEmptyCols: experimentalHideEmptyCols,
  })

  const isSizingAuto = colSizing === ColSizing.auto

  let horizontalAlignClass = isSizingAuto
    ? HorizontalAlignments[colJustify]
    : HorizontalAlignments.left

  if (horizontalAlign != null) {
    horizontalAlignClass = HorizontalAlignments[horizontalAlign]
  }

  return (
    <FlexLayoutContextProvider parent={FlexLayoutTypes.ROW} {...gaps}>
      <div
        className={`${
          breakOnMobile ? 'flex-none flex-ns' : 'flex'
        } ${margins} ${paddings} ${borders} ${horizontalAlignClass} ${
          handles.flexRowContent
        } items-stretch w-100`}
      >
        {cols.map((col, i) => {
          const isLast = i === cols.length - 1
          const colGap = isLast ? 0 : gaps.colGap
          const rowGap = isLast ? 0 : gaps.rowGap

          return (
            <div
              key={i}
              className={`${
                /** If it breaks line on mobile, use the rowGap as bottom padding */
                breakOnMobile
                  ? `pr${colGap}-ns pb${rowGap} pb0-ns`
                  : `pr${colGap}`
              } ${preventVerticalStretch ? '' : 'items-stretch'} ${
                preventHorizontalStretch ? '' : styles.stretchChildrenWidth
              } ${col.width === 'grow' ? 'flex-grow-1' : ''} ${
                experimentalHideEmptyCols ? styles.col : ''
              } flex`}
              style={{
                width:
                  preventHorizontalStretch ||
                  (isSizingAuto && !col.hasDefinedWidth)
                    ? 'auto'
                    : breakOnMobile
                    ? '100%'
                    : col.width,
              }}
            >
              {col.element}
            </div>
          )
        })}
      </div>
    </FlexLayoutContextProvider>
  )
}

const messages = defineMessages({
  title: {
    defaultMessage: '',
    id: 'admin/editor.row.title',
  },
  description: {
    defaultMessage: '',
    id: 'admin/editor.row.description',
  },
})

Row.schema = {
  title: messages.title.id,
  description: messages.description.id,
}

export default Row

```


[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 flex-layout/react/Row.css from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```css
/** Stretches the width of the children to 100% (except images, which would be distorted. They are then centered)
 * This is done because the direct parent of the children of the Row component is flex now, which changes the
 * way children blocks are rendered (children with display: block of non-flex elements have 100% width, and
 * children of flex elements have the minimum possible width in respect of their content).
 * This can be cancelled with the prop `preventHorizontalStretch`
 */

.stretchChildrenWidth {
  justify-content: center;
}
.stretchChildrenWidth > *:not(img) {
  width: 100%;
}

/** Used for hiding empty columns */
.col:empty {
  display: none;
}
```


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

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { defineMessages, useIntl } from 'react-intl'
import { useCssHandles } from 'vtex.css-handles'
import Container from 'vtex.store-components/Container'
import { useResponsiveValues } from 'vtex.responsive-values'

import {
  FlexLayoutTypes,
  useFlexLayoutContext,
} from './components/FlexLayoutContext'
import Row, { Props as RowProps } from './Row'

interface Props extends RowProps {
  fullWidth?: boolean,
  arialabel?: string
}

const CSS_HANDLES = ['flexRow'] as const

const FlexLayout: StorefrontFunctionComponent<Props> = props => {
  const responsiveProps = useResponsiveValues(props) as Props
  const arialabel = responsiveProps.arialabel
  const { fullWidth, htmlId } = responsiveProps
  const context = useFlexLayoutContext()
  const handles = useCssHandles(CSS_HANDLES)

  const intl = useIntl()

  const content = <Row {...responsiveProps} />

  const isTopLevel = context.parent === FlexLayoutTypes.NONE

  const shouldUseContainer = !fullWidth && isTopLevel

  const wrappedContent = shouldUseContainer ? <Container>{content}</Container> : content

  return (
    <div className={handles.flexRow} id={htmlId} aria-label={arialabel ? arialabel : intl.formatMessage(
      { id: 'store/flex-layout.flexLayout-row.aria-label' }, { sectionId: htmlId ?? 'row'})}>
      {wrappedContent}
    </div>
  )
}

const messages = defineMessages({
  title: {
    defaultMessage: '',
    id: 'admin/editor.row.title',
  },
  description: {
    defaultMessage: '',
    id: 'admin/editor.row.description',
  },
})

FlexLayout.schema = {
  title: messages.title.id,
  description: messages.description.id,
}

export default FlexLayout

```


[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 flex-layout/react/FlexLayoutDummy.js from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'

const FlexLayoutDummy = () => {
  console.warn(
    'You are inserting the `flex-layout` block directly. Please use `flex-layout.row` instead.'
  )

  return <span />
}

export default FlexLayoutDummy

```


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

[Assistant]
Here's the implementation:

```json
{
  "flex-layout": {
    "component": "FlexLayoutDummy"
  },
  "flex-layout.row": {
    "component": "FlexLayout",
    "composition": "children",
    "allowed": "*"
  },
  "flex-layout.col": {
    "component": "Col",
    "composition": "children",
    "allowed": "*"
  }
}
```


[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 flex-layout/react/typings/global.d.ts from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { FunctionComponent } from 'react'
import { TachyonsScaleInput } from '../modules/valuesParser'

declare global {
  interface StorefrontFunctionComponent<P = {}> extends FunctionComponent<P> {
    schema?: object
    getSchema?(props?: P): object
  }

  interface StorefrontComponent<P = {}, S = {}> extends Component<P, S> {
    schema?: object
    getSchema?(props: P): object
  }

  interface StorefrontElement extends ReactElement {
    schema?: object
    getSchema?(props: P): object
  }

  interface Gap {
    colGap: TachyonsScaleInput
    rowGap: TachyonsScaleInput
  }

  interface Flex {
    stretchContent: boolean
    grow: boolean
  }

  type BorderBase = 'top' | 'right' | 'bottom' | 'left' | 'all'

  interface Border {
    border: BorderBase | BorderBase[]
    borderWidth: TachyonsScaleInput
    borderColor: string
  }
}

```


[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 flex-layout/react/typings/css.d.ts from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module '*.css' {
  const css: any
  export default css
}

```


[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 flex-layout/react/components/FlexLayoutContext.tsx from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FunctionComponent, useContext, useMemo } from 'react'

export enum FlexLayoutTypes {
  NONE = 'none',
  ROW = 'row',
  COL = 'col',
}

export interface FlexLayoutContextProps {
  parent: FlexLayoutTypes
  colGap: number
  rowGap: number
}

export type FlexLayoutContextValue = number | FlexLayoutTypes

export type FlexLayoutContext = FlexLayoutContextProps & {
  [key: string]: FlexLayoutContextValue
}

const FlexLayoutContext = React.createContext<FlexLayoutContext>({
  parent: FlexLayoutTypes.NONE,
  colGap: 0,
  rowGap: 0,
})

export const FlexLayoutContextProvider: FunctionComponent<
  FlexLayoutContextProps
> = ({ parent, colGap, rowGap, children }) => {
  const value = useMemo(
    () => ({
      parent,
      colGap,
      rowGap,
    }),
    [parent, colGap, rowGap]
  )

  return (
    <FlexLayoutContext.Provider value={value}>
      {children}
    </FlexLayoutContext.Provider>
  )
}

export const useFlexLayoutContext = () => useContext(FlexLayoutContext)

```


[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 flex-layout/react/__tests__/valuesParser.test.js from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```javascript
import { parseBorders } from '../modules/valuesParser'

describe('parseBorders', () => {
  it('should work with border as array', () => {
    const input = {
      border: ['left', 'bottom', 'right', 'top', 'all'],
      borderWidth: 1,
      borderColor: 'red',
    }

    const border = parseBorders(input)

    expect(border).toBe('bl bb br bt ba bw1 b--red')
  })
  it('should work with border as string', () => {
    const input = {
      border: 'all',
      borderWidth: 1,
      borderColor: 'red',
    }

    const border = parseBorders(input)

    expect(border).toBe('ba bw1 b--red')
  })
})

```


[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 flex-layout/react/hooks/responsiveWidth.ts from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```typescript
import React, { ReactElement } from 'react'
import { useDevice } from 'vtex.device-detector'
import { parseWidth } from '../modules/valuesParser'

interface DistributedWidthOptions {
  preserveLayoutOnMobile?: boolean
  hideEmptyCols?: boolean
}

interface ColWithWidth {
  element: React.ReactNode
  width: number | string
  hasDefinedWidth: boolean
  isResponsive: boolean
}

/** Distributes the available width--width that remains after subtracting
 * the widths of the columns the user has set--between the columns that do
 * not have their widths set by the user.
 *
 * For example:
 * There are 3 columns. The user sets the width for the first one to 50%.
 * This function will set the widths of the second and third columns to 25%.
 */
const distributeAvailableWidth = (
  cols: ColWithWidth[],
  { hideEmptyCols = false } = {}
) => {
  const { availableWidth, remainingColsNum, hasAnyWidthGrow } = cols.reduce(
    (acc, col) => {
      const isGrow = col.width === 'grow'
      const width =
        typeof col.width === 'number' ? acc.availableWidth - col.width : 0

      return {
        availableWidth: isGrow ? 0 : width,
        remainingColsNum: acc.remainingColsNum + (col.hasDefinedWidth ? 0 : 1),
        hasAnyWidthGrow: acc.hasAnyWidthGrow || isGrow,
      }
    },
    {
      availableWidth: 100,
      remainingColsNum: 0,
      hasAnyWidthGrow: false,
    }
  )

  if (availableWidth < 0 && !hasAnyWidthGrow) {
    const normalization = -(100 / availableWidth)
    cols = cols.map(col => ({
      ...col,
      width:
        typeof col.width === 'number' ? col.width * normalization : col.width,
    }))
  }

  return cols.map(col => {
    const definedWidth =
      typeof col.width === 'number' ? `${col.width}%` : col.width

    return {
      element: col.element,
      width: col.hasDefinedWidth
        ? definedWidth
        : `${Math.floor(
            Math.max(0, availableWidth) / (hideEmptyCols ? 1 : remainingColsNum)
          )}%`,
      hasDefinedWidth: col.hasDefinedWidth,
    }
  })
}

function isReactElement(element: any): element is ReactElement {
  return !!element && element.props
}

export const useResponsiveWidth = (
  children: React.ReactNode,
  options: DistributedWidthOptions
) => {
  const { device } = useDevice()

  const isPhone = device === 'phone'

  const { preserveLayoutOnMobile = false, hideEmptyCols = false } =
    options || {}

  const cols: ColWithWidth[] = React.Children.toArray(children).map(col => {
    if (!isReactElement(col)) {
      return {
        element: col,
        width: 0,
        hasDefinedWidth: false,
        isResponsive: true,
      }
    }

    const width = parseWidth(
      col.props.width || (col.props.blockProps && col.props.blockProps.width)
    )

    if (width && typeof width === 'object') {
      return {
        element: col,
        width: isPhone ? width.mobile || 0 : width.desktop || 0,
        hasDefinedWidth: true,
        isResponsive: true,
      }
    }

    if (!preserveLayoutOnMobile && isPhone) {
      return {
        element: col,
        width: 0,
        hasDefinedWidth: false,
        isResponsive: false,
      }
    }

    if (typeof width === 'number' || typeof width === 'string') {
      return {
        element: col,
        width,
        hasDefinedWidth: true,
        isResponsive: false,
      }
    }

    return {
      element: col,
      width: 0,
      hasDefinedWidth: false,
      isResponsive: true,
    }
  })

  const isAnyColResponsive = cols.some(col => col.isResponsive)
  const breakOnMobile =
    !preserveLayoutOnMobile && isPhone && !isAnyColResponsive

  return {
    cols: distributeAvailableWidth(cols, { hideEmptyCols }),
    breakOnMobile,
  }
}

```


[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 flex-layout/react/modules/valuesParser.ts from the flex-layout VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { fromPairs, pick, range, toPairs } from 'ramda'

export type TachyonsScaleInput = string | number | undefined
type Group<T, U> = { [key in keyof T]: U }
type TachyonsInputGroup<T> = Group<T, TachyonsScaleInput>
interface ResponsiveInput<T> {
  mobile: T
  desktop: T
}

const MAX_TACHYONS_SCALE = 11

//eslint-disable-next-line @typescript-eslint/no-explicit-any
const isResponsiveInput = <T>(value: any): value is ResponsiveInput<T> =>
  value && value.mobile != null && value.desktop != null

/** Takes a parser of units, and returns a parser that accepts either a
 * value or a responsive input of that same type of value
 * (i.e. {mobile: ..., desktop: ...}), and returns an object of the same
 * format of the input.
 */
export const parseResponsive = <T, U>(parse: (value: T) => U) => (
  value: T | ResponsiveInput<T>
): null | U | { mobile: U; desktop: U } => {
  if (isResponsiveInput(value)) {
    return {
      mobile: parse(value.mobile),
      desktop: parse(value.desktop),
    }
  }

  return parse(value)
}

/** Verifies if the input is a valid Tachyons scale value (i.e. a number
 * between 0 to 11) and converts to number if necessary
 */
const parseTachyonsValue = (value: TachyonsScaleInput, name?: string) => {
  if (!value) {
    return 0
  }

  const supportedValues = range(0, MAX_TACHYONS_SCALE + 1).map(String)

  if (!supportedValues.includes(String(value))) {
    if (name) {
      console.warn(
        `Invalid ${name} value ("${value}"). It should be an integer between 0 and ${MAX_TACHYONS_SCALE}.`
      )
    }

    return 0
  }

  return typeof value === 'string' ? parseInt(value, 10) : value
}

export const parseTachyonsGroup = <T>(group: TachyonsInputGroup<T>) => {
  const pairs = toPairs<TachyonsScaleInput>(group)

  const parsedValues = pairs.map<[string, number]>(([key, value]) => [
    key,
    parseTachyonsValue(value, key),
  ])

  return fromPairs(parsedValues) as Group<T, number>
}

const parseDimension = (input: string): null | number | string => {
  if (typeof input !== 'string') {
    return null
  }

  if (input === 'grow') {
    return 'grow'
  }

  const supportedUnits = ['%']
  const match = input.match(new RegExp(`(\\d*)(${supportedUnits.join('|')})`))

  if (!match) {
    return null
  }

  const value = match[1]
  // TODO: support multiple units
  // const unit = match[2]

  if (value == null) {
    return null
  }

  const parsedValue = parseInt(value, 10)

  return parsedValue
}

export const parseWidth = parseResponsive(parseDimension)

/** TODO: allow responsive values on height
 * (and verify height usage overall)
 **/
export const parseHeight = parseDimension

/** Maps objects keys to Tachyons classes, and returns a function
 * that parses Tachyons scale values to the mapped classes,
 * which in turn returns a string of classNames.
 **/
const mapToClasses = <T>(map: { [key in keyof T]: string }) => (
  props: { [key in keyof T]?: TachyonsScaleInput }
) => {
  const pickedProps = pick(Object.keys(map), props)

  const parsedProps = parseTachyonsGroup(pickedProps)

  const mappedProps = toPairs(parsedProps).map(
    ([key, value]) => `${map[key as (keyof T)] as string}${value}`
  )

  return mappedProps.join(' ')
}

// TODO: allow responsive values on paddings and margins
export const parsePaddings = mapToClasses({
  paddingTop: 'pt',
  paddingBottom: 'pb',
  paddingLeft: 'pl',
  paddingRight: 'pr',
})

export const parseMargins = mapToClasses({
  marginTop: 'mt',
  marginBottom: 'mb',
  marginLeft: 'ml',
  marginRight: 'mr',
})

const borderMap = {
  top: 'bt',
  right: 'br',
  bottom: 'bb',
  left: 'bl',
  all: 'ba',
}

export const parseBorders = ({ border, borderWidth, borderColor }: Border) => {
  const borders = border
    ? ([] as BorderBase[])
        .concat(border)
        .map(base => borderMap[base])
        .join(' ')
    : ''
  const width = borderWidth ? `bw${parseTachyonsValue(borderWidth, 'bw')}` : ''
  const color = borderColor ? `b--${borderColor.split(' ')[0]}` : ''

  return `${borders} ${width} ${color}`
}

```


[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 pwa-gtm-pixel/docs/README.md from the pwa-gtm-pixel VTEX app.

[Assistant]
Here's the implementation:

```markdown
# PWA Google Tag Manager Pixel

This app is an extension of the [Google Tag Manager App](https://github.com/vtex-apps/google-tag-manager) to add PWA Events for your store.

## How to install

First, you need to have the [Google Tag Manager App](https://github.com/vtex-apps/google-tag-manager) installed and configured on your store.

Then open the VTEX App Store and install the app on your store.

or

Run the following command:

```sh
vtex install vtex.pwa-gtm-pixel@1.x
```

## Google Tag Manager Setup

This guide provides instructions to setup all the necessary Tags, Triggers, Variables, and configurations to Google Tag Manager and Google Analytics, so at the end of it you will have all the PWA analytics available in your Google Analytics dashboard.

Open the Google Tag Manager dashboard at https://tagmanager.google.com/.

### Create Variables

#### Data Layer Variables

1. Click in Variable Configuration
2. Choose "Data Layer Variable"
3. Type "installWebApp" in "Data Layer Variable Name"
4. Click Save, and save as "Data Layer Variable - installWebApp"

Do the same thing for the variables: "userChoice".

### Creating Triggers

To create a Trigger, click on "Trigger" on the menu on the left and then on the button New.

#### Custom Events

1. Click in Trigger Configuration
2. Choose "Custom Event"
3. Type "installWebApp" in Event Name
4. Click Save, and save as "Custom Event - installWebApp"

### Creating Tags

To create a Tag, click on "Tags" on the menu on the left and then on the button New.

#### Google Analytics - PWA

1. Click in Tag Configuration
2. Choose "Google Analytics - PWA"
3. Choose Track Type as "Event"
4. Type "PWA" in Category
5. Type "{{Data Layer Variable - userChoice}}" in Action
6. Type "{{Event}}" in Label
7. In Google Analytics Settings choose "{{Google Analytics}}"
8. Choose the Triggers:
    1. "Custom Event - installWebApp"
9. Save as "Google Analytics - PWA"

```


[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 pwa-gtm-pixel/react/index.tsx from the pwa-gtm-pixel VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { canUseDOM } from 'vtex.render-runtime'
import { PixelMessage } from './typings/events'

import push from './modules/push'

export function handleEvents(e: PixelMessage) {
  switch (e.data.eventName) {
    case 'vtex:installWebApp': {
      push({
        event: 'installWebApp',
        userChoice: e.data.userChoice
      })
      return
    }
    default: {
      return
    }
  }
}

if (canUseDOM) {
  window.addEventListener('message', handleEvents)
}

```


[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 pwa-gtm-pixel/react/package.json from the pwa-gtm-pixel VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "scripts": {
    "test": "vtex-test-tools test"
  },
  "dependencies": {
    "ramda": "^0.26.1"
  },
  "devDependencies": {
    "@types/graphql": "^14.5.0",
    "@types/jest": "^24.0.11",
    "@types/node": "^11.13.0",
    "@types/ramda": "^0.26.5",
    "@vtex/test-tools": "^1.1.0",
    "eslint": "^5.16.0",
    "eslint-config-vtex-react": "^4.1.0",
    "graphql": "^14.5.4",
    "prettier": "^1.18.2",
    "tslint-eslint-rules": "^5.4.0",
    "typescript": "3.5.2"
  },
  "version": "1.0.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 pwa-gtm-pixel/store/interfaces.json from the pwa-gtm-pixel VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "pixel.pwaGtm": {
    "component": "index"
  }
}
```


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

[User] Show me the implementation of pwa-gtm-pixel/react/typings/events.d.ts from the pwa-gtm-pixel VTEX app.

[Assistant]
Here's the implementation:

```typescript
export interface PixelMessage extends MessageEvent {
  data:
    | ProductViewData
    | ProductClickData
    | OrderPlacedData
    | PageViewData
    | ProductImpressionData
    | AddToCartData
    | RemoveToCartData
    | HomePageInfo
    | ProductPageInfoData
    | SearchPageInfoData
    | InstallWebAppData
}

export interface EventData {
  event: string
  eventName: string
  currency: string
}

export interface PageInfoData extends EventData {
  event: 'pageInfo'
  eventName: 'vtex:pageInfo'
  accountName: string
  pageTitle: string
  pageUrl: string
}

export interface HomePageInfo extends PageInfoData {
  eventType: 'homeView'
}

export interface ProductPageInfoData extends PageInfoData {
  eventType: 'productView'
}

export interface SearchPageInfoData extends PageInfoData {
  eventType:
    | 'internalSiteSearchView'
    | 'categoryView'
    | 'departmentView'
    | 'emptySearchView'
  category?: CategoryMetaData
  department?: DepartmentMetaData
  search?: SearchMetaData
}

interface CategoryMetaData {
  id: string
  name: string
}

interface DepartmentMetaData {
  id: string
  name: string
}

interface SearchMetaData {
  term: string
  category: CategoryMetaData
  results: number
}

export interface PageViewData extends EventData {
  event: 'pageView'
  eventName: 'vtex:pageView'
  pageTitle: string
  pageUrl: string
  referrer: string
}

export interface AddToCartData extends EventData {
  event: 'addToCart'
  eventName: 'vtex:addToCart'
  items: CartItem[]
}

export interface RemoveToCartData extends EventData {
  event: 'removeFromCart'
  eventName: 'vtex:removeFromCart'
  items: CartItem[]
}

export interface OrderPlacedData extends Order, EventData {
  event: 'orderPlaced'
  eventName: 'vtex:orderPlaced'
}

export interface ProductViewData extends EventData {
  event: 'productView'
  eventName: 'vtex:productView'
  product: ProductDetail
}

export interface ProductClickData extends EventData {
  event: 'productClick'
  eventName: 'vtex:productClick'
  product: ProductSummary
}

export interface ProductImpressionData extends EventData {
  event: 'productImpression'
  eventName: 'vtex:productImpression'
  impressions: Impression[]
  product?: ProductSummary // deprecated, use impressions list!
  position?: number // deprecated, use impressions list!
  list: string
}

export interface InstallWebAppData extends EventData {
  event: 'installWebApp',
  eventName: 'vtex:installWebApp'
  userChoice:
    | 'accepted'
    | 'dismissed'
}

interface CartItem {
  skuId: string
  variant: string
  price: number
  name: string
  quantity: number
  productRefId: string
  brand: string
  category: string
}

export interface Order {
  currency: string
  accountName: string
  orderGroup: string
  salesChannel: string
  coupon: string
  visitorType: string
  visitorContactInfo: string[]
  visitorAddressState: string
  visitorAddressCountry: string
  visitorAddressPostalCode: string
  transactionId: string
  transactionDate: string
  transactionAffiliation: string
  transactionTotal: number
  transactionShipping: number
  transactionSubtotal: number
  transactionDiscounts: number
  transactionTax: number
  transactionCurrency: string
  transactionPaymentType: PaymentType[]
  transactionShippingMethod: ShippingMethod[]
  transactionProducts: ProductOrder[]
  transactionPayment: {
    id: string
  }
}

export interface Impression {
  product: ProductSummary
  position: number
}

export interface PaymentType {
  group: string
  paymentSystemName: string
  installments: number
  value: number
}

export interface ShippingMethod {
  itemId: string
  selectedSla: string
}

export interface ProductOrder {
  id: string
  name: string
  sku: string
  skuRefId: string
  skuName: string
  productRefId: string
  ean: string
  slug: string
  brand: string
  brandId: string
  seller: string
  sellerId: string
  category: string
  categoryId: string
  categoryTree: string[]
  categoryIdTree: string[]
  priceTags: PriceTag[]
  originalPrice: number
  price: number
  sellingPrice: number
  tax: number
  quantity: number
  components: any[]
  measurementUnit: string
  unitMultiplier: number
}

export interface PriceTag {
  identifier: string
  isPercentual: boolean
  value: number
}

interface Product {
  brand: string
  brandId: string
  categories: string[]
  productId: string
  productName: string
  productReference: string
  linkText: string
  items: Item[]
}

export interface ProductSummary extends Product {
  sku: Item
}

export interface ProductDetail extends Product {
  categoryId: string
  categoryTree: { id: string; name: string }[]
  selectedSku: Item
}

export interface Item {
  itemId: string
  name: string
  ean?: string // TODO: provide this info at productImpression
  referenceId: { Key: string; Value: string }
  seller?: Seller
  sellers: Seller[]
}

export interface Seller {
  commertialOffer: CommertialOffer
  sellerId: string
}

export interface CommertialOffer {
  Price: number
  ListPrice: number
  AvailableQuantity: number
}

```


[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 pwa-gtm-pixel/react/typings/vtex.render-runtime.d.ts from the pwa-gtm-pixel VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'vtex.render-runtime' {
  export const canUseDOM: boolean
}

```


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

[User] Show me the implementation of pwa-gtm-pixel/react/typings/global.d.ts from the pwa-gtm-pixel VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface Window extends Window {
  dataLayer: any[]
}

```