@carbon/ibm-products 1.42.1 → 1.43.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. package/css/index-full-carbon.css +154 -24
  2. package/css/index-full-carbon.css.map +1 -1
  3. package/css/index-full-carbon.min.css +2 -2
  4. package/css/index-full-carbon.min.css.map +1 -1
  5. package/css/index-without-carbon.css +154 -24
  6. package/css/index-without-carbon.css.map +1 -1
  7. package/css/index-without-carbon.min.css +2 -2
  8. package/css/index-without-carbon.min.css.map +1 -1
  9. package/css/index.css +154 -24
  10. package/css/index.css.map +1 -1
  11. package/css/index.min.css +2 -2
  12. package/css/index.min.css.map +1 -1
  13. package/es/components/AddSelect/AddSelect.js +1 -1
  14. package/es/components/AddSelect/AddSelectBody.js +1 -1
  15. package/es/components/AddSelect/AddSelectColumn.js +1 -1
  16. package/es/components/Datagrid/Datagrid/Datagrid.js +3 -3
  17. package/es/components/Datagrid/Datagrid/DatagridContent.js +43 -15
  18. package/es/components/Datagrid/Datagrid/DatagridToolbar.js +2 -18
  19. package/es/components/Datagrid/Datagrid/DraggableElement.js +1 -1
  20. package/es/components/Datagrid/Datagrid/addons/Filtering/FilterFlyout.js +65 -34
  21. package/es/components/Datagrid/Datagrid/addons/Filtering/FilterPanel.js +436 -0
  22. package/es/components/Datagrid/Datagrid/addons/Filtering/FilterProvider.js +8 -2
  23. package/es/components/Datagrid/Datagrid/addons/Filtering/constants.js +9 -1
  24. package/es/components/Datagrid/Datagrid/addons/Filtering/hooks/index.js +2 -0
  25. package/es/components/Datagrid/Datagrid/addons/Filtering/hooks/useInitialStateFromFilters.js +3 -1
  26. package/es/components/Datagrid/Datagrid/addons/Filtering/hooks/useSubscribeToEventEmitter.js +23 -0
  27. package/es/components/Datagrid/Datagrid/addons/Filtering/index.js +3 -1
  28. package/es/components/Datagrid/Datagrid/addons/Filtering/motion/variants.js +55 -0
  29. package/es/components/Datagrid/Datagrid/addons/Filtering/utils.js +49 -17
  30. package/es/components/Datagrid/Datagrid.stories/index.js +0 -1
  31. package/es/components/Datagrid/useFiltering.js +10 -3
  32. package/es/components/Datagrid/utils/DatagridActions.js +59 -6
  33. package/lib/components/AddSelect/AddSelect.js +1 -1
  34. package/lib/components/AddSelect/AddSelectBody.js +1 -1
  35. package/lib/components/AddSelect/AddSelectColumn.js +1 -1
  36. package/lib/components/Datagrid/Datagrid/Datagrid.js +3 -3
  37. package/lib/components/Datagrid/Datagrid/DatagridContent.js +43 -15
  38. package/lib/components/Datagrid/Datagrid/DatagridToolbar.js +2 -17
  39. package/lib/components/Datagrid/Datagrid/DraggableElement.js +1 -1
  40. package/lib/components/Datagrid/Datagrid/addons/Filtering/FilterFlyout.js +64 -31
  41. package/lib/components/Datagrid/Datagrid/addons/Filtering/FilterPanel.js +445 -0
  42. package/lib/components/Datagrid/Datagrid/addons/Filtering/FilterProvider.js +7 -1
  43. package/lib/components/Datagrid/Datagrid/addons/Filtering/constants.js +15 -3
  44. package/lib/components/Datagrid/Datagrid/addons/Filtering/hooks/index.js +20 -0
  45. package/lib/components/Datagrid/Datagrid/addons/Filtering/hooks/useInitialStateFromFilters.js +3 -1
  46. package/lib/components/Datagrid/Datagrid/addons/Filtering/hooks/useSubscribeToEventEmitter.js +30 -0
  47. package/lib/components/Datagrid/Datagrid/addons/Filtering/index.js +21 -1
  48. package/lib/components/Datagrid/Datagrid/addons/Filtering/motion/variants.js +64 -0
  49. package/lib/components/Datagrid/Datagrid/addons/Filtering/utils.js +48 -17
  50. package/lib/components/Datagrid/Datagrid.stories/index.js +0 -7
  51. package/lib/components/Datagrid/useFiltering.js +10 -3
  52. package/lib/components/Datagrid/utils/DatagridActions.js +57 -4
  53. package/package.json +2 -2
  54. package/scss/components/Datagrid/styles/_datagrid.scss +18 -18
  55. package/scss/components/Datagrid/styles/_draggableElement.scss +12 -4
  56. package/scss/components/Datagrid/styles/_index.scss +1 -0
  57. package/scss/components/Datagrid/styles/_useInlineEdit.scss +7 -3
  58. package/scss/components/Datagrid/styles/addons/_CustomizeColumnsTearsheet.scss +5 -1
  59. package/scss/components/Datagrid/styles/addons/_FilterPanel.scss +123 -0
  60. package/scss/components/FilterSummary/_filter-summary.scss +1 -0
  61. package/es/components/Datagrid/Datagrid.stories/LeftPanelStory.js +0 -6
  62. package/lib/components/Datagrid/Datagrid.stories/LeftPanelStory.js +0 -13
@@ -0,0 +1,436 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
4
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
5
+ 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; }
6
+ 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; }
7
+ /* eslint-disable react/jsx-key */
8
+
9
+ import React, { useRef, useMemo, useContext, useState, useEffect } from 'react';
10
+ import PropTypes from 'prop-types';
11
+ import { Accordion, AccordionItem, Button, Search, Checkbox, DatePicker, DatePickerInput, Dropdown, FormGroup, NumberInput, RadioButton, RadioButtonGroup } from 'carbon-components-react';
12
+ import { rem } from '@carbon/layout';
13
+ import { pkg } from '../../../../../settings';
14
+ import { BATCH, CHECKBOX, CLEAR_FILTERS, DATE, DROPDOWN, INSTANT, NUMBER, PANEL, RADIO } from './constants';
15
+ import cx from 'classnames';
16
+ import { motion } from 'framer-motion';
17
+ import { panelVariants, innerContainerVariants, actionSetVariants } from './motion/variants';
18
+ import { Close32 } from '@carbon/icons-react';
19
+ import { ActionSet } from '../../../../ActionSet';
20
+ import { FilterContext } from '.';
21
+ import { useInitialStateFromFilters, useSubscribeToEventEmitter } from './hooks';
22
+ import { getInitialStateFromFilters } from './utils';
23
+ import isEqual from 'lodash/isEqual';
24
+ var blockClass = "".concat(pkg.prefix, "--datagrid");
25
+ var componentClass = "".concat(blockClass, "-filter-panel");
26
+ var MotionActionSet = motion(ActionSet);
27
+ var FilterPanel = function FilterPanel(_ref) {
28
+ var _cx;
29
+ var title = _ref.title,
30
+ _ref$closeIconDescrip = _ref.closeIconDescription,
31
+ closeIconDescription = _ref$closeIconDescrip === void 0 ? 'Close filter panel' : _ref$closeIconDescrip,
32
+ _ref$updateMethod = _ref.updateMethod,
33
+ updateMethod = _ref$updateMethod === void 0 ? BATCH : _ref$updateMethod,
34
+ filterSections = _ref.filterSections,
35
+ setAllFilters = _ref.setAllFilters,
36
+ _ref$onApply = _ref.onApply,
37
+ onApply = _ref$onApply === void 0 ? function () {} : _ref$onApply,
38
+ _ref$onCancel = _ref.onCancel,
39
+ onCancel = _ref$onCancel === void 0 ? function () {} : _ref$onCancel,
40
+ _ref$onPanelOpen = _ref.onPanelOpen,
41
+ onPanelOpen = _ref$onPanelOpen === void 0 ? function () {} : _ref$onPanelOpen,
42
+ _ref$onPanelClose = _ref.onPanelClose,
43
+ onPanelClose = _ref$onPanelClose === void 0 ? function () {} : _ref$onPanelClose,
44
+ _ref$showFilterSearch = _ref.showFilterSearch,
45
+ showFilterSearch = _ref$showFilterSearch === void 0 ? false : _ref$showFilterSearch,
46
+ _ref$filterPanelMinHe = _ref.filterPanelMinHeight,
47
+ filterPanelMinHeight = _ref$filterPanelMinHe === void 0 ? 600 : _ref$filterPanelMinHe;
48
+ /** State */
49
+ var _useInitialStateFromF = useInitialStateFromFilters(filterSections, PANEL),
50
+ _useInitialStateFromF2 = _slicedToArray(_useInitialStateFromF, 2),
51
+ filtersState = _useInitialStateFromF2[0],
52
+ setFiltersState = _useInitialStateFromF2[1];
53
+ var _useState = useState([]),
54
+ _useState2 = _slicedToArray(_useState, 2),
55
+ filtersObjectArray = _useState2[0],
56
+ setFiltersObjectArray = _useState2[1];
57
+ var _useState3 = useState(true),
58
+ _useState4 = _slicedToArray(_useState3, 2),
59
+ shouldDisableButtons = _useState4[0],
60
+ setShouldDisableButtons = _useState4[1];
61
+ var _useState5 = useState(false),
62
+ _useState6 = _slicedToArray(_useState5, 2),
63
+ showDividerLine = _useState6[0],
64
+ setShowDividerLine = _useState6[1];
65
+
66
+ /** Refs */
67
+ var filterPanelRef = useRef();
68
+ var filterHeadingRef = useRef();
69
+ var filterSearchRef = useRef();
70
+ var actionSetRef = useRef();
71
+ // When using batch actions we have to store the filters to then apply them later
72
+ var prevFiltersRef = useRef(JSON.stringify(filtersState));
73
+ var prevFiltersObjectArrayRef = useRef(JSON.stringify(filtersObjectArray));
74
+
75
+ /** Memos */
76
+ var showActionSet = useMemo(function () {
77
+ return updateMethod === BATCH;
78
+ }, [updateMethod]);
79
+
80
+ /** Context */
81
+ var _useContext = useContext(FilterContext),
82
+ leftPanelOpen = _useContext.leftPanelOpen,
83
+ setLeftPanelOpen = _useContext.setLeftPanelOpen;
84
+
85
+ /** Methods */
86
+ var closePanel = function closePanel() {
87
+ return setLeftPanelOpen(false);
88
+ };
89
+
90
+ // If the user decides to cancel or click outside the flyout, it reverts back to the filters that were
91
+ // there when they opened the flyout
92
+ var revertToPreviousFilters = function revertToPreviousFilters() {
93
+ setFiltersState(JSON.parse(prevFiltersRef.current));
94
+ setFiltersObjectArray(JSON.parse(prevFiltersObjectArrayRef.current));
95
+ };
96
+ var cancel = function cancel() {
97
+ // Reverting to previous filters only applies when using batch actions
98
+ if (updateMethod === BATCH) {
99
+ revertToPreviousFilters();
100
+ onCancel();
101
+ }
102
+ };
103
+ var reset = function reset() {
104
+ // Get the initial values for the filters
105
+ var initialFiltersState = getInitialStateFromFilters(filterSections, PANEL);
106
+ var initialFiltersObjectArray = [];
107
+
108
+ // Set the state to the initial values
109
+ setFiltersState(initialFiltersState);
110
+ setFiltersObjectArray(initialFiltersObjectArray);
111
+ setAllFilters([]);
112
+
113
+ // Update their respective refs so everything is in sync
114
+ prevFiltersRef.current = JSON.stringify(initialFiltersState);
115
+ prevFiltersObjectArrayRef.current = JSON.stringify(initialFiltersObjectArray);
116
+ };
117
+ var apply = function apply() {
118
+ setAllFilters(filtersObjectArray);
119
+ onApply();
120
+ setShouldDisableButtons(true);
121
+
122
+ // updates the ref so next time the flyout opens we have records of the previous filters
123
+ prevFiltersRef.current = JSON.stringify(filtersState);
124
+ prevFiltersObjectArrayRef.current = JSON.stringify(filtersObjectArray);
125
+ };
126
+ var applyFilters = function applyFilters(_ref2) {
127
+ var column = _ref2.column,
128
+ value = _ref2.value,
129
+ type = _ref2.type;
130
+ // If no end date is selected return because we need the end date to do computations
131
+ if (type === DATE && value.length > 0 && !value[1]) {
132
+ return;
133
+ }
134
+ var filtersObjectArrayCopy = _toConsumableArray(filtersObjectArray);
135
+ // // check if the filter already exists in the array
136
+ var filter = filtersObjectArrayCopy.find(function (item) {
137
+ return item.id === column;
138
+ });
139
+
140
+ // // if filter exists in array then update the filter's new value
141
+ if (filter) {
142
+ filter.value = value;
143
+ } else {
144
+ filtersObjectArrayCopy.push({
145
+ id: column,
146
+ value: value,
147
+ type: type
148
+ });
149
+ }
150
+
151
+ // ATTENTION: this is where you would reset or remove individual filters from the filters array
152
+ if (type === CHECKBOX) {
153
+ /**
154
+ When all checkboxes of a group are all unselected the value still exists in the filtersObjectArray
155
+ This checks if all the checkboxes are selected = false and removes it from the array
156
+ */
157
+ var index = filtersObjectArrayCopy.findIndex(function (filter) {
158
+ return filter.id === column;
159
+ });
160
+
161
+ // If all the selected state is false remove from array
162
+ var shouldRemoveFromArray = filtersObjectArrayCopy[index].value.every(function (val) {
163
+ return val.selected === false;
164
+ });
165
+ if (shouldRemoveFromArray) {
166
+ filtersObjectArrayCopy.splice(index, 1);
167
+ }
168
+ } else if (type === DATE) {
169
+ if (value.length === 0) {
170
+ /**
171
+ Checks to see if the date value is an empty array, if it is that means the user wants
172
+ to reset the date filter
173
+ */
174
+ var _index = filtersObjectArrayCopy.findIndex(function (filter) {
175
+ return filter.id === column;
176
+ });
177
+
178
+ // Remove it from the filters array since there is nothing to filter
179
+ filtersObjectArrayCopy.splice(_index, 1);
180
+ }
181
+ }
182
+ setFiltersObjectArray(filtersObjectArrayCopy);
183
+
184
+ // // Automatically apply the filters if the updateMethod is instant
185
+ if (updateMethod === INSTANT) {
186
+ setAllFilters(filtersObjectArrayCopy);
187
+ }
188
+ };
189
+
190
+ /** Render the individual filter component */
191
+ var renderFilter = function renderFilter(_ref3) {
192
+ var type = _ref3.type,
193
+ column = _ref3.column,
194
+ components = _ref3.props;
195
+ switch (type) {
196
+ case DATE:
197
+ return /*#__PURE__*/React.createElement(DatePicker, _extends({}, components.DatePicker, {
198
+ onChange: function onChange(value) {
199
+ var _components$DatePicke, _components$DatePicke2;
200
+ setFiltersState(_objectSpread(_objectSpread({}, filtersState), {}, _defineProperty({}, column, {
201
+ value: value,
202
+ type: type
203
+ })));
204
+ applyFilters({
205
+ column: column,
206
+ value: value,
207
+ type: type
208
+ });
209
+ (_components$DatePicke = (_components$DatePicke2 = components.DatePicker).onChange) === null || _components$DatePicke === void 0 ? void 0 : _components$DatePicke.call(_components$DatePicke2, value);
210
+ },
211
+ value: filtersState[column].value,
212
+ datePickerType: "range",
213
+ light: true
214
+ }), /*#__PURE__*/React.createElement(DatePickerInput, _extends({
215
+ placeholder: "mm/dd/yyyy",
216
+ labelText: "Start date"
217
+ }, components.DatePickerInput.start)), /*#__PURE__*/React.createElement(DatePickerInput, _extends({
218
+ placeholder: "mm/dd/yyyy",
219
+ labelText: "End date"
220
+ }, components.DatePickerInput.end)));
221
+ case NUMBER:
222
+ return /*#__PURE__*/React.createElement(NumberInput, _extends({
223
+ step: 1,
224
+ allowEmpty: true,
225
+ hideSteppers: true
226
+ }, components.NumberInput, {
227
+ onChange: function onChange(event) {
228
+ var _components$NumberInp, _components$NumberInp2;
229
+ setFiltersState(_objectSpread(_objectSpread({}, filtersState), {}, _defineProperty({}, column, {
230
+ value: event.target.value,
231
+ type: type
232
+ })));
233
+ applyFilters({
234
+ column: column,
235
+ value: event.target.value,
236
+ type: type
237
+ });
238
+ (_components$NumberInp = (_components$NumberInp2 = components.NumberInput).onChange) === null || _components$NumberInp === void 0 ? void 0 : _components$NumberInp.call(_components$NumberInp2, event);
239
+ },
240
+ value: filtersState[column].value,
241
+ light: true
242
+ }));
243
+ case CHECKBOX:
244
+ return /*#__PURE__*/React.createElement(FormGroup, components.FormGroup, filtersState[column].value.map(function (option) {
245
+ return /*#__PURE__*/React.createElement(Checkbox, _extends({
246
+ key: option.labelText
247
+ }, option, {
248
+ onChange: function onChange(isSelected) {
249
+ var _option$onChange;
250
+ var checkboxCopy = filtersState[column].value;
251
+ var foundCheckbox = checkboxCopy.find(function (checkbox) {
252
+ return checkbox.value === option.value;
253
+ });
254
+ foundCheckbox.selected = isSelected;
255
+ setFiltersState(_objectSpread(_objectSpread({}, filtersState), {}, _defineProperty({}, column, {
256
+ value: checkboxCopy,
257
+ type: type
258
+ })));
259
+ applyFilters({
260
+ column: column,
261
+ value: _toConsumableArray(filtersState[column].value),
262
+ type: type
263
+ });
264
+ (_option$onChange = option.onChange) === null || _option$onChange === void 0 ? void 0 : _option$onChange.call(option, isSelected);
265
+ },
266
+ checked: option.selected
267
+ }));
268
+ }));
269
+ case RADIO:
270
+ return /*#__PURE__*/React.createElement(FormGroup, components.FormGroup, /*#__PURE__*/React.createElement(RadioButtonGroup, _extends({}, components.RadioButtonGroup, {
271
+ valueSelected: filtersState[column].value,
272
+ onChange: function onChange(selected) {
273
+ var _components$RadioButt, _components$RadioButt2;
274
+ setFiltersState(_objectSpread(_objectSpread({}, filtersState), {}, _defineProperty({}, column, {
275
+ value: selected,
276
+ type: type
277
+ })));
278
+ applyFilters({
279
+ column: column,
280
+ value: selected,
281
+ type: type
282
+ });
283
+ (_components$RadioButt = (_components$RadioButt2 = components.RadioButtonGroup).onChange) === null || _components$RadioButt === void 0 ? void 0 : _components$RadioButt.call(_components$RadioButt2, selected);
284
+ }
285
+ }), components.RadioButton.map(function (radio) {
286
+ var _ref4, _radio$id;
287
+ return /*#__PURE__*/React.createElement(RadioButton, _extends({
288
+ key: (_ref4 = (_radio$id = radio.id) !== null && _radio$id !== void 0 ? _radio$id : radio.labelText) !== null && _ref4 !== void 0 ? _ref4 : radio.value
289
+ }, radio));
290
+ })));
291
+ case DROPDOWN:
292
+ return /*#__PURE__*/React.createElement(Dropdown, _extends({}, components.Dropdown, {
293
+ selectedItem: filtersState[column].value,
294
+ onChange: function onChange(_ref5) {
295
+ var _components$Dropdown$, _components$Dropdown;
296
+ var selectedItem = _ref5.selectedItem;
297
+ setFiltersState(_objectSpread(_objectSpread({}, filtersState), {}, _defineProperty({}, column, {
298
+ value: selectedItem,
299
+ type: type
300
+ })));
301
+ applyFilters({
302
+ column: column,
303
+ value: selectedItem,
304
+ type: type
305
+ });
306
+ (_components$Dropdown$ = (_components$Dropdown = components.Dropdown).onChange) === null || _components$Dropdown$ === void 0 ? void 0 : _components$Dropdown$.call(_components$Dropdown, selectedItem);
307
+ },
308
+ light: true
309
+ }));
310
+ }
311
+ };
312
+ var renderActionSet = function renderActionSet() {
313
+ return showActionSet && /*#__PURE__*/React.createElement(MotionActionSet, {
314
+ actions: [{
315
+ key: 1,
316
+ kind: 'primary',
317
+ label: 'Apply',
318
+ onClick: apply,
319
+ disabled: shouldDisableButtons
320
+ }, {
321
+ key: 2,
322
+ kind: 'secondary',
323
+ label: 'Cancel',
324
+ onClick: cancel,
325
+ disabled: shouldDisableButtons
326
+ }],
327
+ className: "".concat(componentClass, "__action-set"),
328
+ ref: actionSetRef,
329
+ variants: actionSetVariants
330
+ });
331
+ };
332
+ var onInnerContainerScroll = function onInnerContainerScroll(event) {
333
+ if (event.target.scrollTop > 0) {
334
+ setShowDividerLine(true);
335
+ } else {
336
+ setShowDividerLine(false);
337
+ }
338
+ };
339
+
340
+ /** Effects */
341
+ useEffect(function liftOpenStateToParent() {
342
+ if (leftPanelOpen) {
343
+ onPanelOpen(leftPanelOpen);
344
+ } else {
345
+ onPanelClose(leftPanelOpen);
346
+ }
347
+ }, [leftPanelOpen, onPanelClose, onPanelOpen]);
348
+ useEffect(function setPanelMinimumHeight() {
349
+ var _filterPanelRef$curre;
350
+ (_filterPanelRef$curre = filterPanelRef.current) === null || _filterPanelRef$curre === void 0 ? void 0 : _filterPanelRef$curre.style.setProperty('--filter-panel-min-height', rem(filterPanelMinHeight));
351
+ }, [filterPanelMinHeight]);
352
+ useEffect(function updateDisabledButtonsState() {
353
+ setShouldDisableButtons(isEqual(filtersState, JSON.parse(prevFiltersRef.current)));
354
+ }, [filtersState]);
355
+ useSubscribeToEventEmitter(CLEAR_FILTERS, reset);
356
+ var getScrollableContainerHeight = function getScrollableContainerHeight() {
357
+ var _filterHeadingRef$cur, _filterSearchRef$curr, _actionSetRef$current;
358
+ var filterHeadingHeight = (_filterHeadingRef$cur = filterHeadingRef.current) === null || _filterHeadingRef$cur === void 0 ? void 0 : _filterHeadingRef$cur.getBoundingClientRect().height;
359
+ var filterSearchHeight = (_filterSearchRef$curr = filterSearchRef.current) === null || _filterSearchRef$curr === void 0 ? void 0 : _filterSearchRef$curr.getBoundingClientRect().height;
360
+ var actionSetHeight = (_actionSetRef$current = actionSetRef.current) === null || _actionSetRef$current === void 0 ? void 0 : _actionSetRef$current.getBoundingClientRect().height;
361
+ var height = "calc(100vh - ".concat(filterHeadingHeight, "px - ").concat(showFilterSearch ? filterSearchHeight : 0, "px - ").concat(updateMethod === BATCH ? actionSetHeight : 0, "px)");
362
+ return height;
363
+ };
364
+ return /*#__PURE__*/React.createElement(motion.div, {
365
+ ref: filterPanelRef,
366
+ className: cx(componentClass, "".concat(componentClass, "__container"), (_cx = {}, _defineProperty(_cx, "".concat(componentClass, "--open"), leftPanelOpen), _defineProperty(_cx, "".concat(componentClass, "--batch"), showActionSet), _defineProperty(_cx, "".concat(componentClass, "--instant"), !showActionSet), _cx)),
367
+ initial: false,
368
+ animate: leftPanelOpen ? 'visible' : 'hidden',
369
+ variants: panelVariants
370
+ }, /*#__PURE__*/React.createElement(motion.div, {
371
+ variants: innerContainerVariants
372
+ }, /*#__PURE__*/React.createElement("header", {
373
+ ref: filterHeadingRef,
374
+ className: cx("".concat(componentClass, "__heading"), _defineProperty({}, "".concat(componentClass, "__heading--with-divider"), showDividerLine))
375
+ }, /*#__PURE__*/React.createElement("div", {
376
+ className: "".concat(componentClass, "__title")
377
+ }, title), /*#__PURE__*/React.createElement(Button, {
378
+ hasIconOnly: true,
379
+ renderIcon: Close32,
380
+ iconDescription: closeIconDescription,
381
+ kind: "ghost",
382
+ tooltipPosition: "bottom",
383
+ tooltipAlignment: "end",
384
+ onClick: closePanel
385
+ }), showFilterSearch && /*#__PURE__*/React.createElement("div", {
386
+ ref: filterSearchRef,
387
+ className: "".concat(componentClass, "__search")
388
+ }, /*#__PURE__*/React.createElement(Search, {
389
+ labelText: "Filter search",
390
+ placeHolderText: "Find filters",
391
+ light: true,
392
+ size: "sm"
393
+ }))), /*#__PURE__*/React.createElement("div", {
394
+ className: "".concat(componentClass, "__inner-container"),
395
+ style: {
396
+ height: getScrollableContainerHeight()
397
+ },
398
+ onScroll: onInnerContainerScroll
399
+ }, filterSections.map(function (_ref6) {
400
+ var _ref6$categoryTitle = _ref6.categoryTitle,
401
+ categoryTitle = _ref6$categoryTitle === void 0 ? null : _ref6$categoryTitle,
402
+ _ref6$filters = _ref6.filters,
403
+ filters = _ref6$filters === void 0 ? [] : _ref6$filters,
404
+ hasAccordion = _ref6.hasAccordion;
405
+ return /*#__PURE__*/React.createElement("div", {
406
+ className: "".concat(componentClass, "__category")
407
+ }, categoryTitle && /*#__PURE__*/React.createElement("div", {
408
+ className: "".concat(componentClass, "__category-title")
409
+ }, categoryTitle), hasAccordion ? /*#__PURE__*/React.createElement(Accordion, null, filters.map(function (_ref7) {
410
+ var filterLabel = _ref7.filterLabel,
411
+ filter = _ref7.filter;
412
+ return /*#__PURE__*/React.createElement(AccordionItem, {
413
+ title: filterLabel,
414
+ key: filterLabel
415
+ }, renderFilter(filter));
416
+ })) : filters.map(function (_ref8) {
417
+ var filter = _ref8.filter;
418
+ return renderFilter(filter);
419
+ }));
420
+ })), renderActionSet()));
421
+ };
422
+ FilterPanel.propTypes = {
423
+ closeIconDescription: PropTypes.string,
424
+ filterPanelMinHeight: PropTypes.number,
425
+ filterSections: PropTypes.array,
426
+ onApply: PropTypes.func,
427
+ onCancel: PropTypes.func,
428
+ onPanelClose: PropTypes.func,
429
+ onPanelOpen: PropTypes.func,
430
+ open: PropTypes.bool,
431
+ setAllFilters: PropTypes.func.isRequired,
432
+ showFilterSearch: PropTypes.bool,
433
+ title: PropTypes.string,
434
+ updateMethod: PropTypes.oneOf([BATCH, INSTANT])
435
+ };
436
+ export default FilterPanel;
@@ -5,7 +5,7 @@ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
5
5
  * This source code is licensed under the Apache-2.0 license found in the
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
- import React, { createContext } from 'react';
8
+ import React, { createContext, useState } from 'react';
9
9
  import PropTypes from 'prop-types';
10
10
  import { DATE, DROPDOWN, NUMBER, RADIO, CHECKBOX } from './constants';
11
11
  export var FilterContext = /*#__PURE__*/createContext();
@@ -63,9 +63,15 @@ export var FilterProvider = function FilterProvider(_ref2) {
63
63
  var children = _ref2.children,
64
64
  filters = _ref2.filters;
65
65
  var filterTags = prepareFiltersForTags(filters);
66
+ var _useState = useState(false),
67
+ _useState2 = _slicedToArray(_useState, 2),
68
+ leftPanelOpen = _useState2[0],
69
+ setLeftPanelOpen = _useState2[1];
66
70
  var value = {
67
71
  filterTags: filterTags,
68
- EventEmitter: EventEmitter
72
+ EventEmitter: EventEmitter,
73
+ leftPanelOpen: leftPanelOpen,
74
+ setLeftPanelOpen: setLeftPanelOpen
69
75
  };
70
76
  return /*#__PURE__*/React.createElement(FilterContext.Provider, {
71
77
  value: value
@@ -8,6 +8,10 @@
8
8
  export var BATCH = 'batch';
9
9
  export var INSTANT = 'instant';
10
10
 
11
+ /** Constants for filter variation */
12
+ export var FLYOUT = 'flyout';
13
+ export var PANEL = 'panel';
14
+
11
15
  /** Constants for filter type */
12
16
  export var DATE = 'date';
13
17
  export var NUMBER = 'number';
@@ -16,4 +20,8 @@ export var RADIO = 'radio';
16
20
  export var DROPDOWN = 'dropdown';
17
21
 
18
22
  /** Constants for event emitters */
19
- export var CLEAR_FILTERS = 'clearFilters';
23
+ export var CLEAR_FILTERS = 'clearFilters';
24
+
25
+ /** Constants for panel dimensions */
26
+ export var PANEL_WIDTH = 320;
27
+ export var ACTION_SET_HEIGHT = 64;
@@ -0,0 +1,2 @@
1
+ export { default as useInitialStateFromFilters } from './useInitialStateFromFilters';
2
+ export { default as useSubscribeToEventEmitter } from './useSubscribeToEventEmitter';
@@ -7,9 +7,11 @@ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
7
7
  * restricted by GSA ADP Schedule Contract with IBM Corp.
8
8
  */
9
9
  import { useState } from 'react';
10
+ import { FLYOUT } from '../constants';
10
11
  import { getInitialStateFromFilters } from '../utils';
11
12
  var useInitialStateFromFilters = function useInitialStateFromFilters(filters) {
12
- var _useState = useState(getInitialStateFromFilters(filters)),
13
+ var variation = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : FLYOUT;
14
+ var _useState = useState(getInitialStateFromFilters(filters, variation)),
13
15
  _useState2 = _slicedToArray(_useState, 2),
14
16
  state = _useState2[0],
15
17
  setState = _useState2[1];
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Copyright IBM Corp. 2022, 2023
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import { useEffect, useContext } from 'react';
8
+ import { FilterContext } from '../FilterProvider';
9
+
10
+ /**
11
+ * Subscribes to the filter event emitter
12
+ * @param {string} type - the type of event to call
13
+ * @param {Function} callback - a callback to run when the event is dispatched
14
+ */
15
+ var useSubscribeToEventEmitter = function useSubscribeToEventEmitter(type, callback) {
16
+ var _useContext = useContext(FilterContext),
17
+ EventEmitter = _useContext.EventEmitter;
18
+ useEffect(function subscribeToEmitter() {
19
+ // This event is emitted from the DatagridToolbar component when clearFilters is clicked in FilterSummary
20
+ EventEmitter.subscribe(type, callback);
21
+ });
22
+ };
23
+ export default useSubscribeToEventEmitter;
@@ -4,4 +4,6 @@
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- export { default as FilterFlyout } from './FilterFlyout';
7
+ export { default as FilterFlyout } from './FilterFlyout';
8
+ export { default as FilterPanel } from './FilterPanel';
9
+ export { FilterProvider, FilterContext } from './FilterProvider';
@@ -0,0 +1,55 @@
1
+ import { DURATIONS, EASINGS } from '../../../../../../global/js/utils/motionConstants';
2
+ import { ACTION_SET_HEIGHT, PANEL_WIDTH } from '../constants';
3
+ export var panelVariants = {
4
+ hidden: {
5
+ width: 0,
6
+ overflow: 'hidden',
7
+ transition: {
8
+ duration: DURATIONS.fast02,
9
+ ease: EASINGS.productive.exit,
10
+ when: 'afterChildren'
11
+ }
12
+ },
13
+ visible: {
14
+ width: PANEL_WIDTH,
15
+ overflow: 'visible',
16
+ transition: {
17
+ duration: DURATIONS.moderate02,
18
+ ease: EASINGS.productive.entrance,
19
+ when: 'beforeChildren'
20
+ }
21
+ }
22
+ };
23
+ export var innerContainerVariants = {
24
+ hidden: {
25
+ opacity: 0,
26
+ transition: {
27
+ duration: DURATIONS.fast01,
28
+ ease: EASINGS.productive.exit
29
+ }
30
+ },
31
+ visible: {
32
+ opacity: 1,
33
+ transition: {
34
+ duration: DURATIONS.fast02,
35
+ ease: EASINGS.productive.entrance,
36
+ when: 'beforeChildren'
37
+ }
38
+ }
39
+ };
40
+ export var actionSetVariants = {
41
+ hidden: {
42
+ y: ACTION_SET_HEIGHT,
43
+ transition: {
44
+ duration: DURATIONS.fast01,
45
+ ease: EASINGS.productive.exit
46
+ }
47
+ },
48
+ visible: {
49
+ y: 0,
50
+ transition: {
51
+ duration: DURATIONS.fast02,
52
+ ease: EASINGS.productive.entrance
53
+ }
54
+ }
55
+ };
@@ -5,34 +5,66 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
+ import { FLYOUT, PANEL } from './constants';
9
+
8
10
  // This functions takes the filters passed in and makes an object to track it's state
9
11
  export var getInitialStateFromFilters = function getInitialStateFromFilters(filters) {
12
+ var variation = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : FLYOUT;
10
13
  var initialFilterState = {};
11
- filters.forEach(function (_ref) {
14
+ var setInitialState = function setInitialState(_ref) {
12
15
  var type = _ref.type,
13
16
  column = _ref.column,
14
17
  props = _ref.props;
15
18
  if (type === 'checkbox') {
16
- initialFilterState[column] = props.Checkbox.map(function (_ref2) {
17
- var id = _ref2.id,
18
- labelText = _ref2.labelText,
19
- value = _ref2.value;
20
- return {
21
- id: id,
22
- labelText: labelText,
23
- value: value,
24
- selected: false
25
- };
26
- });
19
+ initialFilterState[column] = {
20
+ value: props.Checkbox.map(function (_ref2) {
21
+ var id = _ref2.id,
22
+ labelText = _ref2.labelText,
23
+ value = _ref2.value;
24
+ return {
25
+ id: id,
26
+ labelText: labelText,
27
+ value: value,
28
+ selected: false
29
+ };
30
+ }),
31
+ type: type
32
+ };
27
33
  } else if (type === 'date') {
28
- initialFilterState[column] = [undefined, undefined];
34
+ initialFilterState[column] = {
35
+ value: [null, null],
36
+ type: type
37
+ };
29
38
  } else if (type === 'number') {
30
- initialFilterState[column] = '';
39
+ initialFilterState[column] = {
40
+ value: '',
41
+ type: type
42
+ };
31
43
  } else if (type === 'radio') {
32
- initialFilterState[column] = '';
44
+ initialFilterState[column] = {
45
+ value: '',
46
+ type: type
47
+ };
33
48
  } else if (type === 'dropdown') {
34
- initialFilterState[column] = '';
49
+ initialFilterState[column] = {
50
+ value: '',
51
+ type: type
52
+ };
35
53
  }
36
- });
54
+ };
55
+ if (variation === FLYOUT) {
56
+ filters.forEach(setInitialState);
57
+ } else if (variation === PANEL) {
58
+ filters.forEach(function (_ref3) {
59
+ var _ref3$filters = _ref3.filters,
60
+ sections = _ref3$filters === void 0 ? [] : _ref3$filters;
61
+ sections.forEach(function (_ref4) {
62
+ var filter = _ref4.filter;
63
+ return setInitialState(filter);
64
+ });
65
+ });
66
+ } else {
67
+ console.error('No variation passed into useInitialStateFromFilters');
68
+ }
37
69
  return initialFilterState;
38
70
  };
@@ -1,5 +1,4 @@
1
1
  export { story as CustomizeColumnStory } from './CustomizeColumnStory';
2
2
  export { default as StickyActionsColumn } from './StickyActionsColumnStory';
3
3
  export { story as RowSizeDropdownStory } from './RowSizeDropdownStory';
4
- export { story as LeftPanelStory } from './LeftPanelStory';
5
4
  export { story as SelectAllWithToggle } from './SelectAllWithToggleStory';