@redsift/table 11.3.0 → 11.3.1-alpha.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.
package/CONTRIBUTING.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Contribute
2
2
 
3
- ## Develop
3
+ ## Setup
4
4
 
5
5
  Make sure you have the following requirements installed: [node](https://nodejs.org/) (v16+) and [yarn](https://yarnpkg.com/en/) (v1.22.0+)
6
6
 
@@ -26,7 +26,7 @@ You can then run the storybook and browse to [http://localhost:9000](http://loca
26
26
  yarn start:storybook
27
27
  ```
28
28
 
29
- ### Architecture
29
+ ## Architecture
30
30
 
31
31
  The Design System is following a monorepo architecture, providing multiple packages based on different use cases.
32
32
 
@@ -68,8 +68,6 @@ The Design System is following a monorepo architecture, providing multiple packa
68
68
 
69
69
  Please make sure to work inside the correct package when making contribution.
70
70
 
71
- ### Shared code
72
-
73
71
  If you need something inside more than one package, do not duplicate the code. Place it inside one package, export it from this package and import it inside the others.
74
72
 
75
73
  For instance, `@redsift/dashboard` and `@redsift/charts` both have a `PieChart` component that both share the `PieChartVariant` type interface. `PieChartVariant` has been implemented inside `@redsift/charts` and is imported inside `@redsift/dashboard`.
@@ -102,9 +100,11 @@ When dependencies are required, we try not to import them entirely to optimise t
102
100
  import * as d3 from 'd3';
103
101
 
104
102
  // do
105
- import { sum, scaleOrdinal } from 'd3';
103
+ import { sum as d3sum, scaleOrdinal as d3scaleOrdinal, ScaleOrdinal as d3ScaleOrdinal } from 'd3';
106
104
  ```
107
105
 
106
+ ## Component
107
+
108
108
  ### Scaffolding
109
109
 
110
110
  Each component should be in its own folder. If a subcomponent can be used as a standalone component, it should be in its own folder too. For instance, `CheckboxGroup` uses `Checkbox` but `Checkbox` can be used alone. In this case, `CheckboxGroup` and `Checkbox` both have their own folder. For `PieChart` and `PieChartSlice`, a `PieChartSlice` can not be used alone. It only exists inside a `PieChart` component. Therefore, both components are inside the same folder.
@@ -191,40 +191,6 @@ size?: PieChartSize;
191
191
 
192
192
  To know how to define your API, to name and document your props, take a look at the existing components.
193
193
 
194
- ## Tests
195
-
196
- We use [jest](https://jestjs.io/) for unit tests and [react-testing-library](https://testing-library.com/docs/react-testing-library/intro) for rendering and writing assertions. We also use [Storyshots](https://storybook.js.org/addons/@storybook/addon-storyshots) to automatically take a code snapshot of every story.
197
-
198
- Please make sure you include tests with your pull requests. Our CI will run the tests on each PR. A minimum of 90% code coverage is required for statements, branches, functions and lines of every package. However, in practice, we try to reach a 100% code coverage.
199
-
200
- We split the tests into 2 groups.
201
-
202
- _Visual tests_
203
-
204
- - A Storybook story should be written for each visual state that a component can be in (based on props).
205
-
206
- _Unit tests_
207
-
208
- - (Props) Anything that should be changed by a prop should be tested via react-testing-library.
209
- - (Events) Anything that should trigger an event should be tested via react-testing-library.
210
-
211
- You can run the tests with:
212
-
213
- ```bash
214
- yarn test
215
- ```
216
-
217
- Or for a specific package with:
218
-
219
- ```bash
220
- yarn test:charts
221
- yarn test:design-system
222
- yarn test:dashboard
223
- yarn test:table
224
- ```
225
-
226
- Do not forget to update the snapshots with the `-u` option when you modify or create stories. However, you should **always** check the generated snapshots to see if they are correct. Do **not** blindly update the snapshots.
227
-
228
194
  ## Linting
229
195
 
230
196
  The code is linted with [eslint](https://eslint.org/). You can run the linter with:
@@ -242,7 +208,7 @@ yarn lint:design-system
242
208
  yarn lint:table
243
209
  ```
244
210
 
245
- ## TypeScript
211
+ ## Typing
246
212
 
247
213
  The code is written in [TypeScript](https://www.typescriptlang.org/). The type checker will usually run in your editor, but also runs when you run:
248
214
 
@@ -329,6 +295,40 @@ Before implementing a component, try to see if there is a [pattern](https://www.
329
295
 
330
296
  However, before using any ARIA, [read this disclaimer carefully](https://www.w3.org/WAI/ARIA/apg/practices/read-me-first/).
331
297
 
298
+ ## Tests
299
+
300
+ We use [jest](https://jestjs.io/) for unit tests and [react-testing-library](https://testing-library.com/docs/react-testing-library/intro) for rendering and writing assertions. We also use [Storyshots](https://storybook.js.org/addons/@storybook/addon-storyshots) to automatically take a code snapshot of every story.
301
+
302
+ Please make sure you include tests with your pull requests. Our CI will run the tests on each PR. A minimum of 90% code coverage is required for statements, branches, functions and lines of every package. However, in practice, we try to reach a 100% code coverage.
303
+
304
+ We split the tests into 2 groups.
305
+
306
+ _Visual tests_
307
+
308
+ - A Storybook story should be written for each visual state that a component can be in (based on props).
309
+
310
+ _Unit tests_
311
+
312
+ - (Props) Anything that should be changed by a prop should be tested via react-testing-library.
313
+ - (Events) Anything that should trigger an event should be tested via react-testing-library.
314
+
315
+ You can run the tests with:
316
+
317
+ ```bash
318
+ yarn test
319
+ ```
320
+
321
+ Or for a specific package with:
322
+
323
+ ```bash
324
+ yarn test:charts
325
+ yarn test:design-system
326
+ yarn test:dashboard
327
+ yarn test:table
328
+ ```
329
+
330
+ Do not forget to update the snapshots with the `-u` option when you modify or create stories. However, you should **always** check the generated snapshots to see if they are correct. Do **not** blindly update the snapshots.
331
+
332
332
  ## Storybook
333
333
 
334
334
  We use [Storybook](https://storybooks.js.org) for local development. Run the following command to start it:
@@ -413,3 +413,27 @@ yarn build:icons
413
413
  yarn build:legacy
414
414
  yarn build:table
415
415
  ```
416
+
417
+ ## Publishing a release
418
+
419
+ ### Stable release
420
+
421
+ 1. Make sure you're on the release branch (ex: `release/vX.Y.Z`) and a PR is opened on Github
422
+ 2. Login to NPM with an authorized account: `npm login`
423
+ 3. Make sure your packages are up to date: `yarn`
424
+ 4. Make sure the CI entirely passed on Github
425
+ 5. (Optional) Make sure the build doesn't crash locally: `yarn build:design-system`
426
+ 6. Publish the packages to NPM: `yarn release vX.Y.Z`
427
+
428
+ ### Alpha release
429
+
430
+ If you need to test your contribution in a product before releasing -and you're not using `yarn link`, you can create an alpha release using the following process:
431
+
432
+ 1. Create an alpha release branch (ex: `release/vX.Y.Z-alpha.N`) based on `release/vX.Y.Z`
433
+ 2. Push it to remote (`git push origin release/vX.Y.Z-alpha.N`)
434
+ 3. Login to NPM with an authorized account: `npm login`
435
+ 4. Make sure your packages are up to date: `yarn`
436
+ 5. (Optional) Make sure the build doesn't crash: `yarn build:design-system`
437
+ 6. Publish the packages to NPM: `yarn release --dist-tag alpha vX.Y.Z-alpha.N`
438
+
439
+ After that if you need to make modification to your contribution, go back to `release/vX.Y.Z` and make the necessary modifications. Then remove the alpha release branch, and redo the process from step 1, incrementing `N` by 1.
package/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _mui_x_data_grid_pro from '@mui/x-data-grid-pro';
2
- import { GridColumnTypesRecord, GridFilterItem, GridCellParams, GridFilterOperator, GridFilterInputValue, GridFilterInputMultipleValue, DataGridProProps, GridPaginationModel, GridFilterModel, GridSortModel, GridSortItem, GridColumnVisibilityModel, GridPinnedColumns, GridSlotsComponent, GridRowSelectionModel, GridApiPro as GridApiPro$1, GridRowParams, GridToolbarExportProps, GridToolbarFilterButtonProps, GridToolbarColumnsButton, GridToolbarDensitySelector } from '@mui/x-data-grid-pro';
2
+ import { GridColumnTypesRecord, GridFilterItem, GridCellParams, GridFilterOperator, GridFilterInputValue, GridFilterInputMultipleValue, DataGridProProps, GridFilterModel, GridPaginationModel, GridSortModel, GridSortItem, GridColumnVisibilityModel, GridPinnedColumns, GridSlotsComponent, GridRowSelectionModel, GridApiPro as GridApiPro$1, GridRowParams, GridToolbarExportProps, GridToolbarFilterButtonProps, GridToolbarColumnsButton, GridToolbarDensitySelector } from '@mui/x-data-grid-pro';
3
3
  export { GridAlignment, GridColDef, GridFilterItem, GridFilterModel, getGridBooleanOperators, getGridDateOperators, getGridSingleSelectOperators } from '@mui/x-data-grid-pro';
4
4
  import { GridInitialStatePro } from '@mui/x-data-grid-pro/models/gridStatePro';
5
5
  import React, { ReactNode, ComponentProps, MutableRefObject, RefObject } from 'react';
@@ -163,6 +163,9 @@ interface StatefulDataGridProps extends DataGridProps {
163
163
 
164
164
  declare const StatefulDataGrid: Comp<StatefulDataGridProps, HTMLDivElement>;
165
165
 
166
+ interface ExtendedGridFilterModel extends GridFilterModel {
167
+ quickFilterValues?: string[];
168
+ }
166
169
  interface ExtendedGridPaginationModel extends GridPaginationModel {
167
170
  direction?: 'next' | 'back';
168
171
  }
@@ -176,8 +179,8 @@ declare const numberOperatorDecoder: Record<string, string>;
176
179
  declare const isOperatorValueValid: (field: string, operator: OperatorValue, columns: DataGridProps['columns']) => boolean;
177
180
  declare const isValueValid: (value: OperatorValue, field: string, columns: DataGridProps['columns'], operator: OperatorValue) => boolean;
178
181
  /** FILTERS */
179
- declare const getFilterModelFromString: (searchString: string, columns: DataGridProps['columns']) => GridFilterModel | 'invalid';
180
- declare const getSearchParamsFromFilterModel: (filterModel: GridFilterModel) => URLSearchParams;
182
+ declare const getFilterModelFromString: (searchString: string, columns: DataGridProps['columns']) => ExtendedGridFilterModel | 'invalid';
183
+ declare const getSearchParamsFromFilterModel: (filterModel: ExtendedGridFilterModel) => URLSearchParams;
181
184
  /** SORT */
182
185
  declare const getSortingFromString: (searchString: string, columns: DataGridProps['columns']) => GridSortModel | 'invalid';
183
186
  declare const getSearchParamsFromSorting: (sorting: GridSortItem[]) => URLSearchParams;
@@ -379,6 +382,8 @@ interface ToolbarProps {
379
382
  /** Configuration object for NLP filter. undefined if disabled. */
380
383
  onFilterModelChange?: (filterModel: GridFilterModel) => void;
381
384
  semanticFilterProps?: GridToolbarFilterSemanticProps;
385
+ /** Whether you want to show the quick filter or not. */
386
+ showQuickFilter?: boolean;
382
387
  }
383
388
 
384
389
  /**
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { GRID_DETAIL_PANEL_TOGGLE_COL_DEF, getGridNumericOperators as getGridNumericOperators$1, GridFilterInputValue, GridFilterInputMultipleValue, getGridStringOperators as getGridStringOperators$1, getGridBooleanOperators, getGridDateOperators, getGridSingleSelectOperators, GridLogicOperator, GridToolbarContainer, GridToolbarFilterButton, GridToolbarColumnsButton, GridToolbarDensitySelector, GridToolbarExport, gridExpandedSortedRowIdsSelector, gridPaginatedVisibleSortedGridRowEntriesSelector, gridPaginatedVisibleSortedGridRowIdsSelector, gridFilteredSortedRowEntriesSelector, gridFilteredSortedRowIdsSelector, useGridApiRef, DataGridPro } from '@mui/x-data-grid-pro';
1
+ import { GRID_DETAIL_PANEL_TOGGLE_COL_DEF, getGridNumericOperators as getGridNumericOperators$1, GridFilterInputValue, GridFilterInputMultipleValue, getGridStringOperators as getGridStringOperators$1, getGridBooleanOperators, getGridDateOperators, getGridSingleSelectOperators, GridLogicOperator, GridToolbarContainer, GridToolbarFilterButton, GridToolbarColumnsButton, GridToolbarDensitySelector, GridToolbarExport, gridExpandedSortedRowIdsSelector, GridToolbarQuickFilter, gridPaginatedVisibleSortedGridRowEntriesSelector, gridPaginatedVisibleSortedGridRowIdsSelector, gridFilteredSortedRowEntriesSelector, gridFilteredSortedRowIdsSelector, useGridApiRef, DataGridPro } from '@mui/x-data-grid-pro';
2
2
  export { getGridBooleanOperators, getGridDateOperators, getGridSingleSelectOperators } from '@mui/x-data-grid-pro';
3
3
  import * as React from 'react';
4
4
  import React__default, { Children, isValidElement, cloneElement, forwardRef, useLayoutEffect, useEffect, useRef, useContext, useState, useCallback, createElement, useMemo } from 'react';
@@ -18132,14 +18132,22 @@ const getFilterModelFromString = (searchString, columns) => {
18132
18132
  return 'invalid';
18133
18133
  }
18134
18134
  let logicOperator = GridLogicOperator.And;
18135
+ let quickFilterValues = [];
18135
18136
  const searchParams = new URLSearchParams();
18136
18137
  for (const [key, value] of new URLSearchParams(searchString)) {
18137
- if (key.startsWith('_') && !['_logicOperator', '_sortColumn', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_columnVisibility', '_pagination'].includes(key)) {
18138
+ if (key.startsWith('_') && !['_logicOperator', '_sortColumn', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_columnVisibility', '_pagination', '_quickFilterValues'].includes(key)) {
18138
18139
  searchParams.set(key, value);
18139
18140
  }
18140
18141
  if (key === '_logicOperator') {
18141
18142
  logicOperator = value === GridLogicOperator.And || value === GridLogicOperator.Or ? value : GridLogicOperator.And;
18142
18143
  }
18144
+ if (key === '_quickFilterValues') {
18145
+ try {
18146
+ quickFilterValues = JSON.parse(decodeURIComponent(value));
18147
+ } catch {
18148
+ quickFilterValues = [];
18149
+ }
18150
+ }
18143
18151
  }
18144
18152
  let id = 5000;
18145
18153
  const fields = columns.map(column => column.field);
@@ -18150,7 +18158,7 @@ const getFilterModelFromString = (searchString, columns) => {
18150
18158
  if (isInvalid) {
18151
18159
  return;
18152
18160
  }
18153
- const field = key.split('[')[0].slice(1); // Slice to remove the _ at the beginning
18161
+ const field = key.split('[')[0].slice(1);
18154
18162
  if (!fields.includes(field)) {
18155
18163
  return;
18156
18164
  }
@@ -18167,7 +18175,6 @@ const getFilterModelFromString = (searchString, columns) => {
18167
18175
  return;
18168
18176
  }
18169
18177
  const operator = splitRight[0];
18170
- // if the operator is not part of the valid operators invalidate the URL
18171
18178
  if (!isOperatorValueValid(field, operator, columns) || Array.isArray(operator)) {
18172
18179
  isInvalid = true;
18173
18180
  return;
@@ -18186,19 +18193,17 @@ const getFilterModelFromString = (searchString, columns) => {
18186
18193
  type
18187
18194
  });
18188
18195
  });
18189
-
18190
- // If we found some condition that results in an invalid URL,
18191
- // return the empty filterModel (this will trigger the localStorage)
18192
- // and will pick up the last valid search
18193
18196
  if (isInvalid) {
18194
18197
  return 'invalid';
18195
18198
  }
18196
18199
  return {
18197
18200
  items,
18198
- logicOperator
18201
+ logicOperator,
18202
+ quickFilterValues
18199
18203
  };
18200
18204
  };
18201
18205
  const getSearchParamsFromFilterModel = filterModel => {
18206
+ var _filterModel$quickFil;
18202
18207
  const searchParams = new URLSearchParams();
18203
18208
  searchParams.set('_logicOperator', filterModel['logicOperator'] || '');
18204
18209
  filterModel['items'].forEach(item => {
@@ -18214,6 +18219,9 @@ const getSearchParamsFromFilterModel = filterModel => {
18214
18219
  searchParams.set(`_${field}[${encodeValue(operator)},${encodeValue(type)}]`, encodeValue(value));
18215
18220
  }
18216
18221
  });
18222
+ if ((_filterModel$quickFil = filterModel.quickFilterValues) !== null && _filterModel$quickFil !== void 0 && _filterModel$quickFil.length) {
18223
+ searchParams.set('_quickFilterValues', encodeURIComponent(JSON.stringify(filterModel.quickFilterValues)));
18224
+ }
18217
18225
  return searchParams;
18218
18226
  };
18219
18227
 
@@ -18549,6 +18557,12 @@ const getFinalSearch = _ref => {
18549
18557
  }
18550
18558
  }
18551
18559
  searchParams.set('v', `${localStorageVersion}`);
18560
+
18561
+ // Add quickFilterValues explicitly if present in filterModel
18562
+ if (filterModel.quickFilterValues && filterModel.quickFilterValues.length > 0) {
18563
+ // Encode array as JSON string to preserve all values in one param
18564
+ searchParams.set('_quickFilterValues', encodeURIComponent(JSON.stringify(filterModel.quickFilterValues)));
18565
+ }
18552
18566
  return new URLSearchParams([...searchParams, ...filterModelSearch, ...sortModelSearch, ...paginationModelSearch, ...tabSearch, ...pinnedColumnsModelSearch, ...columnVisibilityModelSearch]);
18553
18567
  };
18554
18568
  /** Return the state of the table given the URL and the local storage state */
@@ -24642,7 +24656,8 @@ const Toolbar$2 = props => {
24642
24656
  densityButtonProps,
24643
24657
  densityButtonRef,
24644
24658
  onFilterModelChange,
24645
- semanticFilterProps = undefined
24659
+ semanticFilterProps = undefined,
24660
+ showQuickFilter
24646
24661
  } = props;
24647
24662
  if (semanticFilterProps && onFilterModelChange) {
24648
24663
  semanticFilterProps.onFilterModelChange = onFilterModelChange;
@@ -24675,7 +24690,9 @@ const Toolbar$2 = props => {
24675
24690
  }, exportButtonProps, {
24676
24691
  ref: exportButtonRef,
24677
24692
  className: filterButtonProps !== null && filterButtonProps !== void 0 && filterButtonProps.className ? `${filterButtonProps === null || filterButtonProps === void 0 ? void 0 : filterButtonProps.className} redsift-condensed` : 'redsift-condensed'
24678
- })) : null), /*#__PURE__*/React__default.createElement(Flexbox, {
24693
+ })) : null, /*#__PURE__*/React__default.createElement(Flexbox, {
24694
+ marginLeft: "8px"
24695
+ }, showQuickFilter ? /*#__PURE__*/React__default.createElement(GridToolbarQuickFilter, null) : null)), /*#__PURE__*/React__default.createElement(Flexbox, {
24679
24696
  flexGrow: 3
24680
24697
  }, semanticFilterProps ? /*#__PURE__*/React__default.createElement(GridToolbarFilterSemanticField, semanticFilterProps) : null)));
24681
24698
  };
@@ -27598,7 +27615,8 @@ const useStatefulTable = props => {
27598
27615
  const column = apiRef.current.getColumn(item.field);
27599
27616
  item.type = column.type || 'string';
27600
27617
  return item;
27601
- })
27618
+ }),
27619
+ quickFilterValues: model.quickFilterValues || []
27602
27620
  });
27603
27621
  propsOnFilterModelChange === null || propsOnFilterModelChange === void 0 ? void 0 : propsOnFilterModelChange(filterModel, details);
27604
27622
  updateUrl({