@linzjs/step-ag-grid 13.3.1 → 13.4.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/README.md +27 -16
- package/dist/index.css +17 -4
- package/dist/src/components/gridFilter/GridFilterDownloadCsvButton.d.ts +3 -0
- package/dist/src/components/gridFilter/index.d.ts +1 -0
- package/dist/src/components/gridRender/GridRenderGenericCell.d.ts +1 -0
- package/dist/src/contexts/GridContext.d.ts +2 -0
- package/dist/src/contexts/GridContextProvider.d.ts +7 -0
- package/dist/src/contexts/GridContextProvider.test.d.ts +1 -0
- package/dist/step-ag-grid.esm.js +153 -65
- package/dist/step-ag-grid.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Grid.tsx +4 -0
- package/src/components/GridCell.tsx +7 -0
- package/src/components/gridFilter/GridFilterDownloadCsvButton.tsx +43 -0
- package/src/components/gridFilter/GridFilterHeaderIconButton.tsx +1 -1
- package/src/components/gridFilter/GridFilterQuick.tsx +12 -10
- package/src/components/gridFilter/index.ts +1 -0
- package/src/components/gridPopoverEdit/GridPopoverMenu.tsx +1 -0
- package/src/components/gridRender/GridRenderGenericCell.tsx +1 -0
- package/src/contexts/GridContext.tsx +5 -0
- package/src/contexts/GridContextProvider.test.tsx +39 -0
- package/src/contexts/GridContextProvider.tsx +79 -2
- package/src/react-menu3/components/Menu.tsx +2 -2
- package/src/stories/grid/GridPopoverEditBearing.stories.tsx +22 -10
- package/src/stories/grid/GridPopoverEditDropDown.stories.tsx +20 -8
- package/src/stories/grid/GridReadOnly.stories.tsx +5 -2
- package/src/styles/Grid.scss +23 -4
package/package.json
CHANGED
package/src/components/Grid.tsx
CHANGED
|
@@ -187,6 +187,9 @@ export const Grid = ({
|
|
|
187
187
|
colId: "selection",
|
|
188
188
|
editable: false,
|
|
189
189
|
minWidth: 42,
|
|
190
|
+
headerComponentParams: {
|
|
191
|
+
exportable: false,
|
|
192
|
+
},
|
|
190
193
|
maxWidth: 42,
|
|
191
194
|
suppressSizeToFit: true,
|
|
192
195
|
checkboxSelection: true,
|
|
@@ -344,6 +347,7 @@ export const Grid = ({
|
|
|
344
347
|
alwaysShowVerticalScroll={params.alwaysShowVerticalScroll}
|
|
345
348
|
isExternalFilterPresent={isExternalFilterPresent}
|
|
346
349
|
doesExternalFilterPass={doesExternalFilterPass}
|
|
350
|
+
maintainColumnOrder={true}
|
|
347
351
|
/>
|
|
348
352
|
</div>
|
|
349
353
|
</div>
|
|
@@ -114,6 +114,9 @@ export const GridCell = <RowType extends GridBaseRow, Props extends CellEditorCo
|
|
|
114
114
|
// This is so that e.g. bearings can be searched for by DMS or raw number.
|
|
115
115
|
const valueFormatter = props.valueFormatter;
|
|
116
116
|
const filterValueGetter = generateFilterGetter(props.field, props.filterValueGetter, valueFormatter);
|
|
117
|
+
const exportable = props.exportable;
|
|
118
|
+
// Can't leave this here ag-grid will complain
|
|
119
|
+
delete props.exportable;
|
|
117
120
|
|
|
118
121
|
return {
|
|
119
122
|
colId: props.field,
|
|
@@ -144,6 +147,10 @@ export const GridCell = <RowType extends GridBaseRow, Props extends CellEditorCo
|
|
|
144
147
|
originalCellRenderer: props.cellRenderer,
|
|
145
148
|
...props.cellRendererParams,
|
|
146
149
|
},
|
|
150
|
+
headerComponentParams: {
|
|
151
|
+
exportable,
|
|
152
|
+
...props.headerComponentParams,
|
|
153
|
+
},
|
|
147
154
|
};
|
|
148
155
|
};
|
|
149
156
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { CsvExportParams } from "ag-grid-community/dist/lib/interfaces/exportParams";
|
|
2
|
+
import { delay } from "lodash-es";
|
|
3
|
+
import { useContext } from "react";
|
|
4
|
+
|
|
5
|
+
import { LuiMiniSpinner } from "@linzjs/lui";
|
|
6
|
+
|
|
7
|
+
import { GridContext } from "../../contexts/GridContext";
|
|
8
|
+
import { useStateDeferred } from "../../lui/stateDeferredHook";
|
|
9
|
+
import { GridFilterHeaderIconButton } from "./GridFilterHeaderIconButton";
|
|
10
|
+
|
|
11
|
+
export const GridFilterDownloadCsvButton = (csvExportParams: CsvExportParams) => {
|
|
12
|
+
const { downloadCsv } = useContext(GridContext);
|
|
13
|
+
|
|
14
|
+
const [downloading, setDownloading, setDownloadingDeferred] = useStateDeferred(false);
|
|
15
|
+
|
|
16
|
+
const handleDownloadClick = () => {
|
|
17
|
+
setDownloading(true);
|
|
18
|
+
// Defer the download such that the component disabled state can update
|
|
19
|
+
delay(() => {
|
|
20
|
+
downloadCsv(csvExportParams);
|
|
21
|
+
// Defer re-enablement as the browser takes time to process the download
|
|
22
|
+
setDownloadingDeferred(false, 4000);
|
|
23
|
+
}, 100);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
return downloading ? (
|
|
27
|
+
<LuiMiniSpinner
|
|
28
|
+
size={22}
|
|
29
|
+
divProps={{
|
|
30
|
+
role: "status",
|
|
31
|
+
["aria-label"]: "Downloading...",
|
|
32
|
+
style: { width: 42, display: "flex", justifyContent: "center" },
|
|
33
|
+
}}
|
|
34
|
+
/>
|
|
35
|
+
) : (
|
|
36
|
+
<GridFilterHeaderIconButton
|
|
37
|
+
icon={"ic_save_download"}
|
|
38
|
+
title={"Download CSV"}
|
|
39
|
+
onClick={handleDownloadClick}
|
|
40
|
+
disabled={downloading}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
@@ -19,7 +19,7 @@ export const GridFilterHeaderIconButton = forwardRef<HTMLButtonElement, GridFilt
|
|
|
19
19
|
{...buttonProps}
|
|
20
20
|
type={"button"}
|
|
21
21
|
level={"tertiary"}
|
|
22
|
-
className={"
|
|
22
|
+
className={"lui-button-icon-only"}
|
|
23
23
|
ref={ref}
|
|
24
24
|
aria-label={title}
|
|
25
25
|
title={title}
|
|
@@ -16,15 +16,17 @@ export const GridFilterQuick = ({ quickFilterPlaceholder, defaultValue }: GridFi
|
|
|
16
16
|
}, [quickFilterValue, setQuickFilter]);
|
|
17
17
|
|
|
18
18
|
return (
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
19
|
+
<div className="GridFilterQuick-container">
|
|
20
|
+
<input
|
|
21
|
+
aria-label="Search"
|
|
22
|
+
className="GridFilterQuick-input"
|
|
23
|
+
type="text"
|
|
24
|
+
placeholder={quickFilterPlaceholder ?? "Search..."}
|
|
25
|
+
value={quickFilterValue}
|
|
26
|
+
onChange={(event) => {
|
|
27
|
+
setQuickFilterValue(event.target.value);
|
|
28
|
+
}}
|
|
29
|
+
/>
|
|
30
|
+
</div>
|
|
29
31
|
);
|
|
30
32
|
};
|
|
@@ -17,6 +17,7 @@ export const GridPopoverMenu = <RowType extends GridBaseRow>(
|
|
|
17
17
|
maxWidth: 48,
|
|
18
18
|
width: 40,
|
|
19
19
|
editable: colDef.editable != null ? colDef.editable : true,
|
|
20
|
+
exportable: false,
|
|
20
21
|
cellStyle: { justifyContent: "center" },
|
|
21
22
|
cellRenderer: GridRenderPopoutMenuCell,
|
|
22
23
|
...colDef,
|
|
@@ -35,6 +35,7 @@ export interface GenericCellColDef<RowType extends GridBaseRow> extends ColDefT<
|
|
|
35
35
|
valueFormatter?: string | ((params: RowValueFormatterParams<RowType>) => string);
|
|
36
36
|
filterValueGetter?: string | ((params: RowValueGetterParams<RowType>) => string);
|
|
37
37
|
editable?: boolean | ((params: RowEditableCallbackParams<RowType>) => boolean);
|
|
38
|
+
exportable?: boolean;
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
export interface GenericCellRendererParams<RowType extends GridBaseRow> {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ColumnApi, GridApi, RowNode } from "ag-grid-community";
|
|
2
|
+
import { CsvExportParams } from "ag-grid-community/dist/lib/interfaces/exportParams";
|
|
2
3
|
import { createContext, useContext } from "react";
|
|
3
4
|
|
|
4
5
|
import { ColDefT, GridBaseRow } from "../components";
|
|
@@ -43,6 +44,7 @@ export interface GridContextType<RowType extends GridBaseRow> {
|
|
|
43
44
|
getColumns: () => ColDefT<RowType>[];
|
|
44
45
|
invisibleColumnIds: string[];
|
|
45
46
|
setInvisibleColumnIds: (colIds: string[]) => void;
|
|
47
|
+
downloadCsv: (csvExportParams?: CsvExportParams) => void;
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
export const GridContext = createContext<GridContextType<any>>({
|
|
@@ -146,6 +148,9 @@ export const GridContext = createContext<GridContextType<any>>({
|
|
|
146
148
|
console.error("no context provider for doesExternalFilterPass");
|
|
147
149
|
return true;
|
|
148
150
|
},
|
|
151
|
+
downloadCsv: () => {
|
|
152
|
+
console.error("no context provider for downloadCsv");
|
|
153
|
+
},
|
|
149
154
|
});
|
|
150
155
|
|
|
151
156
|
export const useGridContext = <RowType extends GridBaseRow>() => useContext<GridContextType<RowType>>(GridContext);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ValueFormatterParams } from "ag-grid-community/dist/lib/entities/colDef";
|
|
2
|
+
|
|
3
|
+
import { downloadCsvUseValueFormattersProcessCellCallback as Dpcc } from "./GridContextProvider";
|
|
4
|
+
|
|
5
|
+
describe("downloadCsvUseValueFormattersProcessCellCallback", () => {
|
|
6
|
+
test("each type of value for conversion to string", async () => {
|
|
7
|
+
expect(Dpcc({ value: undefined } as any)).toBe("");
|
|
8
|
+
expect(Dpcc({ value: "-" } as any)).toBe("");
|
|
9
|
+
expect(Dpcc({ value: "–" } as any)).toBe("");
|
|
10
|
+
expect(Dpcc({ value: null } as any)).toBe("");
|
|
11
|
+
expect(Dpcc({ value: false } as any)).toBe("false");
|
|
12
|
+
expect(Dpcc({ value: "x" } as any)).toBe("x");
|
|
13
|
+
expect(Dpcc({ value: 123 } as any)).toBe("123");
|
|
14
|
+
expect(Dpcc({ value: { a: 2 } } as any)).toBe('{"a":2}');
|
|
15
|
+
expect(Dpcc({ value: { a: 2 }, column: { getColDef: () => undefined } } as any)).toBe('{"a":2}');
|
|
16
|
+
expect(Dpcc({ value: { a: 2 }, column: { getColDef: () => ({ valueFormatter: undefined }) } } as any)).toBe(
|
|
17
|
+
'{"a":2}',
|
|
18
|
+
);
|
|
19
|
+
expect(
|
|
20
|
+
Dpcc({
|
|
21
|
+
value: { a: 2 },
|
|
22
|
+
column: { getColDef: () => ({ valueFormatter: "registeredValueFormatter" }) },
|
|
23
|
+
} as any),
|
|
24
|
+
).toBe('{"a":2}');
|
|
25
|
+
|
|
26
|
+
expect(
|
|
27
|
+
Dpcc({
|
|
28
|
+
value: { a: 2 },
|
|
29
|
+
column: {
|
|
30
|
+
getColDef: () => ({
|
|
31
|
+
valueFormatter: (params: ValueFormatterParams) => {
|
|
32
|
+
return "xxx" + params.value.a;
|
|
33
|
+
},
|
|
34
|
+
}),
|
|
35
|
+
},
|
|
36
|
+
} as any),
|
|
37
|
+
).toBe("xxx2");
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { ColDef, ColumnApi, GridApi, RowNode } from "ag-grid-community";
|
|
2
2
|
import { CellPosition } from "ag-grid-community/dist/lib/entities/cellPosition";
|
|
3
|
+
import { ValueFormatterParams } from "ag-grid-community/dist/lib/entities/colDef";
|
|
4
|
+
import { CsvExportParams, ProcessCellForExportParams } from "ag-grid-community/dist/lib/interfaces/exportParams";
|
|
3
5
|
import { compact, debounce, defer, delay, difference, isEmpty, last, remove, sortBy } from "lodash-es";
|
|
4
6
|
import { ReactElement, ReactNode, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
5
7
|
|
|
@@ -418,12 +420,18 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: GridCont
|
|
|
418
420
|
[gridApiOp],
|
|
419
421
|
);
|
|
420
422
|
|
|
423
|
+
// waitForExternallySelectedItemsToBeInSync can't use the state as it won't be updated during function execution
|
|
424
|
+
const externallySelectedItemsAreInSyncRef = useRef(false);
|
|
425
|
+
useEffect(() => {
|
|
426
|
+
externallySelectedItemsAreInSyncRef.current = externallySelectedItemsAreInSync;
|
|
427
|
+
}, [externallySelectedItemsAreInSync]);
|
|
428
|
+
|
|
421
429
|
const waitForExternallySelectedItemsToBeInSync = useCallback(async () => {
|
|
422
430
|
// Wait for up to 5 seconds
|
|
423
|
-
for (let i = 0; i < 5000 / 200 && !
|
|
431
|
+
for (let i = 0; i < 5000 / 200 && !externallySelectedItemsAreInSyncRef.current; i++) {
|
|
424
432
|
await wait(200);
|
|
425
433
|
}
|
|
426
|
-
}, [
|
|
434
|
+
}, []);
|
|
427
435
|
|
|
428
436
|
const onFilterChanged = useMemo(
|
|
429
437
|
() =>
|
|
@@ -467,6 +475,26 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: GridCont
|
|
|
467
475
|
}
|
|
468
476
|
}, [invisibleColumnIds, columnApi, getColumns]);
|
|
469
477
|
|
|
478
|
+
/**
|
|
479
|
+
* Download visible columns as a CSV
|
|
480
|
+
*/
|
|
481
|
+
const downloadCsv = useCallback(
|
|
482
|
+
(csvExportParams?: CsvExportParams) => {
|
|
483
|
+
if (!gridApi || !columnApi) return;
|
|
484
|
+
|
|
485
|
+
const columnKeys = columnApi
|
|
486
|
+
?.getColumnState()
|
|
487
|
+
.filter((cs) => !cs.hide && gridApi.getColumnDef(cs.colId)?.headerComponentParams?.exportable !== false)
|
|
488
|
+
.map((cs) => cs.colId);
|
|
489
|
+
gridApi.exportDataAsCsv({
|
|
490
|
+
columnKeys,
|
|
491
|
+
processCellCallback: downloadCsvUseValueFormattersProcessCellCallback,
|
|
492
|
+
...csvExportParams,
|
|
493
|
+
});
|
|
494
|
+
},
|
|
495
|
+
[columnApi, gridApi],
|
|
496
|
+
);
|
|
497
|
+
|
|
470
498
|
return (
|
|
471
499
|
<GridContext.Provider
|
|
472
500
|
value={{
|
|
@@ -502,9 +530,58 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: GridCont
|
|
|
502
530
|
removeExternalFilter,
|
|
503
531
|
isExternalFilterPresent,
|
|
504
532
|
doesExternalFilterPass,
|
|
533
|
+
downloadCsv,
|
|
505
534
|
}}
|
|
506
535
|
>
|
|
507
536
|
{props.children}
|
|
508
537
|
</GridContext.Provider>
|
|
509
538
|
);
|
|
510
539
|
};
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Aggrid defaults to using getters and ignores formatters.
|
|
543
|
+
* step-ag-grid by default has a valueFormatter for every column that defaults to the getter if no valueFormatter
|
|
544
|
+
* This function uses valueFormatter by default
|
|
545
|
+
*/
|
|
546
|
+
export const downloadCsvUseValueFormattersProcessCellCallback = (params: ProcessCellForExportParams): string => {
|
|
547
|
+
const encodeToString = (value: any): string => {
|
|
548
|
+
// Convert nullish values to blank
|
|
549
|
+
if (value === "-" || value === "–" || value == null) {
|
|
550
|
+
return "";
|
|
551
|
+
}
|
|
552
|
+
if (typeof value === "string") {
|
|
553
|
+
return value;
|
|
554
|
+
}
|
|
555
|
+
return JSON.stringify(value);
|
|
556
|
+
};
|
|
557
|
+
|
|
558
|
+
// Try to use valueFormatter
|
|
559
|
+
const colDef = params?.column?.getColDef();
|
|
560
|
+
if (!colDef) return encodeToString(params.value);
|
|
561
|
+
|
|
562
|
+
// All columns in step-ag-grid have a default valueFormatter
|
|
563
|
+
// If you have custom a renderer you need to define your own valueFormatter to produce the text value
|
|
564
|
+
const valueFormatter = colDef.valueFormatter;
|
|
565
|
+
// If no valueFormatter then value _must_ be a string
|
|
566
|
+
if (valueFormatter == null) {
|
|
567
|
+
if (params.value != null && typeof params.value !== "string") {
|
|
568
|
+
console.error(`downloadCsv: valueFormatter missing and getValue is not a string, colId: ${colDef.colId}`);
|
|
569
|
+
}
|
|
570
|
+
return encodeToString(params.value);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// We don't have access to registered functions, so we can't call them
|
|
574
|
+
if (typeof valueFormatter !== "function") {
|
|
575
|
+
console.error(
|
|
576
|
+
`downloadCsv: String type (registered) value formatters are unsupported in downloadCsv, colId: ${colDef.colId}`,
|
|
577
|
+
);
|
|
578
|
+
return encodeToString(params.value);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
const result = valueFormatter({ ...params, data: params.node?.data, colDef } as ValueFormatterParams);
|
|
582
|
+
if (params.value != null && typeof result !== "string") {
|
|
583
|
+
console.error(`downloadCsv: valueFormatter is returning non string values, colDef:", colId: ${colDef.colId}`);
|
|
584
|
+
}
|
|
585
|
+
// We add an extra encodeToString here just in case valueFormatter is returning non string values
|
|
586
|
+
return encodeToString(result);
|
|
587
|
+
};
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "react";
|
|
11
11
|
|
|
12
12
|
import { useCombinedRef, useMenuChange, useMenuStateAndFocus } from "../hooks";
|
|
13
|
-
import { MenuButtonModifiers, RenderProp, RootMenuProps, UncontrolledMenuProps } from "../types";
|
|
13
|
+
import { MenuButtonModifiers, MenuCloseEvent, RenderProp, RootMenuProps, UncontrolledMenuProps } from "../types";
|
|
14
14
|
import { FocusPositions, Keys, getName, isMenuOpen, mergeProps, safeCall } from "../utils";
|
|
15
15
|
import { ControlledMenu } from "./ControlledMenu";
|
|
16
16
|
|
|
@@ -40,7 +40,7 @@ export function MenuFr(
|
|
|
40
40
|
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
41
41
|
|
|
42
42
|
const handleClose = useCallback(
|
|
43
|
-
(e) => {
|
|
43
|
+
(e: MenuCloseEvent) => {
|
|
44
44
|
toggleMenu(false);
|
|
45
45
|
if (e.key) buttonRef.current && buttonRef.current.focus();
|
|
46
46
|
},
|
|
@@ -9,10 +9,15 @@ import {
|
|
|
9
9
|
Grid,
|
|
10
10
|
GridCell,
|
|
11
11
|
GridContextProvider,
|
|
12
|
+
GridFilterColumnsToggle,
|
|
13
|
+
GridFilterDownloadCsvButton,
|
|
14
|
+
GridFilterQuick,
|
|
15
|
+
GridFilters,
|
|
12
16
|
GridPopoverEditBearing,
|
|
13
17
|
GridPopoverEditBearingCorrection,
|
|
14
18
|
GridProps,
|
|
15
19
|
GridUpdatingContextProvider,
|
|
20
|
+
GridWrapper,
|
|
16
21
|
wait,
|
|
17
22
|
} from "../..";
|
|
18
23
|
import "../../styles/GridTheme.scss";
|
|
@@ -97,16 +102,23 @@ const GridPopoverEditBearingTemplate: ComponentStory<typeof Grid> = (props: Grid
|
|
|
97
102
|
] as ITestRow[]);
|
|
98
103
|
|
|
99
104
|
return (
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
105
|
+
<GridWrapper maxHeight={300}>
|
|
106
|
+
<GridFilters>
|
|
107
|
+
<GridFilterQuick />
|
|
108
|
+
<GridFilterColumnsToggle />
|
|
109
|
+
<GridFilterDownloadCsvButton fileName={"customFilename"} />
|
|
110
|
+
</GridFilters>
|
|
111
|
+
<Grid
|
|
112
|
+
data-testid={"bearingsTestTable"}
|
|
113
|
+
{...props}
|
|
114
|
+
readOnly={false}
|
|
115
|
+
externalSelectedItems={externalSelectedItems}
|
|
116
|
+
setExternalSelectedItems={setExternalSelectedItems}
|
|
117
|
+
columnDefs={columnDefs}
|
|
118
|
+
rowData={rowData}
|
|
119
|
+
domLayout={"autoHeight"}
|
|
120
|
+
/>
|
|
121
|
+
</GridWrapper>
|
|
110
122
|
);
|
|
111
123
|
};
|
|
112
124
|
|
|
@@ -9,12 +9,17 @@ import {
|
|
|
9
9
|
Grid,
|
|
10
10
|
GridCell,
|
|
11
11
|
GridContextProvider,
|
|
12
|
+
GridFilterColumnsToggle,
|
|
13
|
+
GridFilterDownloadCsvButton,
|
|
14
|
+
GridFilterQuick,
|
|
15
|
+
GridFilters,
|
|
12
16
|
GridFormSubComponentTextArea,
|
|
13
17
|
GridFormSubComponentTextInput,
|
|
14
18
|
GridPopoverEditDropDown,
|
|
15
19
|
GridPopoverMenu,
|
|
16
20
|
GridProps,
|
|
17
21
|
GridUpdatingContextProvider,
|
|
22
|
+
GridWrapper,
|
|
18
23
|
MenuHeaderItem,
|
|
19
24
|
MenuSeparator,
|
|
20
25
|
MenuSeparatorString,
|
|
@@ -299,14 +304,21 @@ const GridEditDropDownTemplate: ComponentStory<typeof Grid> = (props: GridProps)
|
|
|
299
304
|
] as ITestRow[]);
|
|
300
305
|
|
|
301
306
|
return (
|
|
302
|
-
<
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
307
|
+
<GridWrapper maxHeight={300}>
|
|
308
|
+
<GridFilters>
|
|
309
|
+
<GridFilterQuick />
|
|
310
|
+
<GridFilterColumnsToggle />
|
|
311
|
+
<GridFilterDownloadCsvButton fileName={"customFilename"} />
|
|
312
|
+
</GridFilters>
|
|
313
|
+
<Grid
|
|
314
|
+
{...props}
|
|
315
|
+
externalSelectedItems={externalSelectedItems}
|
|
316
|
+
setExternalSelectedItems={setExternalSelectedItems}
|
|
317
|
+
columnDefs={columnDefs}
|
|
318
|
+
rowData={rowData}
|
|
319
|
+
domLayout={"autoHeight"}
|
|
320
|
+
/>
|
|
321
|
+
</GridWrapper>
|
|
310
322
|
);
|
|
311
323
|
};
|
|
312
324
|
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
wait,
|
|
25
25
|
} from "../..";
|
|
26
26
|
import { GridFilterColumnsToggle } from "../../components";
|
|
27
|
+
import { GridFilterDownloadCsvButton } from "../../components/gridFilter/GridFilterDownloadCsvButton";
|
|
27
28
|
import "../../styles/GridTheme.scss";
|
|
28
29
|
import "../../styles/index.scss";
|
|
29
30
|
|
|
@@ -96,6 +97,7 @@ const GridReadOnlyTemplate: ComponentStory<typeof Grid> = (props: GridProps) =>
|
|
|
96
97
|
headerName: "Popout message",
|
|
97
98
|
maxWidth: 150,
|
|
98
99
|
cellRenderer: () => <>Single Click me!</>,
|
|
100
|
+
exportable: false,
|
|
99
101
|
},
|
|
100
102
|
{
|
|
101
103
|
multiEdit: true,
|
|
@@ -214,7 +216,7 @@ const GridReadOnlyTemplate: ComponentStory<typeof Grid> = (props: GridProps) =>
|
|
|
214
216
|
return (
|
|
215
217
|
<GridWrapper maxHeight={300}>
|
|
216
218
|
<GridFilters>
|
|
217
|
-
<GridFilterQuick
|
|
219
|
+
<GridFilterQuick />
|
|
218
220
|
<GridFilterLessThan text="Age <" field={"age"} />
|
|
219
221
|
<GridFilterButtons<ITestRow>
|
|
220
222
|
luiButtonProps={{ style: { whiteSpace: "nowrap" } }}
|
|
@@ -229,6 +231,7 @@ const GridReadOnlyTemplate: ComponentStory<typeof Grid> = (props: GridProps) =>
|
|
|
229
231
|
]}
|
|
230
232
|
/>
|
|
231
233
|
<GridFilterColumnsToggle />
|
|
234
|
+
<GridFilterDownloadCsvButton />
|
|
232
235
|
</GridFilters>
|
|
233
236
|
<Grid
|
|
234
237
|
data-testid={"readonly"}
|
|
@@ -263,7 +266,7 @@ const GridFilterLessThan = (props: { field: keyof ITestRow; text: string }): JSX
|
|
|
263
266
|
};
|
|
264
267
|
|
|
265
268
|
return (
|
|
266
|
-
<div className={"flex-row-center"}>
|
|
269
|
+
<div className={"GridFilter-container flex-row-center"}>
|
|
267
270
|
<div style={{ whiteSpace: "nowrap" }}>{props.text}</div>
|
|
268
271
|
 
|
|
269
272
|
<input type={"text"} defaultValue={value} onChange={(e) => updateValue(e.target.value)} style={{ width: 64 }} />
|
package/src/styles/Grid.scss
CHANGED
|
@@ -27,17 +27,36 @@
|
|
|
27
27
|
|
|
28
28
|
.Grid-container-filters {
|
|
29
29
|
width: 100%;
|
|
30
|
-
margin-bottom: 16px;
|
|
31
30
|
flex: 0;
|
|
32
31
|
display: flex;
|
|
33
32
|
align-items: center;
|
|
34
33
|
flex-direction: row;
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
padding: 16px;
|
|
35
|
+
background-color: colors.$hint;
|
|
36
|
+
border-bottom: 1px solid colors.$silver;
|
|
37
|
+
border-top: 2px solid colors.$lily;
|
|
37
38
|
}
|
|
38
39
|
|
|
40
|
+
.Grid-container-filters button {
|
|
41
|
+
margin-left: 0 !important;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
%GridFilter-container {
|
|
45
|
+
&:not(:last-child) {
|
|
46
|
+
margin-right: 8px;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.GridFilter-container {
|
|
51
|
+
@extend %GridFilter-container;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.GridFilterQuick-container {
|
|
55
|
+
@extend %GridFilter-container;
|
|
56
|
+
flex: 1;
|
|
57
|
+
}
|
|
39
58
|
|
|
40
|
-
.
|
|
59
|
+
.GridFilterQuick-input {
|
|
41
60
|
width: 100%;
|
|
42
61
|
height: 40px;
|
|
43
62
|
border: 0.06rem solid colors.$silver;
|