slickgrid-react 4.4.1 → 4.6.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slickgrid-react",
3
- "version": "4.4.1",
3
+ "version": "4.6.0",
4
4
  "description": "Slickgrid components made available in React",
5
5
  "keywords": [
6
6
  "react",
@@ -11,20 +11,12 @@
11
11
  ],
12
12
  "main": "./dist/cjs/index.js",
13
13
  "module": "./dist/esm/index.js",
14
- "types": "index.d.ts",
15
- "typesVersions": {
16
- ">=4.2": {
17
- "*": [
18
- "dist/types/*"
19
- ]
20
- }
21
- },
14
+ "types": "./dist/cjs/index.js",
22
15
  "exports": {
23
16
  ".": {
24
17
  "types": "./dist/types/index.d.ts",
25
- "node": "./dist/cjs/index.js",
26
- "require": "./dist/cjs/index.js",
27
- "default": "./dist/esm/index.js"
18
+ "import": "./dist/esm/index.js",
19
+ "require": "./dist/cjs/index.js"
28
20
  },
29
21
  "./package.json": "./package.json"
30
22
  },
@@ -57,6 +49,7 @@
57
49
  ],
58
50
  "scripts": {
59
51
  "build:demo": "webpack --env production",
52
+ "dev": "webpack serve --env development",
60
53
  "delete:dist": "rimraf dist",
61
54
  "lint": "eslint src/slickgrid-react --ext .ts",
62
55
  "build:cjs": "tsc --project src/slickgrid-react/tsconfig.build.json --outDir dist/cjs --module commonjs --declaration false",
@@ -69,7 +62,6 @@
69
62
  "postbuild": "npm-run-all copy-i18n:dist copy-asset-lib",
70
63
  "copy-asset-lib": "copyfiles --up 2 src/assets/lib/** dist",
71
64
  "copy-i18n:dist": "copyfiles --up 3 src/assets/i18n/**/*.* dist/i18n",
72
- "start:dev": "webpack serve --env development",
73
65
  "cypress:open": "cypress open --config-file test/cypress.config.ts",
74
66
  "cypress:ci": "cypress run --config-file test/cypress.config.ts",
75
67
  "test:ci": "npx jest --runInBand --coverage=true --ci --config ./test/jest.config.js",
@@ -96,15 +88,14 @@
96
88
  "/src/slickgrid-react"
97
89
  ],
98
90
  "dependencies": {
99
- "@slickgrid-universal/common": "~4.4.1",
100
- "@slickgrid-universal/custom-footer-component": "~4.4.1",
101
- "@slickgrid-universal/empty-warning-component": "~4.4.1",
102
- "@slickgrid-universal/event-pub-sub": "~4.4.1",
103
- "@slickgrid-universal/pagination-component": "~4.4.1",
91
+ "@slickgrid-universal/common": "~4.6.0",
92
+ "@slickgrid-universal/custom-footer-component": "~4.6.0",
93
+ "@slickgrid-universal/empty-warning-component": "~4.6.0",
94
+ "@slickgrid-universal/event-pub-sub": "~4.6.0",
95
+ "@slickgrid-universal/pagination-component": "~4.6.0",
104
96
  "dequal": "^2.0.3",
105
- "dompurify": "^3.0.8",
106
97
  "font-awesome": "^4.7.0",
107
- "i18next": "^23.8.2",
98
+ "i18next": "^23.10.1",
108
99
  "moment-mini": "^2.29.4",
109
100
  "regenerator-runtime": "^0.14.1",
110
101
  "sortablejs": "^1.15.2"
@@ -115,15 +106,15 @@
115
106
  "@fnando/sparkline": "^0.3.10",
116
107
  "@popperjs/core": "^2.11.8",
117
108
  "@release-it/conventional-changelog": "^8.0.1",
118
- "@slickgrid-universal/composite-editor-component": "~4.4.1",
119
- "@slickgrid-universal/custom-tooltip-plugin": "~4.4.1",
120
- "@slickgrid-universal/excel-export": "~4.4.1",
121
- "@slickgrid-universal/graphql": "~4.4.1",
122
- "@slickgrid-universal/odata": "~4.4.1",
123
- "@slickgrid-universal/rxjs-observable": "~4.4.1",
124
- "@slickgrid-universal/text-export": "~4.4.1",
109
+ "@slickgrid-universal/composite-editor-component": "~4.6.0",
110
+ "@slickgrid-universal/custom-tooltip-plugin": "~4.6.0",
111
+ "@slickgrid-universal/excel-export": "~4.6.0",
112
+ "@slickgrid-universal/graphql": "~4.6.0",
113
+ "@slickgrid-universal/odata": "~4.6.0",
114
+ "@slickgrid-universal/rxjs-observable": "~4.6.0",
115
+ "@slickgrid-universal/text-export": "~4.6.0",
125
116
  "@testing-library/jest-dom": "^6.4.2",
126
- "@testing-library/react": "^14.2.1",
117
+ "@testing-library/react": "^14.2.2",
127
118
  "@testing-library/user-event": "^14.5.2",
128
119
  "@types/bluebird": "^3.5.42",
129
120
  "@types/dompurify": "^3.0.5",
@@ -131,65 +122,65 @@
131
122
  "@types/fnando__sparkline": "^0.3.7",
132
123
  "@types/i18next-xhr-backend": "^1.4.2",
133
124
  "@types/jest": "^29.5.12",
134
- "@types/node": "^20.11.17",
135
- "@types/react": "^18.2.55",
136
- "@types/react-dom": "^18.2.19",
137
- "@types/sortablejs": "^1.15.7",
125
+ "@types/node": "^20.11.30",
126
+ "@types/react": "^18.2.69",
127
+ "@types/react-dom": "^18.2.22",
128
+ "@types/sortablejs": "^1.15.8",
138
129
  "@types/text-encoding-utf-8": "^1.0.5",
139
130
  "@types/webpack": "^5.28.5",
140
- "@typescript-eslint/eslint-plugin": "^7.0.1",
141
- "@typescript-eslint/parser": "^7.0.1",
131
+ "@typescript-eslint/eslint-plugin": "^7.3.1",
132
+ "@typescript-eslint/parser": "^7.3.1",
142
133
  "@webpack-cli/serve": "^2.0.5",
143
- "bootstrap": "^5.3.2",
134
+ "bootstrap": "^5.3.3",
144
135
  "clean-webpack-plugin": "^4.0.0",
145
136
  "concurrently": "^8.2.2",
146
137
  "copy-webpack-plugin": "^12.0.2",
147
138
  "copyfiles": "^2.4.1",
148
139
  "css-loader": "^6.10.0",
149
140
  "custom-event-polyfill": "^1.0.7",
150
- "cypress": "^13.6.4",
151
- "esbuild-loader": "^4.0.3",
152
- "eslint": "^8.56.0",
141
+ "cypress": "^13.7.1",
142
+ "esbuild-loader": "^4.1.0",
143
+ "eslint": "^8.57.0",
153
144
  "eslint-plugin-import": "^2.29.1",
154
145
  "eslint-plugin-prefer-arrow": "^1.2.3",
155
146
  "fetch-jsonp": "^1.3.0",
156
147
  "font-awesome": "^4.7.0",
157
148
  "html-loader": "5.0.0",
158
149
  "html-webpack-plugin": "5.6.0",
159
- "i18next-http-backend": "^2.4.3",
150
+ "i18next-http-backend": "^2.5.0",
160
151
  "isomorphic-fetch": "^3.0.0",
161
152
  "jest": "^29.7.0",
162
153
  "jest-cli": "^29.7.0",
163
154
  "jest-environment-jsdom": "^29.7.0",
164
155
  "jest-extended": "^4.0.2",
165
156
  "jsdom-global": "^3.0.2",
166
- "mini-css-extract-plugin": "^2.8.0",
157
+ "mini-css-extract-plugin": "^2.8.1",
167
158
  "moment-mini": "^2.29.4",
168
159
  "npm-run-all2": "^6.1.2",
169
160
  "promise-polyfill": "^8.3.0",
170
161
  "react": "^18.2.0",
171
162
  "react-dom": "^18.2.0",
172
- "react-i18next": "^14.0.5",
173
- "react-router-dom": "^6.22.0",
174
- "release-it": "^17.0.3",
163
+ "react-i18next": "^14.1.0",
164
+ "react-router-dom": "^6.22.3",
165
+ "release-it": "^17.1.1",
175
166
  "rimraf": "^5.0.5",
176
167
  "rxjs": "^7.8.1",
177
- "sass": "^1.70.0",
178
- "sass-loader": "^14.1.0",
168
+ "sass": "^1.72.0",
169
+ "sass-loader": "^14.1.1",
179
170
  "serve": "^14.2.1",
180
171
  "style-loader": "3.3.4",
181
172
  "ts-jest": "^29.1.2",
182
173
  "ts-loader": "^9.5.1",
183
- "typescript": "^5.3.3",
184
- "webpack": "^5.90.1",
174
+ "typescript": "^5.4.3",
175
+ "webpack": "^5.91.0",
185
176
  "webpack-cli": "^5.1.4",
186
- "webpack-dev-server": "^5.0.0"
177
+ "webpack-dev-server": "^5.0.4"
187
178
  },
188
179
  "engines": {
189
180
  "node": ">=16.15.0",
190
181
  "npm": ">=8.5.0"
191
182
  },
192
183
  "resolutions": {
193
- "caniuse-lite": "1.0.30001584"
184
+ "caniuse-lite": "1.0.30001599"
194
185
  }
195
186
  }
@@ -8,7 +8,6 @@ import {
8
8
  BackendServiceApi,
9
9
  BackendServiceOption,
10
10
  Column,
11
- ColumnEditor,
12
11
  DataViewOption,
13
12
  EventSubscription,
14
13
  ExtensionList,
@@ -394,6 +393,11 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
394
393
  this.displayEmptyDataWarning(finalTotalCount < 1);
395
394
  }
396
395
  }
396
+
397
+ // add dark mode CSS class when enabled
398
+ if (this.gridOptions.darkMode) {
399
+ this.setDarkMode(true);
400
+ }
397
401
  }
398
402
 
399
403
  initialization(eventHandler: SlickEventHandler) {
@@ -849,6 +853,13 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
849
853
  this.sharedService.visibleColumns = args.impactedColumns;
850
854
  });
851
855
 
856
+ this._eventHandler.subscribe(grid.onSetOptions, (_e, args) => {
857
+ // add/remove dark mode CSS class when enabled
858
+ if (args.optionsBefore.darkMode !== args.optionsAfter.darkMode && this.sharedService.gridContainerElement) {
859
+ this.setDarkMode(args.optionsAfter.darkMode);
860
+ }
861
+ });
862
+
852
863
  // load any presets if any (after dataset is initialized)
853
864
  this.loadColumnPresetsWhenDatasetInitialized();
854
865
  this.loadFilterPresetsWhenDatasetInitialized();
@@ -1113,6 +1124,14 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
1113
1124
  return paginationOptions;
1114
1125
  }
1115
1126
 
1127
+ setDarkMode(dark = false) {
1128
+ if (dark) {
1129
+ this.sharedService.gridContainerElement?.classList.add('slick-dark-mode');
1130
+ } else {
1131
+ this.sharedService.gridContainerElement?.classList.remove('slick-dark-mode');
1132
+ }
1133
+ }
1134
+
1116
1135
  /**
1117
1136
  * Dynamically change or update the column definitions list.
1118
1137
  * We will re-render the grid so that the new header and data shows up correctly.
@@ -1226,34 +1245,36 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
1226
1245
 
1227
1246
  /** Load the Editor Collection asynchronously and replace the "collection" property when Promise resolves */
1228
1247
  protected loadEditorCollectionAsync(column: Column) {
1229
- const collectionAsync = (column?.editor as ColumnEditor).collectionAsync;
1230
- (column?.editor as ColumnEditor).disabled = true; // disable the Editor DOM element, we'll re-enable it after receiving the collection with "updateEditorCollection()"
1231
-
1232
- if (collectionAsync instanceof Promise) {
1233
- // wait for the "collectionAsync", once resolved we will save it into the "collection"
1234
- // the collectionAsync can be of 3 types HttpClient, HttpFetch or a Promise
1235
- collectionAsync.then((response: any | any[]) => {
1236
- if (Array.isArray(response)) {
1237
- this.updateEditorCollection(column, response); // from Promise
1238
- } else if (response instanceof Response && typeof response.json === 'function') {
1239
- if (response.bodyUsed) {
1240
- console.warn(`[SlickGrid-React] The response body passed to collectionAsync was already read.`
1241
- + `Either pass the dataset from the Response or clone the response first using response.clone()`);
1242
- } else {
1243
- // from Fetch
1244
- (response as Response).json().then(data => this.updateEditorCollection(column, data));
1248
+ if (column?.editor) {
1249
+ const collectionAsync = column.editor.collectionAsync;
1250
+ column.editor.disabled = true; // disable the Editor DOM element, we'll re-enable it after receiving the collection with "updateEditorCollection()"
1251
+
1252
+ if (collectionAsync instanceof Promise) {
1253
+ // wait for the "collectionAsync", once resolved we will save it into the "collection"
1254
+ // the collectionAsync can be of 3 types HttpClient, HttpFetch or a Promise
1255
+ collectionAsync.then((response: any | any[]) => {
1256
+ if (Array.isArray(response)) {
1257
+ this.updateEditorCollection(column, response); // from Promise
1258
+ } else if (response instanceof Response && typeof response.json === 'function') {
1259
+ if (response.bodyUsed) {
1260
+ console.warn(`[SlickGrid-React] The response body passed to collectionAsync was already read.`
1261
+ + `Either pass the dataset from the Response or clone the response first using response.clone()`);
1262
+ } else {
1263
+ // from Fetch
1264
+ (response as Response).json().then(data => this.updateEditorCollection(column, data));
1265
+ }
1266
+ } else if (response?.content) {
1267
+ this.updateEditorCollection(column, response.content); // from http-client
1245
1268
  }
1246
- } else if (response?.content) {
1247
- this.updateEditorCollection(column, response.content); // from http-client
1248
- }
1249
- });
1250
- } else if (this.rxjs?.isObservable(collectionAsync)) {
1251
- // wrap this inside a setTimeout to avoid timing issue since updateEditorCollection requires to call SlickGrid getColumns() method
1252
- setTimeout(() => {
1253
- this.subscriptions.push(
1254
- (collectionAsync as Observable<any>).subscribe((resolvedCollection) => this.updateEditorCollection(column, resolvedCollection))
1255
- );
1256
- });
1269
+ });
1270
+ } else if (this.rxjs?.isObservable(collectionAsync)) {
1271
+ // wrap this inside a setTimeout to avoid timing issue since updateEditorCollection requires to call SlickGrid getColumns() method
1272
+ setTimeout(() => {
1273
+ this.subscriptions.push(
1274
+ (collectionAsync as Observable<any>).subscribe((resolvedCollection) => this.updateEditorCollection(column, resolvedCollection))
1275
+ );
1276
+ });
1277
+ }
1257
1278
  }
1258
1279
  }
1259
1280
 
@@ -1520,21 +1541,23 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
1520
1541
  * then take back "editor.model" and make it the new "editor" so that SlickGrid Editor Factory still works
1521
1542
  */
1522
1543
  protected swapInternalEditorToSlickGridFactoryEditor(columnDefinitions: Column<TData>[]): Column<TData>[] {
1523
- if (columnDefinitions.some(col => `${col.id}`.includes('.'))) {
1544
+ if (columnDefinitions.some(col => `${col?.id}`.includes('.'))) {
1524
1545
  console.error('[Slickgrid-React] Make sure that none of your Column Definition "id" property includes a dot in its name because that will cause some problems with the Editors. For example if your column definition "field" property is "user.firstName" then use "firstName" as the column "id".');
1525
1546
  }
1526
1547
 
1527
1548
  return columnDefinitions.map((column: Column | any) => {
1528
- // on every Editor which have a "collection" or a "collectionAsync"
1529
- if (column.editor?.collectionAsync) {
1530
- this.loadEditorCollectionAsync(column);
1531
- }
1549
+ if (column) {
1550
+ // on every Editor which have a "collection" or a "collectionAsync"
1551
+ if (column.editor?.collectionAsync) {
1552
+ this.loadEditorCollectionAsync(column);
1553
+ }
1532
1554
 
1533
- return {
1534
- ...column,
1535
- editor: column.editor?.model,
1536
- internalColumnEditor: { ...column.editor }
1537
- };
1555
+ return {
1556
+ ...column,
1557
+ editorClass: column.editor?.model,
1558
+ internalColumnEditor: { ...column.editor }
1559
+ };
1560
+ }
1538
1561
  });
1539
1562
  }
1540
1563
 
@@ -1544,23 +1567,25 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
1544
1567
  * Once we found the new pointer, we will reassign the "editor" and "collection" to the "internalColumnEditor" so it has newest collection
1545
1568
  */
1546
1569
  protected updateEditorCollection<U extends TData = any>(column: Column<U>, newCollection: U[]) {
1547
- (column.editor as ColumnEditor).collection = newCollection;
1548
- (column.editor as ColumnEditor).disabled = false;
1549
-
1550
- // find the new column reference pointer & re-assign the new editor to the internalColumnEditor
1551
- if (Array.isArray(this._columnDefinitions)) {
1552
- const columnRef = this._columnDefinitions.find((col: Column) => col.id === column.id);
1553
- if (columnRef) {
1554
- columnRef.internalColumnEditor = column.editor as ColumnEditor;
1570
+ if (this.grid && column.editor) {
1571
+ column.editor.collection = newCollection;
1572
+ column.editor.disabled = false;
1573
+
1574
+ // find the new column reference pointer & re-assign the new editor to the internalColumnEditor
1575
+ if (Array.isArray(this._columnDefinitions)) {
1576
+ const columnRef = this._columnDefinitions.find((col: Column) => col.id === column.id);
1577
+ if (columnRef) {
1578
+ columnRef.internalColumnEditor = column.editor;
1579
+ }
1555
1580
  }
1556
- }
1557
1581
 
1558
- // get current Editor, remove it from the DOM then re-enable it and re-render it with the new collection.
1559
- const currentEditor = this.grid.getCellEditor() as AutocompleterEditor | SelectEditor;
1560
- if (currentEditor?.disable && currentEditor?.renderDomElement) {
1561
- currentEditor.destroy();
1562
- currentEditor.disable(false);
1563
- currentEditor.renderDomElement(newCollection);
1582
+ // get current Editor, remove it from the DOM then re-enable it and re-render it with the new collection.
1583
+ const currentEditor = this.grid.getCellEditor() as AutocompleterEditor | SelectEditor;
1584
+ if (currentEditor?.disable && currentEditor?.renderDomElement) {
1585
+ currentEditor.destroy();
1586
+ currentEditor.disable(false);
1587
+ currentEditor.renderDomElement(newCollection);
1588
+ }
1564
1589
  }
1565
1590
  }
1566
1591
 
@@ -1570,7 +1595,7 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
1570
1595
  {/* <!-- Header slot if you need to create a complex custom header --> */}
1571
1596
  {this.props.header && <div className="header">{this.props.header}</div>}
1572
1597
 
1573
- <div id={`${this.props.gridId}`} className="slickgrid-container" style={{ width: '100%' }} onBlur={$event => this.commitEdit($event.target)}>
1598
+ <div id={`${this.props.gridId}`} className="slickgrid-container" onBlur={$event => this.commitEdit($event.target)}>
1574
1599
  </div>
1575
1600
 
1576
1601
  {/* <!--Footer slot if you need to create a complex custom footer-- > */}
@@ -61,6 +61,7 @@ export class Constants {
61
61
  TEXT_SORT_ASCENDING: 'Sort Ascending',
62
62
  TEXT_SORT_DESCENDING: 'Sort Descending',
63
63
  TEXT_STARTS_WITH: 'Starts With',
64
+ TEXT_TOGGLE_DARK_MODE: 'Toggle Dark Mode',
64
65
  TEXT_TOGGLE_FILTER_ROW: 'Toggle Filter Row',
65
66
  TEXT_TOGGLE_PRE_HEADER_ROW: 'Toggle Pre-Header Row',
66
67
  TEXT_X_OF_Y_SELECTED: '# of % selected',
@@ -169,6 +169,7 @@ export const GlobalGridOptions: Partial<GridOption> = {
169
169
  exportExcelCommandKey: 'EXPORT_TO_EXCEL',
170
170
  exportTextDelimitedCommandKey: 'EXPORT_TO_TAB_DELIMITED',
171
171
  refreshDatasetCommandKey: 'REFRESH_DATASET',
172
+ toggleDarkModeCommandKey: 'TOGGLE_DARK_MODE',
172
173
  toggleFilterCommandKey: 'TOGGLE_FILTER_ROW',
173
174
  togglePreHeaderCommandKey: 'TOGGLE_PRE_HEADER_ROW',
174
175
  },
@@ -181,6 +182,7 @@ export const GlobalGridOptions: Partial<GridOption> = {
181
182
  hideForceFitButton: false,
182
183
  hideRefreshDatasetCommand: false,
183
184
  hideSyncResizeButton: true,
185
+ hideToggleDarkModeCommand: true,
184
186
  hideToggleFilterCommand: false,
185
187
  hideTogglePreHeaderCommand: false,
186
188
  iconCssClass: 'fa fa-bars',
@@ -191,6 +193,7 @@ export const GlobalGridOptions: Partial<GridOption> = {
191
193
  iconExportExcelCommand: 'fa fa-file-excel-o',
192
194
  iconExportTextDelimitedCommand: 'fa fa-download',
193
195
  iconRefreshDatasetCommand: 'fa fa-refresh',
196
+ iconToggleDarkModeCommand: 'fa fa-moon-o mdi mdi-brightness-4',
194
197
  iconToggleFilterCommand: 'fa fa-random',
195
198
  iconTogglePreHeaderCommand: 'fa fa-random',
196
199
  menuWidth: 16,