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

[User] Show me the implementation of admin-pages/react/InstitutionalPageList.tsx from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useEffect, useMemo } from 'react'
import { Query } from 'react-apollo'
import { defineMessages, useIntl } from 'react-intl'
import { PageHeader } from 'vtex.styleguide'

import Loader from './components/admin/institutional/Form/Loader'
import List from './components/admin/institutional/List/index'
import RoutesQuery from './queries/Routes.graphql'
import { useAdminLoadingContext } from './utils/AdminLoadingContext'

interface QueryData {
  routes: Route[]
}

interface PageListProps {
  data?: QueryData
  isLoading: boolean
}

const messages = defineMessages({
  contentPages: {
    defaultMessage: 'Content Pages',
    id: 'admin/pages.admin-menu-button.content-pages',
  },
})

const PageList: React.FunctionComponent<PageListProps> = ({
  data,
  isLoading,
}) => {
  const intl = useIntl()

  const { startLoading, stopLoading } = useAdminLoadingContext()

  useEffect(() => {
    if (isLoading) {
      startLoading()
    } else {
      stopLoading()
    }
  }, [isLoading, startLoading, stopLoading])

  const institutionalRoutes = useMemo(() => {
    const routes = data && data.routes
    return (routes || []).filter((currRoute: Route) => {
      return (currRoute.context || '').endsWith('ContentPageContext')
    })
  }, [data])

  if (isLoading) {
    return <Loader />
  }

  return (
    <div className="h-100 min-vh-100 overflow-y-auto bg-light-silver">
      <div className="center mw8">
        <PageHeader title={intl.formatMessage(messages.contentPages)} />
        <div className="ph7">
          <List
            hasCreateButton
            routes={institutionalRoutes}
            titleId="admin/pages.admin.pages.list.section.standard"
          />
        </div>
      </div>
    </div>
  )
}

const PageListWithQuery = () => {
  return (
    <Query<QueryData> query={RoutesQuery} variables={{ domain: 'store' }}>
      {({ data, loading: isLoading }) => {
        return <PageList isLoading={isLoading} data={data} />
      }}
    </Query>
  )
}

export default React.memo(PageListWithQuery)

```


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

[User] Show me the implementation of admin-pages/react/PagesAdminWrapper.tsx from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { mapObjIndexed, values } from 'ramda'
import React, { useState } from 'react'
import { defineMessages, useIntl } from 'react-intl'
import { useRuntime } from 'vtex.render-runtime'
import { Tab, Tabs } from 'vtex.styleguide'

import AdminStructure from './components/admin/AdminStructure'
import TargetPathContext from './components/admin/TargetPathContext'
import Loader from './components/Loader'
import { useAdminLoadingContext } from './utils/AdminLoadingContext'

export interface TargetPathRenderProps {
  targetPath: string
  setTargetPath: (s: string) => void
}

const fields = {
  pages: {
    path: 'pages',
    titleId: 'admin/pages.admin.tabs.pages',
  },
  redirects: {
    path: 'redirects',
    titleId: 'admin/pages.admin.tabs.redirects',
  },
}

interface FieldInfo {
  path: string
  titleId: string
}

interface CustomProps {
  targetPath: string
}

defineMessages({
  pages: {
    defaultMessage: 'Pages',
    id: 'admin/pages.admin.tabs.pages',
  },
  redirects: {
    defaultMessage: 'Redirects',
    id: 'admin/pages.admin.tabs.redirects',
  },
})

type Props = CustomProps & RenderContextProps

const PagesAdminWrapper: React.FunctionComponent<Props> = ({ children }) => {
  const [targetPath, setTargetPath] = useState('')
  const { startLoading } = useAdminLoadingContext()
  const runtime = useRuntime()
  const intl = useIntl()

  return (
    <TargetPathContext.Provider value={{ targetPath, setTargetPath }}>
      <AdminStructure title="CMS">
        <div className="ph7">
          <Tabs>
            {values(
              mapObjIndexed(
                (info: FieldInfo, key: string) => (
                  <Tab
                    active={
                      targetPath.startsWith(info.path) &&
                      (targetPath === '' ? targetPath === info.path : true)
                    }
                    key={key}
                    label={intl.formatMessage({ id: info.titleId })}
                    onClick={() => {
                      runtime.navigate({ to: '/admin/app/cms/' + info.path })
                      startLoading()
                      setTargetPath(info.path)
                    }}
                  />
                ),
                fields
              )
            )}
          </Tabs>
        </div>

        <div className="ma7">{runtime.preview ? <Loader /> : children}</div>
      </AdminStructure>
    </TargetPathContext.Provider>
  )
}

export default PagesAdminWrapper

```


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

[User] Show me the implementation of admin-pages/react/Wrapper.tsx from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { ReactNode } from 'react'
import { ToastProvider } from 'vtex.styleguide'
import { AdminLoadingContextProvider } from './utils/AdminLoadingContext'

interface Props {
  children?: ReactNode
}

const Wrapper: React.FunctionComponent<Props> = ({ children }) => (
  <ToastProvider positioning="window">
    <AdminLoadingContextProvider>
      <div className="vh-100">{children}</div>
    </AdminLoadingContextProvider>
  </ToastProvider>
)

export default React.memo(Wrapper)

```


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

[User] Show me the implementation of admin-pages/react/PageFormWrapper.tsx from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'

import PageForm, { Props } from './PageForm'
import { useBinding } from './utils/bindings'

const PageFormWrapper: React.FunctionComponent<Props> = (props: Props) => {
  const [localStorageBinding, setLocalStorageBinding] = useBinding()
  return (
    <PageForm
      {...props}
      localStorageBinding={localStorageBinding}
      setLocalStorageBinding={setLocalStorageBinding}
    />
  )
}

export default PageFormWrapper

```


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

[User] Show me the implementation of admin-pages/react/StoreSettings.tsx from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { injectIntl, InjectedIntlProps } from 'react-intl'

import AdminStructure from './components/admin/AdminStructure'
import Store from './components/admin/store'

const StoreSettings: React.FC<InjectedIntlProps> = ({ intl }) => (
  <AdminStructure
    title={intl.formatMessage({
      defaultMessage: 'Store settings',
      id: 'admin/pages.editor.store.settings.title',
    })}
  >
    <Store />
  </AdminStructure>
)

export default injectIntl(StoreSettings)

```


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

[User] Show me the implementation of admin-pages/react/PageForm.tsx from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { equals } from 'ramda'
import React, { Component } from 'react'
import { withApollo, WithApolloClient } from 'react-apollo'
import { FormattedMessage } from 'react-intl'
import { withRuntimeContext } from 'vtex.render-runtime'
import { Box, ToastConsumer } from 'vtex.styleguide'
import { Binding, Tenant } from 'vtex.tenant-graphql'
import { RouteFormData } from 'pages'

import {
  NEW_ROUTE_ID,
  ROUTES_LIST,
  WRAPPER_PATH,
  DATA_SOURCE,
} from './components/admin/pages/consts'
import Form from './components/admin/pages/Form'
import Operations from './components/admin/pages/Form/Operations'
import Title from './components/admin/pages/Form/Title'
import { formatToFormData } from './components/admin/pages/Form/utils'
import { getRouteTitle } from './components/admin/pages/utils'
import {
  TargetPathContextProps,
  withTargetPath,
} from './components/admin/TargetPathContext'
import Loader from './components/Loader'
import { TargetPathRenderProps } from './PagesAdminWrapper'
import RouteQuery from './queries/Route.graphql'
import RoutesQuery from './queries/Routes.graphql'
import TenantInfoQuery from './queries/TenantInfo.graphql'
import { getStoreBindings } from './utils/bindings'

interface CustomProps {
  params: {
    id: string
  }
  runtime: RenderContext
}

interface BindingProps {
  localStorageBinding?: Binding
  setLocalStorageBinding: (binding: Binding) => void
}

export type Props = BindingProps &
  WithApolloClient<
    CustomProps &
      RenderContextProps &
      TargetPathRenderProps &
      TargetPathContextProps
  >

interface State {
  formData: RouteFormData
  isLoading: boolean
  routeId: string
  storeBindings: Binding[] | null
}

class PageForm extends Component<Props, State> {
  private isNew: boolean
  private defaultFormData: RouteFormData = {
    auth: false,
    blockId: '',
    binding: undefined,
    context: null,
    declarer: null,
    domain: 'store',
    interfaceId: 'vtex.store@2.x:store.custom',
    metaTagDescription: '',
    metaTagKeywords: [],
    pages: [],
    path: '',
    routeId: '',
    title: '',
    uuid: undefined,
    dataSource: DATA_SOURCE,
  }

  public constructor(props: Props) {
    super(props)
    const { localStorageBinding } = props

    const routeId = decodeURIComponent(props.params.id)

    const { client } = props
    let currentRoute = null
    let tenantInfo = null
    let storeBindings = null

    // Find route from cache
    try {
      const { routes } = client.readQuery<{ routes: Route[] }>({
        query: RoutesQuery,
        variables: { domain: 'store', bindingId: localStorageBinding?.id },
      }) || { routes: [] }
      currentRoute = routes.find(
        ({ routeId: routeIdFromRoute }) => routeIdFromRoute === routeId
      )
    } catch (e) {
      // console.error(e)
    }

    // Get tenant data
    try {
      const data =
        client.readQuery<{ tenantInfo: Tenant }>({
          query: TenantInfoQuery,
        }) || null
      tenantInfo = data?.tenantInfo
    } catch (e) {
      console.error(e)
    }
    if (tenantInfo) {
      storeBindings = getStoreBindings(tenantInfo)
      this.setState({
        storeBindings,
      })
      this.defaultFormData.binding =
        localStorageBinding?.id || storeBindings[0].id
    }

    this.isNew = routeId === NEW_ROUTE_ID

    this.state = {
      formData: currentRoute
        ? formatToFormData(currentRoute)
        : this.defaultFormData,
      isLoading: !this.isNew,
      routeId,
      storeBindings,
    }
  }

  public async componentDidMount() {
    const { client, setTargetPath } = this.props
    const { formData, storeBindings } = this.state

    setTargetPath(WRAPPER_PATH)

    // Get tenant info
    if (storeBindings === null) {
      try {
        const { data } = await client.query<{ tenantInfo: Tenant }, {}>({
          query: TenantInfoQuery,
        })
        const tenantInfo = data?.tenantInfo
        if (!tenantInfo) {
          throw Error()
        }
        const storeBindings = getStoreBindings(tenantInfo)
        formData.binding = storeBindings[0].id
        this.setState({
          formData,
          storeBindings,
        })
      } catch (e) {
        console.error(e)
        this.handleExit()
      }
    }

    if (equals(formData, this.defaultFormData) && !this.isNew) {
      // didnt find in cache
      try {
        const {
          data: { route },
        } = await client.query<{ route: Route }>({
          query: RouteQuery,
          variables: {
            domain: 'store',
            routeId: this.state.routeId,
            bindingId: formData.binding,
          },
        })

        if (route) {
          this.setState({
            formData: formatToFormData(route),
            isLoading: false,
          })
        } else {
          this.handleExit()
        }
      } catch (err) {
        console.error(err)
        this.handleExit()
      }
    } else {
      this.setState({ isLoading: false })
    }
  }

  public render() {
    const { setLocalStorageBinding } = this.props
    const { formData, isLoading, storeBindings } = this.state

    return (
      <>
        {isLoading ? (
          <Loader />
        ) : (
          <Operations
            interfaceId={formData.interfaceId}
            binding={formData.binding}
          >
            {({ deleteRoute, saveRoute, templatesResults }) => {
              const templates =
                (templatesResults.data &&
                  templatesResults.data.availableTemplates) ||
                []
              const loading = templatesResults.loading
              return loading ? (
                <Loader />
              ) : (
                <Box>
                  {this.isNew ? (
                    <FormattedMessage id="admin/pages.admin.pages.form.title.new">
                      {text => <Title>{text}</Title>}
                    </FormattedMessage>
                  ) : (
                    formData && <Title>{getRouteTitle(formData)}</Title>
                  )}
                  <ToastConsumer>
                    {({ showToast, hideToast }) => (
                      <Form
                        initialData={formData}
                        isCustomPage={formData.interfaceId.includes(
                          'store.custom'
                        )}
                        onDelete={deleteRoute}
                        onExit={this.handleExit}
                        onSave={saveRoute}
                        templates={templates}
                        showToast={showToast}
                        hideToast={hideToast}
                        storeBindings={storeBindings}
                        setLocalStorageBinding={setLocalStorageBinding}
                      />
                    )}
                  </ToastConsumer>
                </Box>
              )
            }}
          </Operations>
        )}
      </>
    )
  }

  private handleExit = () => {
    this.props.runtime.navigate({ page: ROUTES_LIST, params: {} })
  }
}

export default withApollo(withRuntimeContext(withTargetPath(PageForm)))

```


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

[User] Show me the implementation of admin-pages/react/typings/simple-element-resize-detector.d.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'simple-element-resize-detector' {
  export default function(
    el: Element,
    handler: (el: Element) => void
  ): HTMLIFrameElement
}

```


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

[User] Show me the implementation of admin-pages/react/typings/draft-js.d.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```typescript
import 'draft-js'
declare module 'draft-js' {
  export interface Media {
    block: ContentBlock
    blockProps: { [key: string]: unknown } | undefined
    blockStyleFn?: (block: ContentBlock) => string
    contentState: ContentState
    customStyleFn?: (
      style: DraftInlineStyle,
      block: ContentBlock
    ) => DraftStyleMap
    customStyleMap: DraftStyleMap
    decorator: CompositeDecorator
    direction: string
    forceSelection: boolean
    offsetKey: string
    selection: SelectionState
    tree: Immutable.List<unknown>
  }

  export interface Link {
    children: React.ElementType[]
    contentState: ContentState
    decoratedText: string
    dir: string | null
    entityKey: string
    offsetKey: 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 admin-pages/react/typings/vtex.render-runtime.d.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

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

  export const ExtensionPoint: ReactElement
  export const Helmet: ComponentType<unknown>
  export const Link: ReactElement
  export const NoSSR: ReactElement
  export const RenderContextConsumer: ReactElement
  export const canUseDOM: boolean

  export const withRuntimeContext: <TOriginalProps extends {}>(
    Component: ComponentType<TOriginalProps & RenderContextProps>
  ) => ComponentType<
    Pick<
      TOriginalProps,
      Exclude<keyof TOriginalProps, keyof RenderContextProps>
    >
  >

  export declare const useRuntime: () => RenderContext

  interface RenderComponent {
    getCustomMessages?: (locale: string) => unknown
    schema?: ComponentSchema
    getSchema?: (props: object, otherArgs?: unknown) => ComponentSchema
    uiSchema?: object
  }

  export interface ComponentsRegistry {
    [component: string]: RenderComponent
  }

  export interface Window extends Window {
    __RENDER_8_COMPONENTS__: ComponentsRegistry
  }

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

  const global: Window
}

```


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

[User] Show me the implementation of admin-pages/react/typings/vtex.native-types.d.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'vtex.native-types' {
  import { FunctionComponent } from 'react'
  import { FormattedMessage, InjectedIntlProps } from 'react-intl'

  const formatIOMessage: (
    adaptedMessageDescriptor: FormattedMessage.MessageDescriptor &
      InjectedIntlProps,
    values?: Record<string, MessageValue>
  ) => string

  export const IOMessage: FunctionComponent<
    FormattedMessage.Props & InjectedIntlProps
  >
}

```


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

[User] Show me the implementation of admin-pages/react/typings/text-encoding.d.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'text-encoding' {
  declare const TextEncoder = class TextEnconder {
    public encode(data: string): void
  }
}

```


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

[User] Show me the implementation of admin-pages/react/typings/json-schema-traverse.d.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'json-schema-traverse' {
  const traverse: (
    schema: ComponentSchema,
    opts: (
      schema: JSONSchema6 & { widget: Widget },
      JSONPointer: string
    ) => void
  ) => void

  export default traverse
}

```


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

[User] Show me the implementation of admin-pages/react/typings/global.d.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { DocumentNode } from 'graphql'
import { JSONSchema6 } from 'json-schema'

import { ConfigurationStatus } from '../components/EditorContainer/Sidebar/BlockEditor/typings'
import { State as EditorProviderState } from '../components/EditorProvider'
import { State as HighlightOverlayState } from '../HighlightOverlay'

declare global {
  declare module '*.graphql' {
    const value: DocumentNode
    export default value
  }

  declare module '*.css' {
    interface CssClasses {
      [cssClass: string]: string
    }
    const content: CssClasses
    export default content
  }

  interface Extension {
    after?: string[]
    around?: string[]
    before?: string[]
    blockId: string
    blocks?: InnerBlock[]
    component: string | null
    composition?: 'blocks' | 'children'
    configurationsIds?: string[]
    content: Record<string, unknown>
    contentIds: string[]
    contentMapId?: string
    hasContentSchema: boolean
    implementationIndex?: number
    implements?: string[]
    preview: object | null
    props: Record<string, unknown>
    render: 'client' | 'lazy' | 'server'
    shouldRender?: boolean
    track: string[]
    title?: string
  }

  interface Extensions {
    [name: string]: Extension
  }

  interface Template {
    id: string
  }

  interface ConditionStatementArg {
    subject: string
    verb: string
    objectJSON: string
  }

  interface ConditionArg {
    id?: string
    allMatches: boolean
    statements: ConditionStatementArg[]
  }

  interface PageMetaTags {
    description?: string
    keywords?: string[]
    robots?: string
  }

  interface Page {
    pageId?: string
    condition: ConditionArg
    template: string
  }

  interface Route {
    auth: boolean
    binding?: string
    blockId: string
    context: string | null
    declarer: string | null
    domain: string
    interfaceId: string
    metaTags?: PageMetaTags
    pages: Page[]
    path: string
    routeId: string
    title: string | null
    uuid?: string
    dataSource?: string
    conflicts?: Route[]
    bindingId?: string
  }

  interface Routes {
    [name: string]: Route
  }

  interface HistoryLocation {
    hash: string
    key: string
    pathname: string
    search: string
    state: { navigationRoute: { params: {} } }
  }

  type RuntimeHistory = History & {
    block: (s: string) => () => void
    replace: (s: string) => void
    listen: (
      listenCb: (location: HistoryLocation, action: string) => void
    ) => () => void
    location: HistoryLocation
  }

  interface RenderContext {
    account: RenderRuntime['account']
    addMessages: (newMessages: RenderContext['messages']) => Promise<void>
    binding?: {
      canonicalBaseAddress: string
      id: string
    }
    components: RenderRuntime['components']
    contentMap: RenderRuntime['contentMap']
    culture: RenderRuntime['culture']
    device: ConfigurationDevice
    emitter: RenderRuntime['emitter']
    extensions: RenderRuntime['extensions']
    fetchComponent: (component: string) => Promise<void>
    getSettings: (app: string) => unknown
    history: RuntimeHistory | null
    messages: RenderRuntime['messages']
    navigate: (options: NavigateOptions) => boolean
    onPageChanged: (location: Location) => void
    page: RenderRuntime['page']
    pages: RenderRuntime['pages']
    prefetchPage: (name: string) => Promise<void>
    preview: RenderRuntime['preview']
    production: RenderRuntime['production']
    query?: RenderRuntime['query']
    route: RenderRuntime['route']
    renderMajor: RenderRuntime['renderMajor']
    setDevice: (device: ConfigurationDevice) => void
    updateComponentAssets: (availableComponents: Components) => void
    updateExtension: (name: string, extension: Extension) => Promise<void>
    updateRuntime: (options?: PageContextOptions) => Promise<void>
    workspace: RenderRuntime['workspace']
  }

  interface RenderContextProps {
    runtime: RenderContext
  }

  interface BlockData {
    componentImplementation?: RenderComponent | null
    componentSchema?: ComponentSchema
    configurations?: ExtensionConfiguration[]
    contentSchema?: JSONSchema6
    id?: string
    isSitewide?: boolean
    serverTreePath?: string
    template?: string
    title?: string
  }

  type ConditionType = 'scope' | 'device' | 'custom'

  interface Condition {
    conditionId: string
  }

  type Viewport = 'desktop' | 'mobile' | 'tablet'

  type ConfigurationDevice = 'any' | 'desktop' | 'mobile'

  type EditorMode = 'content' | 'layout' | 'disabled'

  interface EditorConditionSection {
    activeConditions: string[]
    addCondition: (conditionId: string) => void
    removeCondition?: (conditionId: string) => void
  }

  interface EditorContextType extends EditorConditionSection {
    allMatches: boolean
    availableCultures: LabelledLocale[]
    blockData: EditorProviderState['blockData']
    editMode: boolean
    editTreePath: string | null
    getIsLoading: () => boolean
    onChangeIframeUrl: (url: string) => void
    iframeWindow?: Window
    isSidebarVisible: boolean
    messages: RenderRuntime['messages']
    mode: EditorMode
    viewport: Viewport
    setBlockData: (blockData: EditorProviderState['blockData']) => void
    setDevice: (device: ConfigurationDevice) => void
    setIsLoading: (isLoading: boolean) => void
    setMode: (mode: EditorMode) => void
    setViewport: (viewport: Viewport) => void
    editExtensionPoint: (treePath: string | null) => void
    toggleEditMode: () => void
    toggleSidebarVisibility: () => void
  }

  interface RenderRuntime {
    account: string
    accountId: string
    appsEtag: string
    contentMap?: Record<string, Record<string, unknown>>
    customRouting?: boolean
    emitter: EventEmitter
    workspace: string
    disableSSR: boolean
    hints: unknown
    page: string
    version: string
    culture: Culture
    pages: Routes
    route: { id: string; pageContext: PageContext; path: string; params: {} }
    routes: Routes
    extensions: Extensions
    production: boolean
    publicEndpoint: string
    messages: Record<string, string>
    components: Components | Record<string, string[]>
    renderMajor: number
    query?: Record<string, string>
    start: boolean
    settings: {
      [app: string]: unknown
    }
    cacheHints: CacheHints
    preview?: boolean
  }

  type ConfigurationScope = 'entity' | 'template' | 'sitewide'

  interface PageContextOptions {
    scope?: ConfigurationScope
    device?: ConfigurationDevice
    conditions?: string[]
    template?: string
  }

  interface PageContext {
    id: string
    type:
      | 'brand'
      | 'category'
      | 'department'
      | 'product'
      | 'route'
      | 'search'
      | 'subcategory'
      | '*'
  }

  type ConditionSubject = 'date' | 'utm'

  interface ExtensionConfigurationConditionStatement {
    objectJSON: string
    subject: ConditionSubject
    verb: string
  }
  interface ExtensionConfiguration {
    status?: ConfigurationStatus
    condition: {
      allMatches: boolean
      id: string
      pageContext: RenderRuntime['route']['pageContext']
      statements: ExtensionConfigurationConditionStatement[]
    }
    contentId: string | null
    contentJSON: string
    label: string | null
    origin: string | null
  }

  type RedirectTypes = 'PERMANENT' | 'TEMPORARY'

  interface Redirect {
    endDate: string | null
    from: string
    to: string
    type: RedirectTypes
    binding: string
  }

  interface HighlightableIFrame extends HTMLIFrameElement {
    contentWindow: ContentWindow | null
  }

  interface ComponentSchemaProperties {
    [key: string]: ComponentSchema
  }

  interface ComponentSchema extends JSONSchema6 {
    type?: string
    title?: string
    description?: string
    enumNames?: string[]
    widget?: Record<string, string>
    minItems?: number
    properties?: ComponentSchemaProperties
    isLayout?: boolean
    items?: ComponentSchema | ComponentSchema[]
  }

  interface Window {
    __provideRuntime?: (
      runtime: RenderContext,
      messages: Record<string, string>,
      shouldUpdateRuntime: boolean
    ) => Promise<void>
    __setHighlightTreePath: (value: Partial<HighlightOverlayState>) => void
  }

  interface AdminContext {
    startLoading: () => void
    stopLoading: () => void
  }

  type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>

  type BlockRole = 'AFTER' | 'AROUND' | 'BEFORE' | 'BLOCK' | 'TEMPLATE'

  interface FormattedBlock {
    id: Extension['blockId']
    role: 'AFTER' | 'AROUND' | 'BEFORE' | 'BLOCK' | 'TEMPLATE'
  }

  type BlockPath = FormattedBlock[]

  interface InnerBlock {
    blockId: string
    extensionPointId: string
  }

  interface AppSettings {
    message: string
  }

  interface SettingsParsed {
    copyContentBinding?: 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 admin-pages/react/typings/streamsaver.d.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'streamsaver' {
  interface Constructable<T> {
    new (): T
  }

  interface StreamSaver {
    static WritableStream: Constructable<WritableStream>
    createWriteStream: (name: string) => WritableStream
  }

  let WritableStream: WritableStream
  const streamsaver: StreamSaver

  export default streamsaver
}

```


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

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

[Assistant]
Here's the implementation:

```typescript
declare module 'pages' {
  import { ConditionsProps } from 'vtex.styleguide'

  type ConditionsOperators = NonNullable<ConditionsProps['operator']>

  interface Statements {
    subject: string
    verb: string
    object: Record<string, unknown>
    error: unknown
  }

  interface ConditionFormsData {
    id?: string
    allMatches: boolean
    statements: Statements[]
  }

  type PagesFormData = Omit<Page, 'condition'> & {
    condition: ConditionFormsData
    uniqueId: number
    operator: ConditionsOperators
    template: string
  }

  interface KeywordsFormData {
    value: string
    label: string
  }

  type RouteFormData = Omit<Route, 'pages' | 'metaTags'> & {
    pages: PagesFormData[]
    metaTagDescription?: string
    metaTagRobots?: string
    metaTagKeywords?: KeywordsFormData[]
  }
}

```


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

[User] Show me the implementation of admin-pages/react/typings/vtex.styleguide.d.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable @typescript-eslint/camelcase */
/* eslint-disable @typescript-eslint/class-name-casing */
declare module 'vtex.styleguide' {
  import { ReactDatePickerProps } from '@types/react-datepicker'
  import { Component, ComponentType, CSSProperties, ReactNode } from 'react'

  type StyleguideSizes = 'small' | 'regular' | 'large'

  interface TextareaProps
    extends React.DetailedHTMLProps<
      React.TextareaHTMLAttributes<HTMLTextAreaElement>,
      HTMLTextAreaElement
    > {
    error?: boolean
    errorMessage?: string
    helpText?: ReactNode
    resize?: CSSProperties['resize']
    value?: string
    label?: string
    size?: 'small' | 'large' | 'regular'
  }

  interface ToastProviderProps {
    children?: ReactNode
    positioning?: 'parent' | 'window'
  }

  interface ShowToastOptions {
    action?: {
      label: string
      onClick: () => void
    }
    message: string
    duration?: number
    horizontalPosition?: 'right' | 'left'
  }

  export type ShowToastFunction = (a: ShowToastOptions | string) => void

  export interface ToastConsumerFunctions {
    showToast: ShowToastFunction
    hideToast: () => void
    toastState: unknown
  }
  interface ToastConsumerProps {
    children: (mutations: ToastConsumerFunctions) => React.ReactNode
  }

  interface ConditionsStatement {
    subject: string
    verb: string
    object: Record<string, unknown>
    error: unknown
  }

  type ConditionsOperator = 'any' | 'all'
  interface ConditionsLabels {
    addNewCondition: string
    addConditionBtn: string
    delete: string
    noConditions: string
    operatorAll: string
    operatorAnd: string
    operatorAny: string
    operatorOr: string
    headerPrefix: string
    headerSufix: string
  }

  interface ConditionsRenderFnArg {
    statementIndex: number
    statements: ConditionsStatement[]
    isFullWidth: boolean
    values: ConditionsStatement['object']
    error: string | null
    extraParams: ConditionOptionObject['extraParams']
  }

  export type ConditionsRenderFn = (arg: ConditionsRenderFnArg) => ReactElement

  interface ConditionOptionObject {
    renderFn: ConditionsRenderFn
    extraParams: Record<string, unknown>
  }

  interface ConditionsOptionVerb {
    label: string
    value: string
    object: ConditionOptionObject
  }

  export interface ConditionsOptions {
    label: string
    unique?: boolean
    verbs: ConditionsOptionVerb[]
  }

  export interface ConditionsProps {
    canDelete?: boolean
    operator?: ConditionsOperator
    statements?: ConditionsStatement[]
    options: Record<string, ConditionsOptions>
    subjectPlaceholder: string
    noOptionsMessage: string
    isFullWidth?: boolean
    onChangeStatements?: (s: ConditionsStatement[]) => void
    onChangeOperator?: (o: { operator: ConditionsOperator }) => void
    isRtl?: boolean
    showOperator?: boolean
    labels?: ConditionsLabels
  }

  interface StyleguideDatePickerCustomProps {
    error?: boolean
    errorMessage?: string
    helpText?: ReactNode
    label?: string
    locale: string
    placeholder?: string
    size?: StyleguideSizes
    value?: Date
    useTime?: boolean
  }

  type DatePickerProps = Pick<
    | ReactDatePickerProps
    | 'autoFocus'
    | 'disabled'
    | 'excludeDates'
    | 'excludeTimes'
    | 'id'
    | 'includeDates'
    | 'includeTimes'
    | 'maxDate'
    | 'minDate'
    | 'name'
    | 'onChange'
    | 'onFocus'
    | 'onBlur'
    | 'readOnly'
    | 'required'
    | 'tabIndex'
    | 'timeIntervals'
  > &
    StyleguideDatePickerCustomProps

  interface ProgressProps {
    type: 'line' | 'steps'
    percent?: number
  }

  interface AlertProps {
    type: 'success' | 'error' | 'warning'
    children: ReactNode
    action?: {
      onClick: () => void
      label: ReactNode
    }
    autoClose?: number
    onClose?: () => void
  }

  interface ModalProps {
    children: ReactNode
    onClose: (event?: Event) => void
    bottomBar?: ReactNode
    centered?: boolean
    closeOnEsc?: boolean
    closeOnOverlayClick?: boolean
    container?: object
    isOpen?: boolean
    onCloseTransitionFinish?: () => void
    responsiveFullScreen?: boolean
    showTopBar?: boolean
    title?: ReactNode
  }

  export const ActionMenu: ComponentType<Record<string, unknown>>
  export const Alert: ComponentType<AlertProps>
  export const Box: ComponentType<Record<string, unknown>>
  export const Button: ComponentType<Record<string, unknown>>
  export const ButtonWithIcon: ComponentType<Record<string, unknown>>
  export const Card: ComponentType<Record<string, unknown>>
  export const Checkbox: ComponentType<Record<string, unknown>>
  export class DatePicker extends Component<DatePickerProps> {}
  export const ColorPicker: ComponentType<Record<string, unknown>>
  export const Dropdown: ComponentType<Record<string, unknown>>
  export const EmptyState: ComponentType<Record<string, unknown>>
  export class EXPERIMENTAL_Conditions extends Component<ConditionsProps> {}
  export class EXPERIMENTAL_Select extends Component<Record<string, unknown>> {}
  export const IconArrowBack: ComponentType<Record<string, unknown>>
  export const IconBold: ComponentType<Record<string, unknown>>
  export const IconEdit: ComponentType<Record<string, unknown>>
  export const IconCaretDown: ComponentType<Record<string, unknown>>
  export const IconCaretUp: ComponentType<Record<string, unknown>>
  export const IconCheck: ComponentType<Record<string, unknown>>
  export const IconClear: ComponentType<Record<string, unknown>>
  export const IconClose: ComponentType<Record<string, unknown>>
  export const IconDelete: ComponentType<Record<string, unknown>>
  export const IconDownload: ComponentType<Record<string, unknown>>
  export const IconItalic: ComponentType<Record<string, unknown>>
  export const IconImage: ComponentType<Record<string, unknown>>
  export const IconLink: ComponentType<Record<string, unknown>>
  export const IconOptionsDots: ComponentType<Record<string, unknown>>
  export const IconOrderedList: ComponentType<Record<string, unknown>>
  export const IconUnderline: ComponentType<Record<string, unknown>>
  export const IconUnorderedList: ComponentType<Record<string, unknown>>
  export const IconUpload: ComponentType<Record<string, unknown>>
  export const IconWarning: ComponentType<Record<string, unknown>>
  export const Input: ComponentType<Record<string, unknown>>
  export const Modal: ComponentType<ModalProps>
  export const PageHeader: ComponentType<Record<string, unknown>>
  export const Pagination: ComponentType<Record<string, unknown>>
  export class Progress extends Component<ProgressProps> {}
  export const Radio: ComponentType<Record<string, unknown>>
  export const RadioGroup: ComponentType<Record<string, unknown>>
  export const Spinner: ComponentType<Record<string, unknown>>
  export class Textarea extends Component<TextareaProps> {}
  export const Tab: ComponentType<Record<string, unknown>>
  export const Table: ComponentType<Record<string, unknown>>
  export const Tabs: ComponentType<Record<string, unknown>>
  export const Tag: ComponentType<Record<string, unknown>>
  export class ToastConsumer extends Component<ToastConsumerProps> {}
  export class ToastProvider extends Component<ToastProviderProps> {}
  export const ToastContext: React.ContextType<ToastConsumerFunctions>
  export const Toggle: ComponentType<Record<string, unknown>>
  export const Tooltip: ComponentType<Record<string, unknown>>
}

```


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

[User] Show me the implementation of admin-pages/react/queries/TenantInfo.graphql from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```graphql
query TenantInfo {
  tenantInfo {
    bindings {
      canonicalBaseAddress
      id
      supportedLocales
      targetProduct
    }
  }
}

```


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

[User] Show me the implementation of admin-pages/react/queries/Languages.graphql from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```graphql
query Languages {
  languages {
    default
    supported
  }
}

```


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

[User] Show me the implementation of admin-pages/react/queries/RedirectWithoutBinding.graphql from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```graphql
query RedirectWithoutBinding($path: String!) {
  redirect @context(provider: "vtex.rewriter") {
    get(path: $path) {
      binding
      endDate
      from
      to
      type
    }
  }
}

```


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

[User] Show me the implementation of admin-pages/react/queries/Redirects.graphql from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```graphql
query Redirects($limit: Int, $next: String) {
  redirect @context(provider: "vtex.rewriter") {
    listRedirects(limit: $limit, next: $next) {
      routes {
        binding
        endDate
        from
        to
        type
        binding
      }
      next
    }
  }
}

```


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

[User] Show me the implementation of admin-pages/react/queries/Route.graphql from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```graphql
query Route($domain: String, $routeId: String!, $bindingId: String) {
  route(domain: $domain, routeId: $routeId, bindingId: $bindingId) {
    auth
    binding
    blockId
    context
    declarer
    domain
    interfaceId
    path
    routeId
    uuid
    metaTags {
      description
      keywords
      robots
    }
    pages {
      condition {
        allMatches
        id
        statements {
          subject
          verb
          objectJSON
        }
      }
      pageId
      template
    }
    title
  }
}

```


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

[User] Show me the implementation of admin-pages/react/queries/Routes.graphql from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```graphql
query Routes($domain: String, $bindingId: String) {
  routes(domain: $domain, bindingId: $bindingId) {
    auth
    blockId
    binding
    context
    declarer
    domain
    interfaceId
    path
    routeId
    uuid
    metaTags {
      description
      keywords
      robots
    }
    pages {
      condition {
        allMatches
        id
        statements {
          subject
          verb
          objectJSON
        }
      }
      pageId
      template
    }
    title
  }
}

```


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

[User] Show me the implementation of admin-pages/react/queries/SaveRedirect.graphql from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation saveRedirect(
  $endDate: String
  $from: String!
  $to: String!
  $type: RedirectTypes!
  $binding: String
) {
  redirect @context(provider: "vtex.rewriter") {
    save(route: { endDate: $endDate, from: $from, to: $to, type: $type, binding: $binding}) {
      endDate
      from
      to
      type
    }
  }
}

```


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

[User] Show me the implementation of admin-pages/react/queries/DeleteRedirect.graphql from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation DeleteRedirect($path: String!, $binding: String!) {
  redirect @context(provider: "vtex.rewriter") {
    delete(path: $path, locator: { from: $path, binding: $binding }) {
      endDate
      from
      to
      type
    }
  }
}

```


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

[User] Show me the implementation of admin-pages/react/queries/ExtensionConfigurations.graphql from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```graphql
query ExtensionConfigurations(
  $configurationsIds: [String]
  $routeId: String!
  $treePath: String!
  $url: String!
) {
  extensionConfigurations(
    configurationsIds: $configurationsIds
    routeId: $routeId
    treePath: $treePath
    url: $url
  ) {
    allMatches
    conditions
    configurationId
    device
    label
    propsJSON
    routeId
    scope
    url
  }
}

```


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

[User] Show me the implementation of admin-pages/react/queries/Redirect.graphql from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```graphql
query Redirect($path: String!, $binding: String!) {
  redirect @context(provider: "vtex.rewriter") {
    get(path: $path, locator: { from: $path, binding: $binding }) {
      binding
      endDate
      from
      to
      type
    }
  }
}

```


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

[User] Show me the implementation of admin-pages/react/queries/SaveRoute.graphql from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation SaveRoute($route: NewRouteInput) {
  saveRoute(route: $route) {
    auth
    blockId
    binding
    context
    declarer
    domain
    interfaceId
    path
    routeId
    uuid
    metaTags {
      description
      keywords
      robots
    }
    pages {
      condition {
        allMatches
        id
        statements {
          subject
          verb
          objectJSON
        }
      }
      pageId
      template
    }
    title
  }
}

```


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

[User] Show me the implementation of admin-pages/react/queries/DeleteRoute.graphql from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation DeleteRoute($uuid: String!) {
  deleteRoute(uuid: $uuid, dataSource: "vtex.rewriter")
}

```


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

[User] Show me the implementation of admin-pages/react/queries/ContentIOMessage.graphql from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```graphql
query ContentIOMessage($args: TranslateArgs!) {
  translate(args: $args)
}

```


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

[User] Show me the implementation of admin-pages/react/queries/MessagesForDomain.graphql from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetMessagesForDomain(
  $components: [String!]!
  $domain: String!
  $renderMajor: Int!
) {
  messages(
    components: $components
    domain: $domain
    renderMajor: $renderMajor
  ) {
    key
    message
  }
}

```


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

[User] Show me the implementation of admin-pages/react/queries/UploadFile.graphql from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation UploadFile($file: Upload!) {
  uploadFile(file: $file) {
    fileUrl
  }
}

```


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

[User] Show me the implementation of admin-pages/react/queries/AvailableTemplates.graphql from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```graphql
query AvailableTemplates($interfaceId: String) {
  availableTemplates(interfaceId: $interfaceId) {
    id
  }
}

```


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

[User] Show me the implementation of admin-pages/react/utils/AdminLoadingContext.tsx from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

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

const adminLoadingDefaultValue = {
  startLoading: () => {
    window.top.postMessage({ action: { type: 'START_LOADING' } }, '*')
  },
  stopLoading: () => {
    window.top.postMessage({ action: { type: 'STOP_LOADING' } }, '*')
  },
}

const AdminLoadingContext = React.createContext(adminLoadingDefaultValue)

const useAdminLoadingContext = () => useContext(AdminLoadingContext)

const AdminLoadingContextProvider: FunctionComponent = ({ children }) => (
  <AdminLoadingContext.Provider value={adminLoadingDefaultValue}>
    {children}
  </AdminLoadingContext.Provider>
)

export { AdminLoadingContextProvider, useAdminLoadingContext }

```


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

[User] Show me the implementation of admin-pages/react/components/Loader.tsx from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { FormattedMessage } from 'react-intl'

const Loader = () => (
  <FormattedMessage id="admin/pages.admin.loading">
    {text => (
      <span>
        {text}
        …
      </span>
    )}
  </FormattedMessage>
)

export default Loader

```


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

[User] Show me the implementation of admin-pages/react/components/EditorProvider.tsx from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```tsx
import ApolloClient from 'apollo-client'
import { difference, equals, path, pathOr, uniq } from 'ramda'
import React, { Component } from 'react'
import { withApollo } from 'react-apollo'
import { canUseDOM, withRuntimeContext } from 'vtex.render-runtime'
import { ToastProvider } from 'vtex.styleguide'
import {
  injectIntl,
  WrappedComponentProps as ComponentWithIntlProps,
} from 'react-intl'

import { State as HighlightOverlayState } from '../HighlightOverlay'
import {
  editorMessagesFromRuntime,
  getAvailableCultures,
  LabelledLocale,
} from './DomainMessages'
import EditorContainer, { APP_CONTENT_ELEMENT_ID } from './EditorContainer'
import { EditorContext } from './EditorContext'

type Props = RenderContextProps &
  ComponentWithIntlProps & {
    client: ApolloClient<unknown>
    isSiteEditor: boolean
    children?: React.ReactNode
  }

export interface State {
  activeConditions: string[]
  allMatches: boolean
  availableCultures: LabelledLocale[]
  blockData: BlockData
  editMode: boolean
  editTreePath: string | null
  iframeRuntime: RenderContext | null
  iframeWindow?: Window
  isLoading: boolean
  isSidebarVisible: boolean
  messages: RenderRuntime['messages']
  mode: EditorMode
  viewport: Viewport
}

const noop = () => {
  return undefined
}

const getUrlProperties = (href: string) => {
  const match = href.match(
    /^(https?:)\/\/(([^:/?#]*)(?::([0-9]+))?)([/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/
  )

  return (
    match && {
      hash: match[7],
      host: match[2],
      hostname: match[3],
      href,
      pathname: match[5],
      port: match[4],
      protocol: match[1],
      search: match[6],
    }
  )
}

class EditorProvider extends Component<Props, State> {
  private unlisten?: (() => void) | void

  public constructor(props: Props) {
    super(props)

    this.state = {
      activeConditions: [],
      allMatches: true,
      availableCultures: [],
      blockData: {},
      editMode: false,
      editTreePath: null,
      iframeRuntime: null,
      iframeWindow: window.self,
      isLoading: false,
      isSidebarVisible: true,
      messages: {},
      mode: 'content',
      viewport: 'desktop',
    }

    if (canUseDOM) {
      window.top.__provideRuntime = window.self.__provideRuntime = async (
        runtime,
        messages,
        shouldUpdateRuntime
      ) => {
        const { client, intl } = this.props
        const stateIframeRuntime = this.state.iframeRuntime

        let formattedEditorMessages = {}

        try {
          formattedEditorMessages = await editorMessagesFromRuntime({
            client,
            domain: 'admin',
            runtime,
          })
        } catch (e) {
          console.error(e)
        }

        const newMessages = {
          ...this.state.messages,
          ...messages,
          ...formattedEditorMessages,
        }

        this.updateRenderRuntimeMessage(newMessages)

        if (shouldUpdateRuntime) {
          await this.props.runtime.updateRuntime()
        }

        if (!this.state.iframeRuntime) {
          runtime.updateComponentAssets(this.props.runtime.components)
          this.props.runtime.updateComponentAssets({})
        }

        const availableCultures = await getAvailableCultures({ client, intl })

        const newState = {
          availableCultures,
          iframeRuntime: runtime,
          ...(stateIframeRuntime
            ? {}
            : {
                iframeWindow: (window.self.document.getElementById(
                  'store-iframe'
                ) as HTMLIFrameElement).contentWindow as Window,
              }),
          messages: newMessages,
        }

        await new Promise(resolve => {
          this.setState(newState, resolve)
        })

        if (
          stateIframeRuntime &&
          stateIframeRuntime.history &&
          !this.unlisten
        ) {
          this.unlisten = stateIframeRuntime.history.listen(
            (location, action) => {
              const pathFromCurrentPage = stateIframeRuntime.route.path
              const isRootPath =
                pathFromCurrentPage === '/' || location.pathname === '/'
              const hasParamsChanged =
                !location.state ||
                !equals(
                  location.state.navigationRoute.params,
                  stateIframeRuntime.route.params
                )

              const isDifferentPath = isRootPath
                ? pathFromCurrentPage !== location.pathname
                : !pathFromCurrentPage.startsWith(location.pathname) ||
                  hasParamsChanged // to consider canonicals

              const hasNavigated =
                ['PUSH', 'REPLACE', 'POP'].includes(action) && isDifferentPath

              if (hasNavigated) {
                this.handleSetIsLoading(true)
                this.editExtensionPoint(null)
              }
            }
          )
        }
      }
    }
  }

  public componentDidMount() {
    const {
      runtime: { production, emitter },
    } = this.props

    if (window.top) {
      window.top.postMessage({ action: { type: 'STOP_LOADING' } }, '*')
    }

    const appContentElement = document.getElementById(APP_CONTENT_ELEMENT_ID)
    emitter.addListener('localesChanged', this.emitLocaleEventToIframe)

    if (!production) {
      emitter.addListener('localesUpdated', this.emitLocaleEventToIframe)
    }

    // Forward scroll events to window so code doesn't have to hook into #app-content
    if (appContentElement) {
      appContentElement.addEventListener(
        'scroll',
        e => {
          setTimeout(() => window.self.dispatchEvent(e), 0)
        },
        { passive: true }
      )
    }
  }

  public componentWillUnmount() {
    const {
      runtime: { production, emitter },
    } = this.props

    emitter.removeListener('localesChanged', this.emitLocaleEventToIframe)

    if (!production) {
      emitter.removeListener('localesUpdated', this.emitLocaleEventToIframe)
    }

    if (this.unlisten) {
      this.unlisten()
    }
  }

  public emitLocaleEventToIframe = (event: string) => {
    const emitToIframe: RenderRuntime['emitter'] = pathOr({ emit: noop }, [
      'state',
      'iframeRuntime',
      'emitter',
    ])(this)
    emitToIframe.emit('localesChanged', event)
  }

  public editExtensionPoint = (treePath: string | null) => {
    const iframe = document.getElementById('store-iframe') || {}
    const setHighlightTreePath = path<
      (value: Partial<HighlightOverlayState>) => void
    >(['contentWindow', '__setHighlightTreePath'], iframe)
    if (setHighlightTreePath) {
      setHighlightTreePath({
        openBlockTreePath: treePath,
      })
    }

    this.setState({ editTreePath: treePath, editMode: false })
  }

  public handleToggleEditMode = () => {
    const editMode = !this.state.editMode

    this.setState({ editMode }, () => {
      if (window.top) {
        window.top.postMessage({ action: { type: 'STOP_LOADING' } }, '*')
      }
    })
  }

  public toggleSidebarVisibility = () => {
    this.setState(prevState => ({
      ...prevState,
      isSidebarVisible: !prevState.isSidebarVisible,
    }))
  }

  public handleAddCondition = (conditionId: string) => {
    this.setState(
      {
        activeConditions: uniq(this.state.activeConditions.concat(conditionId)),
      },
      () => {
        this.props.runtime.updateRuntime({
          conditions: this.state.activeConditions,
          device: this.props.runtime.device,
        })
      }
    )
  }

  public handleRemoveCondition = (conditionId: string) => {
    const activeConditions = difference(this.state.activeConditions, [
      conditionId,
    ])

    this.setState({ activeConditions }, () => {
      this.props.runtime.updateRuntime({
        conditions: this.state.activeConditions,
        device: this.props.runtime.device,
      })
    })
  }

  public handleSetDevice = (device: ConfigurationDevice) => {
    this.props.runtime.setDevice(device)

    this.handleSetViewport(device === 'any' ? 'desktop' : device)

    this.props.runtime.updateRuntime({
      conditions: this.state.activeConditions,
      device,
    })
  }

  public handleSetViewport = (viewport: Viewport) => {
    this.setState({ viewport })
  }

  public handleSetMode = (mode: EditorMode) => {
    this.setState({ mode, editMode: mode === 'content' ? false : true })
  }

  public handleChangeIframeUrl = (url: string) => {
    window.top.postMessage({ action: { type: 'START_LOADING' } }, '*')

    const convertedUrl = getUrlProperties(url)
    const storePath = convertedUrl
      ? `${convertedUrl.pathname}${convertedUrl.search ?? ''}`
      : url
    const pathname = /^\//.test(storePath) ? storePath : `/${storePath}`

    window.top.location.assign(`/admin/cms/site-editor${pathname}`)
  }

  public handleSetBlockData = (newBlockData: State['blockData']) => {
    this.setState(prevState => ({
      ...prevState,
      blockData: { ...prevState.blockData, ...newBlockData },
    }))
  }

  public render() {
    const { children, isSiteEditor } = this.props

    const {
      activeConditions,
      allMatches,
      availableCultures,
      blockData,
      editMode,
      editTreePath,
      iframeRuntime,
      iframeWindow,
      isSidebarVisible,
      messages,
      mode,
      viewport,
    } = this.state

    const editor: EditorContextType = {
      activeConditions,
      addCondition: this.handleAddCondition,
      allMatches,
      availableCultures,
      blockData,
      editExtensionPoint: this.editExtensionPoint,
      editMode,
      editTreePath,
      getIsLoading: this.getIsLoading,
      iframeWindow,
      isSidebarVisible,
      messages,
      mode,
      onChangeIframeUrl: this.handleChangeIframeUrl,
      removeCondition: this.handleRemoveCondition,
      setBlockData: this.handleSetBlockData,
      setDevice: this.handleSetDevice,
      setIsLoading: this.handleSetIsLoading,
      setMode: this.handleSetMode,
      setViewport: this.handleSetViewport,
      toggleEditMode: this.handleToggleEditMode,
      toggleSidebarVisibility: this.toggleSidebarVisibility,
      viewport,
    }

    return (
      <ToastProvider positioning="parent">
        <EditorContext.Provider value={editor}>
          <EditorContainer
            editor={editor}
            iframeRuntime={iframeRuntime}
            isSiteEditor={isSiteEditor}
          >
            {children}
          </EditorContainer>
        </EditorContext.Provider>
      </ToastProvider>
    )
  }

  private getIsLoading = () => this.state.isLoading

  private updateRenderRuntimeMessage = (messages: Record<string, string>) => {
    this.props.runtime.addMessages(messages)
  }

  private handleSetIsLoading = (isLoading: boolean) => {
    this.setState({ isLoading })
  }
}

const EditorWithApolloAndRuntime = withRuntimeContext(
  withApollo<Omit<React.ComponentProps<typeof EditorProvider>, 'client'>>(
    EditorProvider
  )
)

export default injectIntl(EditorWithApolloAndRuntime)

```


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

[User] Show me the implementation of admin-pages/react/components/EditorContext.tsx from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { createContext, useContext } from 'react'

export const initialEditorContextState: EditorContextType = {
  activeConditions: [],
  addCondition: () => {},
  allMatches: true,
  availableCultures: [],
  blockData: {},
  editExtensionPoint: () => {},
  editMode: false,
  editTreePath: null,
  getIsLoading: () => false,
  iframeWindow: window.self,
  isSidebarVisible: true,
  messages: {},
  mode: 'content',
  onChangeIframeUrl: () => {},
  setDevice: () => {},
  setIsLoading: () => {},
  setMode: () => {},
  setBlockData: () => {},
  setViewport: () => {},
  toggleEditMode: () => {},
  toggleSidebarVisibility: () => {},
  viewport: 'desktop',
}

export const EditorContext = createContext(initialEditorContextState)

EditorContext.displayName = 'EditorContext'

export const useEditorContext = () => useContext(EditorContext)

```


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

[User] Show me the implementation of admin-pages/react/components/Modal.tsx from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { Button, Modal as StyleguideModal } from 'vtex.styleguide'

interface Props {
  isActionDanger?: boolean
  isActionLoading: boolean
  isOpen: boolean
  onClickAction?: (event: Event) => void
  onClickCancel?: (event: Event) => void
  onClose: (event?: Event) => void
  textButtonAction: string
  textButtonCancel: string
  textMessage: string | React.ReactNode
  title?: string
}

const Modal = ({
  isActionDanger = false,
  isActionLoading,
  isOpen,
  onClickAction,
  onClickCancel,
  onClose,
  textButtonAction,
  textButtonCancel,
  textMessage,
  title,
}: Props) => (
  <StyleguideModal centered isOpen={isOpen} onClose={onClose} title={title}>
    <p className="mt6 lh-copy">{textMessage}</p>

    <div className="mt6 flex justify-end">
      <div className="mr3">
        <Button
          disabled={isActionLoading}
          onClick={onClickCancel}
          size="small"
          variation="tertiary"
        >
          {textButtonCancel}
        </Button>
      </div>

      <Button
        isLoading={isActionLoading}
        onClick={onClickAction}
        size="small"
        variation={isActionDanger ? 'danger' : 'primary'}
      >
        {textButtonAction}
      </Button>
    </div>
  </StyleguideModal>
)

export default Modal

```


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

[User] Show me the implementation of admin-pages/react/components/Select.tsx from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { Fragment } from 'react'
import { InjectedIntlProps, injectIntl } from 'react-intl'
import ReactSelect, { Option } from 'react-select'
import { IconCaretDown, IconCaretUp } from 'vtex.styleguide'

interface SelectProps {
  errorMessage?: string
  onChange: (options: string[]) => void
  options: Option[]
  value: string[]
}

type Props = SelectProps & InjectedIntlProps

const Select: React.FunctionComponent<Props> = ({
  errorMessage,
  onChange,
  options,
  intl,
  value,
}) => (
  <Fragment>
    <ReactSelect
      className={`f6 ${errorMessage ? 'b--danger bw1' : ''}`}
      arrowRenderer={(
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        { onMouseDown, isOpen }: any // ArrowRendererProps isn't defining isOpen.
      ) => (
        <div
          className="outline-0"
          onMouseDown={onMouseDown}
          role="listbox"
          tabIndex={0}
        >
          {isOpen ? (
            <IconCaretUp color="#134cd8" size={8} />
          ) : (
            <IconCaretDown color="#134cd8" size={8} />
          )}
        </div>
      )}
      multi
      onChange={optionValues => {
        const formattedValue = (optionValues as Option[]).map(
          (item: Option) => item.value as string
        )
        onChange(formattedValue)
      }}
      options={options}
      style={
        errorMessage
          ? {
              borderColor: '#ff4c4c',
              borderWidth: '.125rem',
            }
          : {}
      }
      placeholder={
        <span className="ml2">
          {intl.formatMessage({
            id: 'admin/pages.editor.components.conditions.custom.placeholder',
          })}
        </span>
      }
      value={value}
    />
    {!!errorMessage && (
      <span className="c-danger f6 mt3 lh-title">
        {intl.formatMessage({
          id: errorMessage,
        })}
      </span>
    )}
  </Fragment>
)

export default injectIntl(Select)

```


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

[User] Show me the implementation of admin-pages/react/components/SeoPreview.tsx from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```tsx
import * as React from 'react'
import { defineMessages, useIntl } from 'react-intl'

interface Props {
  title?: string | null
  description?: string | null
  url?: string | null
}

const messages = defineMessages({
  seoDescription: {
    defaultMessage: '<Page description>',
    id: 'admin/pages.admin.content.general.seo.description',
  },
  seoTitle: {
    defaultMessage: '<Page title>',
    id: 'admin/pages.admin.content.general.seo.page-title',
  },
})

const styles = {
  button: {
    borderRadius: '100%',
    display: 'inline-block',
    height: '10px',
    marginRight: '5px',
    width: '10px',
  },
  buttonClose: {
    backgroundColor: '#ff3d44',
  },
  buttonMaximize: {
    backgroundColor: '#ffa721',
  },
  buttonMinimize: {
    backgroundColor: '#7ed321',
  },
  description: {
    color: '#545454',
  },
  title: {
    color: '#1a0dab',
  },
  url: {
    color: '#006621',
  },
}

const SeoPreview = ({ title, description, url }: Props) => {
  const intl = useIntl()

  return (
    <div className="pl5 pt4 ba br2 bw1 b--muted-4 h-100 pb4">
      <div>
        <span style={{ ...styles.button, ...styles.buttonClose }} />
        <span style={{ ...styles.button, ...styles.buttonMaximize }} />
        <span style={{ ...styles.button, ...styles.buttonMinimize }} />
      </div>
      <div className="pt5">
        <span
          className={`db f4 pb1 word-break ${!title && 'o-30'}`}
          style={styles.title}
        >
          {title || intl.formatMessage(messages.seoTitle)}
        </span>
        <span
          className={`db f6 pb1 word-break ${!url && 'o-30'}`}
          style={styles.url}
        >
          {`${window.location.origin}${url || '/<url>'}`}
        </span>
        <span
          className={`db pt2 f6 fw3 word-break ${!description && 'o-30'}`}
          style={styles.description}
        >
          {description || intl.formatMessage(messages.seoDescription)}
        </span>
      </div>
    </div>
  )
}

export default SeoPreview

```


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

[User] Show me the implementation of admin-pages/react/utils/blocks/typings.d.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```typescript
export type BlockRole = 'after' | 'around' | 'before'

export type BlockRolesForTree = BlockRole | 'blocks'

export interface RelativeBlocks {
  [role: string]: string[] | undefined
}

```


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

[User] Show me the implementation of admin-pages/react/utils/blocks/index.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { BlockRole, BlockRolesForTree, RelativeBlocks } from './typings'

export const getBlockRole = (treePathTail: string): BlockRolesForTree => {
  const blockRoleMatch = treePathTail.match(/\$(after|around|before)_/)

  if (!blockRoleMatch) {
    return 'blocks'
  }

  return blockRoleMatch[1] as BlockRolesForTree
}

export const getBlockPath = (
  extensions: RenderContext['extensions'],
  treePath: string | null
): BlockPath => {
  if (!treePath) {
    return []
  }

  const splitTreePath = treePath.split('/')

  const blockId = extensions[treePath].blockId
  const blockRole = getBlockRole(splitTreePath[splitTreePath.length - 1])

  if (!blockId) {
    return []
  }

  const parentTreePath = splitTreePath
    .slice(0, splitTreePath.length - 1)
    .join('/')

  const formattedBlock: FormattedBlock = {
    id: blockId,
    role: blockRole
      ? (blockRole.toUpperCase() as FormattedBlock['role'])
      : 'BLOCK',
  }

  if (parentTreePath.length === 0) {
    const formattedTemplateBlock: FormattedBlock = {
      ...formattedBlock,
      role: 'TEMPLATE',
    }

    return [formattedTemplateBlock]
  }

  const parentBlockPath = getBlockPath(extensions, parentTreePath)

  if (!parentBlockPath) {
    return []
  }

  return [...parentBlockPath, formattedBlock]
}

export const getParentBlockId = (
  extensions: RenderContext['extensions'],
  splitTreePath: string[]
) => {
  const treePathTail = splitTreePath[splitTreePath.length - 1]

  const maybeBlockInfo = treePathTail.match(/\$(after|around|before)_(\d+)/)

  if (!maybeBlockInfo) {
    return null
  }

  const blockRole = maybeBlockInfo[1] as BlockRole
  const blockIndex = parseInt(maybeBlockInfo[2], 10)

  const parentTreePath = splitTreePath
    .slice(0, splitTreePath.length - 1)
    .join('/')

  const parentBlock = extensions[parentTreePath]

  const parentBlockRoleArray = parentBlock && parentBlock[blockRole]

  const blockId = parentBlockRoleArray && parentBlockRoleArray[blockIndex]

  return blockId
}

export const getRelativeBlocksIds = (
  treePath: string | null,
  extensions: RenderContext['extensions'],
  targetObj: RelativeBlocks
) => {
  if (!treePath) {
    return {}
  }

  return Object.entries(targetObj).reduce<RelativeBlocks>(
    (acc, [currKey, currValue]) =>
      currValue
        ? {
            ...acc,
            [currKey]: currValue.map(
              block => extensions[`${treePath}/${block}`].blockId as string
            ),
          }
        : acc,
    {}
  )
}

export const getSitewideTreePath = (treePath: string) =>
  ['*', ...treePath.split('/').slice(1)].join('/')

```


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

[User] Show me the implementation of admin-pages/react/utils/date/index.test.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { getNextDay, getNextTime, getPreviousTime } from './index'

describe('getNextDay', () => {
  it('returns the day after a given day', () => {
    const input = new Date('2019-04-01T12:07:21.000')

    const expectedOutput = new Date('2019-04-02T00:00:00.000')

    expect(getNextDay(input)).toEqual(expectedOutput)
  })
})

describe('getNextTime', () => {
  it('works with minutes = 0', () => {
    const input = new Date('2019-04-01T12:00:00.000')

    const expectedOutput = new Date('2019-04-01T12:30:00.000')

    expect(getNextTime(input)).toEqual(expectedOutput)
  })

  it('works with 0 < minutes < 30', () => {
    const input = new Date('2019-04-01T12:23:16.000')

    const expectedOutput = new Date('2019-04-01T12:30:00.000')

    expect(getNextTime(input)).toEqual(expectedOutput)
  })

  it('works with minutes = 30', () => {
    const input = new Date('2019-04-01T15:30:00.000')

    const expectedOutput = new Date('2019-04-01T16:00:00.000')

    expect(getNextTime(input)).toEqual(expectedOutput)
  })

  it('works with 30 < minutes <= 59', () => {
    const input = new Date('2019-04-01T12:43:51.000')

    const expectedOutput = new Date('2019-04-01T13:00:00.000')

    expect(getNextTime(input)).toEqual(expectedOutput)
  })

  it('works with time > 23:30', () => {
    const input = new Date('2019-04-01T23:45:34.000')

    const expectedOutput = new Date('2019-04-02T00:00:00.000')

    expect(getNextTime(input)).toEqual(expectedOutput)
  })
})

describe('getPreviousTime', () => {
  it('works with minutes = 0', () => {
    const input = new Date('2019-04-01T12:00:00.000')

    const expectedOutput = new Date('2019-04-01T11:30:00.000')

    expect(getPreviousTime(input)).toEqual(expectedOutput)
  })

  it('works with 0 < minutes < 30', () => {
    const input = new Date('2019-04-01T12:23:16.000')

    const expectedOutput = new Date('2019-04-01T12:00:00.000')

    expect(getPreviousTime(input)).toEqual(expectedOutput)
  })

  it('works with minutes = 30', () => {
    const input = new Date('2019-04-01T15:30:00.000')

    const expectedOutput = new Date('2019-04-01T15:00:00.000')

    expect(getPreviousTime(input)).toEqual(expectedOutput)
  })

  it('works with 30 < minutes <= 59', () => {
    const input = new Date('2019-04-01T12:43:51.000')

    const expectedOutput = new Date('2019-04-01T12:30:00.000')

    expect(getPreviousTime(input)).toEqual(expectedOutput)
  })

  it('works with time = 00:00', () => {
    const input = new Date('2019-04-01T00:00:00.000')

    const expectedOutput = new Date('2019-03-31T23:30:00.000')

    expect(getPreviousTime(input)).toEqual(expectedOutput)
  })
})

```


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

[User] Show me the implementation of admin-pages/react/utils/date/index.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```typescript
import moment from 'moment'

export const getFirstTime = (date: Date) =>
  moment(date)
    .startOf('day')
    .toDate()

export const getFormattedLocalizedDate = (date: string, locale: string) =>
  moment(date)
    .locale(locale)
    .format("lll")

export const getLastTime = (date: Date) => {
  const dateClone = new Date(date)

  dateClone.setHours(23, 30, 0, 0)

  return dateClone
}

export const getNextDay = (date: Date) => {
  const dateClone = new Date(date)

  dateClone.setDate(date.getDate() + 1)
  dateClone.setHours(0, 0, 0, 0)

  return dateClone
}

export const getNextTime = (date: Date) => {
  const dateClone = new Date(date)

  const hours = dateClone.getHours()
  const minutes = dateClone.getMinutes()

  if (minutes >= 0 && minutes < 30) {
    dateClone.setHours(hours, 30, 0, 0)
  } else {
    dateClone.setHours(hours, 0, 0, 0)

    dateClone.setTime(dateClone.getTime() + 60 * 60 * 1000)
  }

  return dateClone
}

export const getPreviousTime = (date: Date) => {
  const dateClone = new Date(date)

  const hours = dateClone.getHours()
  const minutes = dateClone.getMinutes()

  if (minutes > 0 && minutes <= 30) {
    dateClone.setHours(hours, 0, 0, 0)
  } else {
    dateClone.setHours(hours, 30, 0, 0)

    if (minutes === 0) {
      dateClone.setTime(dateClone.getTime() - 60 * 60 * 1000)
    }
  }

  return dateClone
}

export const isLastTime = (time: Date) =>
  time.getHours() === 23 && time.getMinutes() >= 30

export const isSameDay = (dateA?: Date, dateB?: Date) => {
  if (!dateA || !dateB) {
    return false
  }

  return moment(dateA).isSame(dateB, 'day')
}

```


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

[User] Show me the implementation of admin-pages/react/utils/auditEvents/index.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { v4 as uuidv4 } from 'uuid'

export const createEventObject = (
  operation: string,
  entityName: string,
  account: string,
  workspace: string,
  subjectId?: any
) => {
  const event = {
    id: uuidv4(),
    date: new Date().toISOString(),
    mainAccountName: account,
    accountName: account,
    subjectId: subjectId ? subjectId : '',
    application: 'site-editor',
    workspace: workspace,
    operation,
    meta: {
      entityName,
      entityBeforeAction: '',
      entityAfterAction: '',
      remoteIpAddress: '0.0.0.0',
      forwardFromVtexUserAgent: 'cms',
    },
  }

  return event
}

```


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

[User] Show me the implementation of admin-pages/react/utils/components/typings.d.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { JSONSchema6 } from 'json-schema'
import { RenderComponent } from 'vtex.render-runtime'

export type PropsOrContent = Extension['content'] | Extension['props']

export interface GetActiveContentIdParams {
  extensions: RenderContext['extensions']
  treePath: EditorContextType['editTreePath']
}

export interface GetComponentSchemaParams {
  component: RenderComponent | null
  contentSchema?: JSONSchema6
  propsOrContent: PropsOrContent
  runtime: RenderContext
  isContent: boolean
}

export interface GetSchemaPropsOrContentParams {
  messages?: RenderContext['messages']
  schema?: JSONSchema6Definition
  propsOrContent?: Record<string, unknown>
}

export interface GetSchemaPropsOrContentFromRuntimeParams {
  component: RenderComponent | null
  contentSchema?: JSONSchema6
  isContent?: boolean
  messages?: RenderContext['messages']
  propsOrContent: PropsOrContent
  runtime: RenderContext
}

export interface TranslateMessageParams {
  dictionary: Record<string, string>
  id?: string
}

export interface UpdateExtensionFromFormParams {
  data: object
  isContent?: boolean
  runtime: RenderContext
  treePath: 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 admin-pages/react/utils/components/index.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { assocPath, merge, mergeDeepRight, reduce, toPairs } from 'ramda'
import Ajv from 'vtex.ajv'
import { global, Window } from 'vtex.render-runtime'

import {
  GetActiveContentIdParams,
  GetComponentSchemaParams,
  GetSchemaPropsOrContentFromRuntimeParams,
  GetSchemaPropsOrContentParams,
  PropsOrContent,
  TranslateMessageParams,
  UpdateExtensionFromFormParams,
} from './typings'

export const IOMESSAGE_FORMAT_TYPE = 'IOMessage'
export const RICHTEXT_FORMAT_TYPE = 'RichText'
export const IO_MESSAGE_FORMATS = [IOMESSAGE_FORMAT_TYPE, RICHTEXT_FORMAT_TYPE]

const INVISIBLE_CHARACTER = '\u200b'
const INVISIBLE_CHARACTERS_REGEX = new RegExp(INVISIBLE_CHARACTER, 'g')

const reduceProperties = (isContent: boolean) => (
  acc: ComponentSchemaProperties,
  [propertyName, property]: [string, ComponentSchema]
) => {
  if (property.type === 'object') {
    property.properties = reduce(
      reduceProperties(isContent),
      {},
      toPairs(property.properties)
    )
  }
  if (Boolean(property.isLayout) !== isContent) {
    acc[propertyName] = property
  }

  return acc
}

const hideLayoutOrContentFromSchema = (
  schema: ComponentSchema | ComponentSchema[],
  isContent: boolean
) => {
  if (Array.isArray(schema) || Boolean(schema.isLayout) === isContent) {
    return {}
  }

  if (schema.type === 'object' && schema.properties) {
    const newSchema = {
      ...schema,
      properties: reduce(
        reduceProperties(isContent),
        {},
        toPairs(schema.properties)
      ),
    }
    return newSchema
  }

  return schema
}

const setArraySchemaDefaultsDeep: (
  schema: ComponentSchema | ComponentSchema['items']
) => ComponentSchema | ComponentSchema[] = schema => {
  if (!schema || Array.isArray(schema) || schema.type !== 'array') {
    return typeof schema === 'undefined' ? {} : schema
  }

  schema.items = setArraySchemaDefaultsDeep(schema.items)

  if (!schema.minItems || schema.minItems < 1) {
    schema.minItems = 1
  }

  if (schema.items && !Array.isArray(schema.items)) {
    schema.items.properties = {
      __editorItemTitle: {
        default: schema.items.title,
        title: 'Item title',
        type: 'string',
      },
      ...schema.items.properties,
    }
  }

  return schema
}

export const getComponentSchema = ({
  component,
  contentSchema,
  isContent,
  propsOrContent,
  runtime,
}: GetComponentSchemaParams): ComponentSchema => {
  const componentSchema: ComponentSchema = (component &&
    (component.schema ||
      (component.getSchema &&
        component.getSchema(propsOrContent, { routes: runtime.pages })))) || {
    properties: {},
    type: 'object',
  }

  const adaptedComponentSchema = hideLayoutOrContentFromSchema(
    setArraySchemaDefaultsDeep(componentSchema),
    isContent
  )

  if (!contentSchema) {
    return adaptedComponentSchema
  }

  return mergeDeepRight(adaptedComponentSchema, contentSchema) as any
}

export const getExtension = (
  editTreePath: EditorContextType['editTreePath'],
  extensions: RenderContext['extensions']
): Required<Extension> => {
  const {
    after = [],
    around = [],
    before = [],
    blockId = '',
    blocks = [],
    component = null,
    composition = 'blocks',
    configurationsIds = [],
    content = {},
    contentIds = [],
    contentMapId = '',
    hasContentSchema = false,
    implementationIndex = 0,
    implements: extensionImplements = [],
    preview = null,
    props = {},
    render = 'server',
    shouldRender = false,
    track = [],
    title = '',
  } = (editTreePath && extensions[editTreePath]) || {}

  return {
    after,
    around,
    before,
    blockId,
    blocks,
    component,
    composition,
    configurationsIds,
    content,
    contentIds,
    contentMapId,
    hasContentSchema,
    implementationIndex,
    implements: extensionImplements,
    preview,
    props: props || {},
    render,
    shouldRender,
    track,
    title,
  }
}

export const getIframeRenderComponents = () => {
  const iframe = document.getElementById('store-iframe') as HTMLIFrameElement
  if (!iframe) {
    return null
  }
  const window = iframe.contentWindow as Window | null
  if (!window) {
    return null
  }
  return window.__RENDER_8_COMPONENTS__
}

export const getIframeImplementation = (component: string | null) => {
  if (component === null) {
    return null
  }

  const iframeRenderComponents = getIframeRenderComponents()

  return iframeRenderComponents && iframeRenderComponents[component]
}

const translateMessage = ({
  dictionary,
  id,
}: TranslateMessageParams): string => {
  if (!id) {
    return ''
  }

  const translatedMessage = dictionary[id]

  if (translatedMessage) {
    return translatedMessage
  }

  if (translatedMessage === '') {
    return ''
  }

  return id
}

export const updateExtensionFromForm = ({
  data,
  isContent = false,
  runtime,
  treePath,
}: UpdateExtensionFromFormParams) => {
  if (!treePath) {
    return
  }

  return runtime.updateExtension(treePath, {
    ...runtime.extensions[treePath],
    [isContent ? 'content' : 'props']: data,
  })
}

const getIOMessageAjv = () => {
  const opts = {
    allErrors: true,
    nullable: true,
    shouldStoreValidSchema: true,
    useDefaults: true,
  }

  const ajv = new Ajv(opts)
  const validationFunction = (value: string) => {
    return value.length >= 0
  }

  IO_MESSAGE_FORMATS.forEach(format => {
    ajv.addFormat(format, {
      type: 'string',
      validate: validationFunction,
    })
  })

  return ajv
}

const emptyFields: Record<string, unknown> = {
  any: {},
  array: [],
  boolean: false,
  integer: null,
  number: null,
  object: {},
  string: '',
}

const getSchemaEmptyObj = (schema: ComponentSchema, prop: string) => {
  const type =
    schema &&
    schema.properties &&
    schema.properties[prop] &&
    schema.properties[prop].type
  return type ? emptyFields[type] : null
}

const keepTheBlanks = (
  validData: object,
  formData: Record<string, unknown> | undefined,
  schema: Record<string, ComponentSchema>
): Record<string, unknown> => {
  if (!formData) {
    return validData as Record<string, unknown>
  }

  return merge(
    validData,
    toPairs(formData).reduce((acc, [prop, value]) => {
      if (!(prop in validData)) {
        return {
          ...acc,
          [prop]: value == null ? getSchemaEmptyObj(schema, prop) : value,
        }
      }
      return acc
    }, {})
  )
}

export const appendInvisibleCharacter = (text: string) =>
  text + INVISIBLE_CHARACTER

const removeInvisibleCharacters = (text: string) =>
  text.replace(INVISIBLE_CHARACTERS_REGEX, '')

export const getImplementation = (component: string) => {
  return global.__RENDER_8_COMPONENTS__[component]
}

export const getSchemaPropsOrContent = ({
  messages,
  schema,
  propsOrContent,
}: GetSchemaPropsOrContentParams): PropsOrContent => {
  const validate = getIOMessageAjv().compile(schema)
  validate(propsOrContent)

  if (!validate.validatedData) {
    return {}
  }

  const dataFromSchema = validate.validatedData.reduce(
    (acc, { value, format, dataPath, isLayout }) => {
      if (isLayout) {
        return acc
      }

      if (IO_MESSAGE_FORMATS.includes(format)) {
        let adaptedValue

        if (messages) {
          adaptedValue = translateMessage({
            dictionary: messages,
            id: value,
          })
        } else {
          // Removes invisible characters from i18n fields. For more
          // information, please check the I18nInput widget.
          adaptedValue = removeInvisibleCharacters(value)
        }

        return { ...acc, ...assocPath(dataPath, adaptedValue, acc) }
      }

      return { ...acc, ...assocPath(dataPath, value, acc) }
    },
    {}
  )

  return keepTheBlanks(dataFromSchema, propsOrContent, schema)
}

export const getSchemaPropsOrContentFromRuntime = ({
  component,
  contentSchema,
  isContent = false,
  messages,
  propsOrContent,
  runtime,
}: GetSchemaPropsOrContentFromRuntimeParams) => {
  if (!component) {
    return null
  }

  const componentSchema = getComponentSchema({
    component,
    contentSchema,
    isContent,
    propsOrContent,
    runtime,
  })

  return getSchemaPropsOrContent({
    messages,
    propsOrContent,
    schema: componentSchema,
  })
}

export const getActiveContentId = ({
  extensions,
  treePath,
}: GetActiveContentIdParams) => {
  const extension = getExtension(treePath, extensions)

  return extension.contentIds[extension.contentIds.length - 1] || ''
}

```


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

[User] Show me the implementation of admin-pages/react/utils/conditions/typings.d.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```typescript
export interface DateInfo {
  date?: Date
  from?: Date
  to?: Date
}

export type DateVerbOptions = 'between' | 'from' | 'is' | 'to'

```


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

[User] Show me the implementation of admin-pages/react/utils/conditions/index.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ConditionsStatement } from 'vtex.styleguide'

import { DateInfo, DateVerbOptions } from './typings'

const formatDateInfo = (dateInfo: DateInfo, verb: DateVerbOptions) =>
  ({
    between: {
      from: dateInfo.from,
      to: dateInfo.to,
    },
    from: {
      from: dateInfo.date,
    },
    is: {
      from: dateInfo.date,
    },
    to: {
      to: dateInfo.date,
    },
  }[verb])

export const formatStatements = (statements: ConditionsStatement[]) =>
  statements.map(({ object, subject, verb }) => ({
    objectJSON: JSON.stringify(
      formatDateInfo(object as DateInfo, verb as DateVerbOptions)
    ),
    subject: subject as ConditionSubject,
    verb,
  }))

```


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

[User] Show me the implementation of admin-pages/react/utils/bindings/typings.d.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```typescript
export interface DropdownChangeInput {
  target: {
    value: 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 admin-pages/react/utils/bindings/index.ts from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```typescript
import React, { useMemo } from 'react'
import { Binding, Tenant } from 'vtex.tenant-graphql'

const STORE_PRODUCT = 'vtex-storefront'
const LAST_BINDING_KEY = 'vtex.cms-pages.lastBinding'

export const getStoreBindings = (tenant: Tenant) => {
  return tenant.bindings.filter(
    binding => binding.targetProduct === STORE_PRODUCT
  )
}

export const getBindingSelectorOptions = (bindings: Binding[]) =>
  bindings.map(binding => ({
    label: binding.canonicalBaseAddress,
    value: binding.id,
  }))

export const useBinding = (): [
  Binding | undefined,
  React.Dispatch<Binding | undefined>
] => {
  const [binding, setBinding] = React.useState<Binding | undefined>(() => {
    const lastBinding = window.localStorage.getItem(LAST_BINDING_KEY)
    return lastBinding ? (JSON.parse(lastBinding) as Binding) : undefined
  })

  return [
    binding,
    useMemo(() => {
      return (value: Binding | undefined) => {
        if (value) {
          window.localStorage.setItem(LAST_BINDING_KEY, JSON.stringify(value))
        } else {
          window.localStorage.removeItem(LAST_BINDING_KEY)
        }
        setBinding(value)
      }
    }, [setBinding]),
  ]
}

```


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

[User] Show me the implementation of admin-pages/react/components/form/ErrorListTemplate.tsx from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```tsx
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { createPortal } from 'react-dom'
import { AjvError, ErrorListProps } from 'react-jsonschema-form'
import { Alert } from 'vtex.styleguide'

interface State {
  isVisible: boolean
}

class ErrorListTemplate extends Component<ErrorListProps, State> {
  public static defaultProps = {
    errors: [],
  }

  public static propTypes = {
    errors: PropTypes.arrayOf(PropTypes.object),
  }

  public constructor(props: ErrorListProps) {
    super(props)

    this.state = {
      isVisible: true,
    }
  }

  public componentDidUpdate(prevProps: ErrorListProps) {
    const { errors: prevErrors } = prevProps
    const { errors: currErrors } = this.props
    const { isVisible } = this.state

    const haveErrorsChanged =
      currErrors.length !== prevErrors.length ||
      (currErrors.length > 0 &&
        currErrors.reduce<boolean>(
          (acc, error, index) => error.stack !== prevErrors[index].stack || acc,
          false
        ))

    if (!isVisible && haveErrorsChanged) {
      this.setState({ isVisible: true })
    }
  }

  public render() {
    const { errors } = this.props
    const { isVisible } = this.state

    const container = document.getElementById(
      'form__error-list-template___alert'
    )

    return (
      container &&
      createPortal(
        errors.length > 0 && isVisible && (
          <div className="w-100 z-max">
            <Alert onClose={this.handleHide} type="error">
              {errors.length > 1
                ? `There are ${errors.length} invalid inputs.`
                : this.getErrorMessage(errors[0])}
            </Alert>
          </div>
        ),
        container
      )
    )
  }

  private getErrorMessage(error: AjvError) {
    const { message, property } = error

    return `${this.getFormattedFieldName(property)} ${message}`
  }

  private getFormattedFieldName(fieldName: string) {
    return (
      fieldName.charAt(1).toUpperCase() +
      fieldName.slice(2).replace(/([a-z])([A-Z])/g, '$1 $2')
    )
  }

  private handleHide = () => {
    this.setState({ isVisible: false })
  }
}

const StatelessErrorListTemplate: React.FunctionComponent<
  ErrorListProps
> = props => <ErrorListTemplate {...props} />

export default StatelessErrorListTemplate

```


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

[User] Show me the implementation of admin-pages/react/components/form/Radio.tsx from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { JSONSchema6Type } from 'json-schema'
import React, { Component, Fragment } from 'react'
import {
  injectIntl,
  WrappedComponentProps as ComponentWithIntlProps,
} from 'react-intl'
import { WidgetProps } from 'react-jsonschema-form'
import { formatIOMessage } from 'vtex.native-types'
import { Radio as StyleguideRadio } from 'vtex.styleguide'

interface Props extends ComponentWithIntlProps {
  label?: string
  name?: string
  schema: {
    enumNames?: string[]
  }
}

interface State {
  value?: JSONSchema6Type
}

type RadioProps = Props & WidgetProps

class Radio extends Component<RadioProps, State> {
  public constructor(props: RadioProps) {
    super(props)

    this.state = {
      value: props.value,
    }
  }

  public render() {
    const { id, intl, label, name, schema } = this.props

    return (
      <Fragment>
        <span className="dib mb3 w-100">
          {formatIOMessage({ id: label, intl })}
        </span>
        {schema.enum &&
          schema.enum.map((item, index) => (
            <StyleguideRadio
              checked={this.props.value === item}
              id={`${id}-${index}`}
              key={`${id}-${index}`}
              label={this.getLabel(item, index)}
              name={name || `${id}-group`}
              onChange={(event: React.ChangeEvent) =>
                this.handleSelection(event, item)
              }
              value={item}
            />
          ))}
      </Fragment>
    )
  }

  private getLabel = (item: JSONSchema6Type, index: number) => {
    const {
      intl,
      schema: { enumNames },
    } = this.props

    return enumNames && enumNames.length >= index
      ? formatIOMessage({ id: enumNames[index], intl })
      : item && item.toString()
  }

  private handleSelection = (
    event: React.ChangeEvent,
    value: JSONSchema6Type
  ) => {
    event.stopPropagation()

    this.setState({ value })

    this.props.onChange(value)
  }
}

export default injectIntl(Radio)

```


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

[User] Show me the implementation of admin-pages/react/components/form/FieldTemplate.tsx from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { JSONSchema6 } from 'json-schema'
import React from 'react'
import { FieldTemplateProps } from 'react-jsonschema-form'

interface Props {
  children?: React.ReactNode
  classNames: string
  hidden?: boolean
  schema: JSONSchema6
}

const FieldTemplate: React.FunctionComponent<Props & FieldTemplateProps> = ({
  children,
  classNames,
  hidden,
  schema,
}) => {
  const isHidden =
    hidden || (schema.type !== 'object' && (schema as ComponentSchema).isLayout)

  if (isHidden) {
    return null
  }

  return <div className={`${classNames} w-100`}>{children}</div>
}

FieldTemplate.defaultProps = {
  classNames: '',
  hidden: false,
}

export default FieldTemplate

```


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

[User] Show me the implementation of admin-pages/react/components/form/ObjectFieldTemplate.tsx from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { Fragment } from 'react'
import { ObjectFieldTemplateProps } from 'react-jsonschema-form'

const hasFieldToBeDisplayed = (field: ComponentSchema): boolean => {
  if (field.type !== 'object') {
    return !field.isLayout
  }

  return Object.values(field.properties || {}).reduce<boolean>(
    (acc, currValue) => acc || hasFieldToBeDisplayed(currValue),
    false
  )
}

const ObjectFieldTemplate: React.FunctionComponent<
  ObjectFieldTemplateProps
> = ({ properties, schema }) =>
  hasFieldToBeDisplayed(schema as ComponentSchema) ? (
    <Fragment>{properties.map(property => property.content)}</Fragment>
  ) : null

ObjectFieldTemplate.defaultProps = {
  properties: [],
}

export default ObjectFieldTemplate

```


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

[User] Show me the implementation of admin-pages/react/components/form/RichText.tsx from the admin-pages VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'

import I18nInput from './I18nInput'
import { CustomWidgetProps } from './typings'

const RichText: React.FunctionComponent<CustomWidgetProps> = props => (
  <I18nInput {...props} isTextarea />
)

export default RichText

```