@carbon/ibm-products 1.42.1 → 1.43.0

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.
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';