diff --git a/docgen/src/guide/Default_refinements.md b/docgen/src/guide/Default_refinements.md
index 6b06dc6956..88f7aedbdc 100644
--- a/docgen/src/guide/Default_refinements.md
+++ b/docgen/src/guide/Default_refinements.md
@@ -28,6 +28,39 @@ const App = () =>
;
```
+## Hiding default refinements
+
+In some situations not only you want default refinements but you also do not want the user to be able to unselect them.
+
+To do this, you can use a [``](guide/Virtual_widgets.html). It allows you to pre refine any widget without
+rendering anything.
+
+By default the [``](widgets/CurrentRefinements.html) widget or the
+[`connectCurrentRefinements`](connectors/connectCurrentRefinements.html) connector will display your default refinements. If you want to hide them, you need to filter the items with `transformItems`.
+
+```jsx
+import {InstantSearch, SearchBox, Menu} from 'react-instantsearch/dom';
+import {connectMenu} from 'react-instantsearch/connectors';
+
+const VirtualMenu = connectMenu(() => null);
+
+const App = () =>
+
+
+ items.filter(item => item.currentRefinement !== 'Orange')}
+ />
+
+
+
+
+ ;
+```
+
**Notes:**
* The [search state guide](guide/Search_state.html) details all widgets and connectors state values...
* Default refinements are handy when used as [Virtual widgets](guide/Virtual_widgets.html).
@@ -39,4 +72,4 @@ const App = () =>
diff --git a/packages/react-instantsearch/src/connectors/connectHierarchicalMenu.js b/packages/react-instantsearch/src/connectors/connectHierarchicalMenu.js
index 1311681c9d..c9b6c25b88 100644
--- a/packages/react-instantsearch/src/connectors/connectHierarchicalMenu.js
+++ b/packages/react-instantsearch/src/connectors/connectHierarchicalMenu.js
@@ -210,7 +210,7 @@ export default createConnector({
attributeName: rootAttribute,
value: nextState => ({
...nextState,
- [namespace]: {[id]: ''},
+ [namespace]: {...nextState[namespace], [id]: ''},
}),
currentRefinement,
}],
diff --git a/packages/react-instantsearch/src/connectors/connectHierarchicalMenu.test.js b/packages/react-instantsearch/src/connectors/connectHierarchicalMenu.test.js
index 45fdc2257c..852e5d06ec 100644
--- a/packages/react-instantsearch/src/connectors/connectHierarchicalMenu.test.js
+++ b/packages/react-instantsearch/src/connectors/connectHierarchicalMenu.test.js
@@ -209,9 +209,14 @@ describe('connectHierarchicalMenu', () => {
value: metadata.items[0].value,
}],
});
+ });
+
+ it('items value function should clear it from the search state', () => {
+ const metadata = getMetadata({attributes: ['one']}, {hierarchicalMenu: {one: 'one', two: 'two'}});
+
+ const searchState = metadata.items[0].value({hierarchicalMenu: {one: 'one', two: 'two'}});
- const searchState = metadata.items[0].value({hierarchicalMenu: {ok: 'wat'}});
- expect(searchState).toEqual({hierarchicalMenu: {ok: ''}});
+ expect(searchState).toEqual({hierarchicalMenu: {one: '', two: 'two'}});
});
it('should return the right searchState when clean up', () => {
diff --git a/packages/react-instantsearch/src/connectors/connectMenu.js b/packages/react-instantsearch/src/connectors/connectMenu.js
index e3242fb0e5..029b81dd13 100644
--- a/packages/react-instantsearch/src/connectors/connectMenu.js
+++ b/packages/react-instantsearch/src/connectors/connectMenu.js
@@ -143,7 +143,7 @@ export default createConnector({
attributeName: props.attributeName,
value: nextState => ({
...nextState,
- [namespace]: {[id]: ''},
+ [namespace]: {...nextState[namespace], [id]: ''},
}),
currentRefinement,
}],
diff --git a/packages/react-instantsearch/src/connectors/connectMenu.test.js b/packages/react-instantsearch/src/connectors/connectMenu.test.js
index 7fe14c6444..9892f1514d 100644
--- a/packages/react-instantsearch/src/connectors/connectMenu.test.js
+++ b/packages/react-instantsearch/src/connectors/connectMenu.test.js
@@ -184,9 +184,14 @@ describe('connectMenu', () => {
value: metadata.items[0].value,
}],
});
+ });
+
+ it('items value function should clear it from the search state', () => {
+ const metadata = getMetadata({attributeName: 'one'}, {menu: {one: 'one', two: 'two'}});
+
+ const searchState = metadata.items[0].value({menu: {one: 'one', two: 'two'}});
- const searchState = metadata.items[0].value({menu: {wot: 'wat'}});
- expect(searchState).toEqual({menu: {wot: ''}});
+ expect(searchState).toEqual({menu: {one: '', two: 'two'}});
});
it('should return the right searchState when clean up', () => {
diff --git a/packages/react-instantsearch/src/connectors/connectMultiRange.js b/packages/react-instantsearch/src/connectors/connectMultiRange.js
index c24f1b282f..eba82bec84 100644
--- a/packages/react-instantsearch/src/connectors/connectMultiRange.js
+++ b/packages/react-instantsearch/src/connectors/connectMultiRange.js
@@ -132,7 +132,7 @@ export default createConnector({
currentRefinement: label,
value: nextState => ({
...nextState,
- [namespace]: {[id]: ''},
+ [namespace]: {...nextState[namespace], [id]: ''},
}),
});
}
diff --git a/packages/react-instantsearch/src/connectors/connectMultiRange.test.js b/packages/react-instantsearch/src/connectors/connectMultiRange.test.js
index aae0272284..808937f60e 100644
--- a/packages/react-instantsearch/src/connectors/connectMultiRange.test.js
+++ b/packages/react-instantsearch/src/connectors/connectMultiRange.test.js
@@ -144,9 +144,24 @@ describe('connectMultiRange', () => {
currentRefinement: 'YAY',
}],
});
+ });
+
+ it('items value function should clear it from the search state', () => {
+ const metadata = getMetadata(
+ {
+ attributeName: 'one',
+ items: [{
+ label: 'YAY',
+ start: 100,
+ end: 200,
+ }],
+ },
+ {multiRange: {one: '100:200', two: '200:400'}}
+ );
+
+ const searchState = metadata.items[0].value({multiRange: {one: '100:200', two: '200:400'}});
- const searchState = metadata.items[0].value({multiRange: {wot: '100:200'}});
- expect(searchState).toEqual({multiRange: {wot: ''}});
+ expect(searchState).toEqual({multiRange: {one: '', two: '200:400'}});
});
it('should return the right searchState when clean up', () => {
diff --git a/packages/react-instantsearch/src/connectors/connectPagination.js b/packages/react-instantsearch/src/connectors/connectPagination.js
index 7ceec18e6e..618abbeef5 100644
--- a/packages/react-instantsearch/src/connectors/connectPagination.js
+++ b/packages/react-instantsearch/src/connectors/connectPagination.js
@@ -80,9 +80,6 @@ export default createConnector({
},
getMetadata() {
- const id = getId();
- return {
- id,
- };
+ return {id: getId()};
},
});
diff --git a/packages/react-instantsearch/src/connectors/connectRange.js b/packages/react-instantsearch/src/connectors/connectRange.js
index 8f0c5d9c5e..692309044b 100644
--- a/packages/react-instantsearch/src/connectors/connectRange.js
+++ b/packages/react-instantsearch/src/connectors/connectRange.js
@@ -157,7 +157,7 @@ export default createConnector({
attributeName: props.attributeName,
value: nextState => ({
...nextState,
- [namespace]: {[id]: {}},
+ [namespace]: {...nextState[namespace], [id]: {}},
}),
};
}
diff --git a/packages/react-instantsearch/src/connectors/connectRange.test.js b/packages/react-instantsearch/src/connectors/connectRange.test.js
index d14d471508..ed7c7d96ba 100644
--- a/packages/react-instantsearch/src/connectors/connectRange.test.js
+++ b/packages/react-instantsearch/src/connectors/connectRange.test.js
@@ -161,6 +161,14 @@ describe('connectRange', () => {
});
});
+ it('items value function should clear it from the search state', () => {
+ const metadata = getMetadata({attributeName: 'one'}, {range: {one: {min: 5}, two: {max: 4}}});
+
+ const searchState = metadata.items[0].value({range: {one: {min: 5}, two: {max: 4}}});
+
+ expect(searchState).toEqual({range: {one: {}, two: {max: 4}}});
+ });
+
it('should return the right searchState when clean up', () => {
let searchState = cleanUp({attributeName: 'name'}, {
range: {name: 'searchState', name2: 'searchState'},
diff --git a/packages/react-instantsearch/src/connectors/connectRefinementList.js b/packages/react-instantsearch/src/connectors/connectRefinementList.js
index 3a48fa6f4c..810d1bb209 100644
--- a/packages/react-instantsearch/src/connectors/connectRefinementList.js
+++ b/packages/react-instantsearch/src/connectors/connectRefinementList.js
@@ -185,7 +185,7 @@ export default createConnector({
currentRefinement: getCurrentRefinement(props, searchState),
value: nextState => ({
...nextState,
- [namespace]: {[id]: ''},
+ [namespace]: {...nextState[namespace], [id]: ''},
}),
items: getCurrentRefinement(props, searchState).map(item => ({
label: `${item}`,
@@ -196,7 +196,7 @@ export default createConnector({
return {
...nextState,
- [namespace]: {[id]: nextSelectedItems.length > 0 ? nextSelectedItems : ''},
+ [namespace]: {...nextState[namespace], [id]: nextSelectedItems.length > 0 ? nextSelectedItems : ''},
};
},
})),
diff --git a/packages/react-instantsearch/src/connectors/connectRefinementList.test.js b/packages/react-instantsearch/src/connectors/connectRefinementList.test.js
index d6bbbaa738..630a2c214d 100644
--- a/packages/react-instantsearch/src/connectors/connectRefinementList.test.js
+++ b/packages/react-instantsearch/src/connectors/connectRefinementList.test.js
@@ -207,11 +207,21 @@ describe('connectRefinementList', () => {
},
],
});
+ });
+
+ it('items value function should clear it from the search state', () => {
+ const metadata = getMetadata(
+ {attributeName: 'one'},
+ {refinementList: {one: ['one1', 'one2'], two: ['two']}}
+ );
+
+ let searchState = metadata.items[0].items[0].value({refinementList: {one: ['one1', 'one2'], two: ['two']}});
+
+ expect(searchState).toEqual({refinementList: {one: ['one2'], two: ['two']}});
- let searchState = metadata.items[0].items[0].value({refinementList: {wot: ['wat', 'wut']}});
- expect(searchState).toEqual({refinementList: {wot: ['wut']}});
searchState = metadata.items[0].items[1].value(searchState);
- expect(searchState).toEqual({refinementList: {wot: ''}});
+
+ expect(searchState).toEqual({refinementList: {one: '', two: ['two']}});
});
it('should return the right searchState when clean up', () => {
diff --git a/packages/react-instantsearch/src/connectors/connectToggle.js b/packages/react-instantsearch/src/connectors/connectToggle.js
index ade552fcff..6c8f3555b0 100644
--- a/packages/react-instantsearch/src/connectors/connectToggle.js
+++ b/packages/react-instantsearch/src/connectors/connectToggle.js
@@ -95,7 +95,7 @@ export default createConnector({
attributeName: props.attributeName,
value: nextState => ({
...nextState,
- [namespace]: {[id]: false},
+ [namespace]: {...nextState[namespace], [id]: false},
}),
});
}
diff --git a/packages/react-instantsearch/src/connectors/connectToggle.test.js b/packages/react-instantsearch/src/connectors/connectToggle.test.js
index 888fda563b..ab7a991077 100644
--- a/packages/react-instantsearch/src/connectors/connectToggle.test.js
+++ b/packages/react-instantsearch/src/connectors/connectToggle.test.js
@@ -78,9 +78,14 @@ describe('connectToggle', () => {
],
id: 't',
});
+ });
+
+ it('items value function should clear it from the search state', () => {
+ const metadata = getMetadata({attributeName: 'one', label: 'yep'}, {toggle: {one: true, two: false}});
+
+ const searchState = metadata.items[0].value({toggle: {one: true, two: false}});
- const searchState = metadata.items[0].value({toggle: {t: true}});
- expect(searchState).toEqual({toggle: {t: false}});
+ expect(searchState).toEqual({toggle: {one: false, two: false}});
});
it('should return the right searchState when clean up', () => {
diff --git a/packages/react-instantsearch/src/widgets/ClearAll.js b/packages/react-instantsearch/src/widgets/ClearAll.js
index 9d88bc603a..7bc36e647f 100644
--- a/packages/react-instantsearch/src/widgets/ClearAll.js
+++ b/packages/react-instantsearch/src/widgets/ClearAll.js
@@ -6,6 +6,7 @@ import ClearAllComponent from '../components/ClearAll.js';
* to the search.
* @name ClearAll
* @kind widget
+ * @propType {function} [transformItems] - If provided, this function can be used to modify the `items` provided prop of the wrapped component (ex: for filtering or sorting items). this function takes the `items` prop as a parameter and expects it back in return.
* @themeKey ais-ClearAll__root - the widget button
* @translationKey reset - the clear all button value
* @example