rez-table-listing-mui 1.2.14 → 1.2.15

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.
@@ -0,0 +1,512 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import {
3
+ Box,
4
+ Select,
5
+ MenuItem,
6
+ FormControl,
7
+ Typography,
8
+ Checkbox,
9
+ FormControlLabel,
10
+ Grid,
11
+ Alert,
12
+ } from "@mui/material";
13
+
14
+ import ListingValues from "../common/listing-values";
15
+ import {
16
+ DndContext,
17
+ closestCenter,
18
+ KeyboardSensor,
19
+ MouseSensor,
20
+ TouchSensor,
21
+ useSensor,
22
+ useSensors,
23
+ DragEndEvent,
24
+ } from "@dnd-kit/core";
25
+ import {
26
+ QuickTabConfigProps,
27
+ SettingsQuickTabProps,
28
+ } from "../../../types/filter-settings";
29
+ import { TabsStyles } from "../style";
30
+ import InfoAlert from "../common/info-alert";
31
+ import { craftTableFilterSettingsOptionsProps } from "../../../types/table-options";
32
+ import { LANE_SELECTS } from "../constants";
33
+
34
+ const Lane = ({
35
+ filterSettingStates,
36
+ columnsData,
37
+ tabsApiData,
38
+ tabsApiDataLoading,
39
+ }: {
40
+ filterSettingStates: craftTableFilterSettingsOptionsProps;
41
+ columnsData: any;
42
+ tabsApiData?: string[];
43
+ tabsApiDataLoading?: boolean;
44
+ }) => {
45
+ const { settingsData, setSettingsData, saveButtonError, setSaveButtonError } =
46
+ filterSettingStates;
47
+
48
+ const [searchTerm, setSearchTerm] = useState<string>("");
49
+ const [currentQuickAttribute, setCurrentQuickAttribute] = useState<string>(
50
+ settingsData?.quick_tab?.attribute || ""
51
+ );
52
+
53
+ const quickTabStates = settingsData?.quick_tab as any;
54
+
55
+ // In case there is no quick tab state from API
56
+ useEffect(() => {
57
+ const stateToArray =
58
+ (quickTabStates && Object.entries(quickTabStates)) || [];
59
+ const isEmptyState = stateToArray.length ? false : true;
60
+ console.log("columnsData", columnsData);
61
+ console.log("first", columnsData.lanes.map((item: any) => item.name)[0]);
62
+
63
+ if (isEmptyState) {
64
+ setSettingsData((prev) => ({
65
+ ...prev,
66
+ quick_tab: {
67
+ ...prev?.quick_tab,
68
+ attribute: LANE_SELECTS[0].value,
69
+ sorting: "asc",
70
+ },
71
+ }));
72
+ }
73
+ }, [columnsData]);
74
+
75
+ // When user changes attribute
76
+ useEffect(() => {
77
+ if (currentQuickAttribute === settingsData?.quick_tab?.attribute) return;
78
+
79
+ if (tabsApiData?.length) {
80
+ setSettingsData((prev) => ({
81
+ ...prev,
82
+ quick_tab: {
83
+ ...prev?.quick_tab,
84
+ hide_list: tabsApiData,
85
+ show_list: [],
86
+ },
87
+ }));
88
+
89
+ setCurrentQuickAttribute(settingsData?.quick_tab?.attribute || "");
90
+ }
91
+ }, [tabsApiData]);
92
+
93
+ // Validation when user changes show list or hide list
94
+ useEffect(() => {
95
+ const showList = quickTabStates?.show_list || [];
96
+ const hideList = quickTabStates?.hide_list || [];
97
+
98
+ if (showList || hideList) {
99
+ // Check if showList is valid (between 1 and 5 items)
100
+ const isValidShowList = showList.length > 0 && showList.length <= 5;
101
+ const ERROR_CODE = "quick_tab_error";
102
+
103
+ if (!isValidShowList) {
104
+ const errorMessage = {
105
+ type: ERROR_CODE,
106
+ message:
107
+ showList.length === 0
108
+ ? "Quick Lane: Please select at least one item"
109
+ : "Quick Lane: Please select no more than 5 items",
110
+ };
111
+
112
+ // Check if the error is already present in the messages array
113
+ const hasQuickTabError = saveButtonError?.messages?.some(
114
+ (message) => message.type === ERROR_CODE
115
+ );
116
+
117
+ // Update the error state
118
+
119
+ // Later we can use this to show error message when we will make error logic more simple
120
+ // setSaveButtonError((prev) => {
121
+ // const otherMessages =
122
+ // prev?.messages?.filter((message) => message.type !== ERROR_CODE) ||
123
+ // [];
124
+
125
+ // return {
126
+ // ...prev,
127
+ // hasError: true,
128
+ // messages: hasQuickTabError
129
+ // ? [...prev?.messages]
130
+ // : [...otherMessages, errorMessage],
131
+ // };
132
+ // });
133
+ } else {
134
+ const hasOtherMessages = saveButtonError?.messages?.some(
135
+ (message) => message.type !== ERROR_CODE
136
+ );
137
+ // Reset error state if the list is valid
138
+ // setSaveButtonError((prev) => ({
139
+ // ...prev,
140
+ // hasError: hasOtherMessages,
141
+ // messages:
142
+ // prev?.messages?.filter((message) => message.type !== ERROR_CODE) ||
143
+ // [],
144
+ // }));
145
+ }
146
+ }
147
+ }, [quickTabStates?.hide_list, quickTabStates?.show_list]);
148
+
149
+ const sortingOptions = [
150
+ { label: "A-Z", value: "asc" },
151
+ { label: "Z-A", value: "dsc" },
152
+ { label: "Count (Ascending)", value: "count_asc" },
153
+ { label: "Count (Descending)", value: "count_dsc" },
154
+ { label: "Custom", value: "custom" },
155
+ ];
156
+
157
+ // Convert show_list/hide_list to FilterValue[] for rendering only
158
+ const showListValues = (quickTabStates?.show_list || [])?.map((id: any) => ({
159
+ id,
160
+ label: id?.charAt(0)?.toUpperCase() + id?.slice(1),
161
+ }));
162
+ const hideListValues = (quickTabStates?.hide_list || []).map((id: any) => ({
163
+ id,
164
+ label: id?.charAt(0)?.toUpperCase() + id?.slice(1),
165
+ }));
166
+
167
+ const sensors = useSensors(
168
+ useSensor(MouseSensor),
169
+ useSensor(TouchSensor),
170
+ useSensor(KeyboardSensor)
171
+ );
172
+
173
+ // Drag and drop logic, update only local state
174
+ const handleDragEnd = (event: DragEndEvent) => {
175
+ const { active, over } = event;
176
+ if (!over) {
177
+ return;
178
+ }
179
+ const currentContainer = active.data.current?.containerId;
180
+ const overContainer = over.data.current?.containerId;
181
+ if (!currentContainer || !overContainer) return;
182
+ if (currentContainer === overContainer) {
183
+ // Reorder within the same list
184
+ let newShowList = [...(quickTabStates.show_list ?? [])];
185
+ let newHideList = [...(quickTabStates.hide_list ?? [])];
186
+ if (currentContainer === "list") {
187
+ const oldIndex = newHideList.indexOf(String(active.id));
188
+ const newIndex = newHideList.indexOf(String(over.id));
189
+ if (oldIndex !== -1 && newIndex !== -1) {
190
+ const [removed] = newHideList.splice(oldIndex, 1);
191
+ newHideList.splice(newIndex, 0, removed);
192
+ }
193
+ } else {
194
+ const oldIndex = newShowList.indexOf(String(active.id));
195
+ const newIndex = newShowList.indexOf(String(over.id));
196
+ if (oldIndex !== -1 && newIndex !== -1) {
197
+ const [removed] = newShowList.splice(oldIndex, 1);
198
+ newShowList.splice(newIndex, 0, removed);
199
+ }
200
+ }
201
+
202
+ setSettingsData((prev) => ({
203
+ ...prev,
204
+ quick_tab: {
205
+ ...prev?.quick_tab,
206
+ show_list: newShowList,
207
+ hide_list: newHideList,
208
+ },
209
+ }));
210
+ } else {
211
+ // Move between lists
212
+ let newShowList = [...(quickTabStates.show_list ?? [])];
213
+ let newHideList = [...(quickTabStates.hide_list ?? [])];
214
+ if (currentContainer === "list" && overContainer === "lanes") {
215
+ if (newShowList.length >= 5) return; // prevent overflow
216
+ // Move from hide to show
217
+
218
+ const idx = newHideList.indexOf(String(active.id));
219
+ if (idx !== -1) {
220
+ newHideList.splice(idx, 1);
221
+ newShowList.push(String(active.id));
222
+ }
223
+ } else if (currentContainer === "lanes" && overContainer === "list") {
224
+ // Move from show to hide
225
+ const idx = newShowList.indexOf(String(active.id));
226
+ if (idx !== -1) {
227
+ newShowList.splice(idx, 1);
228
+ newHideList.push(String(active.id));
229
+ }
230
+ }
231
+
232
+ setSettingsData((prev) => ({
233
+ ...prev,
234
+ quick_tab: {
235
+ ...prev?.quick_tab,
236
+ show_list: newShowList,
237
+ hide_list: newHideList,
238
+ },
239
+ }));
240
+ }
241
+ };
242
+
243
+ const filteredListValues = hideListValues.filter((value: any) =>
244
+ value?.label?.toLowerCase().includes(searchTerm.toLowerCase())
245
+ );
246
+
247
+ // Show All/Hide All logic (local only)
248
+ const handleShowAll = () => {
249
+ const currentShowList = quickTabStates.show_list || [];
250
+ const currentHideList = quickTabStates.hide_list || [];
251
+
252
+ const availableSlots = 5 - currentShowList.length;
253
+
254
+ if (availableSlots <= 0) return; // Already at limit
255
+
256
+ const limitedHideList = currentHideList.slice(0, availableSlots);
257
+
258
+ setSettingsData((prev) => ({
259
+ ...prev,
260
+ quick_tab: {
261
+ ...prev?.quick_tab,
262
+ show_list: [...currentShowList, ...limitedHideList],
263
+ hide_list: currentHideList.filter(
264
+ (item: string) => !limitedHideList.includes(item)
265
+ ),
266
+ },
267
+ }));
268
+ };
269
+
270
+ const handleHideAll = () => {
271
+ setSettingsData((prev) => ({
272
+ ...prev,
273
+ quick_tab: {
274
+ ...prev?.quick_tab,
275
+ hide_list: [
276
+ ...(prev?.quick_tab?.hide_list || []),
277
+ ...(prev?.quick_tab?.show_list || []),
278
+ ],
279
+ show_list: [],
280
+ },
281
+ }));
282
+ };
283
+
284
+ // Checkbox logic (local only)
285
+ const handleShowSubLaneChange = (e: React.ChangeEvent<HTMLInputElement>) => {
286
+ setSettingsData((prev) => ({
287
+ ...prev,
288
+ quick_tab: {
289
+ ...prev?.quick_tab,
290
+ showSubLane: e.target.checked,
291
+ },
292
+ }));
293
+ };
294
+
295
+ const handleShowColorColumnsChange = (
296
+ e: React.ChangeEvent<HTMLInputElement>
297
+ ) => {
298
+ setSettingsData((prev) => ({
299
+ ...prev,
300
+ quick_tab: {
301
+ ...prev?.quick_tab,
302
+ showColorColumns: e.target.checked,
303
+ },
304
+ }));
305
+ };
306
+
307
+ const handleItemToggle = (itemId: string, fromContainerId: string) => {
308
+ const toShowList = [...(quickTabStates.show_list ?? [])];
309
+ const toHideList = [...(quickTabStates.hide_list ?? [])];
310
+
311
+ if (fromContainerId === "list") {
312
+ if (toShowList.length >= 5) return; // prevent overflow
313
+ // Move from hide_list to show_list
314
+ const index = toHideList.indexOf(itemId);
315
+ if (index > -1) {
316
+ toHideList.splice(index, 1);
317
+ toShowList.push(itemId);
318
+ }
319
+ } else if (fromContainerId === "lanes") {
320
+ // Move from show_list to hide_list
321
+ const index = toShowList.indexOf(itemId);
322
+ if (index > -1) {
323
+ toShowList.splice(index, 1);
324
+ toHideList.push(itemId);
325
+ }
326
+ }
327
+
328
+ setSettingsData((prev) => ({
329
+ ...prev,
330
+ quick_tab: {
331
+ ...prev?.quick_tab,
332
+ show_list: toShowList,
333
+ hide_list: toHideList,
334
+ },
335
+ }));
336
+ };
337
+
338
+ const enableDND = quickTabStates?.sorting === "custom" ? true : false;
339
+
340
+ return (
341
+ <Box
342
+ sx={{
343
+ display: "flex",
344
+ flexDirection: "column",
345
+ // gap: "0.5rem",
346
+ height: "100%",
347
+ }}
348
+ >
349
+ <Typography variant="caption" sx={TabsStyles.mainTabsHeader}>
350
+ *Quick filter settings will be reflected in vertical lanes
351
+ </Typography>
352
+ <Box>
353
+ <Grid sx={{ position: "relative" }} container>
354
+ <Grid size={12}>
355
+ <Box>
356
+ <Grid sx={TabsStyles.mainTabDropdown} size={6}>
357
+ <FormControl sx={TabsStyles.mainTabSelect} size="small">
358
+ <Select
359
+ value={quickTabStates?.attribute || ""}
360
+ onChange={(e) =>
361
+ setSettingsData((prev) => ({
362
+ ...prev,
363
+ quick_tab: {
364
+ ...prev?.quick_tab,
365
+ attribute: e.target.value,
366
+ },
367
+ }))
368
+ }
369
+ displayEmpty
370
+ renderValue={(selected) => {
371
+ if (!selected) {
372
+ return <em>Select Attribute</em>;
373
+ }
374
+ return selected;
375
+ }}
376
+ >
377
+ {LANE_SELECTS.map((lane: any) => (
378
+ <MenuItem key={lane?.key} value={lane?.value}>
379
+ {lane?.value}
380
+ </MenuItem>
381
+ ))}
382
+ </Select>
383
+ </FormControl>
384
+ <FormControl
385
+ sx={TabsStyles.selectDropdownSeparator}
386
+ size="small"
387
+ >
388
+ <Select
389
+ value={quickTabStates?.sorting || "asc"}
390
+ onChange={(e) =>
391
+ setSettingsData((prev) => ({
392
+ ...prev,
393
+ quick_tab: {
394
+ ...prev?.quick_tab,
395
+ sorting: e.target.value,
396
+ },
397
+ }))
398
+ }
399
+ displayEmpty
400
+ renderValue={(selected) => {
401
+ if (!selected) {
402
+ return <em>Sort by</em>;
403
+ }
404
+ const option = sortingOptions.find(
405
+ (opt) => opt.value === selected
406
+ );
407
+ return option?.label || selected;
408
+ }}
409
+ >
410
+ {sortingOptions.map((option) => (
411
+ <MenuItem key={option?.value} value={option?.value}>
412
+ {option?.label}
413
+ </MenuItem>
414
+ ))}
415
+ </Select>
416
+ </FormControl>
417
+ </Grid>
418
+ </Box>
419
+ </Grid>
420
+ <Grid>
421
+ {/* <Alert
422
+ severity="info"
423
+ sx={{
424
+ fontSize: "12px",
425
+ color: "#088AB2",
426
+ }}
427
+ >
428
+ Please select at least 1 and at most 5 values to display as lanes.
429
+ </Alert> */}
430
+ </Grid>
431
+ <DndContext
432
+ sensors={sensors}
433
+ collisionDetection={closestCenter}
434
+ onDragEnd={handleDragEnd}
435
+ >
436
+ <Grid sx={{ mt: 2 }} container spacing={2} size={12}>
437
+ <ListingValues
438
+ buttonText="Show All"
439
+ onClick={handleShowAll}
440
+ headerText="List of Values"
441
+ filteredValues={filteredListValues}
442
+ searchTerm={searchTerm}
443
+ setSearchTerm={setSearchTerm}
444
+ containerId="list"
445
+ tabsApiDataLoading={tabsApiDataLoading}
446
+ onItemToggle={handleItemToggle}
447
+ enableDragAndDrop={enableDND}
448
+ />
449
+ <ListingValues
450
+ buttonText="Hide All"
451
+ onClick={handleHideAll}
452
+ headerText="View as Lanes"
453
+ filteredValues={showListValues}
454
+ containerId="lanes"
455
+ // tabsApiDataLoading={tabsApiDataLoading}
456
+ onItemToggle={handleItemToggle}
457
+ enableDragAndDrop={enableDND}
458
+ AlertComponenet={
459
+ <InfoAlert
460
+ message="Please select at least 1 and at most 5 values to display as
461
+ lanes."
462
+ width={"49%"}
463
+ position="absolute"
464
+ color="#088AB2"
465
+ top={10}
466
+ zIndex={1}
467
+ />
468
+ }
469
+ />
470
+ </Grid>
471
+ </DndContext>
472
+ <Grid size={12}>
473
+ <Box sx={TabsStyles.checkboxStyle}>
474
+ <FormControlLabel
475
+ control={
476
+ <Checkbox
477
+ checked={quickTabStates?.showSubLane || false}
478
+ onChange={handleShowSubLaneChange}
479
+ size="small"
480
+ sx={{
481
+ "&.Mui-checked": {
482
+ color: "#7A5AF8",
483
+ },
484
+ }}
485
+ />
486
+ }
487
+ label="Show Sublane"
488
+ />
489
+ <FormControlLabel
490
+ control={
491
+ <Checkbox
492
+ checked={quickTabStates?.showColorColumns || false}
493
+ onChange={handleShowColorColumnsChange}
494
+ size="small"
495
+ sx={{
496
+ "&.Mui-checked": {
497
+ color: "#7A5AF8",
498
+ },
499
+ }}
500
+ />
501
+ }
502
+ label="Show Color columns"
503
+ />
504
+ </Box>
505
+ </Grid>
506
+ </Grid>
507
+ </Box>
508
+ </Box>
509
+ );
510
+ };
511
+
512
+ export default Lane;
@@ -6,6 +6,18 @@ export const SETTINGS_TABS: { label: string }[] = [
6
6
  { label: "Sorting" },
7
7
  ];
8
8
 
9
+ export const KANBAN_SETTINGS_TABS: { label: string }[] = [
10
+ { label: "Lane" },
11
+ { label: "Group By" },
12
+ ];
13
+
14
+ export const LANE_SELECTS = [
15
+ { key: "stage_group", value: "Stage Group" },
16
+ { key: "stage", value: "Stage" },
17
+ { key: "source", value: "Source" },
18
+ { key: "status", value: "Status" },
19
+ ];
20
+
9
21
  export const TOGGLE_BUTTON_TABS: ToggleButtonTabsProps[] = [
10
22
  { label: "Default", value: true, isDisabled: false },
11
23
  { label: "Tab Wise", value: false, isDisabled: false },
@@ -17,10 +17,13 @@ import { QuickFilterModalProps } from "../../types/filter-settings";
17
17
  import { CustomDialog, DialogTransition } from "./components/custom-dialog";
18
18
  import { dialogStyles } from "./style";
19
19
  import CustomButton from "./components/custom-button";
20
- import { SETTINGS_TABS } from "./constants";
20
+ import { KANBAN_SETTINGS_TABS, SETTINGS_TABS } from "./constants";
21
21
  import Loader from "../common/loader/loader";
22
+ import Lane from "./components/lane";
23
+ import GroupBy from "./components/group-by";
22
24
 
23
25
  export function QuickFilterSettings({
26
+ view = "listing",
24
27
  show,
25
28
  filterSettingStates,
26
29
  onClose,
@@ -108,38 +111,67 @@ export function QuickFilterSettings({
108
111
  <CustomVerticalTabs
109
112
  value={tabValue}
110
113
  onChange={handleTabChange}
111
- tabItems={SETTINGS_TABS}
114
+ tabItems={
115
+ view === "listing" ? SETTINGS_TABS : KANBAN_SETTINGS_TABS
116
+ }
112
117
  />
113
118
 
114
119
  <Box sx={{ flex: "1" }}>
115
- <CustomTabPanel value={tabValue} index={0}>
116
- {tabValue === 0 && (
117
- <QuickTab
118
- filterSettingStates={filterSettingStates}
119
- columnsData={columnsData}
120
- tabsApiData={tabsApiData}
121
- tabsApiDataLoading={tabsApiDataLoading}
122
- />
123
- )}
124
- </CustomTabPanel>
120
+ {view.toLowerCase() === "listing" && (
121
+ <CustomTabPanel value={tabValue} index={0}>
122
+ {tabValue === 0 && (
123
+ <QuickTab
124
+ filterSettingStates={filterSettingStates}
125
+ columnsData={columnsData}
126
+ tabsApiData={tabsApiData}
127
+ tabsApiDataLoading={tabsApiDataLoading}
128
+ />
129
+ )}
130
+ </CustomTabPanel>
131
+ )}
125
132
 
126
- <CustomTabPanel value={tabValue} index={1}>
127
- {tabValue === 1 && (
128
- <Column
129
- filterSettingStates={filterSettingStates}
130
- columnsData={columnsData}
131
- />
132
- )}
133
- </CustomTabPanel>
133
+ {view.toLowerCase() === "listing" && (
134
+ <CustomTabPanel value={tabValue} index={1}>
135
+ {tabValue === 1 && (
136
+ <Column
137
+ filterSettingStates={filterSettingStates}
138
+ columnsData={columnsData}
139
+ />
140
+ )}
141
+ </CustomTabPanel>
142
+ )}
134
143
 
135
- <CustomTabPanel value={tabValue} index={2}>
136
- {tabValue === 2 && (
137
- <Sorting
138
- filterSettingStates={filterSettingStates}
139
- columnsData={columnsData}
140
- />
141
- )}
142
- </CustomTabPanel>
144
+ {view.toLowerCase() === "listing" && (
145
+ <CustomTabPanel value={tabValue} index={2}>
146
+ {tabValue === 2 && (
147
+ <Sorting
148
+ filterSettingStates={filterSettingStates}
149
+ columnsData={columnsData}
150
+ />
151
+ )}
152
+ </CustomTabPanel>
153
+ )}
154
+ {view.toLowerCase() === "kanban" && (
155
+ <CustomTabPanel value={tabValue} index={0}>
156
+ {tabValue === 0 && (
157
+ <Lane
158
+ filterSettingStates={filterSettingStates}
159
+ columnsData={columnsData}
160
+ />
161
+ )}
162
+ </CustomTabPanel>
163
+ )}
164
+
165
+ {view.toLowerCase() === "kanban" && (
166
+ <CustomTabPanel value={tabValue} index={1}>
167
+ {tabValue === 1 && (
168
+ <GroupBy
169
+ filterSettingStates={filterSettingStates}
170
+ columnsData={columnsData}
171
+ />
172
+ )}
173
+ </CustomTabPanel>
174
+ )}
143
175
  </Box>
144
176
  </>
145
177
  )}
@@ -152,7 +184,7 @@ export function QuickFilterSettings({
152
184
  disabled={saveButtonError?.hasError}
153
185
  onClick={handleSaveSetSettingsData}
154
186
  >
155
- Save Quick Filter
187
+ {view === "listing" ? "Save Quick Filter" : "Save Kanban Layout"}
156
188
  </CustomButton>
157
189
  </DialogActions>
158
190
  )}
@@ -97,7 +97,6 @@ export const useDefaultColumns = () => {
97
97
  label: "Status",
98
98
  type: "custom",
99
99
  propName: "renderStatus",
100
- align: "right",
101
100
  },
102
101
  },
103
102
  {
@@ -78,7 +78,7 @@ export function customDebounce<T extends (...args: any[]) => any>(
78
78
 
79
79
  //ENTITY TYPE
80
80
  const ENVIRONMENT = "crm_dev";
81
- export const ENTITY_TYPE = "UPR";
81
+ export const ENTITY_TYPE = "LEAD";
82
82
 
83
83
  const environments = {
84
84
  adm_dev: "http://localhost:4010/api",
@@ -88,9 +88,6 @@ const environments = {
88
88
 
89
89
  const getBaseUrl = () => environments[ENVIRONMENT];
90
90
 
91
- // uat http://13.200.182.92:4010/api
92
- // local http://localhost:4010/api
93
-
94
91
  // API INTEGRATION
95
92
  export const api = axios.create({
96
93
  baseURL: getBaseUrl(),
@@ -2,6 +2,7 @@ import { FilterColumnsDataProps } from "./filter";
2
2
  import { craftTableFilterSettingsOptionsProps } from "./table-options";
3
3
 
4
4
  export interface QuickFilterModalProps {
5
+ view?: string;
5
6
  show?: boolean;
6
7
  filterSettingStates: craftTableFilterSettingsOptionsProps;
7
8
  onClose?: () => void;