diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4d84eb78..9294c39a 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -9,6 +9,8 @@ Before you begin, a couple notes...
- Sign the [Contributor License Agreement](https://www.elastic.co/contributor-agreement/). We are not asking you to assign copyright to us, but to give us the right to distribute your code without restriction. We ask this of all contributors in order to assure our users of the origin and continuing existence of the code. You only need to sign the CLA once.
- Please write simple code and concise documentation, when appropriate.
+**Contributing to the docs?** Refer to [docs/README.md](./docs/README.md).
+
## Running Search UI
### Codebase overview
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 00000000..ec137a87
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,17 @@
+# Working with the docs
+
+The [Search UI docs](https://www.elastic.co/guide/en/search-ui/current/overview.html) are written in [AsciiDoc](https://github.com/elastic/docs?tab=readme-ov-file#asciidoc-guide) and are built using [elastic/docs](https://github.com/elastic/docs).
+
+## Build the docs locally
+
+Before building the docs locally make sure you have:
+
+* Docker
+* Python 3
+* [elastic/docs](https://github.com/elastic/docs) cloned locally
+
+Assuming your local copy of the elastic/docs repo is in the same repo as your local copy of this repo, run this command from inside your local copy of this repo:
+
+```
+../docs/build_docs --doc ./docs/index.asciidoc --chunk 3 --open
+```
diff --git a/docs/api-architecture.asciidoc b/docs/api-architecture.asciidoc
new file mode 100644
index 00000000..e1f4683d
--- /dev/null
+++ b/docs/api-architecture.asciidoc
@@ -0,0 +1,39 @@
+[[api-architecture]]
+= Architecture
+
+++++
+API reference
+++++
+
+// :keywords: architecture
+
+[source,txt]
+----
+ |
+ @elastic/react-search-ui | @elastic/search-ui
+ |
+ |
+ SearchProvider <--------------- SearchDriver
+ | | | |
+ State / | | | | State /
+ Actions | | | | Actions
+ | | | |
+ Components | | |
+ | | | |
+ v v | v
+------------------------------------+----------------------------
+ | | |
+ v v v
+ Using Headless Usage Headless Usage outside
+ Components in React of React
+----
+
+The core is a separate, vanilla JS library which can be used for any JavaScript based implementation.
+
+The Headless Core implements the functionality behind a search experience, but without its own view. It provides the underlying "state" and "actions" associated with that view. For instance, the core provides a `setSearchTerm` action, which can be used to save a `searchTerm` property in the state. Calling `setSearchTerm` using the value of an `` will save the `searchTerm` to be used to build a query.
+
+All of the Components in this library use the Headless Core under the hood. For instance, Search UI provides a `SearchBox` Component for collecting input from a user. But you are not restricted to using just that Component. Since Search UI lets you work directly with "state" and "actions", you could use any type of input you want! As long as your input or Component calls the Headless Core's `setSearchTerm` action, it will "just work". This gives you maximum flexibility over your experience if you need more than the Components in Search UI have to offer.
+
+The `SearchProvider` is a React wrapper around the Headless Core, and makes state and actions available to Search UI
+and in a React https://reactjs.org/docs/context.html[Context], and also via a
+https://reactjs.org/docs/render-props.html[Render Prop].
diff --git a/docs/api-connectors-app-search.asciidoc b/docs/api-connectors-app-search.asciidoc
new file mode 100644
index 00000000..e87680fd
--- /dev/null
+++ b/docs/api-connectors-app-search.asciidoc
@@ -0,0 +1,87 @@
+[[api-connectors-app-search]]
+= App Search Connector
+
+++++
+Connectors API
+++++
+
+// :keywords: app search connector
+
+.Deprecation Notice
+[IMPORTANT]
+====
+App Search connector for Search UI is deprecated and will no longer be
+supported. Please migrate to <>
+for continued support.
+====
+
+This Connector is used to connect Search UI to Elastic's https://www.elastic.co/cloud/app-search-service[App Search] API.
+
+[discrete]
+[[api-connectors-app-search-usage]]
+== Usage
+
+[source,shell]
+----
+npm install --save @elastic/search-ui-app-search-connector
+----
+
+[source,js]
+----
+import AppSearchAPIConnector from "@elastic/search-ui-app-search-connector";
+
+const connector = new AppSearchAPIConnector({
+ searchKey: "search-371auk61r2bwqtdzocdgutmg",
+ engineName: "search-ui-examples",
+ endpointBase: "http://127.0.0.1:3002"
+});
+----
+
+[discrete]
+[[api-connectors-app-search-additional-options]]
+=== Additional options
+
+Additional options will be passed through to the underlying
+https://github.com/elastic/app-search-javascript[APIclient]. Any valid parameter of the client can be used.
+
+[source,js]
+----
+const connector = new AppSearchAPIConnector({
+ searchKey: "search-371auk61r2bwqtdzocdgutmg",
+ engineName: "search-ui-examples",
+ endpointBase: "http://127.0.0.1:3002",
+ cacheResponses: false
+});
+----
+
+[discrete]
+[[api-connectors-app-search-options]]
+== Options
+
+|===
+| Param| Description
+
+| searchKey
+| Required. String. Credential found in your App Search Dashboard
+
+| engineName
+| Required. String. Engine to query, found in your App Search Dashboard
+
+| endpointBase
+| Required. String. Endpoint path, found in your App Search Dashboard
+
+| cacheResponses
+| Optional. Boolean. Default is true. By default, connector will keep an in browser memory result cache of previous requests.
+
+| hostIdentifier
+| Optional. Useful when proxying the Swiftype API or developing against a local API server.
+
+| beforeSearchCall
+| Optional. A hook to amend query options before the request is sent to the API in a query on an "onSearch" event.
+
+| beforeAutocompleteResultsCall
+| Optional. A hook to amend query options before the request is sent to the API in a "results" query on an "onAutocomplete" event.
+
+| beforeAutocompleteSuggestionsCall
+| Optional. A hook to amend query options before the request is sent to the API in a "suggestions" query on an "onAutocomplete" event.
+|===
diff --git a/docs/api-connectors-elasticsearch.asciidoc b/docs/api-connectors-elasticsearch.asciidoc
new file mode 100644
index 00000000..aee6a721
--- /dev/null
+++ b/docs/api-connectors-elasticsearch.asciidoc
@@ -0,0 +1,357 @@
+[[api-connectors-elasticsearch]]
+= Elasticsearch Connector
+
+// :keywords: demo
+
+.Technical preview
+[IMPORTANT]
+====
+Elasticsearch connector for Search UI is currently in technical preview
+status. It is not ready for production use.
+====
+
+Search UI provides a way to connect to Elasticsearch directly without needing Enterprise Search. This is useful for when you dont need the features of Enterprise Search, such as relevance tuning.
+
+The connector uses the same Search UI configuration that other connectors use.
+
+You must specify either the cloud id or on-premise host url for the Elasticsearch connector.
+
+[source,js]
+----
+import ElasticsearchAPIConnector from "@elastic/search-ui-elasticsearch-connector";
+
+const connector = new ElasticsearchAPIConnector({
+ // Either specify the cloud id or host to connect to elasticsearch
+ cloud: {
+ id: "" // cloud id found under your cloud deployment overview page
+ },
+ host: "http://localhost:9200", // host url for the Elasticsearch instance
+ index: "", // index name where the search documents are contained
+ apiKey: "", // Optional. apiKey used to authorize a connection to Elasticsearch instance.
+ // This key will be visible to everyone so ensure its setup with restricted privileges.
+ // See Authentication section for more details.
+ connectionOptions: {
+ // Optional connection options.
+ headers: {
+ "x-custom-header": "value" // Optional. Specify custom headers to send with the request
+ }
+ }
+});
+----
+
+|===
+| Param| Description
+
+| cloud
+| Required if `host` not provided. Object type. The cloud id for the deployment within elastic cloud.
+
+| host
+| Required if `cloud` not provided. String type. The host url to the Elasticsearch instance
+
+| index
+| Required. String type. The search index name
+
+| apiKey
+| Optional. a credential used to access the Elasticsearch instance. See <>
+
+| connectionOptions
+| Optional. Object containing `headers` dictionary of header name to header value.
+|===
+
+[discrete]
+[[api-connectors-elasticsearch-differences-between-app-search-and-elasticsearch-connector]]
+== Differences between App Search and Elasticsearch connector
+
+[discrete]
+[[api-connectors-elasticsearch-applying-filters-to-range-facets]]
+=== Applying Filters to Range Facets
+
+Elasticsearch connector differs in the way filters can be applied to facets. Currently its not possible to apply an explicit range filter to range facets. Elasticsearch connector uses the name thats been given to the option to apply the filter. It uses this name to match the option and creates a the range filter query for the option.
+
+[discrete]
+[[api-connectors-elasticsearch-example-facet-configuration]]
+==== Example Facet Configuration
+
+[source,js]
+----
+{
+ visitors: {
+ type: "range",
+ ranges: [
+ { from: 0, to: 10000, name: "0 - 10000" },
+ { from: 10001, to: 100000, name: "10001 - 100000" },
+ { from: 100001, to: 500000, name: "100001 - 500000" },
+ { from: 500001, to: 1000000, name: "500001 - 1000000" },
+ { from: 1000001, to: 5000000, name: "1000001 - 5000000" },
+ { from: 5000001, to: 10000000, name: "5000001 - 10000000" },
+ { from: 10000001, name: "10000001+" }
+ ]
+ }
+}
+----
+
+[discrete]
+[[api-connectors-elasticsearch-how-to-apply-the-filter]]
+==== How to apply the filter
+
+[source,js]
+----
+ setFilter("visitors", {
+ name: "10001 - 100000", // name of the option
+ from: 10001, // both from and to will be ignored
+ to: 100000
+ });
+----
+
+[discrete]
+[[api-connectors-elasticsearch-applying-a-range-to-a-field-that-isnt-a-facet]]
+==== Applying a range to a field that isn't a facet
+
+If the field isn't a facet, you will be able to apply filters to the search using `value`, `numeric range` and `date range`, depending on the field type.
+
+[source,js]
+----
+ setFilter("precio", {
+ name: "precio",
+ from: rangePrices[0],
+ to: rangePrices[1],
+ });
+----
+
+[discrete]
+[[api-connectors-elasticsearch-none-filter-type]]
+=== 'None' Filter Type
+
+Currently the None filter type is not supported. If this is a feature thats needed, please mention it in this https://github.com/elastic/search-ui/issues/783[issue].
+
+[discrete]
+[[api-connectors-elasticsearch-connection-and-authentication]]
+== Connection & Authentication
+
+.A note about security
+[IMPORTANT]
+====
+This connector will talk to the Elasticsearch instance directly from the
+browser. We **strongly** suggest you take additional steps to keep your
+Elasticsearch instance as secure as possible.
+====
+
+You have the following options available to you for securely exposing your Elasticsearch instance to the internet:
+
+[discrete]
+[[api-connectors-elasticsearch-proxy-the-_search-api-call-through-your-api]]
+=== Proxy the _search API call through your API
+
+This envolves building an API route that will proxy the Elasticsearch call through your API. During the proxy, you are able to:
+
+* Ability to add any additional authentication headers / keys as you proxy the request through the API and to Elasticsearch.
+* Update the Elasticsearch query request to add any filters to filter restricted documents
+* Application performance monitoring of functionality
+* Your own user based authentication for your API
+* Add a caching layer between the API and Elasticsearch
+
+The connector will perform a `_search` query and will derive the endpoint path with the host and index. With `http://localhost:9200` host and `search-ui-example` index, the endpoint path will be `http://localhost:9200/search-ui-example/_search`. The connector will make a POST call with the elasticsearch query in the body of the request. To proxy the request through your API, you need to implement a route and update the connector's settings to use the proxy route.
+
+[discrete]
+[[api-connectors-elasticsearch-use-an-elasticsearch-api-key]]
+=== Use an Elasticsearch api-key
+
+You can restrict access to indices by using an API key. We recommend you create an apiKey that is restricted to the particular index and has read-only authorization. See https://www.elastic.co/guide/en/kibana/master/api-keys.html[Kibana API keys guide]. To use the API key, place it within the Elasticsearch connection configuration.
+
+[discrete]
+[[api-connectors-elasticsearch-autocomplete]]
+== Autocomplete
+
+Search UI supports autocomplete functionality to suggest search terms that provide results. The autocomplete functionality is built on top of the Elasticsearch `suggest` and `bool prefix query` API.
+
+To take advantage of the feature, first update the <> configuration.
+
+Below is an example of what the `autocompleteQuery` may look like.
+
+[source,js]
+----
+autocompleteQuery: {
+ // performs a prefix search on the query
+ results: {
+ resultsPerPage: 5, // number of results to display. Default is 5.
+ search_fields: {
+ // the fields to prefix search on
+ title_suggest: {}
+ },
+ result_fields: {
+ // Add snippet highlighting within autocomplete suggestions
+ title: { snippet: { size: 100, fallback: true }},
+ nps_link: { raw: {} }
+ }
+ },
+ // performs a query to suggest for values that partially match the incomplete query
+ suggestions: {
+ types: {
+ // Limit query to only suggest based on "title" field
+ documents: { fields: ["title_completion"] }
+ },
+ // Limit the number of suggestions returned from the server
+ size: 4
+ }
+}
+
+----
+
+Above we are configuring both the `results` and `suggestions` sections of the autocomplete query.
+
+`results` will need a search field to perform a prefix search on the query. We advise using a `search_as_you_type` field to be used.
+`suggestions` require a `completion` type field to perform a query to suggest for values that partially match the incomplete query.
+
+Below is an example of the mappings for the above example. `title_suggest` is a `search_as_you_type` field and `title_completion` is a `completion` type field.
+
+[source,json]
+----
+{
+ "mappings": {
+ "properties": {
+ "title_suggest": {
+ "type": "search_as_you_type"
+ },
+ "title_completion": {
+ "type": "completion"
+ }
+ }
+ }
+}
+----
+
+With a combination of this configuration + the <> component with autocomplete configuration, your users will be able to see suggestions as they type within the search box.
+
+[discrete]
+[[api-connectors-elasticsearch-nodejs-integration]]
+== Node.js Integration
+
+The Elasticsearch API Connector builds the Elasticsearch query and performs the request directly to Elasticsearch from the browser. Depending on what you're building, you may want this logic to be done on the server and provide your clients a simplified API.
+
+First step is to implement two routes to handle `search` and `autocomplete` requests. In example below, we are using express.js framework to implement these http routes within node.js.
+
+[source,js]
+----
+// index.js
+
+var express = require("express");
+var APIConnector =
+ require("@elastic/search-ui-elasticsearch-connector").default;
+require("cross-fetch/polyfill");
+
+var app = express();
+
+app.use(express.json());
+app.use(express.urlencoded({ extended: false }));
+
+const connector = new APIConnector({
+ host: "http://localhost:9200", // host url for the Elasticsearch instance
+ index: "search-ui-examples", // index name where the search documents are contained
+ apiKey: "apiKeyExample" // Optional. apiKey used to authorize a connection to Elasticsearch instance.
+});
+
+app.post("/search", async (req, res) => {
+ const { query, options } = req.body;
+ const response = await connector.onSearch(query, options);
+ res.json(response);
+});
+
+app.post("/autocomplete", async (req, res) => {
+ const { query, options } = req.body;
+ const response = await connector.onAutocomplete(query, options);
+ res.json(response);
+});
+
+var listener = app.listen(8080, function () {
+ console.log("Listening on port " + listener.address().port);
+});
+----
+
+Next, you can add a simple connector which passes the configuration and query from the client to the server.
+
+[source,js]
+----
+class CustomConnector {
+ constructor(host) {
+ this.host = host;
+ }
+
+ async onSearch(query, options) {
+ const response = await fetch(this.host + "/search", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json"
+ },
+ body: JSON.stringify({
+ query,
+ options
+ })
+ });
+ return response.json();
+ }
+
+ async onAutocomplete(query, options) {
+ const response = await fetch(this.host + "/autocomplete", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json"
+ },
+ body: JSON.stringify({
+ query,
+ options
+ })
+ });
+ return response.json();
+ }
+}
+
+const connector = new CustomConnector("https://my-api-host/");
+
+const config = {
+ alwaysSearchOnInitialLoad: true,
+ apiConnector: connector
+ // ... typical search-ui configuration
+};
+----
+
+Thats it!. You should see the `CustomConnector` executing requests to the server, providing the search state and configuration in the body. The node.js server will use the Elasticsearch connector to perform a search to Elasticsearch and return the results back to the client.
+
+[discrete]
+[[api-connectors-elasticsearch-customise-the-elasticsearch-request-body]]
+== Customise the Elasticsearch Request Body
+
+Elasticsearch connector allows you to customise the Elasticsearch request body before its performed on Elasticsearch. This is useful if you want to customise the query or options before the request is sent to Elasticsearch.
+
+This is an advanced option, the underlying query may change between versions and reading from / mutating the query is brittle, so please be aware to use this sparingly and let us know what you want to achieve through github issues.
+
+Example below is overriding the `query` section of the Elasticsearch request body.
+
+[source,js]
+----
+const connector = new ElasticsearchAPIConnector(
+ {
+ host: "https://example-host.es.us-central1.gcp.cloud.es.io:9243",
+ index: "national-parks",
+ apiKey: "exampleApiKey"
+ },
+ (requestBody, requestState, queryConfig) => {
+ console.log("postProcess requestBody Call", requestBody); // logging out the requestBody before sending to Elasticsearch
+ if (!requestState.searchTerm) return requestBody;
+
+ // transforming the query before sending to Elasticsearch using the requestState and queryConfig
+ const searchFields = queryConfig.search_fields;
+
+ requestBody.query = {
+ multi_match: {
+ query: requestState.searchTerm,
+ fields: Object.keys(searchFields).map((fieldName) => {
+ const weight = searchFields[fieldName].weight || 1;
+ return `${fieldName}^${weight}`;
+ })
+ }
+ };
+
+ return requestBody;
+ }
+);
+----
diff --git a/docs/api-connectors-site-search.asciidoc b/docs/api-connectors-site-search.asciidoc
new file mode 100644
index 00000000..bb10e3bc
--- /dev/null
+++ b/docs/api-connectors-site-search.asciidoc
@@ -0,0 +1,57 @@
+[[api-connectors-site-search]]
+= Site Search Connector
+
+// :keywords: demo
+
+This Connector is used to connect Search UI to Elastic's https://www.elastic.co/cloud/site-search-service[Site Search] API.
+
+While Site Search supports multiple document types, Search UI will only
+support a single document type, and it must be provided up front when
+creating the connector.
+
+Note that Site Search does not support certain features of Search UI:
+
+* `disjunctiveFacets` or `disjunctiveFacetsAnalyticsTags` configuration options
+* Only `value` facets are allowed, no `range` facet support.
+* `sort` option is not supported on facets.
+* `size` option is not supported on facets.
+* Does not support multiple filters applied to a single field.
+* Cannot apply more than 1 range filter on a single field.
+* Analytics tags are not supported in `click`.
+* `suggestions` are not supported in autocomplete, only `results`
+* The `none` filter type is not supported.
+
+[discrete]
+[[api-connectors-site-search-usage]]
+== Usage
+
+[source,shell]
+----
+npm install --save @elastic/search-ui-site-search-connector
+----
+
+[source,js]
+----
+import SiteSearchAPIConnector from "@elastic/search-ui-site-search-connector";
+
+const connector = new SiteSearchAPIConnector({
+ documentType: "national-parks",
+ engineKey: "Z41R5U3Hi4s5gp1aw7kA"
+});
+----
+
+|===
+| Param| Description
+
+| documentType
+| Required. String type. Document Type found in your Site Search Dashboard
+
+| engineKey
+| Required. String type. Credential found in your Site Search Dashboard
+
+| beforeSearchCall
+| Optional. A hook to amend query options before the request is sent to the API in a query on an "onSearch" event.
+
+| beforeAutocompleteResultsCall
+| Optional. A hook to amend query options before the request is sent to the API in a "results" query on an "onAutocomplete" event.
+|===
diff --git a/docs/api-connectors-workplace-search.asciidoc b/docs/api-connectors-workplace-search.asciidoc
new file mode 100644
index 00000000..59319144
--- /dev/null
+++ b/docs/api-connectors-workplace-search.asciidoc
@@ -0,0 +1,78 @@
+[[api-connectors-workplace-search]]
+= Workplace Search Connector
+
+// :keywords: demo
+
+.Deprecation Notice
+[IMPORTANT]
+====
+Workplace Search connector for Search UI is deprecated and will no longer be
+supported. Please migrate to <>
+for continued support.
+====
+
+This Connector is used to connect Search UI to Elastic's https://www.elastic.co/workplace-search/[Workplace Search] API.
+
+[discrete]
+[[api-connectors-workplace-search-usage]]
+== Usage
+
+[source,shell]
+----
+npm install --save @elastic/search-ui-workplace-search-connector
+----
+
+[source,js]
+----
+import WorkplaceSearchAPIConnector from "@elastic/search-ui-workplace-search-connector";
+
+const connector = new WorkplaceSearchAPIConnector({
+ kibanaBase: "https://search-ui-sandbox.kb.us-central1.gcp.cloud.es.io:9243",
+ enterpriseSearchBase:
+ "https://search-ui-sandbox.ent.us-central1.gcp.cloud.es.io",
+ redirectUri: "http://localhost:3000",
+ clientId: "8e495e40fc4e6acf515e557e634de39d4f727f7f60a3afed24a99ce316607c1e"
+});
+----
+
+See the https://github.com/elastic/search-ui/blob/main/examples/sandbox/src/pages/workplace-search/index.js[usage example] in our sandbox app. The example uses a private Elastic Cloud deployment. Make sure to update the configuration values to use with your own https://www.elastic.co/cloud/[Elastic Cloud] deployment.
+
+[discrete]
+[[api-connectors-workplace-search-authentication]]
+== Authentication
+
+The Workplace Search API requires authentication. This connector uses OAuth authentication. You can read more about that https://www.elastic.co/guide/en/workplace-search/current/building-custom-search-workplace-search.html[here] and https://www.elastic.co/guide/en/workplace-search/current/workplace-search-search-oauth.html[here].
+
+Using this connector will populate two additional pieces of Application State:
+
+`isLoggedIn` (boolean) - This can be used to determine whether or not a user is authenticated. Requests using this connector will only work if a user is authenticatied. If this is false, consider showing a "Login" link using the `authorizeUrl` state.
+
+`authorizeUrl` (string) - This can be used to create a "Login" link for users to initiate OAuth authentication.
+
+`logout` - (function) - This action can be used to log out user out of the search experience. Under the hood it 1) deletes the saved token from LocalStorage and 2) logs user out of Enterprise Search and Kibana to prevent the ability to get a new access token.
+
+[discrete]
+[[api-connectors-workplace-search-options]]
+== Options
+
+|===
+| Param| Description
+
+| enterpriseSearchBase
+| Required. String. The publicly accessible url of the Enterprise Search.
+
+| kibanaBase
+| Required. String. The publicly accessible url for the Kibana deployment associated with the Enterprise Search deployment. Used for OAuth authentication.
+
+| redirectUri
+| Required. String. The publicly accessible url of this Search UI deployment, which Kibana will redirect back to after successful OAuth authentication. Must match a URI as configured in the OAuth Application.
+
+| clientId
+| Required. String. Client ID as generated when setting up the OAuth Application.
+
+| beforeSearchCall
+| Optional. A hook to amend query options before the request is sent to the API in a query on an "onSearch" event.
+
+| beforeAutocompleteResultsCall
+| Optional. A hook to amend query options before the request is sent to the API in a "results" query on an "onAutocomplete" event.
+|===
diff --git a/docs/api-core-actions.asciidoc b/docs/api-core-actions.asciidoc
new file mode 100644
index 00000000..1329faef
--- /dev/null
+++ b/docs/api-core-actions.asciidoc
@@ -0,0 +1,564 @@
+[[api-core-actions]]
+= Actions
+
+// :keywords:
+
+To update the state, you can use actions below. Actions are functions that update the Request State and performs an API request.
+
+[source,js]
+----
+setSearchTerm("search term");
+----
+
+To get access to the actions within your component, you must wrap your component with our context HOCs.
+
+[source,jsx]
+----
+// Selects `searchTerm` and `setSearchTerm` for use in Component
+withSearch(({ searchTerm, setSearchTerm }) => ({
+ searchTerm,
+ setSearchTerm
+}))(Component);
+----
+
+See <> for more information.
+
+There are certain cases where you may need to apply one or more actions at a time. Search UI intelligently
+batches actions into a single API call.
+
+For example, if you need to apply two filters at once, it is perfectly acceptable to write the following code:
+
+[source,js]
+----
+addFilter("states", "Alaska", "any");
+addFilter("world_heritage_site", "true");
+----
+
+This will only result in a single API call.
+
+[discrete]
+[[api-core-actions-addfilter]]
+== addFilter
+
+[source,ts]
+----
+addFilter(
+ name: string,
+ value: FilterValue,
+ type: FilterType = "all"
+)
+----
+
+Add a filter in addition to current filters values.
+
+[discrete]
+[[api-core-actions-examples]]
+=== Examples
+
+[source,js]
+----
+addFilter("states", "Alaska");
+addFilter("isPublished", true);
+addFilter("rating", 1);
+
+addFilter("states", ["Alaska", "California"], "all");
+addFilter("states", ["Alaska", "California"], "any");
+
+addFilter("published",{
+ name: "published",
+ from: "2020-01-01",
+ to: "2020-12-31"
+});
+
+addFilter("rating",{
+ name: "badRating",
+ from: 1,
+ to: 6
+});
+
+----
+
+[discrete]
+[[api-core-actions-parameters-1]]
+=== Parameters
+
+|===
+| Parameters| description
+
+| `name`
+| Required. Name of the field
+
+| `value`
+| Required. Filter Value. See `FilterValue` type.
+
+| `type`
+| Optional. Defaults to `all`. How the filter is applied. Can be one of `any`, `all`, `none`
+|===
+
+[discrete]
+[[api-core-actions-setfilter]]
+== setFilter
+
+[source,js]
+----
+setFilter(
+ name: string,
+ value: FilterValue,
+ type: FilterType = "all"
+)
+----
+
+Set a filter value, replacing current filter values.
+
+[discrete]
+[[api-core-actions-examples-2]]
+=== Examples
+
+[source,js]
+----
+setFilter("states", "Alaska");
+setFilter("isPublished", true);
+setFilter("rating", 1);
+
+setFilter("states", ["Alaska", "California"], "all");
+setFilter("states", ["Alaska", "California"], "any");
+
+setFilter("published",{
+ name: "published",
+ from: "2020-01-01",
+ to: "2020-12-31"
+});
+
+setFilter("rating",{
+ name: "badRating",
+ from: 1,
+ to: 6
+});
+
+----
+
+[discrete]
+[[api-core-actions-parameters-3]]
+=== Parameters
+
+|===
+| Parameters| description
+
+| `name`
+| Required. Name of the field
+
+| `value`
+| Required. Filter Value. See `FilterValue` type.
+
+| `type`
+| Optional. Defaults to `all`. How the filter is applied. Can be one of `any`, `all`, `none`
+|===
+
+[discrete]
+[[api-core-actions-removefilter]]
+== removeFilter
+
+Removes filters or filter values.
+
+[source,js]
+----
+removeFilter(
+ name: string,
+ value?: FilterValue,
+ type?: FilterType
+)
+----
+
+[discrete]
+[[api-core-actions-examples-4]]
+=== Examples
+
+[source,js]
+----
+removeFilter("states");
+removeFilter("states", ["Alaska", "California"]);
+
+removeFilter("published", {
+ name: "published",
+ from: "2020-01-01",
+ to: "2020-12-31"
+});
+
+removeFilter("rating", {
+ name: "badRating",
+ from: 1,
+ to: 6
+});
+----
+
+[discrete]
+[[api-core-actions-parameters-5]]
+=== Parameters
+
+|===
+| Parameters| description
+
+| `name`
+| Required. Name of the field
+
+| `value`
+| Optional. Filter Value. Will remove all filters under field if value not specified. See `FilterValue` type.
+
+| `type`
+| Optional. Defaults to `all`. How the filter is applied. Can be one of `any`, `all`, `none`
+|===
+
+[discrete]
+[[api-core-actions-reset]]
+== reset
+
+Reset state to initial search state.
+
+[source,js]
+----
+reset();
+----
+
+[discrete]
+[[api-core-actions-clearfilters]]
+== clearFilters
+
+Clear all filters.
+
+[source,js,subs="attributes"]
+----
+clearFilters((except: string[] = []));
+----
+
+[discrete]
+[[api-core-actions-examples-6]]
+=== Examples
+
+[source,js]
+----
+clearFilters();
+clearFilters(["states"]); // field name
+----
+
+[discrete]
+[[api-core-actions-parameters-7]]
+=== Parameters
+
+|===
+| Parameters| description
+
+| `except`
+| Optional. String array. Field names which you want to ignore being cleared.
+|===
+
+[discrete]
+[[api-core-actions-setcurrent]]
+== setCurrent
+
+Update the current page number. Used for paging.
+
+[source,js]
+----
+setCurrent(current: number)
+----
+
+[discrete]
+[[api-core-actions-examples-8]]
+=== Examples
+
+[source,js]
+----
+setCurrent(2);
+----
+
+[discrete]
+[[api-core-actions-parameters-9]]
+=== Parameters
+
+|===
+| Parameters| description
+
+| `current`
+| Required. Number type. The page number.
+|===
+
+[discrete]
+[[api-core-actions-setresultsperpage]]
+== setResultsPerPage
+
+Update the number of results per page. Used for paging.
+
+[source,js]
+----
+setResultsPerPage(resultsPerPage: number)
+----
+
+[discrete]
+[[api-core-actions-examples-10]]
+=== Examples
+
+[source,js]
+----
+setResultsPerPage(20);
+----
+
+[discrete]
+[[api-core-actions-parameters-11]]
+=== Parameters
+
+|===
+| Parameters| description
+
+| `resultsPerPage`
+| Required. Number type. Sets number of results per page.
+|===
+
+[discrete]
+[[api-core-actions-setsearchterm]]
+== setSearchTerm
+
+[source,js]
+----
+setSearchTerm(
+ searchTerm: string,
+ {
+ autocompleteMinimumCharacters = 0,
+ autocompleteResults = false,
+ autocompleteSuggestions = false,
+ shouldClearFilters = true,
+ refresh = true,
+ debounce = 0
+ }: SetSearchTermOptions = {}
+)
+----
+
+Update the search term. Also gives you the ability to control autocomplete options.
+
+[discrete]
+[[api-core-actions-examples-12]]
+=== Examples
+
+[source,js]
+----
+setSearchTerm("train");
+----
+
+[discrete]
+[[api-core-actions-parameters-13]]
+=== Parameters
+
+|===
+| Parameters| description
+
+| `searchTerm`
+| Required. String type. the new search term to query by
+
+| `options`
+| Optional. Object type. See `SetSearchTermOptions` type.
+|===
+
+[discrete]
+[[api-core-actions-setsearchtermoptions-parameters]]
+=== SetSearchTermOptions Parameters
+
+|===
+| Parameters| description
+
+| `autocompleteMinimumCharacters`
+| Optional. miniumum terms to start performing autocomplete suggestions
+
+| `autocompleteResults`
+| Optional. To perform autocomplete Results
+
+| `autocompleteSuggestions`
+| Optional. To perform autocomplete Suggestions
+
+| `shouldClearFilters`
+| Optional. To clear filters
+
+| `refresh`
+| Optional. To refresh results
+
+| `debounce`
+| Optional.
+|===
+
+[discrete]
+[[api-core-actions-setsort]]
+== setSort
+
+[source,js]
+----
+setSort(
+ sort: SortOption[] | string,
+ sortDirection: SortDirection
+)
+----
+
+Update the sort option.
+
+[discrete]
+[[api-core-actions-parameters-14]]
+=== Parameters
+
+|===
+| Parameters| description
+
+| `sort`
+| `SortOption` or String - field to sort on
+
+| `sortDirection`
+| String - "asc" or "desc"
+|===
+
+[discrete]
+[[api-core-actions-trackclickthrough]]
+== trackClickThrough
+
+[source,js]
+----
+trackClickThrough(
+ documentId: string,
+ tags: string[] = []
+)
+----
+
+Report a clickthrough event, which is when a user clicks on a result link.
+
+[discrete]
+[[api-core-actions-parameters-15]]
+=== Parameters
+
+|===
+| Parameters| description
+
+| `documentId`
+| String - The document ID associated with the result that was clicked
+
+| `tags`
+| Optional. Array[String] Optional tags which can be used to categorize this click event
+|===
+
+[discrete]
+[[api-core-actions-trackautocompleteclickthrough]]
+== trackAutocompleteClickThrough
+
+[source,js]
+----
+trackAutocompleteClickThrough(
+ documentId: string,
+ tags: string[] = []
+)
+----
+
+Report a clickthrough event, which is when a user clicks on an autocomplete suggestion.
+
+[discrete]
+[[api-core-actions-parameters-16]]
+=== Parameters
+
+|===
+| Parameters| description
+
+| `documentId`
+| String - The document ID associated with the result that was clicked
+
+| `tags`
+| Optional. Array[String] Optional tags which can be used to categorize this click event
+|===
+
+[discrete]
+[[api-core-actions-trackautocompletesuggestionclickthrough]]
+== trackAutocompleteSuggestionClickThrough
+
+[NOTE]
+====
+*This action requires the use of the analytics plugin.*
+====
+
+[source,js]
+----
+trackAutocompleteSuggestionClickThrough(
+ suggestion: string,
+ postion: number
+ tags: string[] = []
+)
+----
+
+Report a suggestion clickthrough event, which is when a user clicks on an autocomplete suggestion.
+
+[discrete]
+[[api-core-actions-parameters-17]]
+=== Parameters
+
+|===
+| Parameters| description
+
+| `suggestion`
+| String - The suggestion that was clicked
+
+| `position`
+| Number - The position of the suggestion that was clicked
+
+| `tags`
+| Optional. Array[String] Optional tags which can be used to categorize this click event
+|===
+
+[discrete]
+[[api-core-actions-a11ynotify]]
+== a11yNotify
+
+[source,js]
+----
+a11yNotify(
+ messageFunc: string,
+ messageArgs?: unknown
+)
+----
+
+Reads out a screen reader accessible notification. See `a11yNotificationMessages` under TODO LINK
+
+[discrete]
+[[api-core-actions-parameters-18]]
+=== Parameters
+
+|===
+| Parameters| description
+
+| `messageFunc`
+| String - object key to run as function
+
+| `messageArgs`
+| Object - Arguments to pass to form your screen reader message string
+|===
+
+[discrete]
+[[api-core-actions-types-19]]
+== Types
+
+[discrete]
+[[api-core-actions-filtervalue-and-filtertype-types]]
+=== FilterValue & FilterType Types
+
+`FilterValue` can be either a value type or a range type.
+
+[discrete]
+[[api-core-actions-types-20]]
+==== Types
+
+[source,ts]
+----
+type FilterValue = FilterValueValue | FilterValueRange;
+
+type FieldValue = string | number | boolean | Array;
+
+type FilterValueValue = FieldValue;
+
+type FilterValueRange = {
+ from?: FieldValue;
+ name: string;
+ to?: FieldValue;
+};
+
+type FilterType = "any" | "all" | "none";
+----
diff --git a/docs/api-core-configuration.asciidoc b/docs/api-core-configuration.asciidoc
new file mode 100644
index 00000000..115874a4
--- /dev/null
+++ b/docs/api-core-configuration.asciidoc
@@ -0,0 +1,591 @@
+[[api-core-configuration]]
+= Configuration
+
+++++
+Core API
+++++
+
+// :description: Search UI Configuration API
+// :keywords: configuration
+
+Search UI uses a configuration object to tailor search to your needs. It consists of three parts:
+
+* Search query
+* Autocomplete query
+* Event hooks
+
+See below for details on each part.
+
+See <> page for more information on how to use the configuration with the SearchProvider.
+
+[discrete]
+[[api-core-configuration-search-query-queryconfig]]
+== Search Query (QueryConfig)
+
+This is the configuration for the main search query. Some of these configuration options are not supported by some connectors. Each connector will document the options that are not supported.
+
+[source,js]
+----
+
+searchQuery: {
+ filters: [{ field: "world_heritage_site", values: ["true"] }],
+ facets: {
+ states: { type: "value", size: 30 },
+ }
+ disjunctiveFacets: ["states"], // Array of field names to use for disjunctive searches
+ disjunctiveFacetsAnalyticsTags: ["Ignore"],
+ conditionalFacets: {},
+ search_fields: {
+ title: {},
+ description: {}
+ },
+ result_fields: {
+ title: {
+ snippet: {
+ size: 100,
+ fallback: true
+ }
+ },
+ nps_link: {
+ raw: {}
+ }
+ }
+}
+
+----
+
+[discrete]
+[[api-core-configuration-filters-global-filters]]
+=== Filters (Global Filters)
+
+Using Query Config, it is possible to create "Global" filters. "Global filters" are filters that are added to every query. The user has no control over whether or not this filter is added or removed, it doesn't show up in the query string, and is completely transparent to the user. It is applied IN ADDITION to filters which the user applies.
+
+[source,js]
+----
+filters: [
+ // value filter example
+ { field: "world_heritage_site", values: ["true"] },
+ // Range filter example
+ {
+ field: "acres",
+ values: [{
+ from: 0, to: 1000, name: "Small"
+ }]
+ }
+]
+----
+
+[discrete]
+[[api-core-configuration-facets]]
+=== Facets
+
+Tells Search UI to fetch facet data that can be used with Facet Components.
+
+[source,js]
+----
+ facets: {
+ // example of a value facet
+ states: { type: "value", size: 30 },
+
+ // example of a numeric range facet
+ acres: {
+ type: "range",
+ ranges: [
+ { from: -1, name: "Any" },
+ { from: 0, to: 1000, name: "Small" },
+ { from: 1001, to: 100000, name: "Medium" },
+ { from: 100001, name: "Large" },
+ ],
+ },
+
+ // example of a date range facet
+ date_established: {
+ type: "range",
+ ranges: [
+ {
+ from: "1950-10-05T14:48:00.000Z",
+ name: "Within the last 50 years",
+ },
+ {
+ from: "1900-10-05T14:48:00.000Z",
+ to: "1950-10-05T14:48:00.000Z",
+ name: "50 - 100 years ago",
+ },
+ {
+ to: "1920-10-05T14:48:00.000Z",
+ name: "More than 100 years ago",
+ },
+ ],
+
+ // example of a geo location range facet
+ location: {
+ // center location to base ranges off of
+ center: "37.7749, -122.4194",
+ type: "range",
+ unit: "mi",
+ ranges: [
+ { from: 0, to: 100, name: "Nearby" },
+ { from: 100, to: 500, name: "A longer drive" },
+ { from: 500, name: "Perhaps fly?" },
+ ],
+ },
+ }
+ }
+----
+
+[discrete]
+[[api-core-configuration-disjunctive-faceting]]
+==== Disjunctive Faceting
+
+"Disjunctive" facets are facets that do not change when a selection is made. Meaning, all available options will remain as selectable options even after a selection is made.
+
+Configured in the searchQuery.disjunctiveFacets array. An array of field names. Every field listed here must have been configured in the facets field first. It denotes that a facet should be considered disjunctive. When returning counts for disjunctive facets, the counts will be returned as if no filter is applied on this field, even if one is applied.
+
+[discrete]
+[[api-core-configuration-disjunctivefacetsanalyticstags]]
+===== disjunctiveFacetsAnalyticsTags
+
+Used in conjunction with the disjunctiveFacets parameter. Adding disjunctiveFacets can cause additional API requests to be made to your API, which can create deceiving analytics. These queries will be tagged with "Facet-Only" by default. This field lets you specify a different tag for these.
+
+Example, use ignore as a tag on all disjunctive API calls:
+
+[source,js]
+----
+disjunctiveFacetsAnalyticsTags: ["ignore"];
+----
+
+[discrete]
+[[api-core-configuration-conditional-faceting]]
+==== Conditional Faceting
+
+See <> for more information.
+
+[discrete]
+[[api-core-configuration-search_fields]]
+=== search_fields
+
+Fields which should be searched with search term.
+
+[source,js]
+----
+search_fields: {
+ title: {
+ weight: 10,
+ },
+ description: {},
+ tags: {
+ weight: 5,
+ }
+}
+----
+
+Apply Weights to each search field.
+
+Engine level Weight settings will be applied is none are provided.
+
+Query time Weights take precedence over Engine level values.
+
+All fields specified within the search relevance section will be used for searching if not specified.
+
+[discrete]
+[[api-core-configuration-result_fields]]
+=== result_fields
+
+Select from two ways to render text field values:
+
+* **Raw**: An exact representation of the value within a field. And it is exact! It is not HTML escaped.
+* **Snippet**: A snippet is an HTML escaped representation of the value within a field, where query matches are captured in `` tags.
+
+A raw field defaults to the full field with no character limit outside of max document size. A custom range must be at least 20 characters.
+
+A snippet field defaults to 100 characters. A custom range must be between 20-1000 characters.
+
+Only text fields provide these two options, as they are functions of the deep full-text search capabilities of App Search.
+
+[discrete]
+[[api-core-configuration-raw]]
+==== Raw
+
+[source,js]
+----
+result_fields: {
+ title: {
+ raw: {}
+ },
+ description: {
+ raw: {
+ size: 50
+ }
+ }
+}
+----
+
+|===
+| field| description
+
+| `size`
+| Number - Optional. Length of the return value. Only can be used on text fields. Must be at least 20; defaults to the entire text field. If given for a different field type other than text, it will be silently ignored.
+|===
+
+[discrete]
+[[api-core-configuration-snippet-highlighting]]
+==== Snippet (Highlighting)
+
+Requests a snippet of a text field.
+
+The query match will be wrapped in `` tags, for highlighting, if a match exists.
+
+Use escaped quotations to highlight only on exact, case insensitive matches.
+
+Matches are HTML escaped prior to inserting `` tags. Fallbacks are also HTML escaped.
+
+If requesting a snippet on a non-text field, the snippet field will be null.
+
+If there is no match for your query, the snippet field will be null.
+
+Snippets on an array value will return the first match or null. There is no fallback support.
+
+On synonyms: If a search finds a synonym for a query, the synonym will not be highlighted.
+
+For example, if "path" and "trail" are synonyms and a query is done for "path", the term "trail" will not be highlighted.
+
+[source,js]
+----
+result_fields: {
+ title: {
+ snippet: {
+ size: 100,
+ fallback: true
+ }
+ },
+ description: {
+ raw: {
+ size: 50
+ }
+ }
+}
+----
+
+|===
+| field| description
+
+| `size`
+| Character length of the snippet returned. Must be at least 20; defaults to 100.
+
+| `fallback`
+| If true, fallback to the raw field if no match is found.
+|===
+
+[discrete]
+[[api-core-configuration-autocomplete-query]]
+== Autocomplete Query
+
+This is the configuration that provide relevant query suggestions for incomplete queries. Some of these configuration options are not supported by some connectors. Each connector will document the options that are not supported.
+
+[source,js]
+----
+autocompleteQuery: {
+ // performs a prefix search on the query
+ results: {
+ resultsPerPage: 5, // number of results to display. Default is 5.
+ result_fields: {
+ // Add snippet highlighting within autocomplete suggestions
+ title: { snippet: { size: 100, fallback: true }},
+ nps_link: { raw: {} }
+ }
+ },
+ // performs a query to suggest for values that partially match the incomplete query
+ suggestions: {
+ types: {
+ // Limit query to only suggest based on "title" field
+ documents: { fields: ["title"] }
+ },
+ // Limit the number of suggestions returned from the server
+ size: 4
+ }
+}
+----
+
+[discrete]
+[[api-core-configuration-results]]
+=== Results
+
+`results` will perform autocomplete on the query being typed. This will give back results that are relevant to the query before the user has typed any additional characters.
+
+[source,js]
+----
+results: {
+ resultsPerPage: 5,
+ result_fields: {
+ title: { snippet: { size: 100, fallback: true }},
+ nps_link: { raw: {} }
+ }
+},
+----
+
+|===
+| field| description
+
+| `resultPerPage`
+| Optional. Number type. Number of results suggested
+
+| `result_fields`
+| Optional. To specify the fields for each result hit. Use same configuration as <>
+|===
+
+[discrete]
+[[api-core-configuration-suggestions]]
+=== Suggestions
+
+Suggestions Query configuration for Search UI largely follows the same API as the https://www.elastic.co/guide/en/app-search/current/query-suggestion.html[App Search Search API].
+
+[source,json]
+----
+{
+ "types": {
+ "documents": {
+ "fields": ["title", "states"]
+ }
+ },
+ "size": 4
+}
+----
+
+|===
+| option| type| required?| source
+
+| `types`
+| Object
+| required
+| Object, keyed by "type" of query suggestion, with configuration for that type of suggestion.
+
+| `size`
+| Integer
+| optional
+| Number of suggestions to return.
+|===
+
+[discrete]
+[[api-core-configuration-result-suggestions]]
+=== Result Suggestions
+
+[IMPORTANT]
+====
+*Supported only by the Elasticsearch-connector.*
+====
+
+A different index can be used for the suggestions. Some examples:
+
+* Popular queries index from analytics
+* Brands index from product data
+* Categories index from product data
+
+Below we are using the `popular_queries` index and performing a prefix match search on the `query.suggest` field. One thing to note, make sure the api-key has access to the index.
+
+See <> for more information.
+
+[source,js]
+----
+autocompleteQuery: {
+ suggestions: {
+ popularQueries: {
+ search_fields: {
+ "query.suggest": {} // fields used to query
+ },
+ result_fields: {
+ query: { // fields used for display
+ raw: {}
+ }
+ },
+ index: "popular_queries",
+ queryType: "results"
+ }
+ }
+}
+----
+
+[discrete]
+[[api-core-configuration-event-hooks]]
+== Event Hooks
+
+Search UI exposes a number of event hooks which need handlers to be implemented in order for Search UI
+to function properly.
+
+The easiest way to provide handlers for these events is via an out-of-the-box "Connector", which
+provides pre-built handlers, which can then be configured for your particular use case.
+
+While we do provide out-of-the-box Connectors, it is also possible to implement these handlers directly,
+override Connector methods, or provide "middleware" to Connectors in order to further customize
+how Search UI interacts with your services.
+
+[discrete]
+[[api-core-configuration-event-handlers]]
+==== Event Handlers
+
+|===
+| method| params| return| description
+
+| `onResultClick`
+| `props` - Object
+|
+| This method logs a click-through event to your APIs analytics service. This is triggered when a user clicks on a result on a result page.
+
+|
+| - `query` - String
+|
+| The query used to generate the current results.
+
+|
+| - `documentId` - String
+|
+| The id of the result that a user clicked.
+
+|
+| - `requestId` - String
+|
+| A unique id that ties the click to a particular search request.
+
+|
+| - `tags` - Array[String]
+|
+| Tags used for analytics.
+
+| `onSearch`
+| `state` - <>
+| <>
+|
+
+|
+| `queryConfig` - <>
+|
+|
+
+| `onAutocompleteResultClick`
+| `props` - Object
+|
+| This method logs a click-through event to your APIs analytics service. This is triggered when a user clicks on a result in an autocomplete dropdown
+
+|
+| - `query` - String
+|
+| The query used to generate the current results.
+
+|
+| - `documentId` - String
+|
+| The id of the result that a user clicked.
+
+|
+| - `requestId` - String
+|
+| A unique id that ties the click to a particular search request.
+
+|
+| - `tags` - Array[String]
+|
+| Tags used for analytics.
+
+| `onAutocomplete`
+| `state` - <>
+| <>
+|
+
+|
+| `queryConfig` - Object
+|
+|
+
+|
+| - `results` - <>
+|
+| If this is set, results should be returned for autocomplete.
+
+|
+| - `suggestions` - <>
+|
+| If this is set, query suggestions should be returned for autocomplete.
+|===
+
+Explicitly providing a Handler will override the Handler provided by the Connector.
+
+[source,jsx]
+----
+ {
+ const queryForOtherService = transformSearchUIStateToQuery(
+ requestState,
+ queryConfig
+ );
+ const otherServiceResponse = await callSomeOtherService(
+ queryForOtherService
+ );
+ return transformOtherServiceResponseToSearchUIState(otherServiceResponse);
+ }
+ }}
+/>
+----
+
+[discrete]
+[[api-core-configuration-using-middleware-in-connector-handlers]]
+=== Using middleware in Connector Handlers
+
+Handler implementations can also be used as middleware for Connectors by leveraging
+the `next` function.
+
+[source,jsx]
+----
+ {
+ const updatedState = someStateTransformation(requestState);
+ return next(updatedState, queryConfig);
+ }
+ }}
+/>
+----
+
+[discrete]
+[[api-core-configuration-routing-options]]
+=== Routing Options
+
+Search UI provides a number of options for how to customise how state is serialised onto the URL. Within the config there is a `routingOptions` object which can be used to override the serialisation and parsing of the url to state.
+
+Below is an example of how to use the `routingOptions` object to customise the url to be more SEO friendly.
+
+This will result in the url pattern being like `https://example.com/search/california,alaska?query=shoes`
+
+[source,js]
+----
+const routingOptions = {
+ readUrl: () => {
+ return asPath;
+ },
+ writeUrl: (url, { replaceUrl }) => {
+ const method = router[replaceUrl ? "replace" : "push"];
+ method(url);
+ },
+ stateToUrl: (state) => {
+ const statesFilter = state.filters.find(
+ (filter) => filter.field === "states"
+ );
+ const states = statesFilter ? statesFilter.values.join(",") : "all";
+ return `/search/${states}?query=${state.searchTerm}`;
+ },
+ urlToState: (url) => {
+ const match = url.match(/\/search\/(\w+)\?query=(\w+)/);
+ if (!match) return {};
+ return {
+ searchTerm: match[2],
+ filters: [{ field: "states", values: [match[1].split(",")], type: "any" }]
+ };
+ }
+};
+
+const config = {
+ // search UI config
+ routingOptions: routingOptions
+};
+----
diff --git a/docs/api-core-state.asciidoc b/docs/api-core-state.asciidoc
new file mode 100644
index 00000000..56c950e3
--- /dev/null
+++ b/docs/api-core-state.asciidoc
@@ -0,0 +1,110 @@
+[[api-core-state]]
+= State
+
+// :keywords: state
+
+State can be divided up into a few different types.
+
+. <> - State that is used
+as parameters on Search API calls.
+. <> - State that represents a response from a Search API call.
+. <> - The general state.
+
+Request State and Response State will often have similar values. For instance, `searchTerm` and `resultSearchTerm`.
+`searchTerm` is the current search term in the UI, and `resultSearchTerm` is the term associated with the current
+`results`. This can be relevant in the UI, where you might not want the search term on the page to change until AFTER
+a response is received, so you'd use the `resultSearchTerm` state.
+
+[discrete]
+[[api-core-state-request-state]]
+== Request State
+
+State that is used as parameters on Search API calls.
+
+Request state can be set by:
+
+* Using actions, like `setSearchTerm`
+* The `initialState` option.
+* The URL query string, if `trackUrlState` is enabled.
+
+|===
+| option| Description
+
+| `current`
+| Current page number
+
+| `filters`
+| Array of filters. See Filters section.
+
+| `resultsPerPage`
+|
+
+| `searchTerm`
+| Search terms to search for
+
+| `sort`
+| List of fields and directions to sort on
+|===
+
+[discrete]
+[[api-core-state-response-state]]
+== Response State
+
+State that represents a response from a Search API call.
+
+It is not directly update-able.
+
+It is updated indirectly by invoking an action which results in a new API request.
+
+|===
+| field| description
+
+| `autocompletedResults`
+| An array of results items fetched for an autocomplete dropdown.
+
+| `autocompletedResultsRequestId`
+| A unique ID for the current autocompleted search results.
+
+| `autocompletedSuggestions`
+| A keyed object of query suggestions. It's keyed by type since multiple types of query suggestions can be set here.
+
+| `autocompletedSuggestionsRequestId`
+| A unique ID for the current autocompleted suggestion results.
+
+| `facets`
+| Will be populated if `facets` configured in <>.
+
+| `rawResponse`
+| The response object received from the API
+
+| `requestId`
+| A unique ID for the current search results.
+
+| `results`
+| An array of result items.
+
+| `resultSearchTerm`
+| As opposed the the `searchTerm` state, which is tied to the current search parameter, this is tied to the searchTerm for the current results. There will be a period of time in between when a request is started and finishes where the two pieces of state will differ.
+
+| `totalResults`
+| Total number of results found for the current query.
+|===
+
+[discrete]
+[[api-core-state-application-state]]
+== Application State
+
+Application state is the general application state.
+
+|===
+| field| description
+
+| `error`
+| Error message, if an error was thrown.
+
+| `isLoading`
+| Whether or not a search is currently being performed.
+
+| `wasSearched`
+| Has any query been performed since this driver was created? Can be useful for displaying initial states in the UI.
+|===
diff --git a/docs/api-plugins-analytics-plugin.asciidoc b/docs/api-plugins-analytics-plugin.asciidoc
new file mode 100644
index 00000000..c8866e10
--- /dev/null
+++ b/docs/api-plugins-analytics-plugin.asciidoc
@@ -0,0 +1,85 @@
+[[api-core-plugins-analytics-plugin]]
+= Analytics Plugin
+
+++++
+Plugins
+++++
+
+// :keywords:
+
+Use the Analytics Plugin to send analytics events to the Behavioral Analytics Product. Follow the instructions to set up the plugin.
+
+[discrete]
+[[api-core-plugins-analytics-plugin-installation]]
+== Installation
+
+[source,bash]
+----
+yarn add @elastic/search-ui-analytics-plugin
+## OR
+npm install @elastic/search-ui-analytics-plugin
+----
+
+[discrete]
+[[api-core-plugins-analytics-plugin-basic-usage]]
+== Basic Usage
+
+Add the Analytics Plugin to your Search UI configuration like so:
+
+[source,js]
+----
+import AnalyticsPlugin from "@elastic/search-ui-analytics-plugin";
+
+// search ui configuration
+const config = {
+ apiConnector: connector,
+ searchQuery: { ... },
+ plugins: [ AnalyticsPlugin() ]
+}
+----
+
+By default, the Analytics Plugin will use the Behavioral Analytics client provided when using script tag integration.
+
+[discrete]
+[[api-core-plugins-analytics-plugin-passing-in-a-custom-analytics-client]]
+=== Passing in a custom analytics client
+
+If you integrated Behavioral Analytics using the `@elastic/behavioral-analytics-javascript-tracker` NPM package, you can pass in a custom analytics client to the Analytics Plugin.
+
+[source,js]
+----
+
+import AnalyticsPlugin from "@elastic/search-ui-analytics-plugin";
+import { createTracker, getTracker } from "@elastic/behavioral-analytics-javascript-tracker";
+
+createTracker({
+ // the DSN can be found in the Behavioral Analytics Collections view page
+ dsn: "https://my-analytics-dsn.elastic.co"
+})
+
+// search ui configuration
+const config = {
+ apiConnector: connector,
+ searchQuery: { ... },
+ plugins: [
+ AnalyticsPlugin({
+ client: getTracker()
+ })
+ ]
+}
+----
+
+[discrete]
+[[api-core-plugins-analytics-plugin-options]]
+== Options
+
+The Analytics Plugin accepts the following parameters:
+
+|===
+| Option| Type| Description| Default
+
+| `client`
+| `AnalyticsTracker`
+| The Behavioral Analytics client to use. Read more on https://github.com/elastic/behavioral-analytics-tracker[Behavioral Analytics Tracker repo]
+| `window.elasticAnalytics`
+|===
diff --git a/docs/api-react-components-error-boundary.asciidoc b/docs/api-react-components-error-boundary.asciidoc
new file mode 100644
index 00000000..bb94c3ff
--- /dev/null
+++ b/docs/api-react-components-error-boundary.asciidoc
@@ -0,0 +1,64 @@
+[[api-react-components-error-boundary]]
+= ErrorBoundary
+
+// :keywords: demo
+
+Handle unexpected errors.
+
+[discrete]
+[[api-react-components-error-boundary-example]]
+== Example
+
+[source,jsx]
+----
+import { ErrorBoundary } from "@elastic/react-search-ui";
+
+...
+
+
+
Some Content
+
+----
+
+[discrete]
+[[api-react-components-error-boundary-properties]]
+== Properties
+
+|===
+| Name| Description
+
+| className
+|
+
+| children
+| Content to show if no error has occurred, will be replaced with error messaging if there was an error.
+
+| view
+| Used to override the default view for this Component. See <> below.
+
+| *
+| Any other property passed will be passed through and available to use in a Custom View
+|===
+
+[discrete]
+[[api-react-components-error-boundary-view-customization]]
+== View customization
+
+A complete guide to view customization can be found in the <> section.
+
+The following properties are available in the view:
+
+|===
+| Name| Description
+
+| className
+| Passed through from main component.
+
+| children
+| Content to show if no error has occurred, will be replaced with error messaging if there was an error.
+
+| error
+| Type: `string`. The error message to show if an error occurred.
+|===
+
+See https://github.com/elastic/search-ui/blob/main/packages/react-search-ui-views/src/ErrorBoundary.tsx[ErrorBoundary.tsx] for an example.
diff --git a/docs/api-react-components-facet.asciidoc b/docs/api-react-components-facet.asciidoc
new file mode 100644
index 00000000..f75379bc
--- /dev/null
+++ b/docs/api-react-components-facet.asciidoc
@@ -0,0 +1,169 @@
+[[api-react-components-facet]]
+= Facet
+
+// :keywords: facet
+
+Show a Facet filter for a particular field.
+
+Must configure the corresponding field in the `SearchProvider` <> object.
+
+[discrete]
+[[api-react-components-facet-example]]
+== Example
+
+[source,jsx]
+----
+import { Facet } from "@elastic/react-search-ui";
+import { MultiCheckboxFacet } from "@elastic/react-search-ui-views";
+
+...
+
+
+ {() => (
+
+ )}
+
+----
+
+[discrete]
+[[api-react-components-facet-example-of-an-or-based-facet-filter]]
+== Example of an OR based Facet filter
+
+Certain configuration of the `Facet` Component will require a "disjunctive" facet to work
+correctly. "Disjunctive" facets are facets that do not change when a selection is made. Meaning, all available options
+will remain as selectable options even after a selection is made.
+
+[source,jsx]
+----
+import { Facet } from "@elastic/react-search-ui";
+import { MultiCheckboxFacet } from "@elastic/react-search-ui-views";
+
+...
+
+
+ {() => (
+
+ )}
+
+----
+
+[discrete]
+[[api-react-components-facet-properties]]
+== Properties
+
+|===
+| Name| Description
+
+| className
+|
+
+| field
+| Field name corresponding to this filter. This requires that the corresponding field has been configured in `facets` on the top level Provider.
+
+| filterType
+| The type of filter to apply with the selected values. I.e., should "all" of the values match, or just "any" of the values, or "none" of the values. Note: See the example above which describes using "disjunctive" facets in conjunction with filterType.
+
+| label
+| A static label to show in the facet filter.
+
+| show
+| The number of facet filter options to show before concatenating with a "Show more" link.
+
+| isFilterable
+| Whether or not to show Facet quick filter.
+
+| view
+| Used to override the default view for this Component. See <> below.
+
+| *
+| Any other property passed will be passed through and available to use in a Custom View
+|===
+
+[discrete]
+[[api-react-components-facet-view-customization]]
+== View customization
+
+A complete guide to view customization can be found in the <> section.
+
+The following properties are available in the view:
+
+|===
+| Name| Description
+
+| className
+| Passed through from main component.
+
+| label
+| Type: `string`. Passed through from main component.
+
+| onMoreClick
+| Type: `() => void`. Used for a "Show more" link. Call this to show more options.
+
+| onRemove
+| Type: `(value: FieldValue) => void`. Call this when a user removes a facet filter selection. Pass the `value` from the corresponding selection from `options`.
+
+| onChange
+| Type: `(value: FieldValue) => void`. Call this when a user changes a facet filter selection. Pass the `value` from the corresponding selection from `options`.
+
+| onSelect
+| Type: `(value: FieldValue) => void`. Call this when a user adds a facet filter selection. Pass the `value` from the corresponding selection from `options`.
+
+| options
+| Type: `FacetValue[]`. The options to show available for selection for this facet. `selected` property will be true if this values is selected.
+
+| showMore
+| Type: `boolean`. Whether or not to show a "Show more" link. If there are no more options available to show, then this will be `false`.
+
+| values
+| Type: `FilterValue[]`. A list of all the selected values. This can also be deduced be inspected the `selected` properties of the `options`.
+
+| showSearch
+| Type: `boolean`. Whether or not the compopnent is `isFilterable`. This would indicates that a filter search box should be shown.
+
+| onSearch
+| Type: `(value: string) => void`. Call this to filter down the facet options shown. Used if there is a search box shown in relation to `showSearch`.
+
+| searchPlaceholder
+| Type: `string`. The placeholder fo show in the filter search box when `showSearch` is true.
+|===
+
+See https://github.com/elastic/search-ui/blob/main/packages/react-search-ui-views/src/MultiCheckboxFacet.tsx[MultiCheckboxFacet.tsx] for an example.
+
+When overriding Facet views, note that there are pre-built options that you can choose from, in addition to providing your own:
+
+[source,jsx]
+----
+import {
+ BooleanFacet,
+ SingleSelectFacet,
+ SingleLinksFacet
+} from "@elastic/react-search-ui-views";
+
+// Default out-of-the-box view
+
+
+// Choose an alternate out-of-the-box view
+
+----
diff --git a/docs/api-react-components-paging-info.asciidoc b/docs/api-react-components-paging-info.asciidoc
new file mode 100644
index 00000000..8b52fa5b
--- /dev/null
+++ b/docs/api-react-components-paging-info.asciidoc
@@ -0,0 +1,66 @@
+[[api-react-components-paging-info]]
+= PagingInfo
+
+// :keywords: demo
+
+Paging details, like "1 - 20 of 100 results".
+
+[discrete]
+[[api-react-components-paging-info-example]]
+== Example
+
+[source,jsx]
+----
+
+import { PagingInfo } from "@elastic/react-search-ui";
+
+...
+
+
+----
+
+[discrete]
+[[api-react-components-paging-info-properties]]
+== Properties
+
+|===
+| Name| Description
+
+| className
+|
+
+| view
+| Used to override the default view for this Component. See <> below.
+
+| *
+| Any other property passed will be passed through and available to use in a Custom View
+|===
+
+[discrete]
+[[api-react-components-paging-info-view-customization]]
+== View customization
+
+A complete guide to view customization can be found in the <> section.
+
+The following properties are available in the view:
+
+|===
+| Name| Description
+
+| className
+| Passed through from main component.
+
+| end
+| Type: `number`. The position of the last result shown on this page of reuslts.
+
+| searchTerm
+| Type: `string`. The current search term.
+
+| start
+| Type: `number`. The position of the first result shown on this page of reuslts.
+
+| totalResults
+| Type: `number`. The total number of results.
+|===
+
+See https://github.com/elastic/search-ui/blob/main/packages/react-search-ui-views/src/PagingInfo.tsx[PagingInfo.tsx] for an example.
diff --git a/docs/api-react-components-paging.asciidoc b/docs/api-react-components-paging.asciidoc
new file mode 100644
index 00000000..4ebc6463
--- /dev/null
+++ b/docs/api-react-components-paging.asciidoc
@@ -0,0 +1,66 @@
+[[api-react-components-paging]]
+= Paging
+
+// :keywords: Paging
+
+Navigate through pagination.
+
+[discrete]
+[[api-react-components-paging-example]]
+== Example
+
+[source,jsx]
+----
+
+import { Paging } from "@elastic/react-search-ui";
+
+...
+
+
+----
+
+[discrete]
+[[api-react-components-paging-properties]]
+== Properties
+
+|===
+| Name| Description
+
+| className
+|
+
+| view
+| Used to override the default view for this Component. See <> below.
+
+| *
+| Any other property passed will be passed through and available to use in a Custom View
+|===
+
+[discrete]
+[[api-react-components-paging-view-customization]]
+== View customization
+
+A complete guide to view customization can be found in the <> section.
+
+The following properties are available in the view:
+
+|===
+| Name| Description
+
+| className
+| Passed through from main component.
+
+| current
+| Type: `number`. The current page
+
+| resultsPerPage
+| Type: `number`. The number of results that are shown per page.
+
+| onChange
+| function(value: number) - call this with the newly selected page number
+
+| totalPages
+| Type: `number`. The total number of pages.
+|===
+
+See https://github.com/elastic/search-ui/blob/main/packages/react-search-ui-views/src/Paging.tsx[Paging.tsx] for an example.
diff --git a/docs/api-react-components-result.asciidoc b/docs/api-react-components-result.asciidoc
new file mode 100644
index 00000000..c8f0b210
--- /dev/null
+++ b/docs/api-react-components-result.asciidoc
@@ -0,0 +1,147 @@
+[[api-react-components-result]]
+= Result
+
+// :keywords: demo
+
+[discrete]
+[[api-react-components-result-result]]
+== Result
+
+Displays a search result.
+
+[discrete]
+[[api-react-components-result-example]]
+=== Example
+
+[source,jsx]
+----
+
+import { Result } from "@elastic/react-search-ui";
+
+...
+
+
+ {({ results }) => {
+ return (
+
+ {results.map(result => (
+
+ ))}
+
+ );
+ }}
+
+----
+
+[discrete]
+[[api-react-components-result-configuring-search-queries]]
+=== Configuring search queries
+
+Certain aspects of search results can be configured in `SearchProvider`, using the `searchQuery` configuration, such as
+term highlighting and search fields. See the <> guide
+for more information.
+
+[discrete]
+[[api-react-components-result-properties]]
+=== Properties
+
+|===
+| Name| Description
+
+| className
+|
+
+| titleField
+| Name of field to use as the title from each result.
+
+| shouldTrackClickThrough
+| Whether or not to track a clickthrough event when clicked.
+
+| clickThroughTags
+| Tags to send to analytics API when tracking clickthrough.
+
+| urlField
+| Name of field to use as the href from each result.
+
+| result
+| Type: `SearchResult`. An object representing the search result to render.
+
+| view
+| Used to override the default view for this Component. See <> below.
+
+| *
+| Any other property passed will be passed through and available to use in a Custom View
+|===
+
+[discrete]
+[[api-react-components-result-view-customization]]
+=== View customization
+
+A complete guide to view customization can be found in the <> section.
+
+Example:
+
+[source,jsx]
+----
+const CustomResultView = ({
+ result,
+ onClickLink
+}: {
+ result: SearchResult,
+ onClickLink: () => void
+}) => (
+
+ {/* use 'raw' values of fields to access values without snippets */}
+
+
+
+ {/* Use the 'snippet' property of fields with dangerouslySetInnerHtml to render snippets */}
+
+
+
+);
+
+;
+----
+
+The following properties are available in the view:
+
+|===
+| Name| Description
+
+| className
+| Passed through from main component.
+
+| result
+| Type: `SearchResult`. An object representing the search result to render.
+
+| onClickLink
+| function() - Call this when a link is clicked to trigger click tracking. Only triggered if `shouldTrackClickThrough` was set to true on the main component.
+
+| titleField
+| Passed through from main component. Not usually needed for custom views.
+
+| urlField
+| Passed through from main component. Not usually needed for custom views.
+
+| thumbnailField
+| Passed through from main component. Not usually needed for custom views.
+|===
+
+See https://github.com/elastic/search-ui/blob/main/packages/react-search-ui-views/src/Result.tsx[Result.tsx] for an example.
diff --git a/docs/api-react-components-results-per-page.asciidoc b/docs/api-react-components-results-per-page.asciidoc
new file mode 100644
index 00000000..9b72a0f1
--- /dev/null
+++ b/docs/api-react-components-results-per-page.asciidoc
@@ -0,0 +1,93 @@
+[[api-react-components-results-per-page]]
+= ResultsPerPage
+
+// :keywords: demo
+
+Shows a dropdown for selecting the number of results to show per page.
+
+Uses [20, 40, 60] as default options. You can use `options` prop to pass custom options.
+
+**Note:** When passing custom options make sure one of the option values match
+the current `resultsPerPageProp` value, which is 20 by default.
+To override `resultsPerPage` default value, use the <> property.
+
+[discrete]
+[[api-react-components-results-per-page-example]]
+== Example
+
+[source,jsx]
+----
+
+import { ResultsPerPage } from "@elastic/react-search-ui";
+
+...
+
+
+----
+
+[discrete]
+[[api-react-components-results-per-page-example-using-custom-options]]
+== Example using custom options
+
+[source,jsx]
+----
+
+import { SearchProvider, ResultsPerPage } from "@elastic/react-search-ui";
+
+
+
+
+----
+
+[discrete]
+[[api-react-components-results-per-page-properties]]
+== Properties
+
+|===
+| Name| Description
+
+| className
+|
+
+| options
+| Type: `number[]`. Dropdown options to select the number of results to show per page.
+
+| view
+| Used to override the default view for this Component. See <> below.
+
+| *
+| Any other property passed will be passed through and available to use in a Custom View.
+|===
+
+[discrete]
+[[api-react-components-results-per-page-view-customization]]
+== View customization
+
+A complete guide to view customization can be found in the <> section.
+
+The following properties are available in the view:
+
+|===
+| Name| Description
+
+| className
+| Passed through from main component.
+
+| onChange
+| function(value: number) - Call this function with the select value from `options` after a user has made a selection.
+
+| options
+| Passed through from main component.
+
+| value
+| The currently selected option.
+|===
+
+See https://github.com/elastic/search-ui/blob/main/packages/react-search-ui-views/src/ResultsPerPage.tsx[ResultsPerPage.tsx] for an example.
diff --git a/docs/api-react-components-results.asciidoc b/docs/api-react-components-results.asciidoc
new file mode 100644
index 00000000..9212a029
--- /dev/null
+++ b/docs/api-react-components-results.asciidoc
@@ -0,0 +1,88 @@
+[[api-react-components-results]]
+= Results
+
+// :description: Search UI React Results Component
+// :keywords: demo
+
+Displays all search results.
+
+[discrete]
+[[api-react-components-results-example]]
+== Example
+
+[source,jsx]
+----
+
+import { Results } from "@elastic/react-search-ui";
+
+...
+
+
+----
+
+[discrete]
+[[api-react-components-results-configuring-search-queries]]
+== Configuring search queries
+
+Certain aspects of search results can be configured in `SearchProvider`, using the `searchQuery` configuration, such as
+term highlighting and search fields. See the <> guide
+for more information.
+
+[discrete]
+[[api-react-components-results-properties]]
+== Properties
+
+|===
+| Name| Description
+
+| className
+|
+
+| titleField
+| Name of field to use as the title from each result.
+
+| shouldTrackClickThrough
+| Whether or not to track a clickthrough event when clicked.
+
+| clickThroughTags
+| Tags to send to analytics API when tracking clickthrough.
+
+| urlField
+| Name of field to use as the href from each result.
+
+| thumbnailField
+| Name of field to use for thumbnail image. Should be a valid URL and at least 220px wide.
+
+| resultView
+| See <>
+
+| view
+| Used to override the default view for this Component. See <> below.
+
+| *
+| Any other property passed will be passed through and available to use in a Custom View
+|===
+
+[discrete]
+[[api-react-components-results-view-customization]]
+== View customization
+
+A complete guide to view customization can be found in the <> section.
+
+This component accepts two view props: `view` and `resultView`. The `resultView` allows you to customize the individual result items that are displayed. The `view` prop allows you to customize that wrapper around those results, which by default is simply a `ul` element.
+
+A separate guide specifically for customizing the Result component can be found <>, which can be used for providing a `resultView` prop.
+
+The following properties are available in the view:
+
+|===
+| Name| Description
+
+| className
+| Passed through from main component
+
+| children
+|
+|===
+
+See https://github.com/elastic/search-ui/blob/main/packages/react-search-ui-views/src/Results.tsx[Results.tsx] for an example.
diff --git a/docs/api-react-components-search-box.asciidoc b/docs/api-react-components-search-box.asciidoc
new file mode 100644
index 00000000..b1ba0922
--- /dev/null
+++ b/docs/api-react-components-search-box.asciidoc
@@ -0,0 +1,574 @@
+[[api-react-components-search-box]]
+= SearchBox
+
+++++
+React components
+++++
+
+// :keywords: demo
+
+Input element which accepts search terms and triggers a new search query.
+
+[discrete]
+[[api-react-components-search-box-example]]
+== Example
+
+[source,jsx]
+----
+
+import { SearchBox } from "@elastic/react-search-ui";
+
+...
+
+
+----
+
+[discrete]
+[[api-react-components-search-box-configuring-search-queries]]
+== Configuring search queries
+
+The input from `SearchBox` will be used to trigger a new search query. That query can be further customized
+in the `SearchProvider` configuration, using the `searchQuery` property. See the <> guide for more information.
+
+[discrete]
+[[api-react-components-search-box-example-of-passing-custom-props-to-text-input-element]]
+== Example of passing custom props to text input element
+
+[source,jsx]
+----
+
+----
+
+[discrete]
+[[api-react-components-search-box-example-using-autocomplete-results]]
+== Example using autocomplete results
+
+"Results" are search results. The default behavior for autocomplete
+results is to link the user directly to a result when selected, which is why
+a "titleField" and "urlField" are required for the default view.
+
+[source,jsx]
+----
+
+----
+
+[discrete]
+[[api-react-components-search-box-example-using-autocomplete-suggestions]]
+== Example using autocomplete suggestions
+
+"Suggestions" are different than "results". Suggestions are suggested queries. Unlike an autocomplete result, a
+suggestion does not go straight to a result page when selected. It acts as a regular search query and
+refreshes the result set.
+
+[source,jsx]
+----
+
+----
+
+[discrete]
+[[api-react-components-search-box-example-using-autocomplete-suggestions-and-autocomplete-results]]
+== Example using autocomplete suggestions and autocomplete results
+
+The default view will show both results and suggestions, divided into
+sections. Section titles can be added to help distinguish between the two.
+
+[source,jsx]
+----
+
+----
+
+[discrete]
+[[api-react-components-search-box-example-retrieving-suggestions-from-another-index]]
+== Example retrieving suggestions from another index
+
+[IMPORTANT]
+====
+*Supported only by the Elasticsearch-connector.*
+====
+
+A different index can be used for the suggestions. Some examples:
+
+* Popular queries index from analytics
+* Brands index from product data
+* Categories index from product data
+
+Below we are using the `popular_queries` index and performing a prefix match search on the `query.suggest` field. One thing to note, make sure the api-key has access to the index.
+
+[discrete]
+[[api-react-components-search-box-autocomplete-configuration]]
+=== Autocomplete Configuration
+
+[source,jsx]
+----
+autocompleteQuery: {
+ suggestions: {
+ types: {
+ popularQueries: {
+ search_fields: {
+ "query.suggest": {} // fields used to query
+ },
+ result_fields: {
+ query: { // fields used for display
+ raw: {}
+ }
+ },
+ index: "popular_queries",
+ queryType: "results"
+ }
+ },
+ size: 4
+ }
+}
+----
+
+[discrete]
+[[api-react-components-search-box-component-configuration]]
+=== Component Configuration
+
+[source,jsx]
+----
+
+----
+
+You also have the option to customise the `view` of the autocomplete to show more fields.
+
+[discrete]
+[[api-react-components-search-box-configuring-autocomplete-queries]]
+== Configuring autocomplete queries
+
+Autocomplete queries can be customized in the `SearchProvider` configuration, using the `autocompleteQuery` property.
+See the <> for more information.
+
+[source,jsx]
+----
+
+
+
+----
+
+[discrete]
+[[api-react-components-search-box-example-using-multiple-types-of-autocomplete-suggestions]]
+== Example using multiple types of autocomplete suggestions
+
+"Suggestions" can be generated via multiple methods. They can be derived from
+common terms and phrases inside of documents, or be "popular" queries
+generated from actual search queries made by users. This will differ
+depending on the particular Search API you are using.
+
+**Note**: Elastic App Search currently only supports type "documents", and Elastic Site Search and Workplace Search
+do not support suggestions. This is purely illustrative in case a Connector is used that
+does support multiple types.
+
+[source,jsx]
+----
+
+
+
+----
+
+[discrete]
+[[api-react-components-search-box-example-using-autocomplete-in-a-site-header]]
+== Example using autocomplete in a site header
+
+This is an example from a https://www.gatsbyjs.org/[Gatsby] site, which overrides "submit" to navigate a user to the search
+page for suggestions, and maintaining the default behavior when selecting a result.
+
+[source,jsx]
+----
+ {
+ navigate("/search?q=" + searchTerm);
+ }}
+ onSelectAutocomplete={(selection, {}, defaultOnSelectAutocomplete) => {
+ if (selection.suggestion) {
+ navigate("/search?q=" + selection.suggestion);
+ } else {
+ defaultOnSelectAutocomplete(selection);
+ }
+ }}
+/>
+----
+
+[discrete]
+[[api-react-components-search-box-properties]]
+== Properties
+
+|===
+| Name| Description
+
+| className
+|
+
+| shouldClearFilters
+| Should existing filters be cleared when a new search is performed?
+
+| inputProps
+| Props for underlying 'input' element. I.e., `{ placeholder: "Enter Text"}`.
+
+| searchAsYouType
+| Executes a new search query with every key stroke. You can fine tune the number of queries made by adjusting the `debounceLength` parameter.
+
+| debounceLength
+| When using `searchAsYouType`, it can be useful to "debounce" search requests to avoid creating an excessive number of requests. This controls the length to debounce / wait.
+
+| autocompleteResults
+| Configure and autocomplete search results. Boolean option is primarily available for implementing custom views.
+
+| autocompleteSuggestions
+| Configure and autocomplete query suggestions. Boolean option is primarily available for implementing custom views. Configuration may or may not be keyed by "Suggestion Type", as APIs for suggestions may support may than 1 type of suggestion. If it is not keyed by Suggestion Type, then the configuration will be applied to the first type available.
+
+| autocompleteMinimumCharacters
+| Minimum number of characters before autocompleting.
+
+| onSelectAutocomplete
+| Allows overriding behavior when selected, to avoid creating an entirely new view. In addition to the current `selection`, various helpers are passed as `options` to the second parameter. This third parameter is the default `onSelectAutocomplete`, which allows you to defer to the original behavior.
+
+| onSubmit
+| Allows overriding behavior when submitted. Receives the search term from the search box.
+
+| autocompleteView
+| Used to override only the autocomplete dropdown. See <> below.
+
+| inputView
+| Used to override only the input box. See <> below.
+
+| view
+| Used to override the default view for this Component. See <> below.
+
+| *
+| Any other property passed will be passed through and available to use in a Custom View
+|===
+
+[discrete]
+[[api-react-components-search-box-autocompleteresultsoptions]]
+=== AutocompleteResultsOptions
+
+|===
+| Name| Description
+
+| linkTarget
+| Used to open links in a new tab.
+
+| sectionTitle
+| Title to show in section within dropdown.
+
+| shouldTrackClickThrough
+| Only applies to Results, not Suggestions.
+
+| clickThroughTags
+| Tags to send to analytics API when tracking clickthrough.
+
+| titleField
+| Field within a Result to use as the "title".
+
+| urlField
+| Field within a Result to use for linking.
+|===
+
+[discrete]
+[[api-react-components-search-box-autocompletesuggestionsoptions]]
+=== AutocompleteSuggestionsOptions
+
+|===
+| Name| Description
+
+| sectionTitle
+| Title to show in section within dropdown
+|===
+
+[discrete]
+[[api-react-components-search-box-view-customization]]
+== View customization
+
+A complete guide to view customization can be found in the <> section.
+
+[discrete]
+[[api-react-components-search-box-full-view-customization]]
+=== Full view customization
+
+You can customize the entire view using the `view` prop. This is useful to use an entirely different
+autocomplete library (we use https://github.com/downshift-js/downshift[downshift]). A SearchBox component at its simplest could look like the following:
+
+[source,jsx]
+----
+ (
+
+ )}
+/>
+----
+
+The full list of props available to this view are as follows:
+
+|===
+| Name| Description
+
+| className
+| Passed through from main component.
+
+| inputView
+a| Component to use for text input. When rendering, pass all props documented below in the <> section.
+
+Note that this can be challenging to do since some of the required props are generated by Downshift. It's generally advised not to try to use this property directly when creating a custom view.
+
+| isFocused
+| Type: `boolean`. Whether or not the input currently has focus. Will only work if you have correct spread `inputProps` over your input box.
+
+| onChange
+| Type: `(value: string) => void`. When a user changes the input of the search input box, call this with the new value.
+
+| onSubmit
+| Type: `(e: FormEvent) => void`. Handle a "submission" of the search box. Typically used directly on a `form` element surrounding your input box.
+
+| value
+| Type: `string`. The current user input to show in the input box.
+
+| inputProps
+| An object containing props that should be spread over the input box element. You'll need to do this in order to have the `isFocused` prop work.
+
+| autocompleteView
+a| Component to use for Autocomplete. When rendering, pass all props documented below in the <> section.
+
+Note that this can be challenging to do since some of the required props are generated by Downshift. It's generally advised not to try to use this property directly when creating a custom view.
+
+| completeSuggestion
+| Type: `(searchQuery: string) => void`.
+
+| notifyAutocompleteSelected
+| Type: `(selection: any) => void`.
+
+| autocompletedSuggestionsCount
+| Type: `number`.
+
+| autocompleteSuggestions
+| Type: +boolean {vbar} AutocompleteSuggestion+.
+
+| autocompletedSuggestions
+| Type: `AutocompletedSuggestions`.
+
+| autocompletedResults
+| Type: `AutocompletedResult[]`.
+
+| autocompleteResults
+| Type: +AutocompleteResult {vbar} boolean+.
+
+| onSelectAutocomplete
+| Type: `(selectedItem: any) => void`. Call this with the selected item (whether it is a result or a suggestion) when an autocomplete selection is made in the autocomplete dropdown.
+
+| allAutocompletedItemsCount
+| Type: `number`. The number of items that would be shown in an autocomplete. If 0, no need to show the autocomplete.
+
+| useAutocomplete
+| Type: `boolean`. Whether or not to show an autocomplete dropdown.
+|===
+
+See https://github.com/elastic/search-ui/blob/main/packages/react-search-ui-views/src/SearchBox.tsx[SearchBox.tsx] for an example.
+
+[discrete]
+[[api-react-components-search-box-input-view-customization]]
+=== Input view customization
+
+For making small customizations, like simply hiding the search button, or rearranging DOM structure, full customization is often overkill.
+
+You can also just customize the input section of the search box using the `inputView` prop.
+
+[source,jsx]
+----
+ (
+ <>
+
+
+ {getAutocomplete()}
+
+
+ >
+ )}
+/>
+----
+
+Note that `getInputProps` and `getButtonProps` are
+https://kentcdodds.com/blog/how-to-give-rendering-control-to-users-with-prop-getters[prop getters].
+They are meant return a props object to spread over their corresponding UI elements. This lets you arrange
+elements however you'd like in the DOM. It also lets you pass additional properties. You should pass properties
+through these functions, rather directly on elements, in order to not override base values. For instance,
+adding a `className` through these functions will assure that the className is only appended, not overriding the base class values.
+
+`getAutocomplete` is used to determine where the autocomplete dropdown will be shown.
+
+The full list of props available to this view are as follows:
+
+|===
+| Name| Description
+
+| getAutocomplete
+| Type: `() => JSX.Element`. Call this method wherever you would like your autocomplete to appear. Typically, directly below your input box.
+
+| getButtonProps
+| Type: `() => Object`. Spread the return value of this function over your "Search" button, which submit your search.
+
+| getInputProps
+| Type: `() => JSX`. Spread the return value of this function over the `input` element you are using for your search box.
+|===
+
+See https://github.com/elastic/search-ui/blob/main/packages/react-search-ui-views/src/SearchInput.tsx[SearchInput.tsx] for an example.
+
+[discrete]
+[[api-react-components-search-box-autocomplete-view-customization]]
+=== Autocomplete view customization
+
+In addition to the `inputView` customization, you can also make targed customization to the autocomplete view using the `autocompleteView` prop.
+
+For example:
+
+[source,jsx]
+----
+ (
+
+ {autocompletedResults.map((result, i) => (
+
+ Result {i}: {result.title.snippet}
+
+ ))}
+
+ )}
+/>
+----
+
+The full list of props available to this view are as follows:
+
+|===
+| Name| Description
+
+| allAutocompletedItemsCount
+| Type: `number`. The number of items that would be shown in an autocomplete. If 0, no need to show the autocomplete.
+
+| autocompleteResults
+| Type: +boolean {vbar} AutocompleteResult+. Configuration object passed through from main component.
+
+| autocompletedResults
+| Type: `AutocompletedResult[]`. The search results generated by an autocomplete query.
+
+| autocompletedSuggestions
+| Type: `AutocompletedSuggestions`. The suggestions generated by an autocomplete suggestions query.
+
+| autocompletedSuggestionsCount
+| Type: `number`. The total number of suggestions generated by an autocomplete suggestions query.
+
+| autocompleteSuggestions
+| Type: +boolean {vbar} AutocompleteSuggestion+. Configuration object passed through from main component.
+
+| onSelectAutocomplete
+| Type: `(selectedItem: any) => void`. Call this with the selected item (whether it is a result or a suggestion) when an autocomplete selection is made in the autocomplete dropdown.
+
+| getItemProps
+| Type: `{ key: string, index: number, item: AutocompletedSuggestion }) => any`. A function that will generate props to spread over an individual item in the autocomplete list.
+
+| getMenuProps
+| Type: `({ className: string }) => any`. A function that will generate props to spread over the main autocomplete dropdown element.
+|===
+
+See https://github.com/elastic/search-ui/blob/main/packages/react-search-ui-views/src/Autocomplete.tsx[Autocomplete.tsx] for an example.
diff --git a/docs/api-react-components-sorting.asciidoc b/docs/api-react-components-sorting.asciidoc
new file mode 100644
index 00000000..79d30043
--- /dev/null
+++ b/docs/api-react-components-sorting.asciidoc
@@ -0,0 +1,85 @@
+[[api-react-components-sorting]]
+= Sorting
+
+// :keywords: demo
+
+Shows a dropdown for selecting the current Sort.
+
+[discrete]
+[[api-react-components-sorting-example]]
+== Example
+
+[source,jsx]
+----
+
+import { Sorting } from "@elastic/react-search-ui";
+
+...
+
+
+----
+
+[discrete]
+[[api-react-components-sorting-properties]]
+== Properties
+
+|===
+| Name| Description
+
+| className
+|
+
+| label
+| A static label to show in the Sorting Component.
+
+| sortOptions
+|
+
+| view
+| Used to override the default view for this Component. See <> below.
+
+| *
+| Any other property passed will be passed through and available to use in a Custom View
+|===
+
+[discrete]
+[[api-react-components-sorting-view-customization]]
+== View customization
+
+A complete guide to view customization can be found in the <> section.
+
+The following properties are available in the view:
+
+|===
+| Name| Description
+
+| className
+| Passed through from main component.
+
+| label
+| The label to display for this component. For example: "Sort by".
+
+| onChange
+| function(value: string) - Pass the value to this callback from the selected sort option
+
+| options
+| `{ value: string; label: string;}[]` - Options to display
+
+| value
+| string - The currently selected value
+|===
+
+See https://github.com/elastic/search-ui/blob/main/packages/react-search-ui-views/src/Sorting.tsx[Sorting.tsx] for an example.
diff --git a/docs/api-react-search-provider.asciidoc b/docs/api-react-search-provider.asciidoc
new file mode 100644
index 00000000..cfac5e59
--- /dev/null
+++ b/docs/api-react-search-provider.asciidoc
@@ -0,0 +1,149 @@
+[[api-react-search-provider]]
+= SearchProvider
+
+++++
+React API
+++++
+
+// :keywords: core
+
+The `SearchProvider` is a React wrapper around the Headless Core, and makes state and actions available to Search UI
+and in a React https://reactjs.org/docs/context.html[Context], and also via a
+https://reactjs.org/docs/render-props.html[Render Prop].
+
+It looks like this:
+
+[source,jsx]
+----
+import { SearchProvider, SearchBox } from "@elastic/react-search-ui";
+import AppSearchAPIConnector from "@elastic/search-ui-app-search-connector";
+
+const connector = new AppSearchAPIConnector({
+ searchKey: "search-371auk61r2bwqtdzocdgutmg",
+ engineName: "search-ui-examples",
+ endpointBase: "http://my-app-search-host:3002"
+});
+
+const configurationOptions = {
+ apiConnector: connector,
+ searchQuery: { ... },
+ autocompleteQuery: { ... },
+ hasA11yNotifications: true,
+ a11yNotificationMessages: {
+ searchResults: ({ start, end, totalResults, searchTerm }) =>
+ `Searching for "${searchTerm}". Showing ${start} to ${end} results out of ${totalResults}.`
+ },
+ alwaysSearchOnInitialLoad: true
+};
+
+const App = () => (
+
+
+
+
+
+);
+----
+
+|===
+| option| type| description
+
+| `apiConnector`
+| APIConnector
+| Instance of a Connector. See Connectors API section.
+
+| `onSearch`
+| function
+| You may provide individual handlers instead of a Connector, override individual Connector handlers, or act as middleware to Connector methods.
+// See <> for more information.
+
+| `onAutocomplete`
+| function
+| You may provide individual handlers instead of a Connector, override individual Connector handlers, or act as middleware to Connector methods.
+// See <> for more information.
+
+| `onResultClick`
+| function
+| You may provide individual handlers instead of a Connector, override individual Connector handlers, or act as middleware to Connector methods.
+// See <> for more information.
+
+| `onAutocompleteResultClick`
+| function
+| You may provide individual handlers instead of a Connector, override individual Connector handlers, or act as middleware to Connector methods.
+// See <> for more information.
+
+| `autocompleteQuery`
+| <>
+| Configuration options for the autocomplete query.
+
+| `debug`
+| Boolean
+| Trace log actions and state changes. Default is false.
+
+| `initialState`
+| Object
+| Set inital state of Search UI. See <> for more information.
+
+| `searchQuery`
+| <>
+| Configuration options for the main search query.
+
+| `trackUrlState`
+| Boolean
+| By default, <> will be synced with the browser url. To turn this off, pass `false`.
+
+| `urlPushDebounceLength`
+| Integer
+| The amount of time in milliseconds to debounce/delay updating the browser url after the UI update. This, for example, prevents excessive history entries while a user is still typing in a live search box. Default is 500.
+
+| `hasA11yNotifications`
+| Boolean
+| Search UI will create a visually hidden live region to announce search results & other actions to screen reader users. This accessibility feature will be turned on by default in our 2.0 release. Default is false.
+
+| `a11yNotificationMessages`
+| Object
+| You can override our default screen reader packages/search-ui/src/A11yNotifications.js#L49[messages] (e.g. for localization), or create your own custom notification, by passing in your own key and message function(s).
+
+| `alwaysSearchOnInitialLoad`
+| Boolean
+| If true, Search UI will always do an initial search, even when no inital Request State is set.
+|===
+
+[discrete]
+[[api-react-search-provider-context]]
+== Context
+
+The "Context" is a flattened object containing, as keys, all <> and <>.
+
+We refer to it as "Context" because it is implemented with a https://reactjs.org/docs/context.html[React Context].
+
+ex.
+
+[source,js]
+----
+{
+ resultsPerPage: 10, // Request State
+ setResultsPerPage: () => {}, // Action
+ current: 1, // Request State
+ setCurrent: () => {}, // Action
+ error: '', // Response State
+ isLoading: false, // Response State
+ totalResults: 1000, // Response State
+ ...
+}
+----
+
+[discrete]
+[[api-react-search-provider-initial-state]]
+== Initial State
+
+This is useful for defaulting a search term, sort, etc.
+
+Example
+
+[source,js]
+----
+ initialState: { searchTerm: "test", resultsPerPage: 40 }
+----
+
+See <> for more properties that can be set in initial state.
diff --git a/docs/api-react-with-search.asciidoc b/docs/api-react-with-search.asciidoc
new file mode 100644
index 00000000..b35d0742
--- /dev/null
+++ b/docs/api-react-with-search.asciidoc
@@ -0,0 +1,103 @@
+[[api-react-with-search]]
+= WithSearch & withSearch
+
+// :keywords: component hocs
+
+If you wish to use Search UI and build your own custom component, you will need to use our HOCs to use Search UI's core state and actions.
+
+There are two HOCs for accessing Search UI's state & actions, `withSearch` and
+`WithSearch`. They use the https://reactjs.org/docs/higher-order-components.html[HOC] and
+https://reactjs.org/docs/render-props.html[Render Props] patterns, respectively. The two methods
+are similar, and choosing between the two is mostly personal preference.
+
+Both methods expose a `mapContextToProps` function which allows you to pick which state and actions
+from context you need to work with.
+
+[discrete]
+[[api-react-with-search-mapcontexttoprops]]
+== mapContextToProps
+
+`mapContextToProps` allows you to pick which state and actions
+from Context you need to work with. `withSearch` and `WithSearch` both use https://reactjs.org/docs/react-api.html#reactpurecomponent[React.PureComponent],
+and will only re-render when the picked state has changed.
+
+|===
+| name| type| description
+
+| context
+| Object
+| The current Context
+
+| props
+| Object
+| The current props
+|===
+
+ex.:
+
+[source,jsx]
+----
+import { withSearch } from "@elastic/react-search-ui";
+
+const Component = ({ searchTerm, setSearchTerm }) => {
+ return (
+