# sitesearch-ux-vue

Library to build Site Search page

## changelog
changelog is documented at CHANGELOG.md

## Installation
npm install following package
`npm install --save @searchstax-inc/searchstudio-ux-vue`

Add following code to `<head>`

```
<script type="text/javascript">
      var _msq = _msq || []; //declare object
      var analyticsBaseUrl = 'https://analytics-us-east.searchstax.co';
      (function () {
        var ms = document.createElement('script');
        ms.type = 'text/javascript';
        ms.src = 'https://static.searchstax.co/studio-js/v3/js/studio-analytics.js';
        var s = document.getElementsByTagName('script')[0];
        s.parentNode.insertBefore(ms, s);
      })();
    </script>
```
## Usage

After importing SearchstaxWrapper component needs to wrap all other components:

```

<SearchstaxWrapper
    :language="sampleConfig.language"
    :model="sampleConfig.model"
    :searchURL="sampleConfig.searchURL"
    :suggesterURL="sampleConfig.suggesterURL"
    :trackApiKey="sampleConfig.trackApiKey"
    :searchAuth="sampleConfig.searchAuth"
    :authType="sampleConfig.authType"
    :router="sampleConfig.router"
    :beforeSearch="sampleConfig.hooks.beforeSearch" // callback function to intercept search object before search is fired
    :afterSearch="sampleConfig.hooks.afterSearch" //  callback function to handle results after search is fired

  >
  // other components will go there

  </SearchstaxWrapper>
```

## Initialization
Initialization object needs to be of type: [ISearchstaxConfig](https://github.com/searchstax/searchstudio-ux-js/blob/main/src/interfaces/connector.interface.ts#L5)

Initialization example
```
sampleConfig = {
    language: "en",
    model: "Main Profile",
    searchURL: "",
    suggesterURL: "",
    trackApiKey: "",
    searchAuth: "",
    authType: "basic",
    router: {
      enabled: true,
      routeName: "searchstax",
      title: (result: ISearchObject) => {
        return "Search results for: " + result.query;
      },
      ignoredKeys: [],
    },
    hooks: {
      beforeSearch: function (props: ISearchObject) {
        const propsCopy = { ...props };
        return propsCopy;
      },
      afterSearch: function (results: ISearchstaxParsedResult[]) {
        const copy = [...results];
        return copy;
      },
    }
  };
```

## Initial layout
Our base theme is designed with this layout in mind but it is optional as all widgets have id parameters and can be attached to any element.
```
<SearchstaxWrapper
    :language="sampleConfig.language"
    :model="sampleConfig.model"
    :searchURL="sampleConfig.searchURL"
    :suggesterURL="sampleConfig.suggesterURL"
    :trackApiKey="sampleConfig.trackApiKey"
    :searchAuth="sampleConfig.searchAuth"
    :authType="sampleConfig.authType"
    :router="sampleConfig.router"
    :beforeSearch="sampleConfig.hooks.beforeSearch" // callback function to intercept search object before search is fired
    :afterSearch="sampleConfig.hooks.afterSearch" //  callback function to handle results after search is fired
  >
    <template #default>
      <div class="searchstax-page-layout-container">
        <SearchstaxInputWidget
          :afterAutosuggest="afterAutosuggest"
          :beforeAutosuggest="beforeAutosuggest"
          :suggestAfterMinChars="3"
        >
        </SearchstaxInputWidget>
        <div class="search-details-container">
          <SearchstaxSearchFeedbackWidget></SearchstaxSearchFeedbackWidget>
          <SearchstaxSortingWidget></SearchstaxSortingWidget>
        </div>
        <div class="searchstax-page-layout-facet-result-container">
          <div class="searchstax-page-layout-facet-container">
            <SearchstaxFacetsWidget
              :facetingType="'or'"
              :itemsPerPageDesktop="3"
              :itemsPerPageMobile="99"
            >
            </SearchstaxFacetsWidget>
          </div>
          <div class="searchstax-page-layout-result-container">
            <div id="searchstax-external-promotions-layout-container"></div>
            <SearchstaxResultWidget :afterLinkClick="afterLinkClick">
            </SearchstaxResultWidget>
            <div id="searchstax-related-searches-container"></div>
            <SearchstaxPaginationWidget>
            </SearchstaxPaginationWidget>
          </div>
        </div>
      </div>
    </template>
  </SearchstaxWrapper>
```

### widgets
Following widgets are available:

[Answer Widget](#answer-widget)

[Input Widget](#input-widget)

[Location Widget](#location-widget)

[Result Widget](#result-widget)

[Facets Widget](#facets-widget)

[Pagination Widget](#pagination-widget)

[SearchFeedback Widget](#searchfeedback-widget)

[RelatedSearches Widget](#relatedsearches-widget)

[ExternalPromotions Widget](#externalpromotions-widget)

[sorting Widget](#sorting-widget)

### Answer Widget ###
SearchStax Site Search solution offers Vue widgets to assist in building your custom search page.

The SearchstaxAnswerWidget component for Vue provides an AI answer widget for your searches.

**Usage**

```
<SearchstaxAnswerWidget :showMoreAfterWordCount="10"></SearchstaxAnswerWidget>
```

**Props**

- showMoreAfterWordCount - number(default 100) determining after how many words UI will show “Show More” view.
- feedbackWidget – an optional object that configures thumbs-up and thumbs-down feedback functionality.

Example of feedbackWidget config:
```
const feedbackConfig = {
    renderFeedbackWidget: true,
    emailOverride: searchstaxEmailOverride,
    thumbsUpValue: 10,
    thumbsDownValue: 0
  }
```


**searchAnswerTemplate**

The templates prop allows customizing the answer UI.

It receives the following props:

- answerData – Data object of type: ISearchstaxAnswerData
- showMore - Handler for exiting the show more view

**Example**

```
<SearchstaxAnswerWidget :showMoreAfterWordCount="100" :feedbackwidget="feedbackConfig">
      <template #answer="{ answerData, showMore }">
        {{&SearchstaxAnswerWidget}}
      </template>
    </SearchstaxAnswerWidget>
```

### Input Widget ###

SearchStax Site Search solution offers a Vue search-input widget to assist with your custom search page.

The SearchstaxInputWidget provides a search input box with autosuggest/autocomplete functionality.

**Usage**
```
<SearchstaxInputWidget
          :afterAutosuggest="afterAutosuggest"
          :beforeAutosuggest="beforeAutosuggest"
          :suggestAfterMinChars="3"
        ></SearchstaxInputWidget>
```

**Props**

- suggestAfterMinChars - default 3. Number of characters needed for autosuggest to start triggering
- beforeAutosuggest - callback function that gets called before firing autosuggest. autosuggestProps are being passed as a property and can be modified, if passed along further search will execute with modified properties, if null is returned then event gets canceled and search never fires.
- afterAutosuggest - callback function that gets called after autosuggest has values but before rendering. It needs to return same type of data but it can be modified.


**inputWidgetTemplate**

The inputTemplate prop allows customizing the input UI.

It receives the following props:

- suggestions – Array of autosuggestion results
- onMouseLeave - Handler for mouse leave event
- onMouseOver - Handler for mouse over event
- onMouseClick - Handler for mouse click event

**example**
```
<SearchstaxInputWidget
          :afterAutosuggest="afterAutosuggest"
          :beforeAutosuggest="beforeAutosuggest"
          :suggestAfterMinChars="3"
        >
          <template #input="{ suggestions, onMouseLeave, onMouseOver, onMouseClick }">
            {{&SearchstaxInputWidget}}
          </template>
        </SearchstaxInputWidget>
```
### Location Widget ###

SearchStax Site Search solution offers a Vue search-location widget to assist with your custom search page.

The SearchstaxLocationWidget provides a location search input with location-based search functionality.

**Usage**

```
{{&SearchstaxLocationWidgetConfig}}
<SearchstaxLocationWidget :locationDecode="locationWidgetConfig.locationDecodeFunction" :locationDecodeCoordinatesToAddress="locationWidgetConfig.locationDecodeCoordinatesToAddress" :locationValuesOverride="locationWidgetConfig.locationValuesOverride" :locationSearchEnabled="locationWidgetConfig.locationSearchEnabled">
</SearchstaxLocationWidget>
```

**Props**

- locationDecode - callback function to override location decoding
- locationDecodeCoordinatesToAddress - callback function to override location decoding

**Template Override**

The searchLocationTemplate prop allows customizing the location input UI.

It receives the following props:

- locationData –  data containing info on when to show certain elements
- inputValue – value of location input
- locationBlur - Handler for location input blur
- radiusChange - Handler for location radius change
- selectValue  - Value of radius select
- inputChange - location input change handler
- locationError - boolean stating if location has error
- getCurrentLocation - Handler for getting current location from browser


**Example**

```
{{&SearchstaxLocationWidgetConfig}}
{{&SearchstaxLocationWidget}}
<SearchstaxLocationWidget :locationDecode="locationWidgetConfig.locationDecode" :locationDecodeCoordinatesToAddress="locationWidgetConfig.locationDecodeCoordinatesToAddress" :locationValuesOverride="locationWidgetConfig.locationValuesOverride" :locationSearchEnabled="locationWidgetConfig.locationSearchEnabled">
    <template
      #location="{
        locationData,
        inputValue,
        locationBlur,
        radiusChange,
        selectValue,
        inputChange,
        locationError,
        getCurrentLocation
      }"
    >
                {{&SearchstaxLocationWidget}}
    </template>
  </SearchstaxLocationWidget>
```

### Result Widget ###

The SearchStax Site Search solution offers a Vue results widget to assist with your custom search page.

The SearchstaxResultsWidget component displays the search results.

**Usage**

```
<SearchstaxResultWidget :afterLinkClick="afterLinkClick"  :renderMethod="'“pagination”'" :resultsPerPage="10"></SearchstaxResultWidget>
```

**Props**

- renderMethod – either “pagination” or “infiniteScroll”.
- resultsPerPage – number of results on a page.
- afterLinkClick – Callback function invoked when a result link is clicked. Allows modifying the result object.

**Result Template Override**

The resultsTemplate prop allows customizing the result UI.

It receives following props:
- searchResults - Array of result items
- resultClicked - Handler for result click events


**No Results Template Override**

The noResultTemplate prop allows customizing the result UI.

It receives following props:

- searchResults - Array of result items
- resultClicked - Handler for result click events
- searchTerm - Search input term
- metadata - Metadata object
- executeSearch - Handler for executing srearch
- store - Main store of app

**Example of default render method**
```
 <SearchstaxResultWidget :afterLinkClick="afterLinkClick">
              <template #results="{ searchResults, resultClicked }">
                {{&SearchstaxResultWidgetDefault}}
              </template>
              <template #noResult="{ searchResults, resultClicked, searchTerm, metadata, executeSearch, store }">
                {{&SearchstaxResultWidgetNoResults}}
              </template>
            </SearchstaxResultWidget>
```

**Example of infinite scroll and pagination render methods**
```


 <SearchstaxResultWidget :afterLinkClick="afterLinkClick" :renderMethod="'infiniteScroll'" :resultsPerPage="10">
              <template #results="{ searchResults, resultClicked }">
                {{&SearchstaxResultWidgetDefault}}
              </template>
              <template #noResult="{ searchResults, resultClicked, searchTerm, metadata, executeSearch, store }">
                {{&SearchstaxResultWidgetNoResults}}
              </template>
            </SearchstaxResultWidget>

```



### Pagination Widget ###

The SearchStax Site Search solution offers a Vue pagination widget to assist with you custom search page.

The SearchstaxPaginationWidget component displays pagination controls for search results.

**Usage**

```
<SearchstaxPaginationWidget></SearchstaxPaginationWidget>
```

**Main Template Override**

Main template for the pagination controls.

It receives following props:

- paginationData – Pagination info object
- previousPage – Handler for previous page click
- nextPage - – Handler for next page click


**Infinite Scroll Template Override**

Main template for the pagination controls in infinite scroll mode.

It receives following props:
- isLastPage - boolean, true if its last page
- results - results.length can be used if there are results

**Example**

```
<SearchstaxPaginationWidget>
  <template #pagination="{ paginationData, previousPage, nextPage }">
    {{&SearchstaxPaginationWidgetDefault}}
  </template>
</SearchstaxPaginationWidget>
// infinite scroll example
<SearchstaxPaginationWidget>
  <template #infiniteScroll="{ nextPage }">
    {{&SearchstaxPaginationWidgetInfiniteScroll}}
  </template>
</SearchstaxPaginationWidget>
```

### Facets Widget ###

The SearchStax Site Search solution offers a Vue SearchstaxFacetsWidget component to display facets on your custom search page.

**Facet Selection and Order**

Facet lists are configured and ordered on the Site Search [Faceting Tab](https://www.searchstax.com/docs/searchstudio/faceting-tab/).

**Usage**

```
<SearchstaxFacetsWidget
              :facetingType="'or'"
              :itemsPerPageDesktop="3"
              :itemsPerPageMobile="99"
            ></SearchstaxFacetsWidget>
```

**Props**

- facetingType: "and" | "or" | "showUnavailable" | "tabs"; // type that determines how facets will behave
- specificFacets?: string[]; // optional array of facet names that if provided will only render those facets
- itemsPerPageDesktop: number; // default expanded facets for desktop
- itemsPerPageMobile: number; // default expanded facets for mobile
- beforeFacetsRender `(facets: IFacetData[]) => IFacetData[]` — Called with the current facets array before the widget renders. Return the same or a modified array to filter, reorder, or transform facets (e.g., hide certain facets or change their order).


**Main Template Desktop Override**

Main wrapper template for desktop facets display.

It receives following props:
- facetsTemplateDataDesktop -  Facets data object
- isNotDeactivated - Check if facet group is active
- toggleFacetGroup - Toggle facet group active state
- isChecked - Check if facet value is selected
- selectFacet - Handler for facet select
- showMoreLessDesktop - Show more/less facets handler
- facetContainers - Object of facet DOM containers
- updateRefDesktop - Handler for keeping checkbox references


**Main Template Mobile Override**

Main wrapper template for mobile facets display.

It receives following props:
- facetsTemplateDataMobile - Facets data object
- selectedFacetsCheckboxes - Selected facet values
- isNotDeactivated - Check if facet group is active
- toggleFacetGroup - Toggle facet group active state
- isChecked - Check if facet value is selected
- selectFacet - Handler for facet select
- showMoreLessDesktop - Show more/less facets handler
- facetContainers - Object of facet DOM containers
- openOverlay - Handler to open mobile overlay
- unselectFacet - Handler to unselect specific facet
- unselectAll - Handler to unselect all facets
- closeOverlay - Handler to close mobile overlay
- updateRefMobile - Handler for keeping mobile checkbox references


**Example**
```
<SearchstaxFacetsWidget
 :facetingType="'or'"
 :itemsPerPageDesktop="3"
 :itemsPerPageMobile="99"
>
 <template
   #desktopFacets="{ facetsTemplateDataDesktop, isNotDeactivated, toggleFacetGroup, isChecked, selectFacet, showMoreLessDesktop, facetContainers, updateRefDesktop }"
 >
  {{&SearchstaxFacetsWidgetDesktop}}
 </template>
 <template
   #mobileFacets="{ facetsTemplateDataMobile, selectedFacetsCheckboxes, isNotDeactivated, toggleFacetGroup, isChecked, selectFacet, showMoreLessDesktop, facetContainers, openOverlay, unselectFacet, unselectAll, closeOverlay, updateRefMobile }"
 >
 {{&SearchstaxFacetsWidgetMobile}}
 </template>
</SearchstaxFacetsWidget>
```

### SearchFeedback Widget ###

The SearchStax Site Search solution provides a search feedback widget to support your Vue search pages.

The SearchstaxSearchFeedbackWidget displays search feedback and stats.

**Usage**

```
<SearchstaxSearchFeedbackWidget></SearchstaxSearchFeedbackWidget>
```

**Main Template Override**

Main template for the search feedback message.

It receives following props:
- searchFeedbackData - Feedback data object
- onOriginalQueryClick - Handler for clicking on original query suggestion

**Example**
```
<SearchstaxSearchFeedbackWidget>
            <template #searchFeedback="{ searchFeedbackData, onOriginalQueryClick }">
                {{&SearchstaxSearchFeedbackWidgetTemplate}}
            </template>
          </SearchstaxSearchFeedbackWidget>
```

### RelatedSearches widget ###

The SearchStax Site Search solution offers a Vue widget for displaying related searches.

The SearchstaxRelatedSearchesWidget for Vue component displays related searches.

**Usage**
```
  <SearchstaxRelatedSearchesWidget
              :relatedSearchesURL="config.relatedSearchesURL"
              :relatedSearchesAPIKey="config.relatedSearchesAPIKey"
            ></SearchstaxRelatedSearchesWidget>
```

**Props**

- relatedSearchesURL: API URL for fetching related searches
- relatedSearchesAPIKey?: API key for related searches API

**Main Template Override**

Main template for related searches.

It receives following props:

- relatedData - Related searches data object
- executeSearch - Handler to run new search from related term

**Example**

```
<SearchstaxRelatedSearchesWidget
              :relatedSearchesURL="config.relatedSearchesURL"
              :relatedSearchesAPIKey="config.relatedSearchesAPIKey"
            >
              <template #related="{ relatedData, executeSearch }">
              {{&SearchstaxRelatedSearchesWidget}}
              </template>
            </SearchstaxRelatedSearchesWidget>
```

### ExternalPromotions widget ###

The SearchStax Site Search solution offers a Vue external-promotions widget for your custom search page.

The SearchstaxExternalPromotionsWidget component displays external promotions fetched from the API.

**Usage**

```
<SearchstaxExternalPromotionsWidget></SearchstaxExternalPromotionsWidget>
```

**Main Template Override**

Main template for external promotions.

It receives following props:

- externalPromotionsData – External promotions data object
- trackClick – Handler for tracking link clicks

**Example**
```
<SearchstaxExternalPromotionsWidget>
              <template #externalPromotions="{ externalPromotionsData, trackClick }">
                {{&SearchstaxExternalPromotionsWidget}}
              </template>
            </SearchstaxExternalPromotionsWidget>
```


### Sorting Widget ###

The SearchStax Site Search solution offers a Vue sorting widget for your custom search page.

The SearchstaxSortingWidget component displays sorting options for search results.

**Usage**

```
<SearchstaxSortingWidget></SearchstaxSortingWidget>
```

**Main Template Override**

Main template for sorting widget.

It receives following props:

- sortingData – Sorting data object
- orderChange – Handler for sorting change
- selectedSorting – Current selected sorting

**Example**

```
<SearchstaxSortingWidget>
            <template #sorting="{ sortingData, orderChange, selectedSorting }">
                {{&SearchstaxSortingWidget}}
            </template>
          </SearchstaxSortingWidget>
```


## Template overrides
Templates use vue templating.

## STYLING

scss styles can be imported from searchstudio-ux-js
```
 @import './../node_modules/@searchstax-inc/searchstudio-ux-js/dist/styles/scss/mainTheme.scss';
```
css can be taken from

```
./../node_modules/@searchstax-inc/searchstudio-ux-js/dist/styles/mainTheme.css
```