@bento-core/facet-filter 1.0.1-popsci.2 → 1.0.1-popsci.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -95,6 +95,8 @@ export const facetsConfig = [{
95
95
  minLowerBound: 0,
96
96
  maxUpperBound: 100,
97
97
  quantifier: 'Years',
98
+ CustomLowerUpperBound: CustomLowerUpperBound, // Custom component for displaying lower and upper bounds
99
+ CustomSliderValue: CustomSliderValue, // Custom component for displaying slider value
98
100
  ].
99
101
  ```
100
102
  1. **apiForFiltering** refers to object key for retrieving name and subjects count from query response (DASHBOARD_QUERY)
@@ -244,12 +246,66 @@ className={clsx(classes.sectionSummaryText, classes[facetClasses])}
244
246
  ## 10 CLearAllFilterButton Component
245
247
  Bento Core provides 1. function to clear all active filters, 2. disable flag (true incase of no active filters). Client is responsible for defining view (custom html).
246
248
  ```
247
- import { generateClearAllFilterBtn } from 'bento-core';
249
+ import { ClearAllFiltersBtn, FacetFilter } from '@bento-core/facet-filter';
250
+ import { getFilters } from '@bento-core/facet-filter';
248
251
 
249
252
  const CustomClearAllFiltersBtn = ({ onClearAllFilters, disable }) => {
250
253
  //...custom component 1. bind onClearFilters fn
251
254
  // 2. disable flag to disable button
252
- }
255
+ }
256
+ // get filter data
257
+ // filterState: state.statusReducer.filterState, (from reducer)
258
+ // const activeFilters = getFilters(filterState) // formating
259
+
260
+ <ClearAllFiltersBtn
261
+ Component={CustomClearAllFiltersBtn}
262
+ activeFilters={activeFilters}
263
+ />
264
+ ```
265
+
266
+ ## 11 Facet Value Component
267
+ ```
268
+ // response
269
+ // filterCaseCountByProgram: [{group: "COP", subjects: 301}]
270
+ const {
271
+ name,
272
+ customName,
273
+ subjects,
274
+ customSubjects,
275
+ tooltip,
276
+ } = checkboxItem;
277
+
278
+ // 1. by default facet value component display group ("COP")
279
+ // 2. set customName to display customize value
280
+ // 3. by default facet value component display subjects (301)
281
+ // 4. set customSubjects to display customize value or adjust correct field for subject count
282
+ // 5. tooltip - provide text value to tooltip text
283
+
284
+ /**
285
+ * Add Bento frontend filter count/subjects
286
+ * Add tootip text
287
+ */
288
+ const filterData = facetsConfig.reduce((acc, item) => {
289
+ const facetValues = searchData[item.apiPath];
290
+ if (!facetValues) {
291
+ return acc;
292
+ }
293
+ const subjectCounts = [...facetValues].map((checkbox) => {
294
+ const text = tooltipText[item.tooltipKey];
295
+ return {
296
+ ...checkbox,
297
+ customSubjects: checkbox.count,
298
+ tooltip: text ? text[checkbox.group] : undefined,
299
+ };
300
+ });
301
+ return { ...acc, [item.apiPath]: [...subjectCounts] };
302
+ }, {});
253
303
 
254
- const ClearAllFiltersButton = () => generateClearAllFilterBtn(CustomClearAllFiltersBtn);
304
+ <FacetFilter
305
+ data={filterData}
306
+ facetSectionConfig={facetSectionVariables}
307
+ facetsConfig={facetsConfig}
308
+ CustomFacetSection={CustomFacetSection}
309
+ CustomFacetView={CustomFacetView}
310
+ />
255
311
  ```
@@ -12,13 +12,13 @@ var _FacetFilterView = _interopRequireDefault(require("./FacetFilterView"));
12
12
  const _excluded = ["section"];
13
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
14
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
15
+ function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
16
+ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
15
17
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
16
18
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
17
19
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
18
20
  function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
19
21
  function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
20
- function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
21
- function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
22
22
  const FacetFilterController = props => {
23
23
  /**
24
24
  * update checkbox state
@@ -29,7 +29,8 @@ const FacetFilterController = props => {
29
29
  filterState,
30
30
  data,
31
31
  facetsConfig,
32
- facetSectionConfig
32
+ facetSectionConfig,
33
+ tooltipText = {}
33
34
  } = props;
34
35
  const updateFacetState = filterSections => {
35
36
  const updateSections = [...filterSections];
@@ -37,9 +38,16 @@ const FacetFilterController = props => {
37
38
  for (const [key, value] of Object.entries(filterState)) {
38
39
  updateSections.forEach(sideBar => {
39
40
  if (sideBar.type === _Types.InputTypes.CHECKBOX && sideBar.datafield === key) {
40
- sideBar.facetValues.forEach(item => {
41
- item.isChecked = value[item.name] ? value[item.name] : false;
41
+ const {
42
+ facetValues = []
43
+ } = sideBar;
44
+ const updateFacetVals = facetValues.map(item => {
45
+ const facetVal = item[sideBar.field];
46
+ return _objectSpread(_objectSpread({}, item), {}, {
47
+ isChecked: value[facetVal] ? value[facetVal] : false
48
+ });
42
49
  });
50
+ sideBar.facetValues = updateFacetVals;
43
51
  }
44
52
  if (sideBar.type === _Types.InputTypes.SLIDER && sideBar.datafield === key) {
45
53
  sideBar.facetValues = value;
@@ -49,9 +57,13 @@ const FacetFilterController = props => {
49
57
  } else {
50
58
  updateSections.forEach(sideBar => {
51
59
  if (sideBar.type === _Types.InputTypes.CHECKBOX) {
52
- sideBar.facetValues.forEach(item => {
53
- item.isChecked = false;
54
- });
60
+ const {
61
+ facetValues = []
62
+ } = sideBar;
63
+ const updateFacetVals = facetValues.map(item => _objectSpread(_objectSpread({}, item), {}, {
64
+ isChecked: false
65
+ }));
66
+ sideBar.facetValues = updateFacetVals;
55
67
  }
56
68
  /**
57
69
  * set default value for slider - on clear all filter
@@ -96,6 +108,7 @@ const FacetFilterController = props => {
96
108
  * Construct filter object
97
109
  * 1. add facet values to facets
98
110
  * 2. add 'name' key to each facet value
111
+ * 3. add '
99
112
  */
100
113
  const addFacetValues = facets => {
101
114
  const updateFacets = [];
@@ -105,19 +118,13 @@ const FacetFilterController = props => {
105
118
  facetValues: []
106
119
  });
107
120
  const {
108
- field,
109
121
  ApiLowerBoundName,
110
122
  ApiUpperBoundName,
111
123
  apiForFiltering
112
124
  } = updateFacet;
113
125
  if (data[apiForFiltering]) {
114
126
  if (Array.isArray(data[apiForFiltering])) {
115
- const updateField = data[apiForFiltering].map(item => {
116
- const addField = _objectSpread({}, item);
117
- addField.name = item[field];
118
- return addField;
119
- });
120
- updateFacet.facetValues = updateField;
127
+ updateFacet.facetValues = data[apiForFiltering];
121
128
  }
122
129
  /**
123
130
  * add object to facet values
@@ -140,7 +147,7 @@ const FacetFilterController = props => {
140
147
  * Generate facet sections state
141
148
  *
142
149
  */
143
- const displayFacets = facetsConfig.filter(facet => facet.show).slice(0, 16);
150
+ const displayFacets = facetsConfig.filter(facet => facet.show);
144
151
  const facetStates = addFacetValues(displayFacets);
145
152
  const updateState = updateFacetState(facetStates);
146
153
  const facetSections = arrangeBySections(updateState);
@@ -25,7 +25,7 @@ var _default = () => ({
25
25
  sortGroupItem: {
26
26
  cursor: 'pointer',
27
27
  fontFamily: 'Nunito',
28
- fontSize: '10px',
28
+ fontSize: '11px',
29
29
  marginRight: '32px'
30
30
  }
31
31
  });
@@ -9,7 +9,6 @@ var _core = require("@material-ui/core");
9
9
  var _FacetFilterStyle = _interopRequireDefault(require("./FacetFilterStyle"));
10
10
  var _FacetSectionView = _interopRequireDefault(require("./components/section/FacetSectionView"));
11
11
  var _ReduxFacetView = _interopRequireDefault(require("./components/facet/ReduxFacetView"));
12
- var _FilterItems = _interopRequireDefault(require("./components/inputs/FilterItems"));
13
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
13
  /* eslint-disable arrow-body-style */
15
14
  /* eslint-disable padded-blocks */
@@ -29,11 +28,7 @@ const BentoFacetFilter = _ref => {
29
28
  }, section.items.map(facet => /*#__PURE__*/_react.default.createElement(_ReduxFacetView.default, {
30
29
  facet: facet,
31
30
  CustomView: CustomFacetView
32
- }, /*#__PURE__*/_react.default.createElement(_core.List, {
33
- className: "List_".concat(facet.label)
34
- }, /*#__PURE__*/_react.default.createElement(_FilterItems.default, {
35
- facet: facet
36
- }))))))));
31
+ }))))));
37
32
  };
38
33
  var _default = (0, _core.withStyles)(_FacetFilterStyle.default)(BentoFacetFilter);
39
34
  exports.default = _default;
@@ -46,7 +46,7 @@ var _default = () => ({
46
46
  sortGroupItem: {
47
47
  cursor: 'pointer',
48
48
  fontFamily: 'Nunito',
49
- fontSize: '10px',
49
+ fontSize: '11px',
50
50
  marginRight: '32px'
51
51
  },
52
52
  NonSortGroup: {
@@ -57,25 +57,25 @@ var _default = () => ({
57
57
  },
58
58
  NonSortGroupItem: {
59
59
  fontFamily: 'Nunito',
60
- fontSize: '10px',
60
+ fontSize: '11px',
61
61
  marginRight: '32px'
62
62
  },
63
63
  sortGroupItemCounts: {
64
64
  cursor: 'pointer',
65
65
  fontFamily: 'Nunito',
66
- fontSize: '10px',
66
+ fontSize: '11px',
67
67
  float: 'right',
68
68
  marginRight: '10px',
69
69
  marginTop: '5px'
70
70
  },
71
71
  highlight: {
72
- color: '#b2c6d6'
72
+ color: '#537A9D'
73
73
  },
74
74
  showMore: {
75
75
  textAlign: 'right',
76
76
  paddingRight: '5px',
77
77
  cursor: 'pointer',
78
- fontSize: '10px',
78
+ fontSize: '11px',
79
79
  width: '100%'
80
80
  }
81
81
  });
@@ -35,7 +35,7 @@ const FacetView = _ref => {
35
35
  const onExpandFacet = () => setExpand(!expand);
36
36
 
37
37
  /**
38
- * expand section incase of active local search
38
+ * Expand section incase of active local search
39
39
  */
40
40
  (0, _react.useEffect)(() => {
41
41
  if (autoComplete && autoComplete.length > 0 || upload && upload.length > 0) {
@@ -8,6 +8,12 @@ var _default = () => ({
8
8
  listItemGutters: {
9
9
  padding: '10px 20px 10px 0px'
10
10
  },
11
+ listItemRoot: {
12
+ cursor: 'pointer',
13
+ '&:hover': {
14
+ backgroundColor: 'rgba(0, 0, 0, 0.04)'
15
+ }
16
+ },
11
17
  checkboxRoot: {
12
18
  marginLeft: '5px',
13
19
  height: 12
@@ -4,13 +4,16 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _react = _interopRequireDefault(require("react"));
7
+ var _react = _interopRequireWildcard(require("react"));
8
8
  var _styles = require("@material-ui/core/styles");
9
9
  var _core = require("@material-ui/core");
10
+ var _TouchRipple = _interopRequireDefault(require("@material-ui/core/ButtonBase/TouchRipple"));
10
11
  var _clsx = _interopRequireDefault(require("clsx"));
11
12
  var _icons = require("@material-ui/icons");
12
13
  var _CheckboxStyle = _interopRequireDefault(require("./CheckboxStyle"));
13
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
16
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
14
17
  /* eslint-disable no-unused-vars */
15
18
  /* eslint-disable no-unused-vars */
16
19
  /* eslint-disable react/jsx-wrap-multilines */
@@ -18,8 +21,8 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
18
21
  /* eslint-disable object-curly-newline */
19
22
  /* eslint-disable object-shorthand */
20
23
  /* eslint-disable react/jsx-one-expression-per-line */
24
+ /* eslint-disable no-useless-escape */
21
25
 
22
- const alignment = 'flex-start';
23
26
  const CheckBoxView = _ref => {
24
27
  let {
25
28
  classes,
@@ -29,19 +32,35 @@ const CheckBoxView = _ref => {
29
32
  facet
30
33
  } = _ref;
31
34
  const {
32
- name,
33
- subjects,
34
35
  isChecked = false,
35
36
  index,
36
37
  section,
37
- tooltip,
38
- label
38
+ tooltip
39
39
  } = checkboxItem;
40
+ const {
41
+ field = 'group',
42
+ count = 'subjects',
43
+ customCount = text => "(".concat(text, ")"),
44
+ defaultValue = ''
45
+ } = facet;
40
46
  const indexType = index % 2 === 0 ? 'Even' : 'Odd';
41
- const checkedSection = "".concat(section).toLowerCase().replace(' ', '_');
47
+ const checkedSection = "".concat(section).toLowerCase().replace(/\ /g, '_');
48
+ const name = checkboxItem[field] || defaultValue || 'N/A';
49
+ const checkboxId = "checkbox_".concat(facet.label, "_").concat(name);
50
+ const rippleRef = (0, _react.useRef)(null);
51
+ const handleRippleStart = event => {
52
+ if (rippleRef.current) {
53
+ rippleRef.current.start(event);
54
+ }
55
+ };
56
+ const handleRippleStop = event => {
57
+ if (rippleRef.current) {
58
+ rippleRef.current.stop(event);
59
+ }
60
+ };
42
61
  const handleToggle = () => {
43
62
  const toggleCheckBoxItem = {
44
- name: name,
63
+ name: checkboxItem[field],
45
64
  datafield: datafield,
46
65
  isChecked: !isChecked
47
66
  };
@@ -53,30 +72,37 @@ const CheckBoxView = _ref => {
53
72
  ["".concat(checkedSection, "NameUnChecked")]: !isChecked,
54
73
  ["".concat(checkedSection, "NameChecked")]: isChecked
55
74
  })
56
- }, label ? /*#__PURE__*/_react.default.createElement(_core.Typography, {
57
- className: classes.checkboxLabel
58
- }, label) : /*#__PURE__*/_react.default.createElement(_core.Typography, {
75
+ }, /*#__PURE__*/_react.default.createElement(_core.Typography, {
59
76
  className: classes.checkboxName
60
77
  }, name));
61
78
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_core.ListItem, {
79
+ component: "div",
62
80
  width: 1,
63
- button: true,
64
81
  alignItems: "flex-start",
65
82
  onClick: handleToggle,
83
+ onMouseDown: handleRippleStart,
84
+ onMouseUp: handleRippleStop,
85
+ onMouseLeave: handleRippleStop,
66
86
  classes: {
67
- gutters: classes.listItemGutters
87
+ gutters: classes.listItemGutters,
88
+ root: classes.listItemRoot
68
89
  },
69
90
  className: (0, _clsx.default)({
70
91
  ["".concat(checkedSection, "Checked").concat(indexType)]: isChecked
71
92
  })
72
93
  }, /*#__PURE__*/_react.default.createElement(_core.Checkbox, {
73
- id: "checkbox_".concat(facet.label, "_").concat(name),
94
+ id: checkboxId,
74
95
  icon: /*#__PURE__*/_react.default.createElement(_icons.CheckBoxOutlineBlank, {
75
96
  style: {
76
97
  fontSize: 18
77
- }
98
+ },
99
+ className: checkedSection
78
100
  }),
79
- onClick: handleToggle,
101
+ inputProps: {
102
+ 'aria-label': 'checkbox',
103
+ tabIndex: -1,
104
+ 'aria-hidden': true
105
+ },
80
106
  checked: isChecked,
81
107
  checkedIcon: /*#__PURE__*/_react.default.createElement(_icons.CheckBox, {
82
108
  style: {
@@ -88,18 +114,26 @@ const CheckBoxView = _ref => {
88
114
  color: "secondary",
89
115
  classes: {
90
116
  root: classes.checkboxRoot
117
+ },
118
+ style: {
119
+ pointerEvents: 'none'
91
120
  }
92
121
  }), tooltip ? /*#__PURE__*/_react.default.createElement(_core.Tooltip, {
93
122
  id: datafield,
94
123
  title: tooltip
95
124
  }, /*#__PURE__*/_react.default.createElement("div", {
96
125
  className: datafield
97
- }, /*#__PURE__*/_react.default.createElement(LabelComponent, null))) : /*#__PURE__*/_react.default.createElement(LabelComponent, null), /*#__PURE__*/_react.default.createElement(_core.ListItemText, null), /*#__PURE__*/_react.default.createElement(_core.Typography, {
126
+ }, name)) : /*#__PURE__*/_react.default.createElement(LabelComponent, null), /*#__PURE__*/_react.default.createElement(_core.ListItemText, {
127
+ className: "".concat(checkedSection, "_md_space")
128
+ }), /*#__PURE__*/_react.default.createElement(_core.Typography, {
98
129
  className: (0, _clsx.default)("".concat(checkedSection, "Subjects"), {
99
130
  ["".concat(checkedSection, "SubjectUnChecked")]: !isChecked,
100
131
  ["".concat(checkedSection, "SubjectChecked")]: isChecked
101
132
  })
102
- }, "(".concat(subjects, ")"))), /*#__PURE__*/_react.default.createElement(_core.Divider, {
133
+ }, customCount(checkboxItem[count] || 0)), /*#__PURE__*/_react.default.createElement(_TouchRipple.default, {
134
+ ref: rippleRef,
135
+ center: true
136
+ })), /*#__PURE__*/_react.default.createElement(_core.Divider, {
103
137
  style: {
104
138
  backgroundColor: isChecked ? '#FFFFFF' : '#b1b1b1',
105
139
  margin: '0px',
@@ -39,7 +39,8 @@ function InputMinMaxView(_ref) {
39
39
  step: 1,
40
40
  min: minLowerBound,
41
41
  max: maxUpperBound,
42
- type: 'number'
42
+ type: 'number',
43
+ 'aria-label': 'slider'
43
44
  }
44
45
  });
45
46
  }
@@ -29,7 +29,9 @@ const SliderView = _ref => {
29
29
  maxUpperBound,
30
30
  quantifier,
31
31
  datafield,
32
- facetValues
32
+ facetValues,
33
+ CustomLowerUpperBound,
34
+ CustomSliderValue
33
35
  } = facet;
34
36
  const lowerBoundValue = facetValues[0];
35
37
  const upperBoundValue = facetValues[1];
@@ -102,13 +104,24 @@ const SliderView = _ref => {
102
104
  thumb: isValid() ? classes.thumb : classes.invalidThumb,
103
105
  track: isValid() ? classes.track : classes.invalidTrack
104
106
  }
105
- })), /*#__PURE__*/_react.default.createElement(_core.Box, {
107
+ })), typeof CustomLowerUpperBound === 'function' ? CustomLowerUpperBound({
108
+ minLowerBound,
109
+ maxUpperBound,
110
+ classes
111
+ }) : /*#__PURE__*/_react.default.createElement(_core.Box, {
106
112
  className: classes.lowerUpperBound
107
113
  }, /*#__PURE__*/_react.default.createElement(_core.Typography, {
108
114
  className: classes.lowerBound
109
115
  }, minLowerBound), /*#__PURE__*/_react.default.createElement(_core.Typography, {
110
116
  className: classes.upperBound
111
- }, maxUpperBound))), (sliderValue[0] > minLowerBound || sliderValue[1] < maxUpperBound) && /*#__PURE__*/_react.default.createElement(_core.Typography, {
117
+ }, maxUpperBound))), typeof CustomSliderValue === 'function' ? CustomSliderValue({
118
+ sliderValue,
119
+ minLowerBound,
120
+ maxUpperBound,
121
+ isValid,
122
+ quantifier,
123
+ classes
124
+ }) : (sliderValue[0] > minLowerBound || sliderValue[1] < maxUpperBound) && /*#__PURE__*/_react.default.createElement(_core.Typography, {
112
125
  className: isValid() ? classes.sliderText : classes.invalidSliderText
113
126
  }, sliderValue[0], ' - ', sliderValue[1], "\xA0", quantifier));
114
127
  };
@@ -46,28 +46,30 @@ const sortBySection = _ref => {
46
46
  let {
47
47
  facetValues,
48
48
  sort_type,
49
- sortBy
49
+ sortBy,
50
+ field,
51
+ count = 'subjects'
50
52
  } = _ref;
51
53
  const sortfacetValues = [...facetValues];
52
54
  if (!sortfacetValues) {
53
55
  return facetValues;
54
56
  }
55
57
  if (sortBy === sortType.NUMERIC) {
56
- sortfacetValues.sort((a, b) => b.subjects - a.subjects);
58
+ sortfacetValues.sort((a, b) => b[count] - a[count]);
57
59
  } else {
58
- sortfacetValues.sort((a, b) => lowerCaseString(a.name) > lowerCaseString(b.name) || -(lowerCaseString(a.name) < lowerCaseString(b.name)));
60
+ sortfacetValues.sort((a, b) => lowerCaseString(a[field]) > lowerCaseString(b[field]) || -(lowerCaseString(a[field]) < lowerCaseString(b[field])));
59
61
  }
60
62
  if (sort_type === sortType.CUSTOM_NUMBER && sortBy !== sortType.NUMERIC) {
61
63
  sortfacetValues.sort((a, b) => {
62
- const aNumbs = getNumberArray(a.name);
63
- const bNumbs = getNumberArray(b.name);
64
+ const aNumbs = getNumberArray(a[field]);
65
+ const bNumbs = getNumberArray(b[field]);
64
66
  const aNumb = Number(aNumbs[0]);
65
67
  const bNumb = Number(bNumbs[0]);
66
68
  return aNumbs.length === bNumbs.length ? aNumb > bNumb : -(aNumb <= bNumb);
67
69
  });
68
70
  }
69
71
  if (sort_type === sortType.RANGE && sortBy !== sortType.NUMERIC) {
70
- sortfacetValues.sort((a, b) => startIndex(a.name) > startIndex(b.name) || -(startIndex(a.name) < startIndex(b.name)));
72
+ sortfacetValues.sort((a, b) => startIndex(a[field]) > startIndex(b[field]) || -(startIndex(a[field]) < startIndex(b[field])));
71
73
  }
72
74
  /**
73
75
  * Display checked item always on top
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bento-core/facet-filter",
3
- "version": "1.0.1-popsci.2",
3
+ "version": "1.0.1-popsci.4",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -25,5 +25,5 @@
25
25
  },
26
26
  "author": "CTOS Bento Team",
27
27
  "license": "ISC",
28
- "gitHead": "5c65b1486cf1962dce93f6e71019e6079d82a4ba"
28
+ "gitHead": "3b3ccdfd3f5870b13f64d3642c7d8ab1649cf632"
29
29
  }
@@ -25,6 +25,7 @@ const FacetFilterController = (props) => {
25
25
  data,
26
26
  facetsConfig,
27
27
  facetSectionConfig,
28
+ tooltipText = {},
28
29
  } = props;
29
30
 
30
31
  const updateFacetState = (filterSections) => {
@@ -33,9 +34,15 @@ const FacetFilterController = (props) => {
33
34
  for (const [key, value] of Object.entries(filterState)) {
34
35
  updateSections.forEach((sideBar) => {
35
36
  if (sideBar.type === InputTypes.CHECKBOX && sideBar.datafield === key) {
36
- sideBar.facetValues.forEach((item) => {
37
- item.isChecked = value[item.name] ? value[item.name] : false;
37
+ const { facetValues = [] } = sideBar;
38
+ const updateFacetVals = facetValues.map((item) => {
39
+ const facetVal = item[sideBar.field];
40
+ return {
41
+ ...item,
42
+ isChecked: value[facetVal] ? value[facetVal] : false,
43
+ };
38
44
  });
45
+ sideBar.facetValues = updateFacetVals;
39
46
  }
40
47
  if (sideBar.type === InputTypes.SLIDER && sideBar.datafield === key) {
41
48
  sideBar.facetValues = value;
@@ -45,9 +52,12 @@ const FacetFilterController = (props) => {
45
52
  } else {
46
53
  updateSections.forEach((sideBar) => {
47
54
  if (sideBar.type === InputTypes.CHECKBOX) {
48
- sideBar.facetValues.forEach((item) => {
49
- item.isChecked = false;
50
- });
55
+ const { facetValues = [] } = sideBar;
56
+ const updateFacetVals = facetValues.map((item) => ({
57
+ ...item,
58
+ isChecked: false,
59
+ }));
60
+ sideBar.facetValues = updateFacetVals;
51
61
  }
52
62
  /**
53
63
  * set default value for slider - on clear all filter
@@ -83,6 +93,7 @@ const FacetFilterController = (props) => {
83
93
  * Construct filter object
84
94
  * 1. add facet values to facets
85
95
  * 2. add 'name' key to each facet value
96
+ * 3. add '
86
97
  */
87
98
  const addFacetValues = (facets) => {
88
99
  const updateFacets = [];
@@ -90,19 +101,13 @@ const FacetFilterController = (props) => {
90
101
  facets.forEach((facet) => {
91
102
  const updateFacet = { ...facet, facetValues: [] };
92
103
  const {
93
- field,
94
104
  ApiLowerBoundName,
95
105
  ApiUpperBoundName,
96
106
  apiForFiltering,
97
107
  } = updateFacet;
98
108
  if (data[apiForFiltering]) {
99
109
  if (Array.isArray(data[apiForFiltering])) {
100
- const updateField = data[apiForFiltering].map((item) => {
101
- const addField = { ...item };
102
- addField.name = item[field];
103
- return addField;
104
- });
105
- updateFacet.facetValues = updateField;
110
+ updateFacet.facetValues = data[apiForFiltering];
106
111
  }
107
112
  /**
108
113
  * add object to facet values
@@ -125,7 +130,7 @@ const FacetFilterController = (props) => {
125
130
  * Generate facet sections state
126
131
  *
127
132
  */
128
- const displayFacets = facetsConfig.filter((facet) => facet.show).slice(0, 16);
133
+ const displayFacets = facetsConfig.filter((facet) => facet.show);
129
134
  const facetStates = addFacetValues(displayFacets);
130
135
  const updateState = updateFacetState(facetStates);
131
136
  const facetSections = arrangeBySections(updateState);
@@ -19,7 +19,7 @@ export default () => ({
19
19
  sortGroupItem: {
20
20
  cursor: 'pointer',
21
21
  fontFamily: 'Nunito',
22
- fontSize: '10px',
22
+ fontSize: '11px',
23
23
  marginRight: '32px',
24
24
  },
25
25
  });
@@ -3,13 +3,11 @@
3
3
  import React from 'react';
4
4
  import {
5
5
  Divider,
6
- List,
7
6
  withStyles,
8
7
  } from '@material-ui/core';
9
8
  import styles from './FacetFilterStyle';
10
9
  import FacetSectionView from './components/section/FacetSectionView';
11
10
  import FacetView from './components/facet/ReduxFacetView';
12
- import FilterItems from './components/inputs/FilterItems';
13
11
 
14
12
  const BentoFacetFilter = ({
15
13
  sideBarSections,
@@ -33,13 +31,7 @@ const BentoFacetFilter = ({
33
31
  <FacetView
34
32
  facet={facet}
35
33
  CustomView={CustomFacetView}
36
- >
37
- <List className={`List_${facet.label}`}>
38
- <FilterItems
39
- facet={facet}
40
- />
41
- </List>
42
- </FacetView>
34
+ />
43
35
  ))}
44
36
  </FacetSectionView>
45
37
  </>
@@ -40,7 +40,7 @@ export default () => ({
40
40
  sortGroupItem: {
41
41
  cursor: 'pointer',
42
42
  fontFamily: 'Nunito',
43
- fontSize: '10px',
43
+ fontSize: '11px',
44
44
  marginRight: '32px',
45
45
  },
46
46
  NonSortGroup: {
@@ -51,25 +51,25 @@ export default () => ({
51
51
  },
52
52
  NonSortGroupItem: {
53
53
  fontFamily: 'Nunito',
54
- fontSize: '10px',
54
+ fontSize: '11px',
55
55
  marginRight: '32px',
56
56
  },
57
57
  sortGroupItemCounts: {
58
58
  cursor: 'pointer',
59
59
  fontFamily: 'Nunito',
60
- fontSize: '10px',
60
+ fontSize: '11px',
61
61
  float: 'right',
62
62
  marginRight: '10px',
63
63
  marginTop: '5px',
64
64
  },
65
65
  highlight: {
66
- color: '#b2c6d6',
66
+ color: '#537A9D',
67
67
  },
68
68
  showMore: {
69
69
  textAlign: 'right',
70
70
  paddingRight: '5px',
71
71
  cursor: 'pointer',
72
- fontSize: '10px',
72
+ fontSize: '11px',
73
73
  width: '100%',
74
74
  },
75
75
  });
@@ -2,6 +2,12 @@ export default () => ({
2
2
  listItemGutters: {
3
3
  padding: '10px 20px 10px 0px',
4
4
  },
5
+ listItemRoot: {
6
+ cursor: 'pointer',
7
+ '&:hover': {
8
+ backgroundColor: 'rgba(0, 0, 0, 0.04)',
9
+ },
10
+ },
5
11
  checkboxRoot: {
6
12
  marginLeft: '5px',
7
13
  height: 12,
@@ -5,7 +5,9 @@
5
5
  /* eslint-disable object-curly-newline */
6
6
  /* eslint-disable object-shorthand */
7
7
  /* eslint-disable react/jsx-one-expression-per-line */
8
- import React from 'react';
8
+ /* eslint-disable no-useless-escape */
9
+
10
+ import React, { useRef } from 'react';
9
11
  import { withStyles } from '@material-ui/core/styles';
10
12
  import {
11
13
  Checkbox,
@@ -15,15 +17,15 @@ import {
15
17
  Tooltip,
16
18
  Box,
17
19
  Typography,
20
+ ButtonBase,
18
21
  } from '@material-ui/core';
22
+ import TouchRipple from '@material-ui/core/ButtonBase/TouchRipple';
19
23
  import clsx from 'clsx';
20
24
  import {
21
25
  CheckBox as CheckBoxIcon, CheckBoxOutlineBlank as CheckBoxBlankIcon,
22
26
  } from '@material-ui/icons';
23
27
  import styles from './CheckboxStyle';
24
28
 
25
- const alignment = 'flex-start';
26
-
27
29
  const CheckBoxView = ({
28
30
  classes,
29
31
  checkboxItem,
@@ -32,20 +34,39 @@ const CheckBoxView = ({
32
34
  facet,
33
35
  }) => {
34
36
  const {
35
- name,
36
- subjects,
37
37
  isChecked = false,
38
38
  index,
39
39
  section,
40
40
  tooltip,
41
- label,
42
41
  } = checkboxItem;
42
+ const {
43
+ field = 'group',
44
+ count = 'subjects',
45
+ customCount = (text) => `(${text})`,
46
+ defaultValue = '',
47
+ } = facet;
48
+
43
49
  const indexType = index % 2 === 0 ? 'Even' : 'Odd';
44
- const checkedSection = `${section}`.toLowerCase().replace(' ', '_');
50
+ const checkedSection = `${section}`.toLowerCase().replace(/\ /g, '_');
51
+ const name = checkboxItem[field] || defaultValue || 'N/A';
52
+ const checkboxId = `checkbox_${facet.label}_${name}`;
53
+ const rippleRef = useRef(null);
54
+
55
+ const handleRippleStart = (event) => {
56
+ if (rippleRef.current) {
57
+ rippleRef.current.start(event);
58
+ }
59
+ };
60
+
61
+ const handleRippleStop = (event) => {
62
+ if (rippleRef.current) {
63
+ rippleRef.current.stop(event);
64
+ }
65
+ };
45
66
 
46
67
  const handleToggle = () => {
47
68
  const toggleCheckBoxItem = {
48
- name: name,
69
+ name: checkboxItem[field],
49
70
  datafield: datafield,
50
71
  isChecked: !isChecked,
51
72
  };
@@ -60,65 +81,75 @@ const CheckBoxView = ({
60
81
  [`${checkedSection}NameChecked`]: isChecked,
61
82
  })}
62
83
  >
63
- {label ? (
64
- <Typography className={classes.checkboxLabel}>{label}</Typography>
65
- ) : (<Typography className={classes.checkboxName}>{name}</Typography>)}
84
+ <Typography className={classes.checkboxName}>
85
+ {name}
86
+ </Typography>
66
87
  </Box>
67
88
  );
68
89
 
69
90
  return (
70
91
  <>
71
- <ListItem
72
- width={1}
73
- button
74
- alignItems="flex-start"
75
- onClick={handleToggle}
76
- classes={{ gutters: classes.listItemGutters }}
77
- className={clsx({ [`${checkedSection}Checked${indexType}`]: isChecked })}
78
- >
79
- <Checkbox
80
- id={`checkbox_${facet.label}_${name}`}
81
- icon={<CheckBoxBlankIcon style={{ fontSize: 18 }} />}
92
+ <ListItem
93
+ component="div"
94
+ width={1}
95
+ alignItems="flex-start"
82
96
  onClick={handleToggle}
83
- checked={isChecked}
84
- checkedIcon={(
85
- <CheckBoxIcon
86
- style={{
87
- fontSize: 18,
88
- }}
89
- className={`${checkedSection}CheckedIcon`}
90
- />
97
+ onMouseDown={handleRippleStart}
98
+ onMouseUp={handleRippleStop}
99
+ onMouseLeave={handleRippleStop}
100
+ classes={{ gutters: classes.listItemGutters, root: classes.listItemRoot }}
101
+ className={clsx({ [`${checkedSection}Checked${indexType}`]: isChecked })}
102
+ >
103
+ <Checkbox
104
+ id={checkboxId}
105
+ icon={(
106
+ <CheckBoxBlankIcon
107
+ style={{ fontSize: 18 }}
108
+ className={checkedSection}
109
+ />
110
+ )}
111
+ inputProps={{ 'aria-label': 'checkbox', tabIndex: -1, 'aria-hidden': true }}
112
+ checked={isChecked}
113
+ checkedIcon={(
114
+ <CheckBoxIcon
115
+ style={{
116
+ fontSize: 18,
117
+ }}
118
+ className={`${checkedSection}CheckedIcon`}
119
+ />
120
+ )}
121
+ disableRipple
122
+ color="secondary"
123
+ classes={{ root: classes.checkboxRoot }}
124
+ style={{ pointerEvents: 'none' }}
125
+ />
126
+ { tooltip ? (
127
+ <Tooltip id={datafield} title={tooltip}>
128
+ <div className={datafield}>
129
+ {name}
130
+ </div>
131
+ </Tooltip>
132
+ ) : (
133
+ <LabelComponent />
91
134
  )}
92
- disableRipple
93
- color="secondary"
94
- classes={{ root: classes.checkboxRoot }}
135
+ <ListItemText className={`${checkedSection}_md_space`} />
136
+ <Typography
137
+ className={clsx(`${checkedSection}Subjects`, {
138
+ [`${checkedSection}SubjectUnChecked`]: !isChecked,
139
+ [`${checkedSection}SubjectChecked`]: isChecked,
140
+ })}
141
+ >
142
+ {customCount(checkboxItem[count] || 0)}
143
+ </Typography>
144
+ <TouchRipple ref={rippleRef} center />
145
+ </ListItem>
146
+ <Divider
147
+ style={{
148
+ backgroundColor: isChecked ? '#FFFFFF' : '#b1b1b1',
149
+ margin: '0px',
150
+ height: isChecked ? '2px' : '1px',
151
+ }}
95
152
  />
96
- { tooltip ? (
97
- <Tooltip id={datafield} title={tooltip}>
98
- <div className={datafield}>
99
- <LabelComponent />
100
- </div>
101
- </Tooltip>
102
- ) : (
103
- <LabelComponent />
104
- )}
105
- <ListItemText />
106
- <Typography
107
- className={clsx(`${checkedSection}Subjects`, {
108
- [`${checkedSection}SubjectUnChecked`]: !isChecked,
109
- [`${checkedSection}SubjectChecked`]: isChecked,
110
- })}
111
- >
112
- {`(${subjects})`}
113
- </Typography>
114
- </ListItem>
115
- <Divider
116
- style={{
117
- backgroundColor: isChecked ? '#FFFFFF' : '#b1b1b1',
118
- margin: '0px',
119
- height: isChecked ? '2px' : '1px',
120
- }}
121
- />
122
153
  </>
123
154
  );
124
155
  };
@@ -37,6 +37,7 @@ function InputMinMaxView({
37
37
  min: minLowerBound,
38
38
  max: maxUpperBound,
39
39
  type: 'number',
40
+ 'aria-label': 'slider',
40
41
  }}
41
42
  />
42
43
  );
@@ -14,7 +14,15 @@ const SliderView = ({
14
14
  onSliderToggle,
15
15
  filterState,
16
16
  }) => {
17
- const { minLowerBound, maxUpperBound, quantifier, datafield, facetValues } = facet;
17
+ const {
18
+ minLowerBound,
19
+ maxUpperBound,
20
+ quantifier,
21
+ datafield,
22
+ facetValues,
23
+ CustomLowerUpperBound,
24
+ CustomSliderValue,
25
+ } = facet;
18
26
  const lowerBoundValue = facetValues[0];
19
27
  const upperBoundValue = facetValues[1];
20
28
 
@@ -99,24 +107,26 @@ const SliderView = ({
99
107
  }}
100
108
  />
101
109
  </div>
102
- <Box className={classes.lowerUpperBound}>
103
- <Typography className={classes.lowerBound}>
104
- {minLowerBound}
105
- </Typography>
106
- <Typography className={classes.upperBound}>
107
- {maxUpperBound}
108
- </Typography>
109
- </Box>
110
+ {typeof CustomLowerUpperBound === 'function' ? (
111
+ CustomLowerUpperBound({ minLowerBound, maxUpperBound, classes })
112
+ ) : (
113
+ <Box className={classes.lowerUpperBound}>
114
+ <Typography className={classes.lowerBound}>
115
+ {minLowerBound}
116
+ </Typography>
117
+ <Typography className={classes.upperBound}>
118
+ {maxUpperBound}
119
+ </Typography>
120
+ </Box>
121
+ )}
110
122
  </div>
111
123
  {/* Change to red if invalid range */}
112
- {
113
- (sliderValue[0] > minLowerBound || sliderValue[1] < maxUpperBound)
114
- && (
115
- <Typography
116
- className={isValid()
117
- ? classes.sliderText
118
- : classes.invalidSliderText}
119
- >
124
+ {typeof CustomSliderValue === 'function' ? (
125
+ CustomSliderValue({
126
+ sliderValue, minLowerBound, maxUpperBound, isValid, quantifier, classes })
127
+ ) : (
128
+ (sliderValue[0] > minLowerBound || sliderValue[1] < maxUpperBound) && (
129
+ <Typography className={isValid() ? classes.sliderText : classes.invalidSliderText}>
120
130
  {sliderValue[0]}
121
131
  {' - '}
122
132
  {sliderValue[1]}
@@ -124,7 +134,7 @@ const SliderView = ({
124
134
  {quantifier}
125
135
  </Typography>
126
136
  )
127
- }
137
+ )}
128
138
  </>
129
139
  );
130
140
  };
package/src/utils/Sort.js CHANGED
@@ -37,22 +37,28 @@ export const getNumberArray = (range) => {
37
37
  * @param {array} checkboxData
38
38
  * @return {array}
39
39
  */
40
- export const sortBySection = ({ facetValues, sort_type, sortBy }) => {
40
+ export const sortBySection = ({
41
+ facetValues,
42
+ sort_type,
43
+ sortBy,
44
+ field,
45
+ count = 'subjects',
46
+ }) => {
41
47
  const sortfacetValues = [...facetValues];
42
48
  if (!sortfacetValues) {
43
49
  return facetValues;
44
50
  }
45
51
  if (sortBy === sortType.NUMERIC) {
46
- sortfacetValues.sort((a, b) => b.subjects - a.subjects);
52
+ sortfacetValues.sort((a, b) => b[count] - a[count]);
47
53
  } else {
48
- sortfacetValues.sort(((a, b) => (lowerCaseString(a.name) > lowerCaseString(b.name)
49
- || -(lowerCaseString(a.name) < lowerCaseString(b.name)))));
54
+ sortfacetValues.sort(((a, b) => (lowerCaseString(a[field]) > lowerCaseString(b[field])
55
+ || -(lowerCaseString(a[field]) < lowerCaseString(b[field])))));
50
56
  }
51
57
 
52
58
  if (sort_type === sortType.CUSTOM_NUMBER && sortBy !== sortType.NUMERIC) {
53
59
  sortfacetValues.sort((a, b) => {
54
- const aNumbs = getNumberArray(a.name);
55
- const bNumbs = getNumberArray(b.name);
60
+ const aNumbs = getNumberArray(a[field]);
61
+ const bNumbs = getNumberArray(b[field]);
56
62
  const aNumb = Number(aNumbs[0]);
57
63
  const bNumb = Number(bNumbs[0]);
58
64
  return (aNumbs.length === bNumbs.length) ? aNumb > bNumb : -(aNumb <= bNumb);
@@ -60,8 +66,8 @@ export const sortBySection = ({ facetValues, sort_type, sortBy }) => {
60
66
  }
61
67
 
62
68
  if (sort_type === sortType.RANGE && sortBy !== sortType.NUMERIC) {
63
- sortfacetValues.sort(((a, b) => (startIndex(a.name) > startIndex(b.name)
64
- || -(startIndex(a.name) < startIndex(b.name)))));
69
+ sortfacetValues.sort(((a, b) => (startIndex(a[field]) > startIndex(b[field])
70
+ || -(startIndex(a[field]) < startIndex(b[field])))));
65
71
  }
66
72
  /**
67
73
  * Display checked item always on top