@linzjs/step-ag-grid 2.1.3 → 2.2.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/dist/index.js +106 -14
- package/dist/index.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/lui/ActionButton.d.ts +15 -0
- package/dist/src/lui/reactUtils.d.ts +6 -0
- package/dist/src/lui/reactUtils.test.d.ts +1 -0
- package/dist/src/lui/stateDeferredHook.d.ts +4 -0
- package/dist/src/lui/timeoutHook.d.ts +8 -0
- package/dist/src/lui/timeoutHook.test.d.ts +1 -0
- package/dist/step-ag-grid.esm.js +107 -16
- package/dist/step-ag-grid.esm.js.map +1 -1
- package/package.json +4 -3
- package/src/index.ts +2 -0
- package/src/lui/ActionButton.scss +32 -0
- package/src/lui/ActionButton.tsx +76 -0
- package/src/lui/reactUtils.test.tsx +47 -0
- package/src/lui/reactUtils.tsx +14 -0
- package/src/lui/stateDeferredHook.tsx +29 -0
- package/src/lui/timeoutHook.test.tsx +38 -0
- package/src/lui/timeoutHook.tsx +40 -0
- package/src/stories/components/ActionButton.stories.tsx +33 -0
- package/src/stories/{components → grid}/FormTest.scss +0 -0
- package/src/stories/{components → grid}/FormTest.tsx +0 -0
- package/src/stories/{components → grid}/GridPopoutBearing.stories.tsx +7 -10
- package/src/stories/{components → grid}/GridPopoutEditDropDown.stories.tsx +20 -23
- package/src/stories/{components → grid}/GridPopoutEditGeneric.stories.tsx +6 -9
- package/src/stories/{components → grid}/GridPopoutEditGenericTextArea.stories.tsx +57 -18
- package/src/stories/{components → grid}/GridPopoutEditMultiSelect.stories.tsx +6 -9
- package/src/stories/{components → grid}/GridReadOnly.stories.tsx +6 -8
- /package/src/stories/{components → react-menu}/ReactMenu.stories.tsx +0 -0
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@linzjs/step-ag-grid",
|
|
3
3
|
"repository": "github:linz/step-ag-grid.git",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "2.
|
|
5
|
+
"version": "2.2.0",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"aggrid",
|
|
8
8
|
"ag-grid",
|
|
@@ -91,9 +91,10 @@
|
|
|
91
91
|
"@storybook/react": "6.5.13",
|
|
92
92
|
"@storybook/test-runner": "^0.9.0",
|
|
93
93
|
"@storybook/testing-library": "^0.0.13",
|
|
94
|
+
"@testing-library/dom": "^8.19.0",
|
|
94
95
|
"@testing-library/jest-dom": "^5.16.5",
|
|
95
|
-
"@testing-library/react": "^
|
|
96
|
-
"@testing-library/user-event": "^
|
|
96
|
+
"@testing-library/react": "^12.1.5",
|
|
97
|
+
"@testing-library/user-event": "^13.5.0",
|
|
97
98
|
"@types/debounce-promise": "^3.1.5",
|
|
98
99
|
"@types/jest": "^29.2.2",
|
|
99
100
|
"@types/lodash-es": "^4.17.6",
|
package/src/index.ts
CHANGED
|
@@ -34,5 +34,7 @@ export { TextAreaInput } from "./lui/TextAreaInput";
|
|
|
34
34
|
export { TextInputFormatted } from "./lui/TextInputFormatted";
|
|
35
35
|
export { GridSubComponentTextArea } from "./components/GridSubComponentTextArea";
|
|
36
36
|
|
|
37
|
+
export * from "./lui/ActionButton";
|
|
38
|
+
|
|
37
39
|
export * from "./utils/bearing";
|
|
38
40
|
export * from "./utils/util";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
@use "../../node_modules/@linzjs/lui/dist/scss/Foundation/Variables/ColorVars" as colors;
|
|
2
|
+
|
|
3
|
+
.ActionButton {
|
|
4
|
+
display: flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.ActionButton .LuiIcon {
|
|
9
|
+
margin: 0 4px !important;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.ActionButton-minimalArea {
|
|
13
|
+
position: relative;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.ActionButton-minimalAreaDisplay {
|
|
17
|
+
position: absolute;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.ActionButton-minimalAreaExpand {
|
|
21
|
+
visibility: hidden;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.ActionButton-inProgress {
|
|
25
|
+
cursor: progress;
|
|
26
|
+
color: #007198 !important;
|
|
27
|
+
background-color: colors.$polar !important;
|
|
28
|
+
|
|
29
|
+
svg * {
|
|
30
|
+
fill: transparent !important;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import "./ActionButton.scss";
|
|
2
|
+
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import { useEffect } from "react";
|
|
5
|
+
import { LuiButton, LuiIcon, LuiMiniSpinner } from "@linzjs/lui";
|
|
6
|
+
import { IconName } from "@linzjs/lui/dist/components/LuiIcon/LuiIcon";
|
|
7
|
+
import { usePrevious } from "./reactUtils";
|
|
8
|
+
import { useStateDeferred } from "./stateDeferredHook";
|
|
9
|
+
|
|
10
|
+
export interface ActionButtonProps {
|
|
11
|
+
icon: IconName;
|
|
12
|
+
name: string;
|
|
13
|
+
inProgressName?: string;
|
|
14
|
+
title?: string;
|
|
15
|
+
dataTestId?: string;
|
|
16
|
+
size?: "xs" | "sm" | "md" | "lg" | "xl" | "ns";
|
|
17
|
+
className?: string;
|
|
18
|
+
onClick?: () => void;
|
|
19
|
+
inProgress?: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Kept this less than one second, so I don't have issues with waitFor as it defaults to 1s
|
|
23
|
+
const minimumInProgressTimeMs = 950;
|
|
24
|
+
|
|
25
|
+
export const ActionButton = ({
|
|
26
|
+
icon,
|
|
27
|
+
name,
|
|
28
|
+
inProgressName,
|
|
29
|
+
dataTestId,
|
|
30
|
+
inProgress,
|
|
31
|
+
className,
|
|
32
|
+
title,
|
|
33
|
+
onClick,
|
|
34
|
+
size = "sm",
|
|
35
|
+
}: ActionButtonProps): JSX.Element => {
|
|
36
|
+
const lastInProgress = usePrevious(inProgress ?? false);
|
|
37
|
+
const [localInProgress, setLocalInProgress, setLocalInProgressDeferred] = useStateDeferred<boolean>(!!inProgress);
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (inProgress == lastInProgress) return;
|
|
41
|
+
inProgress ? setLocalInProgress(true) : setLocalInProgressDeferred(false, minimumInProgressTimeMs);
|
|
42
|
+
}, [inProgress, lastInProgress, setLocalInProgress, setLocalInProgressDeferred]);
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<LuiButton
|
|
46
|
+
data-testid={dataTestId}
|
|
47
|
+
type={"button"}
|
|
48
|
+
level={"tertiary"}
|
|
49
|
+
title={title ?? name}
|
|
50
|
+
aria-label={name}
|
|
51
|
+
className={clsx("lui-button-icon", "ActionButton", className, localInProgress && "ActionButton-inProgress")}
|
|
52
|
+
size={"lg"}
|
|
53
|
+
onClick={onClick}
|
|
54
|
+
disabled={localInProgress}
|
|
55
|
+
>
|
|
56
|
+
{localInProgress ? (
|
|
57
|
+
<LuiMiniSpinner
|
|
58
|
+
size={16}
|
|
59
|
+
divProps={{
|
|
60
|
+
"data-testid": "loading-spinner",
|
|
61
|
+
style: { padding: 0, margin: 0, paddingRight: 8 },
|
|
62
|
+
role: "status",
|
|
63
|
+
["aria-label"]: "Loading",
|
|
64
|
+
}}
|
|
65
|
+
/>
|
|
66
|
+
) : (
|
|
67
|
+
<LuiIcon name={icon} alt={name} size={size} />
|
|
68
|
+
)}
|
|
69
|
+
<span className={"ActionButton-minimalArea"}>
|
|
70
|
+
<span className={"ActionButton-minimalAreaDisplay"}>{(localInProgress ? inProgressName : name) ?? name}</span>
|
|
71
|
+
{/* This makes sure the button expands to fill maximum length text at all times */}
|
|
72
|
+
<span className={"ActionButton-minimalAreaExpand"}>{name}</span>
|
|
73
|
+
</span>
|
|
74
|
+
</LuiButton>
|
|
75
|
+
);
|
|
76
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { usePrevious } from "./reactUtils";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { act, render } from "@testing-library/react";
|
|
4
|
+
import { screen } from "@testing-library/dom";
|
|
5
|
+
|
|
6
|
+
interface WrapperProps {
|
|
7
|
+
value: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let extPrevious: boolean | undefined = undefined;
|
|
11
|
+
|
|
12
|
+
const UsePreviousWrapper = ({ value }: WrapperProps): JSX.Element => {
|
|
13
|
+
const previous = usePrevious<boolean>(value);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
extPrevious = previous;
|
|
16
|
+
}, [previous]);
|
|
17
|
+
|
|
18
|
+
return <div />;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const TestComponent = (): JSX.Element => {
|
|
22
|
+
const [value, setValue] = useState(false);
|
|
23
|
+
|
|
24
|
+
const toggleValue = () => setValue((value) => !value);
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<>
|
|
28
|
+
<button onClick={toggleValue}>Change value</button>
|
|
29
|
+
<UsePreviousWrapper value={value} />
|
|
30
|
+
</>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
describe("usePrevious", () => {
|
|
35
|
+
test("usePrevious", async () => {
|
|
36
|
+
render(<TestComponent />);
|
|
37
|
+
const button = await screen.findByText("Change value");
|
|
38
|
+
|
|
39
|
+
expect(extPrevious).toBeUndefined();
|
|
40
|
+
|
|
41
|
+
act(() => button.click());
|
|
42
|
+
expect(extPrevious).toBe(false);
|
|
43
|
+
|
|
44
|
+
act(() => button.click());
|
|
45
|
+
expect(extPrevious).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Track previous values of states.
|
|
5
|
+
*
|
|
6
|
+
* @param value Value to track.
|
|
7
|
+
*/
|
|
8
|
+
export const usePrevious = <T extends unknown>(value: T): T | undefined => {
|
|
9
|
+
const ref = useRef<T>();
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
ref.current = value;
|
|
12
|
+
}, [value]);
|
|
13
|
+
return ref.current;
|
|
14
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useCallback, useRef, useState } from "react";
|
|
2
|
+
import { useTimeoutHook } from "./timeoutHook";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Defers state change up to a minimum time since last state change.
|
|
6
|
+
*/
|
|
7
|
+
export const useStateDeferred = <T extends unknown>(
|
|
8
|
+
initialValue: T,
|
|
9
|
+
): [T, (v: T) => void, (v: T, w: number) => void] => {
|
|
10
|
+
const startTime = useRef<number>(0);
|
|
11
|
+
const timeoutHook = useTimeoutHook();
|
|
12
|
+
|
|
13
|
+
const [value, _setValue] = useState(initialValue);
|
|
14
|
+
|
|
15
|
+
const setValue = useCallback((newValue: T) => {
|
|
16
|
+
startTime.current = Date.now();
|
|
17
|
+
_setValue(newValue);
|
|
18
|
+
}, []);
|
|
19
|
+
|
|
20
|
+
const setValueDeferred = useCallback(
|
|
21
|
+
(newValue: T, minimumWaitTimeMs: number) => {
|
|
22
|
+
const waitTimeMs = Math.max(minimumWaitTimeMs - (Date.now() - startTime.current), 0);
|
|
23
|
+
timeoutHook(() => _setValue(newValue), waitTimeMs);
|
|
24
|
+
},
|
|
25
|
+
[timeoutHook],
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
return [value, setValue, setValueDeferred];
|
|
29
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useTimeoutHook } from "./timeoutHook";
|
|
2
|
+
import { render } from "@testing-library/react";
|
|
3
|
+
|
|
4
|
+
describe("useTimeoutHook", () => {
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
jest.useFakeTimers();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
jest.useRealTimers();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const TestComponent = (props: { callback: () => void; repeat?: number }) => {
|
|
14
|
+
const timeoutHook = useTimeoutHook();
|
|
15
|
+
for (let i = 0; i < (props.repeat ?? 1); i++) {
|
|
16
|
+
timeoutHook(() => props.callback(), 1000);
|
|
17
|
+
}
|
|
18
|
+
return <div />;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
test("invokes on timeout", async () => {
|
|
22
|
+
const callback = jest.fn();
|
|
23
|
+
|
|
24
|
+
render(<TestComponent callback={callback} />);
|
|
25
|
+
expect(callback).toHaveBeenCalledTimes(0);
|
|
26
|
+
jest.runAllTimers();
|
|
27
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("invokes once on double invocation", async () => {
|
|
31
|
+
const callback = jest.fn();
|
|
32
|
+
|
|
33
|
+
render(<TestComponent callback={callback} repeat={2} />);
|
|
34
|
+
expect(callback).toHaveBeenCalledTimes(0);
|
|
35
|
+
jest.runAllTimers();
|
|
36
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef } from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Cancels timeouts on scope being destroyed.
|
|
5
|
+
*
|
|
6
|
+
* This could almost be a debounce, but debounce tracks by function reference, this tracks by hook reference.
|
|
7
|
+
* This could have been implemented using debounce if the callers function was wrapped in useCallback,
|
|
8
|
+
* but there's no way to enforce that, so it would lead to bugs.
|
|
9
|
+
*/
|
|
10
|
+
export const useTimeoutHook = () => {
|
|
11
|
+
const timeout = useRef<ReturnType<typeof setTimeout>>();
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Clear any pending timeouts.
|
|
15
|
+
*/
|
|
16
|
+
const clearTimeouts = () => {
|
|
17
|
+
if (timeout.current) {
|
|
18
|
+
const tc = timeout.current;
|
|
19
|
+
timeout.current = undefined;
|
|
20
|
+
clearTimeout(tc);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Call this when your action has completed.
|
|
26
|
+
*/
|
|
27
|
+
const invoke = useCallback((fn: () => void, waitTimeMs: number) => {
|
|
28
|
+
clearTimeouts();
|
|
29
|
+
timeout.current = setTimeout(fn, waitTimeMs);
|
|
30
|
+
}, []);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Clear timeout on loss of scope.
|
|
34
|
+
*/
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
return () => clearTimeouts();
|
|
37
|
+
}, []);
|
|
38
|
+
|
|
39
|
+
return invoke;
|
|
40
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import "@linzjs/lui/dist/scss/base.scss";
|
|
2
|
+
import "@linzjs/lui/dist/fonts";
|
|
3
|
+
|
|
4
|
+
import { ComponentMeta, ComponentStory } from "@storybook/react/dist/ts3.9/client/preview/types-6-3";
|
|
5
|
+
import { ActionButton } from "../../lui/ActionButton";
|
|
6
|
+
import { useCallback, useState } from "react";
|
|
7
|
+
import { wait } from "../../utils/util";
|
|
8
|
+
|
|
9
|
+
export default {
|
|
10
|
+
title: "Components / ButtonTextWithIcon",
|
|
11
|
+
component: ActionButton,
|
|
12
|
+
args: {},
|
|
13
|
+
} as ComponentMeta<typeof ActionButton>;
|
|
14
|
+
|
|
15
|
+
const ActionButtonTemplate: ComponentStory<typeof ActionButton> = () => {
|
|
16
|
+
const [inProgress, setInProgress] = useState(false);
|
|
17
|
+
const performAction = useCallback(async () => {
|
|
18
|
+
setInProgress(true);
|
|
19
|
+
await wait(1000);
|
|
20
|
+
setInProgress(false);
|
|
21
|
+
}, []);
|
|
22
|
+
return (
|
|
23
|
+
<ActionButton
|
|
24
|
+
icon={"ic_add"}
|
|
25
|
+
name={"Add new row"}
|
|
26
|
+
inProgressName={"Adding..."}
|
|
27
|
+
inProgress={inProgress}
|
|
28
|
+
onClick={performAction}
|
|
29
|
+
/>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const ActionButtonSimple = ActionButtonTemplate.bind({});
|
|
File without changes
|
|
File without changes
|
|
@@ -24,7 +24,7 @@ export default {
|
|
|
24
24
|
},
|
|
25
25
|
decorators: [
|
|
26
26
|
(Story) => (
|
|
27
|
-
<div style={{ width:
|
|
27
|
+
<div style={{ width: 1024, height: 400 }}>
|
|
28
28
|
<GridUpdatingContextProvider>
|
|
29
29
|
<GridContextProvider>
|
|
30
30
|
<Story />
|
|
@@ -83,15 +83,11 @@ const GridReadOnlyTemplate: ComponentStory<typeof Grid> = (props: GridProps) =>
|
|
|
83
83
|
[],
|
|
84
84
|
);
|
|
85
85
|
|
|
86
|
-
const rowData =
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
{ id: 1002, bearing1: null, bearingCorrection: 355.1 },
|
|
92
|
-
] as ITestRow[],
|
|
93
|
-
[],
|
|
94
|
-
);
|
|
86
|
+
const [rowData, setRowData] = useState([
|
|
87
|
+
{ id: 1000, bearing1: 1.234, bearingCorrection: 90 },
|
|
88
|
+
{ id: 1001, bearing1: 1.565, bearingCorrection: 240 },
|
|
89
|
+
{ id: 1002, bearing1: null, bearingCorrection: 355.1 },
|
|
90
|
+
] as ITestRow[]);
|
|
95
91
|
|
|
96
92
|
return (
|
|
97
93
|
<Grid
|
|
@@ -100,6 +96,7 @@ const GridReadOnlyTemplate: ComponentStory<typeof Grid> = (props: GridProps) =>
|
|
|
100
96
|
setExternalSelectedItems={setExternalSelectedItems}
|
|
101
97
|
columnDefs={columnDefs}
|
|
102
98
|
rowData={rowData}
|
|
99
|
+
domLayout={"autoHeight"}
|
|
103
100
|
/>
|
|
104
101
|
);
|
|
105
102
|
};
|
|
@@ -22,7 +22,7 @@ export default {
|
|
|
22
22
|
},
|
|
23
23
|
decorators: [
|
|
24
24
|
(Story) => (
|
|
25
|
-
<div style={{ width:
|
|
25
|
+
<div style={{ width: 1024, height: 400 }}>
|
|
26
26
|
<GridUpdatingContextProvider>
|
|
27
27
|
<GridContextProvider>
|
|
28
28
|
<Story />
|
|
@@ -245,28 +245,24 @@ const GridEditDropDownTemplate: ComponentStory<typeof Grid> = (props: GridProps)
|
|
|
245
245
|
[optionsFn, optionsObjects],
|
|
246
246
|
);
|
|
247
247
|
|
|
248
|
-
const rowData =
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
},
|
|
267
|
-
] as ITestRow[],
|
|
268
|
-
[],
|
|
269
|
-
);
|
|
248
|
+
const [rowData, setRowData] = useState([
|
|
249
|
+
{
|
|
250
|
+
id: 1000,
|
|
251
|
+
position: "Tester",
|
|
252
|
+
position2: "1",
|
|
253
|
+
position3: "Tester",
|
|
254
|
+
position4: { code: "O1", desc: "Object One" },
|
|
255
|
+
code: "O1",
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
id: 1001,
|
|
259
|
+
position: "Developer",
|
|
260
|
+
position2: "2",
|
|
261
|
+
position3: "Developer",
|
|
262
|
+
position4: { code: "O2", desc: "Object Two" },
|
|
263
|
+
code: "O2",
|
|
264
|
+
},
|
|
265
|
+
] as ITestRow[]);
|
|
270
266
|
|
|
271
267
|
return (
|
|
272
268
|
<Grid
|
|
@@ -275,6 +271,7 @@ const GridEditDropDownTemplate: ComponentStory<typeof Grid> = (props: GridProps)
|
|
|
275
271
|
setExternalSelectedItems={setExternalSelectedItems}
|
|
276
272
|
columnDefs={columnDefs}
|
|
277
273
|
rowData={rowData}
|
|
274
|
+
domLayout={"autoHeight"}
|
|
278
275
|
/>
|
|
279
276
|
);
|
|
280
277
|
};
|
|
@@ -20,7 +20,7 @@ export default {
|
|
|
20
20
|
},
|
|
21
21
|
decorators: [
|
|
22
22
|
(Story) => (
|
|
23
|
-
<div style={{ width:
|
|
23
|
+
<div style={{ width: 1024, height: 400 }}>
|
|
24
24
|
<GridUpdatingContextProvider>
|
|
25
25
|
<GridContextProvider>
|
|
26
26
|
<Story />
|
|
@@ -57,14 +57,10 @@ const GridPopoutEditGenericTemplate: ComponentStory<typeof Grid> = (props: GridP
|
|
|
57
57
|
[],
|
|
58
58
|
);
|
|
59
59
|
|
|
60
|
-
const rowData =
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
{ id: 1001, name: "PEG V SD523", nameType: "PEG", numba: "V", plan: "SD 523" },
|
|
65
|
-
] as IFormTestRow[],
|
|
66
|
-
[],
|
|
67
|
-
);
|
|
60
|
+
const [rowData, setRowData] = useState([
|
|
61
|
+
{ id: 1000, name: "IS IS DP12345", nameType: "IS", numba: "IX", plan: "DP 12345" },
|
|
62
|
+
{ id: 1001, name: "PEG V SD523", nameType: "PEG", numba: "V", plan: "SD 523" },
|
|
63
|
+
] as IFormTestRow[]);
|
|
68
64
|
|
|
69
65
|
return (
|
|
70
66
|
<Grid
|
|
@@ -73,6 +69,7 @@ const GridPopoutEditGenericTemplate: ComponentStory<typeof Grid> = (props: GridP
|
|
|
73
69
|
setExternalSelectedItems={setExternalSelectedItems}
|
|
74
70
|
columnDefs={columnDefs}
|
|
75
71
|
rowData={rowData}
|
|
72
|
+
domLayout={"autoHeight"}
|
|
76
73
|
/>
|
|
77
74
|
);
|
|
78
75
|
};
|
|
@@ -7,12 +7,14 @@ import { ComponentMeta, ComponentStory } from "@storybook/react/dist/ts3.9/clien
|
|
|
7
7
|
import { GridUpdatingContextProvider } from "../../contexts/GridUpdatingContextProvider";
|
|
8
8
|
import { GridContextProvider } from "../../contexts/GridContextProvider";
|
|
9
9
|
import { Grid, GridProps } from "../../components/Grid";
|
|
10
|
-
import { useMemo, useState } from "react";
|
|
10
|
+
import { useCallback, useMemo, useState } from "react";
|
|
11
11
|
import { ColDefT, GridCell } from "../../components/GridCell";
|
|
12
12
|
import { IFormTestRow } from "./FormTest";
|
|
13
13
|
import { isFloat, wait } from "../../utils/util";
|
|
14
14
|
import { GridPopoverTextArea } from "../../components/gridPopoverEdit/GridPopoverTextArea";
|
|
15
15
|
import { GridPopoverTextInput } from "../../components/gridPopoverEdit/GridPopoverTextInput";
|
|
16
|
+
import { ActionButton } from "../../lui/ActionButton";
|
|
17
|
+
import { GridPopoverMenu } from "../../components/gridPopoverEdit/GridPopoverMenu";
|
|
16
18
|
|
|
17
19
|
export default {
|
|
18
20
|
title: "Components / Grids",
|
|
@@ -23,7 +25,7 @@ export default {
|
|
|
23
25
|
},
|
|
24
26
|
decorators: [
|
|
25
27
|
(Story) => (
|
|
26
|
-
<div style={{ width:
|
|
28
|
+
<div style={{ width: 1024, height: 400 }}>
|
|
27
29
|
<GridUpdatingContextProvider>
|
|
28
30
|
<GridContextProvider>
|
|
29
31
|
<Story />
|
|
@@ -36,6 +38,11 @@ export default {
|
|
|
36
38
|
|
|
37
39
|
const GridPopoutEditGenericTemplate: ComponentStory<typeof Grid> = (props: GridProps) => {
|
|
38
40
|
const [externalSelectedItems, setExternalSelectedItems] = useState<any[]>([]);
|
|
41
|
+
const [rowData, setRowData] = useState([
|
|
42
|
+
{ id: 1000, name: "IS IS DP12345", nameType: "IS", numba: "IX", plan: "DP 12345", distance: 10 },
|
|
43
|
+
{ id: 1001, name: "PEG V SD523", nameType: "PEG", numba: "V", plan: "SD 523", distance: null },
|
|
44
|
+
] as IFormTestRow[]);
|
|
45
|
+
|
|
39
46
|
const columnDefs: ColDefT<IFormTestRow>[] = useMemo(
|
|
40
47
|
() => [
|
|
41
48
|
GridCell({
|
|
@@ -123,27 +130,59 @@ const GridPopoutEditGenericTemplate: ComponentStory<typeof Grid> = (props: GridP
|
|
|
123
130
|
},
|
|
124
131
|
},
|
|
125
132
|
),
|
|
133
|
+
GridPopoverMenu(
|
|
134
|
+
{
|
|
135
|
+
headerName: "Delete menu",
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
multiEdit: true,
|
|
139
|
+
editorParams: {
|
|
140
|
+
options: async (_) => [
|
|
141
|
+
{
|
|
142
|
+
label: "Delete",
|
|
143
|
+
action: async (selectedRows) => {
|
|
144
|
+
await wait(1500);
|
|
145
|
+
setRowData(rowData.filter((data) => !selectedRows.some((row) => row.id == data.id)));
|
|
146
|
+
return true;
|
|
147
|
+
},
|
|
148
|
+
supportsMultiEdit: true,
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
),
|
|
126
154
|
],
|
|
127
|
-
[],
|
|
155
|
+
[rowData],
|
|
128
156
|
);
|
|
129
157
|
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
[]
|
|
137
|
-
|
|
158
|
+
const [inProgress, setInProgress] = useState(false);
|
|
159
|
+
|
|
160
|
+
const addRowAction = useCallback(async () => {
|
|
161
|
+
setInProgress(true);
|
|
162
|
+
await wait(1000);
|
|
163
|
+
const lastRow = rowData[rowData.length - 1];
|
|
164
|
+
setRowData([...rowData, { id: lastRow.id + 1, name: "?", nameType: "?", numba: "?", plan: "", distance: null }]);
|
|
165
|
+
setInProgress(false);
|
|
166
|
+
}, [rowData]);
|
|
138
167
|
|
|
139
168
|
return (
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
169
|
+
<>
|
|
170
|
+
<Grid
|
|
171
|
+
{...props}
|
|
172
|
+
externalSelectedItems={externalSelectedItems}
|
|
173
|
+
setExternalSelectedItems={setExternalSelectedItems}
|
|
174
|
+
columnDefs={columnDefs}
|
|
175
|
+
rowData={rowData}
|
|
176
|
+
domLayout={"autoHeight"}
|
|
177
|
+
/>
|
|
178
|
+
<ActionButton
|
|
179
|
+
icon={"ic_add"}
|
|
180
|
+
name={"Add new row"}
|
|
181
|
+
inProgressName={"Adding..."}
|
|
182
|
+
inProgress={inProgress}
|
|
183
|
+
onClick={addRowAction}
|
|
184
|
+
/>
|
|
185
|
+
</>
|
|
147
186
|
);
|
|
148
187
|
};
|
|
149
188
|
|
|
@@ -24,7 +24,7 @@ export default {
|
|
|
24
24
|
},
|
|
25
25
|
decorators: [
|
|
26
26
|
(Story) => (
|
|
27
|
-
<div style={{ width:
|
|
27
|
+
<div style={{ width: 1024, height: 400 }}>
|
|
28
28
|
<GridUpdatingContextProvider>
|
|
29
29
|
<GridContextProvider>
|
|
30
30
|
<Story />
|
|
@@ -119,14 +119,10 @@ const GridEditMultiSelectTemplate: ComponentStory<typeof Grid> = (props: GridPro
|
|
|
119
119
|
];
|
|
120
120
|
}, []);
|
|
121
121
|
|
|
122
|
-
const rowData =
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
{ id: 1001, position: "Developer", position2: "2", position3: "Developer" },
|
|
127
|
-
] as ITestRow[],
|
|
128
|
-
[],
|
|
129
|
-
);
|
|
122
|
+
const [rowData, setRowData] = useState([
|
|
123
|
+
{ id: 1000, position: "Tester", position2: "1", position3: "Tester" },
|
|
124
|
+
{ id: 1001, position: "Developer", position2: "2", position3: "Developer" },
|
|
125
|
+
] as ITestRow[]);
|
|
130
126
|
|
|
131
127
|
return (
|
|
132
128
|
<Grid
|
|
@@ -135,6 +131,7 @@ const GridEditMultiSelectTemplate: ComponentStory<typeof Grid> = (props: GridPro
|
|
|
135
131
|
setExternalSelectedItems={setExternalSelectedItems}
|
|
136
132
|
columnDefs={columnDefs}
|
|
137
133
|
rowData={rowData}
|
|
134
|
+
domLayout={"autoHeight"}
|
|
138
135
|
/>
|
|
139
136
|
);
|
|
140
137
|
};
|
|
@@ -24,7 +24,7 @@ export default {
|
|
|
24
24
|
},
|
|
25
25
|
decorators: [
|
|
26
26
|
(Story) => (
|
|
27
|
-
<div style={{ width:
|
|
27
|
+
<div style={{ width: 1024, height: 400 }}>
|
|
28
28
|
<GridUpdatingContextProvider>
|
|
29
29
|
<GridContextProvider>
|
|
30
30
|
<Story />
|
|
@@ -151,13 +151,10 @@ const GridReadOnlyTemplate: ComponentStory<typeof Grid> = (props: GridProps) =>
|
|
|
151
151
|
[],
|
|
152
152
|
);
|
|
153
153
|
|
|
154
|
-
const rowData
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
],
|
|
159
|
-
[],
|
|
160
|
-
);
|
|
154
|
+
const [rowData, setRowData] = useState([
|
|
155
|
+
{ id: 1000, position: "Tester", age: 30, desc: "Tests application", dd: "1" },
|
|
156
|
+
{ id: 1001, position: "Developer", age: 12, desc: "Develops application", dd: "2" },
|
|
157
|
+
]);
|
|
161
158
|
|
|
162
159
|
return (
|
|
163
160
|
<Grid
|
|
@@ -166,6 +163,7 @@ const GridReadOnlyTemplate: ComponentStory<typeof Grid> = (props: GridProps) =>
|
|
|
166
163
|
setExternalSelectedItems={setExternalSelectedItems}
|
|
167
164
|
columnDefs={columnDefs}
|
|
168
165
|
rowData={rowData}
|
|
166
|
+
domLayout={"autoHeight"}
|
|
169
167
|
/>
|
|
170
168
|
);
|
|
171
169
|
};
|