# Visualizer UI Documentation

## Get Started

    <html>
      <head>
        <link href="https://visualizer.byondxr.com/releases/visualizer-ui/3.0.112/index.css" rel="stylesheet" />
      </head>
      <body>
        <div
          class="visualizer"
          data-role="visualizer"
          experienceId="<your experience id, optional if using hashExperienceId>"
          hashExperienceId="<your hashed experience id, optional if using experienceId>"
          sceneConfigurationLabel="<optional, the maximum width image size to use on mobile, a number from 0 to 2048>"
          sceneId="<optional, will lunch a scene by scene id>"
          defaultProduct="<optional, product sku, will display the product on all available supported application>"
          defaultProducts="<optional, a stringified key vale pair, key: application, value: product sku, will present those as defaults >"
        ></div>
        <script>
          const containerElement = document.querySelector('[data-role="visualizer"]')
          containerElement.addEventListener('visualizerLoaded', (event) => {
            const visualizer = event.detail.visualizer
          })
        </script>
        <script src="https://visualizer.byondxr.com/releases/visualizer-ui/3.0.112/index.js"></script>
      </body>
    </html>

## Customization, Theming Supported & css variables

It can be given as a configuration linked to the experienceId Otherwise as a HTML and CSS as in the examples bellow..

To override a css rules add a css file like in the example https://visualizer.byondxr.com/releases/visualizer-ui/3.0.112/examples/globalVariables.css

### Changing constant titles labels and icons

pass a stringified object as an attribute into the base div element

#### example

    <body>
      <div
        class="visualizer"
        data-role="visualizer"
        experienceId="<your experience id here>"
        constants='{"menu":{"hotspots":{"label":"Hotspots"}}}'
      ></div>
    </body>

#### a full Documentation of custom labels titles and icons can be found under the Constants section

https://visualizer.byondxr.com/releases/visualizer-ui/3.0.112/doc/modules/src_app_iconstants.html"

#### an example for a constant object can be found at

https://visualizer.byondxr.com/releases/visualizer-ui/3.0.112/examples/Constants.json"

### Client API

It is accessed through an object that is attached to the visualizer container:

    const container = document.querySelector('[data-role="visualizer"]')
    container.visualizerUI.showAddToCart('sku')

Documentation of the methods available on that object: https://visualizer.byondxr.com/releases/visualizer-ui/3.0.112/doc/modules/src_app_clientapitypes.html

## Launcher

Documentation: https://visualizer.byondxr.com/releases/visualizer-ui/3.0.112/doc/modules/generated_doc_launchertypes.html

    export type IFavoriteScene = {
        id: string;
        image: string;
        favorites: IFavorite[];
        scene: IScene;
    };
    export type IFavoriteSceneList = IFavoriteScene[];

    export type IProduct = {
        sku: string;
        name?: string;
        title: string;
        description?: string;
        application: string;
        image: string;
        price?: string;
        facets?: IFacet[];
        badges?: string[];
        applications?: string[];
        _id: string;
    };
    export type IFavorite = {
        product: IProduct;
    };
    export type IFavoriteProductList = IFavorite[];

    export type IProductSkuAndApplication = {
        sku: string;
        application: string;
    };
    export type IFavoriteProductSkuAndApplication = {
        product: IProductSkuAndApplication;
    };
    export type IFavoriteProductSkuAndApplicationList = IFavoriteProductSkuAndApplication[];

    type TLaunchParam = {
        selector?: string
        sceneId?: string
        defaultApplication?: string
        defaultProduct?: string | number
        scene_configuration?: string
        experienceId?: string
        hashExperienceId?: string
        maxProductMapSize?: string | number
        maxProductMapSizeMobile?: string | number
        maxMapSize?: string | number
        maxMapSizeMobile?: string | number
        defaultProducts?: { [index: string]: string | number }
        productsList?: (string | number)[]
        favoriteScenes?: IFavoriteSceneList
        favoriteProducts?:  IFavoriteProductList | IFavoriteProductSkuAndApplicationList
    }

    type TVisualizerContainer: Element

    window.launchVisualizer(params: TLaunchParams): Promise<TVisualizerContainer>

### Launcher example

            <button
                onClick={() => {
                    window.launchVisualizer({
                        experienceId: 'G2GcP2',
                        defaultProducts: { Countertop: '1200302000' },
                        defaultProduct: '1200302000',
                        productsList: ['1200302000', '334442000']
                        sceneId: '6',
                        scene_configuration: 'US-EN',
                    }).then((visualizerContainer)=>{
                        // Here the visualizer is loaded and you can do with it whatever you need such as:
                        visualizerContainer.visualizerUI.showAddToCart('sku')
                        visualizerContainer.visualizer.setFavoriteProducts([ {product: {application: 'Backsplash', sku: '1040502005'}} ])
                    })
                }}
            >
                Launch
            </button>

## Favorites

        /** set favorite scenes */
        abstract setFavoriteScenes(favoriteScenes: IFavoriteSceneList);

        /** set favorite products */
        abstract setFavoriteProducts(favoriteProducts: IFavoriteProductList | IFavoriteProductShortList);

Code example:

    // subscribe to events that save favorites to localstorage
    let subscribe = (container) => {
      const saveProducts = (param) => {
        localStorage.setItem('favoriteProducts', JSON.stringify(param.favorites))
      }
      const saveScenes = (param) => {
        localStorage.setItem('favoriteScenes', JSON.stringify(param.favoriteScenes))
      }
      container.Visualizer.addListener('productAddedToFavorites', saveProducts)
      container.Visualizer.addListener('productRemovedFromFavorites', saveProducts)
      container.Visualizer.addListener('sceneAddedToFavorites', saveScenes)
      container.Visualizer.addListener('sceneRemovedFromFavorites', saveScenes)

      // upon new start of application - read from localstorage
      container.Visualizer.setFavoriteProducts(JSON.parse(localStorage.getItem('favoriteProducts')))
      container.Visualizer.setFavoriteScenes(JSON.parse(localStorage.getItem('favoriteScenes')))
    }

Subscribe to the Visualizer by acquiring its container. Example:

    container = document.querySelector('[data-role="visualizer"]')
    subscribe(container)

If the container is not there beause it will be launched, then use the launchVisualizer promise to acquire the container

            <button onclick="
                const productsInitExampleSkus = ()=> {
                    const products = [   {product: {application: 'Backsplash', sku: '1040502005'}},
                            {product: {application: 'Countertop', sku: '1400402005'}},
                            {product: {application: 'Countertop', sku: '1401102015'}},
                            {product: {application: 'Countertop', sku: '1400302005'}} ]
                    localStorage.setItem('favoriteProducts', JSON.stringify(products))
                }

                productsInitExampleSkus()

            ">
                example - saves favorite product sku/application pairs to localstorage
            </button>
            <button
                onClick={() => {
                    window.launchVisualizer({
                        experienceId: 'G2GcP2',
                        defaultProducts: { Countertop: '1200302000' },
                        defaultProduct: '1200302000',
                        sceneId: '6',
                        scene_configuration: 'US-EN',
                    }).then((visualizerContainer)=>{
                        // Here the visualizer is loaded and you can do with it whatever you need
                        subscribe(visualizerContainer)
                    })
                }}
            >
                Launch
            </button>

## Badges

### Badges look

- the badges are absolute pusition relative to the image of the product

    "theme": {
      "catalogBadges": {
            "badgeField": "__FilterSize",
            "badges": [
              {
                "name": "new",
                "label": "New",
                "bgcolor": "red",
                "icon": {
                  "url": "https://web-apps.byondxr.com/assets/alony/icons/photo-camera.svg"
                }
              },
              {
                "style": {
                  "right": "0",
                  "left": "auto",
                  "borderRadius": "3px 0px 0px 3px"
                },
                "name": "sale",
                "label": "30% SALE",
                "bgcolor": "C58"
              }
            ]
         }
    }

### First option

Definitions (badges) are read from the catalog custom fields.

### Second option

Badges are provided on client . First client will receive event: 'productsListed' with this eventData: { detail: { products: { sku: string }[] } } Then, on his own time, he will call client-api function provided with badges:

    const elm = document.querySelector('[data-role="visualizer"]')
    elm.addEventListener('productsListed', (event) => {
      let products = event.detail.products
      console.log(products)
      products[0].badges = ['sale']
      products[1].badges = ['new']
      elm.visualizerUI.setProductsBadges({ products })
    })

    export type TSetProductsBadgesParams = {
        products: {
            sku: string
            badges: string[]
        }[]
    }

    setProductsBadges: (params: TSetProductsBadgesParams) => void

## Product details dialog

### Additional Product fields

detailsText:

- it will show in the dialog as an additonal text
- this name is not final, is just an example (till then, the string shows just an example )

### Theme settings

- Modify launch button text and visibility (which is always add-to-cart)
- Modify product details dialog button

    {
      "theme": {
        "buttons": {
          "add_to_cart": {
            "label": "More Details",
            "visible": true
          },
          "productDetails": {
            "add_to_cart": {
              "label": "Add to cart",
              "visible": true
            }
          }
        }
      }
    }

### Per application settings in the publisher config

- existense of productDetails config under application object as bellow - will enable the Launch button to open the dialog

#### PD example

    {
      "applications": [
        {
          "application": "application-name",
          "productDetails": {
            "model": {
              "edges": [
                {
                  "imageUrl": "https://i.ibb.co/bX6N02D/edge1.png",
                  "label": "edgeccccc text 1 QA TEST",
                  "animationName": "",
                  "id": "edge1"
                },
                {
                  "imageUrl": "https://i.ibb.co/bX6N02D/edge1.png",
                  "label": "edge text 2",
                  "animationName": "CT 02",
                  "id": "edge2"
                },
                {
                  "imageUrl": "https://i.ibb.co/bgZmztN/edge2.png",
                  "label": "edge text 3",
                  "animationName": "CT 03",
                  "id": "edge3"
                }
              ],
              "modelUrl": "https://drive.google.com/uc?export=download&id=1z2LzIw_iJuif2huNdFxCRskR_HzIDZVC",
              "envConfig": { "url": "", "intensity": "1" },
              "distance": "4.1",
              "yRotate": "60",
              "xRotate": "50"
            },
            "fields": {
              "detailsText": {
                "visible": true
              },
              "description": {
                "visible": true
              },
              "price": {
                "visible": true
              },
              "title": {
                "visible": true
              }
            },
            "buttons": {
              "addToCart": {
                "visible": true
              }
            }
          }
        }
      ]
    }

#### PD Types

    export interface IButtonConfiguration {
      visible?: boolean
    }
    export interface IFieldConfiguration {
      visible?: boolean
    }
    export interface IProductDetailsButtonsConfiguration {
      addToCart?: IButtonConfiguration
    }

    export interface IProductDetailsFieldsConfiguration {
      price?: IFieldConfiguration
      title?: IFieldConfiguration
      description?: IFieldConfiguration
      detailsText?: IFieldConfiguration
    }
    export interface IProductDetailsEdgeConfiguration {
      id: string
      animationName: string
      label: string
      imageUrl: string
    }

    export interface IProductDetailsModelConfiguration {
      modelUrl: string
      envConfig?: { url?: string; intensity?: string }
      xRotate?: number
      yRotate?: number
      distance?: number
      edges: IProductDetailsEdgeConfiguration[]
    }

    export interface IProductDetails {
      buttons?: IProductDetailsButtonsConfiguration
      fields?: IProductDetailsFieldsConfiguration
      model: IProductDetailsModelConfiguration
    }

    export interface IApplication {
      application: string
      title: string
      image?: string
      productDetails?: IProductDetails
      buttons?: IApplicationButtonsConfiguration
      fields?: IApplicationFieldsConfiguration
    }

### Sorting of products according to specific custom field value

config:

    {
      "products": {
        "order": {
          "field": "custom field name"
        }
      }
    }

The value of this custom field will be numeric and according to this value the products will be sorted. Otherwise the default is to sort products by title ascending

Generated using TypeDoc