├── .eslintrc.yml ├── .github └── workflows │ ├── js-tests.yml │ └── npm-publish.yml ├── .gitignore ├── .prettierrc ├── CHANGES.md ├── LICENSE ├── README.md ├── deploy_docs.sh ├── docs ├── docs │ ├── assets │ │ ├── getting_started_resultslist.png │ │ ├── getting_started_search.png │ │ └── url_params.gif │ ├── components │ │ ├── active_filters.md │ │ ├── bucket_aggregation.md │ │ ├── count.md │ │ ├── empty_results.md │ │ ├── error.md │ │ ├── layout_switcher.md │ │ ├── pagination.md │ │ ├── react_search_kit.md │ │ ├── results_grid.md │ │ ├── results_list.md │ │ ├── results_loader.md │ │ ├── results_multi_layout.md │ │ ├── results_per_page.md │ │ ├── search_bar.md │ │ ├── sort.md │ │ ├── sort_by.md │ │ ├── sort_order.md │ │ ├── toggle.md │ │ └── with_state.md │ ├── connect_your_rest_apis.md │ ├── create_your_component.md │ ├── filters_aggregations.md │ ├── getting_started.md │ ├── main_concepts.md │ ├── ui_customisation.md │ └── using_url_parameters.md └── website │ ├── README.md │ ├── core │ └── Footer.js │ ├── package-lock.json │ ├── package.json │ ├── pages │ └── en │ │ ├── help.js │ │ └── index.js │ ├── sidebars.json │ ├── siteConfig.js │ └── static │ ├── css │ ├── code-blocks-buttons.css │ └── custom.css │ ├── img │ ├── docusaurus.svg │ ├── favicon.png │ ├── favicon │ │ └── favicon.ico │ ├── logo-cern.png │ ├── oss_logo.png │ └── screenshot.png │ └── js │ └── code-blocks-buttons.js ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── index.html └── manifest.json ├── rollup.config.js └── src ├── demos ├── App.js ├── cern-videos-namespaced │ ├── Results.js │ ├── app.js │ ├── cern-videos-2 │ │ ├── App.js │ │ └── index.js │ └── cern-videos-3 │ │ ├── App.js │ │ └── index.js ├── cern-videos │ ├── App.js │ ├── Results.js │ └── index.js ├── opensearch │ ├── App.js │ ├── DemoOSRequestSerializer.js │ ├── Results.js │ ├── docker │ │ ├── docker-compose.yml │ │ ├── nginx │ │ │ ├── Dockerfile │ │ │ └── site.conf │ │ ├── os-random-data.json │ │ └── os2-mappings.json │ └── index.js └── zenodo │ ├── App.js │ ├── Results.js │ └── index.js ├── index.js ├── lib ├── api │ ├── UrlHandlerApi.js │ ├── UrlHandlerApi.test.js │ ├── UrlParamValidator.js │ ├── contrib │ │ ├── index.js │ │ ├── invenio │ │ │ ├── InvenioRecordsResourcesRequestSerializer.js │ │ │ ├── InvenioRecordsResourcesRequestSerializer.test.js │ │ │ ├── InvenioRequestSerializer.js │ │ │ ├── InvenioRequestSerializer.test.js │ │ │ ├── InvenioResponseSerializer.js │ │ │ ├── InvenioSearchApi.js │ │ │ ├── InvenioSearchApi.test.js │ │ │ ├── InvenioSuggestionApi.js │ │ │ └── index.js │ │ └── opensearch │ │ │ ├── OSRequestSerializer.js │ │ │ ├── OSRequestSerializer.test.js │ │ │ ├── OSResponseSerializer.js │ │ │ ├── OSSearchApi.js │ │ │ ├── OSSearchApi.test.js │ │ │ └── index.js │ ├── errors.js │ └── index.js ├── components │ ├── ActiveFilters │ │ ├── ActiveFilters.js │ │ └── index.js │ ├── AutocompleteSearchBar │ │ ├── AutocompleteSearchBar.js │ │ ├── AutocompleteSearchBar.scss │ │ └── index.js │ ├── Bootstrap │ │ ├── Bootstrap.js │ │ ├── Bootstrap.test.js │ │ └── index.js │ ├── BucketAggregation │ │ ├── BucketAggregation.js │ │ ├── BucketAggregationValues.js │ │ └── index.js │ ├── Count │ │ ├── Count.js │ │ └── index.js │ ├── EmptyResults │ │ ├── EmptyResults.js │ │ └── index.js │ ├── Error │ │ ├── Error.js │ │ └── index.js │ ├── HOC │ │ ├── index.js │ │ ├── withState.js │ │ └── withState.test.js │ ├── LayoutSwitcher │ │ ├── LayoutSwitcher.js │ │ └── index.js │ ├── Pagination │ │ ├── Pagination.js │ │ └── index.js │ ├── ReactSearchKit │ │ ├── AppContext.js │ │ ├── ReactSearchKit.js │ │ ├── ReactSearchKit.test.js │ │ └── index.js │ ├── ResultsGrid │ │ ├── ResultsGrid.js │ │ └── index.js │ ├── ResultsList │ │ ├── ResultsList.js │ │ └── index.js │ ├── ResultsLoader │ │ ├── ResultsLoader.js │ │ └── index.js │ ├── ResultsMultiLayout │ │ ├── ResultsMultiLayout.js │ │ └── index.js │ ├── ResultsPerPage │ │ ├── ResultsPerPage.js │ │ └── index.js │ ├── SearchBar │ │ ├── SearchBar.js │ │ └── index.js │ ├── ShouldRender │ │ ├── ShouldRender.js │ │ └── index.js │ ├── Sort │ │ ├── Sort.js │ │ └── index.js │ ├── SortBy │ │ ├── SortBy.js │ │ └── index.js │ ├── SortOrder │ │ ├── SortOrder.js │ │ └── index.js │ ├── Toggle │ │ ├── Toggle.js │ │ └── index.js │ └── index.js ├── events.js ├── index.js ├── state │ ├── actions │ │ ├── index.js │ │ ├── query.js │ │ └── query.test.js │ ├── reducers │ │ ├── app.js │ │ ├── index.js │ │ ├── query.js │ │ └── results.js │ ├── selectors │ │ ├── index.js │ │ ├── query.js │ │ └── query.test.js │ └── types │ │ └── index.js ├── store.js ├── storeConfig.js └── util.js ├── polyfill.js └── setupTests.js /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | extends: 2 | - '@inveniosoftware/invenio' 3 | - '@inveniosoftware/invenio/prettier' 4 | 5 | env: 6 | browser: true 7 | es6: true 8 | jest: true 9 | -------------------------------------------------------------------------------- /.github/workflows/js-tests.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | schedule: 11 | # * is a special character in YAML so you have to quote this string 12 | - cron: '0 2 * * 5' 13 | workflow_dispatch: 14 | inputs: 15 | reason: 16 | description: 'Reason' 17 | required: false 18 | default: 'Manual trigger' 19 | 20 | jobs: 21 | Tests: 22 | runs-on: ubuntu-latest 23 | 24 | strategy: 25 | matrix: 26 | node-version: [22.x, 18.x, 16.x] 27 | 28 | steps: 29 | - name: Checkout 30 | uses: actions/checkout@v4 31 | 32 | - name: Use Node.js ${{ matrix.node-version }} 33 | uses: actions/setup-node@v4 34 | with: 35 | node-version: ${{ matrix.node-version }} 36 | 37 | - name: Install & Build 38 | run: npm ci 39 | 40 | - name: Lint 41 | run: npm run lint 42 | 43 | - name: Test 44 | run: npm test 45 | 46 | - name: Coverage 47 | run: npm test -- --coverage 48 | -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | push: 5 | tags: 6 | - v* 7 | 8 | jobs: 9 | Publish: 10 | runs-on: ubuntu-20.04 11 | 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v3 15 | 16 | - name: Setup Node.js 17 | uses: actions/setup-node@v3 18 | with: 19 | node-version: '18.x' 20 | registry-url: 'https://registry.npmjs.org' 21 | 22 | - name: Install and Build 23 | run: | 24 | npm ci 25 | npm run build 26 | 27 | - name: Deploy docs 28 | run: bash deploy_docs.sh 29 | env: 30 | GH_EMAIL: info@inveniosoftware.org 31 | GH_NAME: inveniobot 32 | GH_TOKEN: ${{secrets.GITHUB_TOKEN}} 33 | 34 | - name: Publish on NPM 35 | run: npm publish 36 | env: 37 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Subset of: https://github.com/github/gitignore/blob/master/Node.gitignore 2 | # Logs 3 | logs 4 | *.log 5 | npm-debug.log* 6 | yarn-debug.log* 7 | yarn-error.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | *.lcov 18 | 19 | # Dist folder 20 | dist 21 | 22 | # Dependency directories 23 | node_modules/ 24 | jspm_packages/ 25 | 26 | # Optional npm cache directory 27 | .npm 28 | 29 | # Optional eslint cache 30 | .eslintcache 31 | 32 | # Output of 'npm pack' 33 | *.tgz 34 | 35 | # Yarn Integrity file 36 | .yarn-integrity 37 | 38 | # dotenv environment variables file 39 | .env 40 | .env.test 41 | 42 | # yarn v2 43 | .yarn/cache 44 | .yarn/unplugged 45 | .yarn/build-state.yml 46 | .pnp.* 47 | 48 | # Documentation 49 | /docs/website/build 50 | /docs/website/node_modules 51 | /docs/website/i18n 52 | 53 | # VSCode 54 | .history 55 | 56 | **.DS_Store -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | "@inveniosoftware/eslint-config-invenio/prettier-config" 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (C) 2015-2019 CERN. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | # React-SearchKit 10 | 11 | ![Build status](https://github.com/inveniosoftware/react-searchkit/workflows/CI/badge.svg) 12 | [![Release](https://img.shields.io/npm/v/react-searchkit)](https://www.npmjs.com/package/react-searchkit) 13 | [![License](https://img.shields.io/github/license/inveniosoftware/react-searchkit)](https://github.com/inveniosoftware/react-searchkit/blob/master/LICENSE) 14 | [![Downloads](https://img.shields.io/npm/dm/react-searchkit)](https://www.npmjs.com/package/react-searchkit) 15 | 16 | React-SearchKit is a React library that allows you to build in an easy way your search application. 17 | 18 | Main features: 19 | 20 | - ready-to-use collection of UI components 21 | - configurable REST API endpoint and serialization 22 | - configurable URL parameters handling for deep linking 23 | 24 | ![React-SearchKit screenshot](docs/website/static/img/screenshot.png) 25 | 26 | ## Examples 27 | 28 | You can find a collection of examples in the `src/demos` folder: 29 | 30 | - OpenSearch, an example on how to query OpenSearch (see below) 31 | - Zenodo.org, an example on how to query an Invenio 3 instance 32 | - CERN Videos, another Invenio 3 example 33 | 34 | Install dependencies and run the React app to try them out (see steps below). 35 | 36 | ### OpenSearch 37 | 38 | To run the OpenSearch backend for the demo, you can use Docker. A `docker-compose` file with `ES 7` and `nginx` as reverse proxy is available and ready to use. 39 | Run the services: 40 | 41 | ```bash 42 | cd src/demos/opensearch/docker 43 | docker-compose up 44 | ``` 45 | 46 | Then, init the demo data: 47 | 48 | ```bash 49 | curl -XPUT 'http://localhost:9200/random?pretty' -H 'Content-Type: application/json' -d @os2-mappings.json 50 | curl -XPOST 'http://localhost:9200/random/_bulk' -H 'Content-Type: application/json' --data-binary @os-random-data.json 51 | curl -XGET 'http://localhost:9200/random/_count?pretty' 52 | ``` 53 | 54 | Demo data have been randomly generated using . 55 | 56 | > Delete data in the cluster: `curl -X DELETE 'http://localhost:9200/_all'` 57 | 58 | ## Developer guide 59 | 60 | React-SearchKit uses [create-react-app](https://create-react-app.dev/) as development toolkit. 61 | 62 | Install the library: 63 | 64 | ```bash 65 | npm install 66 | ``` 67 | 68 | Start the demo application: 69 | 70 | ```bash 71 | npm start 72 | ``` 73 | 74 | The library uses [Jest](https://jestjs.io/) as test runner. To run the tests: 75 | 76 | ```bash 77 | npm test 78 | ``` 79 | 80 | The library uses `rollup` to build a final version inside the `/dist` folder and it will build CommonJS and ES Modules versions: 81 | 82 | ```bash 83 | npm run build 84 | ``` 85 | -------------------------------------------------------------------------------- /deploy_docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | git config --global user.name "${GH_NAME}" 4 | git config --global user.email "${GH_EMAIL}" 5 | echo "machine github.com login ${GH_NAME} password ${GH_TOKEN}" > ~/.netrc 6 | cd docs/website && npm install && GIT_USER="${GH_NAME}" npm run publish-gh-pages 7 | -------------------------------------------------------------------------------- /docs/docs/assets/getting_started_resultslist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inveniosoftware/react-searchkit/761a35be4e478a7783b9d81d8af3cf3beb74425c/docs/docs/assets/getting_started_resultslist.png -------------------------------------------------------------------------------- /docs/docs/assets/getting_started_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inveniosoftware/react-searchkit/761a35be4e478a7783b9d81d8af3cf3beb74425c/docs/docs/assets/getting_started_search.png -------------------------------------------------------------------------------- /docs/docs/assets/url_params.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inveniosoftware/react-searchkit/761a35be4e478a7783b9d81d8af3cf3beb74425c/docs/docs/assets/url_params.gif -------------------------------------------------------------------------------- /docs/docs/components/active_filters.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: active-filters 3 | title: ActiveFilters 4 | --- 5 | 6 | `ActiveFilters` renders the current selected filters by the user as a list of labels. 7 | 8 | Each label has a `close` icon which can be clicked to remove the selected filter. 9 | 10 | ## Usage 11 | 12 | ```jsx 13 | 14 | ``` 15 | 16 | ## Props 17 | 18 | * **overridableId** `String` *optional* 19 | 20 | An optional string to define a specific overridable id. 21 | 22 | ## Usage when overriding 23 | 24 | ```jsx 25 | const MyActiveFilters = ({ filters, removeActiveFilter, getLabel }) => { 26 | ... 27 | } 28 | 29 | const overriddenComponents = { 30 | "ActiveFilters.element": MyActiveFilters 31 | }; 32 | ``` 33 | 34 | ### Parameters 35 | 36 | * **filters** `Array` 37 | 38 | The `filters` `query` state. It contains the list of active filters selected by the user. Each element is a list `[ "", "" ]`. 39 | 40 | * **removeActiveFilter** `Function` 41 | 42 | Function to be called with the active filter list as parameter if you want to remove one of the active filters `removeActiveFilter()`. 43 | 44 | * **getLabel** `Function` 45 | 46 | Function to be called to get a display label for the given active filter `getLabel(filter)`. 47 | -------------------------------------------------------------------------------- /docs/docs/components/bucket_aggregation.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: bucket-aggregation 3 | title: BucketAggregation 4 | --- 5 | 6 | `BucketAggregation` renders the list of search results aggregations as checkboxes. 7 | 8 | By default it supports child aggregations. The user can select aggregations to filter results. 9 | 10 | ## Usage 11 | 12 | ```jsx 13 | 24 | ``` 25 | 26 | ## Props 27 | 28 | * **title** `String` 29 | 30 | The title to display for the aggregation. 31 | 32 | * **agg** `Object` 33 | 34 | An object that describes the aggregation to look for in the `results`: 35 | 36 | * **field** `String`: the field name 37 | 38 | * **aggName** `String`: the aggregation name to look for in `results` 39 | 40 | * **childAgg** `Object`: a child aggregation with the same format as the `agg` prop 41 | 42 | * **overridableId** `String` *optional* 43 | 44 | An optional string to define a specific overridable id. 45 | 46 | ## Usage when overriding 47 | 48 | ```jsx 49 | const MyBucketAggregation = ({title, containerCmp}) => { 50 | return ( 51 | 52 | 53 | {title} 54 | {containerCmp} 55 | 56 | 57 | ); 58 | } 59 | 60 | const BucketAggregationContainer = ({ valuesCmp }) => { 61 | ... 62 | } 63 | 64 | const MyBucketAggregationValues = ({ bucket, label, onFilterClicked, isSelected, childAggCmps }) => { 65 | ... 66 | } 67 | 68 | const overriddenComponents = { 69 | "BucketAggregation.element": MyBucketAggregation, 70 | "BucketAggregationContainer.element": MyBucketAggregationContainer, 71 | "BucketAggregationValues.element": MyBucketAggregationValues, 72 | }; 73 | ``` 74 | 75 | ### BucketAggregation parameters 76 | 77 | Component that wraps the bucket aggregations and renders a title and the container of aggregations. 78 | 79 | * **title** `String` 80 | 81 | The title to render. 82 | 83 | * **containerCmp** `React component` 84 | 85 | The `BucketAggregationContainer` to render. 86 | 87 | * **agg** `Object` 88 | 89 | Same object as in the props. 90 | 91 | * **updateQueryFilters** `Function` 92 | 93 | A function to call to update the current selected filters. 94 | 95 | ### BucketAggregationContainer parameters 96 | 97 | Component that wraps the list of aggregations. 98 | 99 | * **valuesCmp** `React component` 100 | 101 | List of components of each aggregation value. 102 | 103 | ### BucketAggregationValues parameters 104 | 105 | Component that renders each of the aggregation. 106 | 107 | * **bucket** `Array` 108 | 109 | The bucket to display, which by default contains the `key` field with the value and the `doc_count` number. 110 | 111 | * **label** `String` 112 | 113 | The label to display. 114 | 115 | * **isSelected** `Boolean` 116 | 117 | `true` if this value is active/selected, `false` otherwise. 118 | 119 | * **onFilterClicked** `Function` 120 | 121 | The function to be called when the user click on this value to activate the filter. It should be called with the `bucket.key` parameter. 122 | 123 | * **getChildAggCmps** `Function` 124 | 125 | A function to be called to render child component. It accepts the current `bucket` as parameter and it will render recursively this component. It returns a list of child components. 126 | -------------------------------------------------------------------------------- /docs/docs/components/count.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: count 3 | title: Count 4 | --- 5 | 6 | `Count` renders the number of search results. 7 | 8 | Useful to display the total number of results after a search. 9 | 10 | The component is **not** displayed while executing the search query or if there are no results. 11 | 12 | ## Usage 13 | 14 | ```jsx 15 | 16 | ``` 17 | 18 | ## Props 19 | 20 | - **label** `Function` _optional_ 21 | 22 | An optional function to wrap the component with a prefix and suffix string.
23 | E.g. `label={(cmp) => <> Found {cmp} results} />` 24 | 25 | * **overridableId** `String` *optional* 26 | 27 | An optional string to define a specific overridable id. 28 | 29 | ## Usage when overriding 30 | 31 | ```jsx 32 | const MyCount = ({ totalResults }) => { 33 | return
Found {totalResults} results.
; 34 | } 35 | 36 | const overriddenComponents = { 37 | "Count.element": MyCount 38 | }; 39 | ``` 40 | 41 | ### Parameters 42 | 43 | * **totalResults** `Number` 44 | 45 | The current value of the `total` `results` state representing the number of results. 46 | -------------------------------------------------------------------------------- /docs/docs/components/empty_results.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: empty-results 3 | title: EmptyResults 4 | --- 5 | 6 | `EmptyResults` is a component that renders in case of 0 results. 7 | 8 | The component is **not** displayed while executing the search query, when there is no error or when the number of 9 | results is greater than 0. 10 | 11 | ## Usage 12 | 13 | ```jsx 14 | 15 | ``` 16 | 17 | ## Props 18 | 19 | * **overridableId** `String` *optional* 20 | 21 | An optional string to define a specific overridable id. 22 | 23 | ## Usage when overriding 24 | 25 | ```jsx 26 | const MyEmptyResults = ({ queryString, resetQuery, extraContent }) => { 27 | ... 28 | } 29 | 30 | const overriddenComponents = { 31 | "EmptyResults.element": MyEmptyResults 32 | }; 33 | ``` 34 | 35 | ### Parameters 36 | 37 | * **queryString** `String` 38 | 39 | The current value of the `queryString` `query` state. 40 | 41 | * **resetQuery** `Function` 42 | 43 | A function to call to reset the current search query. 44 | 45 | * **extraContent** `React component` 46 | 47 | Any extra React component to be rendered. 48 | 49 | * **userSelectionFilters** `Array` 50 | 51 | List of the currently selected filters. 52 | -------------------------------------------------------------------------------- /docs/docs/components/error.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: error 3 | title: Error 4 | --- 5 | 6 | `Error` renders the errors returned by the REST API, e.g. 4xx or 5xx. 7 | 8 | The component is **not** displayed while executing the search query or if there is no error. 9 | 10 | ## Usage 11 | 12 | ```jsx 13 | 14 | ``` 15 | 16 | ## Usage when overriding 17 | 18 | ```jsx 19 | const MyError = ({ error }) => { 20 | ... 21 | } 22 | 23 | const overriddenComponents = { 24 | "Error.element": MyError 25 | }; 26 | ``` 27 | 28 | ### Parameters 29 | 30 | * **error** `Object` 31 | 32 | The current value of the `error` `results` state, containing the error returned by the search API connector. 33 | -------------------------------------------------------------------------------- /docs/docs/components/layout_switcher.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: layout-switcher 3 | title: LayoutSwitcher 4 | --- 5 | 6 | `LayoutSwitcher` renders a pair of buttons that allows the user to change results layout between `list` and `grid`. 7 | 8 | It is normally used in combination with `ResultMultiLayout`, which wraps `ResultsList` and `ResultsGrid`. 9 | 10 | The component is **not** displayed while executing the search query, if the current layout is not set or if 11 | there are no results. 12 | 13 | ## Usage 14 | 15 | ```jsx 16 | 17 | ``` 18 | 19 | ## Props 20 | 21 | * **defaultLayout** `String` *optional* 22 | 23 | The default layout, one of `list` or `grid`. Default value: `list`. 24 | 25 | * **overridableId** `String` *optional* 26 | 27 | An optional string to define a specific overridable id. 28 | 29 | ## Usage when overriding 30 | 31 | ```jsx 32 | const MyLayoutSwitcher = ({ currentLayout, onLayoutChange }) => { 33 | ... 34 | } 35 | 36 | const overriddenComponents = { 37 | "LayoutSwitcher.element": MyLayoutSwitcher 38 | }; 39 | ``` 40 | 41 | ### Parameters 42 | 43 | * **currentLayout** `String` 44 | 45 | The current value of the `layout` `query` state. 46 | 47 | * **onLayoutChange** `function` 48 | 49 | The function to call when the user wants to change the current layout to change the `query` state. `onLayoutChange(newValue)` 50 | -------------------------------------------------------------------------------- /docs/docs/components/pagination.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: pagination 3 | title: Pagination 4 | --- 5 | 6 | `Pagination` renders the controls for navigating the search result pages. 7 | 8 | The component is **not** displayed while executing the search query, if the current page or results per page are not set 9 | or if there are no results. 10 | 11 | ## Usage 12 | 13 | ```jsx 14 | const options = { showEllipsis: false, showLastIcon: false } 15 | 16 | ``` 17 | 18 | ## Props 19 | 20 | * **options** `object` *optional* 21 | 22 | An object that can contain: 23 | 24 | * **boundaryRangeCount** `Number`: Number of always visible pages at the beginning and end. Default value: `1`. 25 | * **siblingRangeCount** `Number`: Number of always visible pages before and after the current one. Default value: `1`. 26 | * **showEllipsis** `Boolean`: Show '...' for hidden pages. Default value: `true`. 27 | * **showFirst** `Boolean`: Show the icon to go to the first page. Default value: `true`. 28 | * **showLast** `Boolean`: Show the icon to go to the last page. Default value: `true`. 29 | * **showPrev** `Boolean`: Show the icon to go to the previous page. Default value: `true`. 30 | * **showNext** `Boolean`: Show the icon to go to the next page. Default value: `true`. 31 | * **size** `String`: Component size, one of `["mini", "tiny", "small", "large", "huge", "massive"]`. 32 | 33 | * **overridableId** `String` *optional* 34 | 35 | An optional string to define a specific overridable id. 36 | 37 | ## Usage when overriding 38 | 39 | ```jsx 40 | const MyPagination = ({ currentPage, currentSize, totalResults, onPageChange, options }) => { 41 | ... 42 | } 43 | 44 | const overriddenComponents = { 45 | "Pagination.element": MyPagination 46 | }; 47 | ``` 48 | 49 | ### Parameters 50 | 51 | * **currentPage** `Number` 52 | 53 | The current value of the `page` `query` state. 54 | 55 | * **currentSize** `Number` 56 | 57 | The current value of the `size` `query` state, to be able to calculate the total number of pages. 58 | 59 | * **totalResults** `Number` 60 | 61 | The current value of the `total` `results` state representing the number of results, to be able to calculate the total number of pages. 62 | 63 | * **onPageChange** `Number` 64 | 65 | Function to call when the user wants to change the page to change the `query` state. `onPageChange(newValue)` 66 | 67 | * **options** `object` 68 | 69 | The options prop passed to the component. 70 | 71 | * **showWhenOnlyOnePage** `Boolean` 72 | 73 | Allows to configure whether or not the component will render when there is only one page of results available. Default value: `true`. 74 | 75 | 76 | -------------------------------------------------------------------------------- /docs/docs/components/react_search_kit.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: react-searchkit 3 | title: ReactSearchKit 4 | --- 5 | 6 | `ReactSearchKit` is the base component that wraps your search application. 7 | 8 | It provides state and configuration to the application. 9 | 10 | ## Usage 11 | 12 | ```jsx 13 | 14 | ... React-SearchKit components ... 15 | 16 | ``` 17 | 18 | See the [complete guide](main_concepts.md) for detailed information. 19 | 20 | ## Props 21 | 22 | - **searchApi** `object` _required_ 23 | 24 | An instance of the adapter class for your search backend. 25 | 26 | - **urlHandlerApi** `object` _optional_ 27 | 28 | An object containing configuration for handling URL parameters: 29 | 30 | - **enabled** `boolean`: `true` if URL parameters should be updated `false` otherwise. Default `true`. 31 | - **overrideConfig** `object`: 32 | 33 | - **keepHistory** `boolean`: `true` if each change of the URL parameters should push a new state to the browser history, `false` if it should replace it instead. Default `true`. 34 | - **urlFilterSeparator** `object`: a character(s) to override the default character defined in `UrlHandlerApi`, used when separating child filters. 35 | - **urlParamsMapping** `object`: an object to override the default mapping defined in `UrlHandlerApi`, used when serializing each query state field to an URL parameter. 36 | - **urlParamValidator** `object`: an object to override the default implementation of `UrlParamValidator` in `UrlHandlerApi`. 37 | - **urlParser** `object`: an object to override the default implementation of `UrlParser` in `UrlHandlerApi`. 38 | 39 | - **customHandler** `object`: override entirely the default class `UrlHandlerApi`. 40 | 41 | - **searchOnInit** `boolean` _optional_ 42 | 43 | A boolean to perform a search when the application is mounted. Default `true`. 44 | 45 | - **appName** `string` _optional_ 46 | 47 | A name to uniquely identify the application. Useful when enabling the `event listener` (read below) and when multiple ReactSearchKit apps are loaded in the same page. 48 | 49 | The `overridable-id` of each component will be prefixed by this `appName` ([see here](https://inveniosoftware.github.io/react-searchkit/docs/ui-customisation)). Default is empty string `'' ` (no namespacing). 50 | 51 | - **eventListenerEnabled** `boolean` _optional_ 52 | 53 | If `true` the application listens to the `queryChanged` event else if `false` no listener is registered. When this event is emitted the application triggers a search based on the payload that is passed to the event at the emission time. Default `false`. 54 | 55 | - **overridableId** `String` *optional* 56 | 57 | An optional string to define a specific overridable id. 58 | 59 | - **initialQueryState** `object` _optional_ 60 | 61 | Set the initial state of your ReactSearchKit application. It will be used to render each component with these default selected values and to perform the first search query, if `searchOnInit` is set to `true`. 62 | The object keys must match the query state fields and the values must be valid values that correspond to the values passed to each parameters. 63 | 64 | - **defaultSortingOnEmptyQueryString** `object` _optional_ 65 | 66 | It is sometimes useful to automatically change the default sorting in case the query string is set or left empty. 67 | A typical case is when your app should return by default the most recent items when the user did not search for anything in particular, but it should instead return the best matching items when searching with a particular query string. 68 | When enabled, the behavior will be the following: 69 | 70 | * if the user did **not** change sorting, the default sorting with an **empty** query string will be the one defined with this prop `defaultSortingOnEmptyQueryString`. 71 | * if the user did **not** change sorting, the default sorting with a query string will be the one defined with the prop `initialQueryState`. 72 | * if the user **did** change sorting and selected a value, then the user preference will be kept, independently of the presence or absence of the query string. 73 | 74 | - **sortBy** `string`: the query state `sortBy` value to use on empty query string. 75 | 76 | - **sortOrder** `string`: the query state `sortOrder` value to use on empty query string. 77 | 78 | -------------------------------------------------------------------------------- /docs/docs/components/results_grid.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: results-grid 3 | title: ResultsGrid 4 | --- 5 | 6 | `ResultsGrid` renders the list of results as a grid. 7 | 8 | ## Usage 9 | 10 | ```jsx 11 | 12 | ``` 13 | 14 | ## Props 15 | 16 | * **resultsPerRow** `int` *optional* 17 | 18 | The number of results to display in each row. Default value: `3`. 19 | 20 | * **overridableId** `String` *optional* 21 | 22 | An optional string to define a specific overridable id. 23 | 24 | * **onResultsRendered** `func` *optional* 25 | 26 | An optional function to define set of actions to be performed after the component is rendered. For example: render MathJax to display mathematical equations. 27 | 28 | ## Usage when overriding 29 | 30 | ```jsx 31 | const MyResultsGridContainer = ({ results, resultsPerRow }) => { 32 | ... 33 | } 34 | 35 | const MyResultsGridItem = ({ results, resultsPerRow }) => { 36 | ... 37 | } 38 | 39 | const overriddenComponents = { 40 | "ResultsGrid.container": MyResultsGridContainer 41 | "ResultsGrid.item": MyResultsGridItem 42 | }; 43 | ``` 44 | 45 | ### ResultsGridContainer parameters 46 | 47 | Component that wraps the grid of result's items. 48 | 49 | * **results** `Array` 50 | 51 | The list of results to display to the user. 52 | 53 | * **resultsPerRow** `Number` 54 | 55 | The prop `resultsPerRow` defined when using the component. 56 | 57 | 58 | ### ResultsGridItem parameters 59 | 60 | Component that will render a specicif result item. 61 | 62 | * **result** `Object` 63 | 64 | The result object to render. 65 | 66 | * **index** `Number` 67 | 68 | The index number of the result object. 69 | -------------------------------------------------------------------------------- /docs/docs/components/results_list.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: results-list 3 | title: ResultsList 4 | --- 5 | 6 | `ResultsList` renders the list of results as a simple list. 7 | 8 | ## Usage 9 | 10 | ```jsx 11 | 12 | ``` 13 | 14 | ## Props 15 | 16 | * **overridableId** `String` *optional* 17 | 18 | An optional string to define a specific overridable id. 19 | 20 | * **onResultsRendered** `func` *optional* 21 | 22 | An optional function to define set of actions to be performed after the component is rendered. For example: render MathJax to display mathematical equations. 23 | 24 | ## Usage when overriding 25 | 26 | ```jsx 27 | const MyResultsListContainer = ({ results, resultsPerRow }) => { 28 | ... 29 | } 30 | 31 | const MyResultsListItem = ({ results, resultsPerRow }) => { 32 | ... 33 | } 34 | 35 | const overriddenComponents = { 36 | "ResultsList.container": MyResultsListContainer 37 | "ResultsList.item": MyResultsListItem 38 | }; 39 | ``` 40 | 41 | ### ResultsListContainer parameters 42 | 43 | Component that wraps the list of result's items. 44 | 45 | * **results** `Array` 46 | 47 | The list of results to display to the user. 48 | 49 | ### ResultsListItem parameters 50 | 51 | Component that will render a specicif result item. 52 | 53 | * **result** `Object` 54 | 55 | The result object to render. 56 | 57 | * **index** `Number` 58 | 59 | The index number of the result object. 60 | 61 | -------------------------------------------------------------------------------- /docs/docs/components/results_loader.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: results-loader 3 | title: ResultsLoader 4 | --- 5 | 6 | `ResultsLoader` renders a loading indicator while performing a REST API request and refreshing the results. 7 | 8 | ## Usage 9 | 10 | ```jsx 11 | 12 | ``` 13 | 14 | ## Props 15 | 16 | * **overridableId** `String` *optional* 17 | 18 | An optional string to define a specific overridable id. 19 | 20 | ## Usage when overriding 21 | 22 | ```jsx 23 | const MyResultsLoader = () => { 24 | ... 25 | } 26 | 27 | const overriddenComponents = { 28 | "ResultsLoader.element": MyResultsLoader 29 | }; 30 | ``` 31 | -------------------------------------------------------------------------------- /docs/docs/components/results_multi_layout.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: results-multi-layout 3 | title: ResultsMultiLayout 4 | --- 5 | 6 | `ResultsMultiLayout` is an uncontrolled component that listens to the application's `layout` state and 7 | renders results in a `list` ([ResultsList](components/results_list.md)) or `grid` ([ResultsGrid](components/results_grid.md)) 8 | respectively. Can be used in combination with the `LayoutSwitcher` component to change the results layout in controllable way. 9 | By default it renders results as a list. 10 | 11 | ## Usage 12 | 13 | ```jsx 14 | 15 | ``` 16 | 17 | ## Props 18 | 19 | * **overridableId** `String` *optional* 20 | 21 | An optional string to define a specific overridable id. 22 | 23 | * **onResultsRendered** `func` *optional* 24 | 25 | An optional function to define set of actions to be performed after the component is rendered. For example: render MathJax to display mathematical equations. 26 | 27 | ## Usage when overriding 28 | 29 | ```jsx 30 | const MyResultsMultiLayout = ({ layout }) => { 31 | ... 32 | } 33 | 34 | const overriddenComponents = { 35 | "ResultsMultiLayout.element": MyResultsMultiLayout 36 | }; 37 | ``` 38 | 39 | ### Parameters 40 | 41 | * **layout** `String` 42 | 43 | The current selected layout. Possible values: `list` or `grid`. 44 | -------------------------------------------------------------------------------- /docs/docs/components/results_per_page.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: results-per-page 3 | title: ResultsPerPage 4 | --- 5 | 6 | `ResultsPerPage` renders a list of the possible number of results per page. 7 | 8 | The component is **not** displayed while executing the search query or if there are no results. 9 | 10 | ## Usage 11 | 12 | ```jsx 13 | 16 | ``` 17 | 18 | ## Props 19 | 20 | * **values** `Array` 21 | 22 | A list of possible values, where each value has the format `{ text: "Fifty", value: 50 }`. 23 | 24 | - **label** `function` _optional_ 25 | 26 | An optional function to wrap the component with a prefix and suffix string.
27 | E.g. `label={(cmp) => <> Show {cmp} results per page}` 28 | 29 | * **overridableId** `String` *optional* 30 | 31 | An optional string to define a specific overridable id. 32 | 33 | ## Usage when overriding 34 | 35 | ```jsx 36 | const MyResultsPerPage = ({ currentSize, options, onValueChange, ariaLabel, selectOnNavigation }) => { 37 | ... 38 | } 39 | 40 | const overriddenComponents = { 41 | "ResultsPerPage.element": MyResultsPerPage 42 | }; 43 | ``` 44 | 45 | ### Parameters 46 | 47 | * **currentSize** `String` 48 | 49 | The current value of the `size` `query` state. 50 | 51 | * **options** `Array` 52 | 53 | The options passed as prop to the component. 54 | 55 | * **onValueChange** `Gunction` 56 | 57 | The function to call when the user changes the number of results per page to change the `query` state. `onValueChange(newValue)` 58 | 59 | * **ariaLabel** `String` 60 | 61 | The ARIA (Accessibility) label to add to the component. 62 | 63 | * **selectOnNavigation** `Boolean` 64 | 65 | When using a dropdown, set if the `onValueChange` should be called when the new dropdown item is selected with arrow keys, or only on click or on enter. 66 | 67 | * **showWhenOnlyOnePage** `Boolean` 68 | 69 | Allows to configure whether or not the component will render when there is only one page of results available. Default value: `true`. -------------------------------------------------------------------------------- /docs/docs/components/search_bar.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: search-bar 3 | title: SearchBar 4 | --- 5 | 6 | `SearchBar` renders an input box for queries and a Search button. 7 | 8 | As default behavior, the search can be triggered clicking on the button or pressing the `enter` keystroke. 9 | 10 | ## Usage 11 | 12 | ```jsx 13 | 14 | ``` 15 | 16 | ## Props 17 | 18 | * **placeholder** `String` *optional* 19 | 20 | The placeholder value of the search box. Default value: `Type something`. 21 | 22 | * **overridableId** `String` *optional* 23 | 24 | An optional string to define a specific overridable id. 25 | 26 | ## Usage when overriding 27 | 28 | ```jsx 29 | const MySearchBar = ({ queryString, onBtnSearchClick, onInputChange, onKeyPress, placeholder, actionProps, uiProps }) => { 30 | ... 31 | } 32 | 33 | const overriddenComponents = { 34 | "SearchBar.element": MySearchBar 35 | }; 36 | ``` 37 | 38 | ### Parameters 39 | 40 | * **placeholder** `String` 41 | 42 | The prop `placeholder` defined when using the component. 43 | 44 | * **queryString** `String` 45 | 46 | The current value of the `queryString` `query` state. 47 | 48 | * **onInputChange** `Function` 49 | 50 | A function to be called every time the user changes the query string to change the `query` state. `onInputChange(queryString)` 51 | 52 | * **onBtnSearchClick** `Function` 53 | 54 | A function to be called when the user clicks on the the search button. 55 | 56 | * **onKeyPress** `Function` 57 | 58 | A function to be called on key press to handle the Enter button pressed. 59 | 60 | * **actionProps** `Object` 61 | 62 | Semantic-UI props for the action button. 63 | 64 | * **uiProps** `Object` 65 | 66 | Semantic-UI props for the search bar. 67 | -------------------------------------------------------------------------------- /docs/docs/components/sort.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: sort 3 | title: Sort 4 | --- 5 | 6 | `Sort` renders a list of possible sort by and sort order options in one single component. 7 | 8 | The component is **not** displayed while executing the search query or if there are no results. 9 | 10 | ## Usage 11 | 12 | ```jsx 13 | 27 | ``` 28 | 29 | ## Props 30 | 31 | * **values** `Array` 32 | 33 | A list of possible values, where each value has the format `{ text: "Newest", sortBy: "", sortOrder: "" }`. 34 | 35 | - **label** `function` _optional_ 36 | 37 | An optional function to wrap the component with a prefix and suffix string.
38 | E.g. `label={(cmp) => <> sorted by {cmp}}` 39 | 40 | * **overridableId** `String` *optional* 41 | 42 | An optional string to define a specific overridable id. 43 | 44 | ## Usage when overriding 45 | 46 | ```jsx 47 | const MySort = ({ currentSortBy, options, onValueChange, ariaLabel, selectOnNavigation }) => { 48 | ... 49 | } 50 | 51 | const overriddenComponents = { 52 | "Sort.element": MySort 53 | }; 54 | ``` 55 | 56 | ### Parameters 57 | 58 | * **currentSortBy** `String` 59 | 60 | The current value of the `sortBy` `query` state. 61 | 62 | * **currentSortOrder** `String` 63 | 64 | The current value of the `sortOrder` `query` state. 65 | 66 | * **options** `Array` 67 | 68 | The options passed as prop to the component. 69 | 70 | * **onValueChange** `function` 71 | 72 | The function to call when the user changes the sort by field value to change the `query` state. `onValueChange(newValue)` 73 | 74 | * **ariaLabel** `String` 75 | 76 | The ARIA (Accessibility) label to add to the component. 77 | 78 | * **selectOnNavigation** `Boolean` 79 | 80 | When using a dropdown, set if the `onValueChange` should be called when the new dropdown item is selected with arrow keys, or only on click or on enter. 81 | -------------------------------------------------------------------------------- /docs/docs/components/sort_by.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: sort-by 3 | title: SortBy 4 | --- 5 | 6 | `SortBy` renders a list of possible sort options. 7 | 8 | The component is **not** displayed while executing the search query or if there are no results. 9 | 10 | ## Usage 11 | 12 | ```jsx 13 | 16 | ``` 17 | 18 | ## Props 19 | 20 | * **values** `Array` 21 | 22 | A list of possible values, where each value has the format `{ text: "Creation Date", value: "created" }`. 23 | 24 | - **label** `function` _optional_ 25 | 26 | An optional function to wrap the component with a prefix and suffix string.
27 | E.g. `label={(cmp) => <> sorted by {cmp}}` 28 | 29 | * **overridableId** `String` *optional* 30 | 31 | An optional string to define a specific overridable id. 32 | 33 | ## Usage when overriding 34 | 35 | ```jsx 36 | const MySortBy = ({ currentSortBy, options, onValueChange, ariaLabel, selectOnNavigation }) => { 37 | ... 38 | } 39 | 40 | const overriddenComponents = { 41 | "SortBy.element": MySortBy 42 | }; 43 | ``` 44 | 45 | ### Parameters 46 | 47 | * **currentSortBy** `String` 48 | 49 | The current value of the `sortBy` `query` state. 50 | 51 | * **options** `Array` 52 | 53 | The options passed as prop to the component. 54 | 55 | * **onValueChange** `function` 56 | 57 | The function to call when the user changes the sort by field value to change the `query` state. `onValueChange(newValue)` 58 | 59 | * **ariaLabel** `String` 60 | 61 | The ARIA (Accessibility) label to add to the component. 62 | 63 | * **selectOnNavigation** `Boolean` 64 | 65 | When using a dropdown, set if the `onValueChange` should be called when the new dropdown item is selected with arrow keys, or only on click or on enter. 66 | 67 | -------------------------------------------------------------------------------- /docs/docs/components/sort_order.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: sort-order 3 | title: SortOrder 4 | --- 5 | 6 | `SortOrder` renders a list of the possible sort order values, i.e. ascending/descending. 7 | 8 | The component is **not** displayed while executing the search query or if there are no results. 9 | 10 | ## Usage 11 | 12 | ```jsx 13 | 16 | ``` 17 | 18 | ## Props 19 | 20 | * **values** `Array` 21 | 22 | A list of possible values, where each value has the format `{ text: "Asc", value: "asc" }`. 23 | 24 | - **label** `function` _optional_ 25 | 26 | An optional function to wrap the component with a prefix and suffix string.
27 | E.g. `label={(cmp) => <> sorted by {cmp}}` 28 | 29 | * **overridableId** `String` *optional* 30 | 31 | An optional string to define a specific overridable id. 32 | 33 | ## Usage when overriding 34 | 35 | ```jsx 36 | const MySortOrder = ({ currentSortOrder, options, onValueChange, ariaLabel, selectOnNavigation }) => { 37 | ... 38 | } 39 | 40 | const overriddenComponents = { 41 | "SortOrder.element": MySortOrder 42 | }; 43 | ``` 44 | 45 | ### Parameters 46 | 47 | * **currentSortOrder** `String` 48 | 49 | The current value of the `sortOrder` `query` state. 50 | 51 | * **options** `Array` 52 | 53 | The options passed as prop to the component. 54 | 55 | * **onValueChange** `function` 56 | 57 | The function to call when the user changes the sort order field value to change the `query` state. `onValueChange(newValue)` 58 | 59 | * **ariaLabel** `String` 60 | 61 | The ARIA (Accessibility) label to add to the component. 62 | 63 | * **selectOnNavigation** `Boolean` 64 | 65 | When using a dropdown, set if the `onValueChange` should be called when the new dropdown item is selected with arrow keys, or only on click or on enter. 66 | 67 | 68 | -------------------------------------------------------------------------------- /docs/docs/components/toggle.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: toggle 3 | title: Toggle 4 | --- 5 | 6 | `Toggle` renders a Toggle Checkbox in a Card element providing a filter for the performed search. 7 | 8 | ## Usage 9 | 10 | ```jsx 11 | 16 | ``` 17 | 18 | ## Props 19 | 20 | * **title** `String` *optional* 21 | 22 | The optional title for the Card element. 23 | 24 | * **label** `label` *optional* 25 | 26 | An optional label to for the Checkbox element. 27 | 28 | * **filterValue** `Array` 29 | 30 | An array containing the filter to be applied to the search query when active. 31 | 32 | * **overridableId** `String` *optional* 33 | 34 | An optional string to define a specific overridable id. 35 | 36 | ## Usage when overriding 37 | 38 | ```jsx 39 | const MyCount = ({ totalResults }) => { 40 | return
Found {totalResults} results.
; 41 | } 42 | 43 | const overriddenComponents = { 44 | "SearchFilters.ToggleComponent.element": MyCount 45 | }; 46 | ``` 47 | 48 | ### Parameters 49 | 50 | * **title** `String` *optional* 51 | 52 | The optional title for the Card element. 53 | 54 | * **label** `label` *optional* 55 | 56 | An optional label to for the Checkbox element. 57 | 58 | * **filterValue** `Array` 59 | 60 | An array containing the filter to be applied to the search query when active. 61 | 62 | * **userSelectionFilters** `Array` 63 | 64 | The list of currently selected filters by the user. 65 | 66 | * **updateQueryFilters** `Function` 67 | 68 | The function to call to add or remove a filter from the list of selected ones `updateQueryFilters(filter)`. 69 | -------------------------------------------------------------------------------- /docs/docs/components/with_state.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: with-state 3 | title: withState 4 | --- 5 | 6 | `withState` is a high order component, which is used to expose the redux state and 7 | actions to external components. 8 | 9 | The component receives the up-to-date state every time something is changed and 10 | through its props it gains access to 11 | 12 | - `currentResultsState` 13 | - `currentQueryState` 14 | - `updateQueryState` 15 | 16 | > Do **not** mutate directly the state inside your wrapped component. Instead, use the function `updateQueryState` to pass your new query. 17 | 18 | ## Usage 19 | 20 | ```jsx 21 | class _StateLogger extends Component { 22 | render() { 23 | return ( 24 |
25 | Current query state
{JSON.stringify(this.props.currentQueryState, null, 2)}
26 |
27 |
28 | Current results state
{JSON.stringify(this.props.currentResultsState, null, 2)}
29 |
30 | ); 31 | } 32 | } 33 | 34 | const StateLogger = withState(_StateLogger); 35 | ``` 36 | -------------------------------------------------------------------------------- /docs/docs/create_your_component.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: create-your-component 3 | title: Create Your Component 4 | --- 5 | 6 | You can create your own component by taking advantage of the [withState](components/with_state.md) component. The `withState` component will inject the current query state, the results state and the function to update the query state and allows you to set new user inputs, trigger a search or display results in a custom way. See the component's documentation for more information. 7 | -------------------------------------------------------------------------------- /docs/docs/filters_aggregations.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: filters-aggregations 3 | title: Filters And Aggregations 4 | --- 5 | 6 | ## Filters 7 | 8 | Filters allow to refine search results with exact match on specific fields. For example, if your data have a number field `age`, you can request results that have a specific exact value `age=25`. 9 | 10 | In React-SearchKit, the query state contains a field called `filters` which contains the list of filters selected by the user. 11 | 12 | [Filters](https://opensearch.org/docs/latest/query-dsl/query-filter-context/) and [Aggregations](https://opensearch.org/docs/latest/aggregations/) are fundamental concepts of OpenSearch. 13 | However, they can be applied to any backend or REST APIs. 14 | 15 | ## Aggregations 16 | 17 | Aggregations can be defined as a set of complex summaries for the search results. Or in other words, a grouping of the search results to provide different statistics. For example, for the previous query `age=25`, the search results can include the list of all possible values for the field `age` and the number of results for each value. 18 | 19 | For example, for each existing `age` value: 20 | 21 | * `25`: 3 results 22 | * `26`: 2 results 23 | * `31`: 18 results 24 | * etc. 25 | 26 | In OpenSearch, there are several types of aggregations available. React-SearchKit comes out of the box with a component that implements [Bucket Terms Aggregations](https://opensearch.org/docs/latest/aggregations/bucket/terms/), but any other aggregation should be easy to implement. 27 | 28 | ## Bucket aggregations 29 | 30 | The `` component defines the name of the aggregation to request to the backend or OpenSearch and the field to compute the aggregations on. 31 | For example: 32 | 33 | ```jsx 34 | 40 | ``` 41 | 42 | > It is your responsibility to create the search request to your backend taking into account the configured aggregations. 43 | 44 | The `results` state should then contains aggregations results in the object `aggregations`. The `` component expects the OpenSearch format: 45 | 46 | ```json 47 | { 48 | "ages_aggregation": { 49 | "buckets": [ 50 | { 51 | "key": 25, 52 | "doc_count": 3 53 | }, 54 | { 55 | "key": 26, 56 | "doc_count": 2 57 | }, 58 | { 59 | "key": 31, 60 | "doc_count": 18 61 | } 62 | ] 63 | } 64 | } 65 | ``` 66 | 67 | The `filters` query state will contain the list of filters that the user has selected. Given that you can have multiple aggregations configured, each filter should be formatted as `[ "", "" ]`, for example: 68 | 69 | ```json 70 | { 71 | ... 72 | "filters": [ 73 | [ "ages_aggregation", 25 ], 74 | [ "ages_aggregation", 31 ] 75 | ] 76 | } 77 | ``` 78 | -------------------------------------------------------------------------------- /docs/docs/ui_customisation.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: ui-customisation 3 | title: Customise The Look And Feel 4 | --- 5 | 6 | React-SearchKit uses [Semantic UI React](https://react.semantic-ui.com/) as UI framework. 7 | 8 | The best way to style each available component is to follow the recommended way documented in Semantic UI React [Theming section](https://react.semantic-ui.com/theming). 9 | 10 | Asides from styling, RSK components can be overridden completely (using [react-overridable](https://github.com/indico/react-overridable) internally). 11 | 12 | By passing a map with IDs and components we can override the default components with our own custom components. 13 | To allow for this functionality you should wrap your RSK app with the react-overridable "OverridableContext" and 14 | pass it a map of components you have defined. 15 | 16 | In the following example you can see a simplified setup. 17 | ```jsx 18 | const CustomResultsListItem = (overriddenComponentProps) => ( 19 | 20 | 21 | {overriddenComponentProps.title} 22 | 23 | 24 | ) 25 | 26 | const overriddenComponents = { 27 | 'ResultsList.item': CustomResultsListItem 28 | }; 29 | 30 | 31 | 32 | ... 33 | 34 | 35 | ``` 36 | 37 | The ID used for overriding a component can be found by searching the component in the RSK [library](https://github.com/inveniosoftware/react-searchkit/tree/master/src/lib/components) 38 | and looking at the ID passed to the `Overridable` component. The ID is built using a function called `buildUID` which allows us to namespace our IDs if needed. 39 | 40 | ```jsx 41 | //If there is no `appName` prop passed to the main RSK component` 42 | const id = buildUID('Count.Element'); // outputs 'Count.Element' 43 | const id2 = buildUID('Count.Element', 'ExampleOverridenId'); // outputs 'Count.Element.ExampleOverridenId' 44 | // If there is an `appName` prop passed with value 'exampleAppName' (namespacing) 45 | const id3 = buildUID('Count.Element'); // outputs 'exampleAppName.Count.Element' 46 | 47 | 48 | ``` 49 | 50 | For elaborated examples please have a look at our [code demos](https://github.com/inveniosoftware/react-searchkit/tree/master/src/demos). 51 | -------------------------------------------------------------------------------- /docs/website/core/Footer.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of React-SearchKit. 3 | * Copyright (C) 2018-2023 CERN. 4 | * 5 | * React-SearchKit is free software; you can redistribute it and/or modify it 6 | * under the terms of the MIT License; see LICENSE file for more details. 7 | */ 8 | 9 | const React = require("react"); 10 | 11 | const siteConfig = require(process.cwd() + "/siteConfig.js"); 12 | 13 | class Footer extends React.Component { 14 | render() { 15 | return ( 16 | 55 | ); 56 | } 57 | } 58 | 59 | module.exports = Footer; 60 | -------------------------------------------------------------------------------- /docs/website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "examples": "docusaurus-examples", 4 | "start": "docusaurus-start", 5 | "build": "docusaurus-build", 6 | "publish-gh-pages": "docusaurus-publish", 7 | "write-translations": "docusaurus-write-translations", 8 | "version": "docusaurus-version", 9 | "rename-version": "docusaurus-rename-version" 10 | }, 11 | "devDependencies": { 12 | "docusaurus": "^1.14.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /docs/website/pages/en/help.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of React-SearchKit. 3 | * Copyright (C) 2018 CERN. 4 | * 5 | * React-SearchKit is free software; you can redistribute it and/or modify it 6 | * under the terms of the MIT License; see LICENSE file for more details. 7 | */ 8 | 9 | const React = require("react"); 10 | 11 | const CompLibrary = require("../../core/CompLibrary.js"); 12 | const Container = CompLibrary.Container; 13 | const GridBlock = CompLibrary.GridBlock; 14 | const MarkdownBlock = CompLibrary.MarkdownBlock; 15 | 16 | const siteConfig = require(process.cwd() + "/siteConfig.js"); 17 | 18 | class Help extends React.Component { 19 | render() { 20 | const supportLinks = [ 21 | { 22 | content: `Have a look to the [Getting Started guide](${siteConfig.baseUrl}docs/getting-started) to better understand how React-SearchKit works and how it can help you to build your own SearchKit app.\n\nRead the [advanced guide](${siteConfig.baseUrl}docs/advanced) to know how to customize, extend and create your own components.`, 23 | title: "Browse the documentation", 24 | }, 25 | { 26 | content: 27 | "Join the [Invenio Discord channel](https://discord.gg/8qatqBC) to ask questions and get help.", 28 | title: "Join the community", 29 | }, 30 | { 31 | content: 32 | "React-SearchKit is part of the Invenio software organization.\n- Have a look to the [Invenio](https://inveniosoftware.org/) website to know more about the project.\n- Announcements and news are published in the official [Invenio blog](https://inveniosoftware.org/blog/).\n- Follow Invenio on [Twitter](https://twitter.com/inveniosoftware).", 33 | title: "Stay up to date", 34 | }, 35 | ]; 36 | 37 | return ( 38 |
39 | 40 |
41 |
42 |

43 |
Need help?
44 |

45 |
46 |

47 | 48 | React-SearchKit is born at [CERN](https://home.cern). It is under active 49 | development and used by websites built on top of 50 | [Invenio](https://inveniosoftware.org/). 51 | 52 |

53 | 54 |
55 |
56 |
57 | ); 58 | } 59 | } 60 | 61 | module.exports = Help; 62 | -------------------------------------------------------------------------------- /docs/website/pages/en/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of React-SearchKit. 3 | * Copyright (C) 2018 CERN. 4 | * 5 | * React-SearchKit is free software; you can redistribute it and/or modify it 6 | * under the terms of the MIT License; see LICENSE file for more details. 7 | */ 8 | 9 | const React = require("react"); 10 | 11 | const CompLibrary = require("../../core/CompLibrary.js"); 12 | 13 | const Container = CompLibrary.Container; 14 | const GridBlock = CompLibrary.GridBlock; 15 | 16 | const siteConfig = require(process.cwd() + "/siteConfig.js"); 17 | 18 | class Button extends React.Component { 19 | render() { 20 | return ( 21 | 26 | ); 27 | } 28 | } 29 | 30 | Button.defaultProps = { 31 | target: "_self", 32 | }; 33 | 34 | class Header extends React.Component { 35 | render() { 36 | return ( 37 |
38 |
39 |
40 |
41 |

42 | {siteConfig.title} 43 | {siteConfig.tagline} 44 |

45 |
46 |
47 |
48 | 51 | 56 |
57 |
58 |
59 | 72 |
73 |
74 |
75 |
76 | ); 77 | } 78 | } 79 | 80 | class Home extends React.Component { 81 | render() { 82 | return ( 83 |
84 |
85 |
86 | 87 | 108 | 109 | 110 |
111 | Screenshot 116 |
117 |
118 |
119 |
120 | ); 121 | } 122 | } 123 | 124 | module.exports = Home; 125 | -------------------------------------------------------------------------------- /docs/website/sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "*": { 3 | "Guide": [ 4 | "getting-started", 5 | "main-concepts", 6 | "connect-your-rest-apis", 7 | "using-url-parameters", 8 | "filters-aggregations", 9 | "ui-customisation" 10 | ], 11 | "Components": [ 12 | "components/react-searchkit", 13 | "components/active-filters", 14 | "components/bucket-aggregation", 15 | "components/count", 16 | "components/empty-results", 17 | "components/error", 18 | "components/layout-switcher", 19 | "components/pagination", 20 | "components/results-grid", 21 | "components/results-list", 22 | "components/results-loader", 23 | "components/results-multi-layout", 24 | "components/results-per-page", 25 | "components/search-bar", 26 | "components/sort", 27 | "components/sort-by", 28 | "components/sort-order", 29 | "components/toggle", 30 | "components/with-state" 31 | ], 32 | "Extending": ["create-your-component"] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /docs/website/siteConfig.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of React-SearchKit. 3 | * Copyright (C) 2018 CERN. 4 | * 5 | * React-SearchKit is free software; you can redistribute it and/or modify it 6 | * under the terms of the MIT License; see LICENSE file for more details. 7 | */ 8 | 9 | const siteConfig = { 10 | title: 'React-SearchKit', 11 | tagline: 'A simple yet powerful UI search kit built with React', 12 | url: 'https://inveniosoftware.github.io', 13 | baseUrl: '/react-searchkit/', // Base URL for your project */ 14 | // For github.io type URLs, you would set the url and baseUrl like: 15 | // url: 'https://facebook.github.io', 16 | // baseUrl: '/test-site/', 17 | 18 | // Used for publishing and more 19 | projectName: 'react-searchkit', 20 | organizationName: 'inveniosoftware', 21 | // For top-level user or org sites, the organization is still the same. 22 | // e.g., for the https://JoelMarcey.github.io site, it would be set like... 23 | // organizationName: 'JoelMarcey' 24 | 25 | // For no header links in the top nav bar -> headerLinks: [], 26 | headerLinks: [ 27 | { doc: 'getting-started', label: 'Docs' }, 28 | { doc: 'components/react-searchkit', label: 'Components' }, 29 | { doc: 'create-your-component', label: 'Extending' }, 30 | { page: 'help', label: 'Help' }, 31 | ], 32 | 33 | // If you have users set above, you add it here: 34 | // users, 35 | 36 | /* path to images for header/footer */ 37 | headerIcon: '', 38 | footerIcon: '', 39 | favicon: 'img/favicon.png', 40 | 41 | /* Colors for website */ 42 | colors: { 43 | primaryColor: '#28688a', 44 | secondaryColor: 'rgba(10, 73, 105, 0.91)', 45 | }, 46 | 47 | /* Custom fonts for website */ 48 | /* 49 | fonts: { 50 | myFont: [ 51 | "Times New Roman", 52 | "Serif" 53 | ], 54 | myOtherFont: [ 55 | "-apple-system", 56 | "system-ui" 57 | ] 58 | }, 59 | */ 60 | 61 | highlight: { 62 | // Highlight.js theme to use for syntax highlighting in code blocks. 63 | theme: 'default', 64 | }, 65 | 66 | // Add custom scripts here that would be placed in