@linzjs/step-ag-grid 8.4.2 → 9.0.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 +4 -4
- package/dist/index.css +3 -0
- package/dist/src/components/gridForm/GridFormMultiSelect.d.ts +5 -4
- package/dist/src/lui/TextAreaInput.d.ts +1 -0
- package/dist/src/lui/TextInputFormatted.d.ts +1 -0
- package/dist/src/react-menu3/components/FocusableItem.d.ts +1 -1
- package/dist/src/react-menu3/components/MenuItem.d.ts +3 -1
- package/dist/src/react-menu3/components/SubMenu.d.ts +1 -1
- package/dist/src/react-menu3/utils/withHovering.d.ts +2 -2
- package/dist/src/utils/textMatcher.d.ts +1 -1
- package/dist/src/utils/textMatcher.test.d.ts +1 -0
- package/dist/step-ag-grid.esm.js +502 -735
- package/dist/step-ag-grid.esm.js.map +1 -1
- package/package.json +42 -42
- package/src/components/Grid.tsx +29 -27
- package/src/components/gridForm/GridFormDropDown.tsx +12 -14
- package/src/components/gridForm/GridFormMultiSelect.tsx +31 -29
- package/src/components/gridForm/GridFormPopoverMenu.tsx +18 -22
- package/src/components/gridForm/GridFormSubComponentTextArea.tsx +1 -1
- package/src/components/gridForm/GridFormSubComponentTextInput.tsx +1 -1
- package/src/components/gridForm/GridFormTextArea.tsx +1 -1
- package/src/components/gridForm/GridFormTextInput.tsx +1 -1
- package/src/lui/TextAreaInput.tsx +3 -1
- package/src/lui/TextInputFormatted.tsx +3 -1
- package/src/react-menu3/components/ControlledMenu.tsx +19 -6
- package/src/react-menu3/components/MenuItem.tsx +1 -1
- package/src/react-menu3/utils/withHovering.tsx +3 -3
- package/src/stories/grid/GridKeyboardInteractions.stories.tsx +261 -0
- package/src/stories/grid/{GridPopoutBearing.stories.tsx → GridPopoverEditBearing.stories.tsx} +4 -4
- package/src/stories/grid/{GridPopoutEditDropDown.stories.tsx → GridPopoverEditDropDown.stories.tsx} +10 -2
- package/src/stories/grid/{GridPopoutEditMultiSelect.stories.tsx → GridPopoverEditMultiSelect.stories.tsx} +0 -0
- package/src/stories/grid/gridFormInteraction/GridFormDropDownInteraction.stories.tsx +137 -0
- package/src/stories/grid/gridFormInteraction/GridFormEditBearingCorrectionInteraction.stories.tsx +92 -0
- package/src/stories/grid/gridFormInteraction/GridFormEditBearingInteraction.stories.tsx +91 -0
- package/src/stories/grid/gridFormInteraction/GridFormMultiSelectInteraction.stories.tsx +153 -0
- package/src/stories/grid/gridFormInteraction/GridFormPopoverMenuInteraction.stories.tsx +171 -0
- package/src/stories/grid/gridFormInteraction/GridFormTextAreaInteraction.stories.tsx +78 -0
- package/src/stories/grid/gridFormInteraction/GridFormTextInputInteraction.stories.tsx +85 -0
- package/src/stories/grid/{gridForm → gridFormStatic}/GridFormDropDown.stories.tsx +1 -1
- package/src/stories/grid/{gridForm → gridFormStatic}/GridFormEditBearing.stories.tsx +1 -1
- package/src/stories/grid/{gridForm → gridFormStatic}/GridFormEditBearingCorrection.stories.tsx +1 -1
- package/src/stories/grid/{gridForm → gridFormStatic}/GridFormMessage.stories.tsx +1 -1
- package/src/stories/grid/{gridForm → gridFormStatic}/GridFormMultiSelect.stories.tsx +1 -1
- package/src/stories/grid/{gridForm → gridFormStatic}/GridFormPopoverMenu.stories.tsx +1 -1
- package/src/stories/grid/{gridForm → gridFormStatic}/GridFormTextArea.stories.tsx +1 -1
- package/src/stories/grid/{gridForm → gridFormStatic}/GridFormTextInput.stories.tsx +1 -1
- package/src/stories/react-menu/ReactMenu.stories.tsx +66 -3
- package/src/styles/Grid.scss +3 -0
- package/src/utils/testUtil.ts +1 -0
- package/src/utils/textMatcher.test.ts +38 -0
- package/src/utils/textMatcher.ts +9 -2
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import "@linzjs/lui/dist/scss/base.scss";
|
|
2
|
+
import "@linzjs/lui/dist/fonts";
|
|
3
|
+
import "../../styles/index.scss";
|
|
4
|
+
import "../../styles/GridTheme.scss";
|
|
5
|
+
|
|
6
|
+
import { ComponentMeta, ComponentStory } from "@storybook/react/dist/ts3.9/client/preview/types-6-3";
|
|
7
|
+
import { GridUpdatingContextProvider } from "../../contexts/GridUpdatingContextProvider";
|
|
8
|
+
import { GridContextProvider } from "../../contexts/GridContextProvider";
|
|
9
|
+
import { Grid, GridProps } from "../../components/Grid";
|
|
10
|
+
import { useMemo, useState } from "react";
|
|
11
|
+
import { wait } from "../../utils/util";
|
|
12
|
+
import { GridPopoverMenu } from "../../components/gridPopoverEdit/GridPopoverMenu";
|
|
13
|
+
import { ColDefT, GridCell } from "../../components/GridCell";
|
|
14
|
+
import { GridPopoverMessage } from "../../components/gridPopoverEdit/GridPopoverMessage";
|
|
15
|
+
import { MenuOption } from "../../components/gridForm/GridFormPopoverMenu";
|
|
16
|
+
import { GridFormSubComponentTextInput } from "../../components/gridForm/GridFormSubComponentTextInput";
|
|
17
|
+
import { GridFormSubComponentTextArea } from "../../components/gridForm/GridFormSubComponentTextArea";
|
|
18
|
+
import { GridIcon } from "../../components/GridIcon";
|
|
19
|
+
import { userEvent, waitFor } from "@storybook/testing-library";
|
|
20
|
+
import { expect, jest } from "@storybook/jest";
|
|
21
|
+
|
|
22
|
+
export default {
|
|
23
|
+
title: "Components / Grids",
|
|
24
|
+
component: Grid,
|
|
25
|
+
args: {
|
|
26
|
+
quickFilter: true,
|
|
27
|
+
quickFilterValue: "",
|
|
28
|
+
quickFilterPlaceholder: "Quick filter...",
|
|
29
|
+
selectable: false,
|
|
30
|
+
rowSelection: "single",
|
|
31
|
+
},
|
|
32
|
+
decorators: [
|
|
33
|
+
(Story) => (
|
|
34
|
+
<div style={{ width: 1024, height: 400 }}>
|
|
35
|
+
<GridUpdatingContextProvider>
|
|
36
|
+
<GridContextProvider>
|
|
37
|
+
<Story />
|
|
38
|
+
</GridContextProvider>
|
|
39
|
+
</GridUpdatingContextProvider>
|
|
40
|
+
</div>
|
|
41
|
+
),
|
|
42
|
+
],
|
|
43
|
+
} as ComponentMeta<typeof Grid>;
|
|
44
|
+
|
|
45
|
+
interface ITestRow {
|
|
46
|
+
id: number;
|
|
47
|
+
position: string;
|
|
48
|
+
age: number;
|
|
49
|
+
desc: string;
|
|
50
|
+
dd: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const multiEditAction = jest.fn().mockImplementation(async () => {
|
|
54
|
+
await wait(500);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const eAction = jest.fn<boolean, []>().mockReturnValue(true);
|
|
58
|
+
|
|
59
|
+
const GridKeyboardInteractionsTemplate: ComponentStory<typeof Grid> = (props: GridProps) => {
|
|
60
|
+
const [externalSelectedItems, setExternalSelectedItems] = useState<any[]>([]);
|
|
61
|
+
const columnDefs: ColDefT<ITestRow>[] = useMemo(
|
|
62
|
+
() => [
|
|
63
|
+
GridCell({
|
|
64
|
+
field: "id",
|
|
65
|
+
headerName: "Id",
|
|
66
|
+
initialWidth: 65,
|
|
67
|
+
maxWidth: 85,
|
|
68
|
+
}),
|
|
69
|
+
GridCell({
|
|
70
|
+
field: "position",
|
|
71
|
+
headerName: "Position",
|
|
72
|
+
initialWidth: 65,
|
|
73
|
+
maxWidth: 150,
|
|
74
|
+
cellRendererParams: {
|
|
75
|
+
warning: (props) => props.value === "Tester" && "Testers are testing",
|
|
76
|
+
info: (props) => props.value === "Developer" && "Developers are awesome",
|
|
77
|
+
},
|
|
78
|
+
}),
|
|
79
|
+
GridCell({
|
|
80
|
+
field: "age",
|
|
81
|
+
headerName: "Age",
|
|
82
|
+
initialWidth: 65,
|
|
83
|
+
maxWidth: 85,
|
|
84
|
+
}),
|
|
85
|
+
GridCell({
|
|
86
|
+
field: "desc",
|
|
87
|
+
headerName: "Description",
|
|
88
|
+
initialWidth: 150,
|
|
89
|
+
maxWidth: 200,
|
|
90
|
+
}),
|
|
91
|
+
GridPopoverMessage(
|
|
92
|
+
{
|
|
93
|
+
headerName: "Popout message",
|
|
94
|
+
maxWidth: 150,
|
|
95
|
+
cellRenderer: () => <>Single Click me!</>,
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
multiEdit: true,
|
|
99
|
+
editorParams: {
|
|
100
|
+
message: async (selectedRows): Promise<string> => {
|
|
101
|
+
await wait(1000);
|
|
102
|
+
return `There are ${selectedRows.length} row(s) selected`;
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
),
|
|
107
|
+
GridCell({
|
|
108
|
+
headerName: "Custom edit",
|
|
109
|
+
maxWidth: 100,
|
|
110
|
+
editable: true,
|
|
111
|
+
valueFormatter: () => "Press E",
|
|
112
|
+
cellRendererParams: {
|
|
113
|
+
rightHoverElement: (
|
|
114
|
+
<GridIcon icon={"ic_launch_modal"} title={"Title text"} className={"GridCell-editableIcon"} />
|
|
115
|
+
),
|
|
116
|
+
editAction: () => {
|
|
117
|
+
//
|
|
118
|
+
},
|
|
119
|
+
shortcutKeys: {
|
|
120
|
+
e: eAction,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
}),
|
|
124
|
+
GridPopoverMenu(
|
|
125
|
+
{},
|
|
126
|
+
{
|
|
127
|
+
multiEdit: true,
|
|
128
|
+
editorParams: {
|
|
129
|
+
defaultAction: async ({ menuOption }) => {
|
|
130
|
+
// eslint-disable-next-line no-console
|
|
131
|
+
console.log("clicked", { menuOption });
|
|
132
|
+
},
|
|
133
|
+
options: async (selectedItems) => {
|
|
134
|
+
// Just doing a timeout here to demonstrate deferred loading
|
|
135
|
+
await wait(500);
|
|
136
|
+
return [
|
|
137
|
+
{
|
|
138
|
+
label: "Single edit only",
|
|
139
|
+
action: async () => {
|
|
140
|
+
//
|
|
141
|
+
},
|
|
142
|
+
disabled: selectedItems.length > 1,
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
label: "Multi-edit",
|
|
146
|
+
action: multiEditAction,
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
label: "Disabled item",
|
|
150
|
+
disabled: "Disabled for test",
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
label: "Developer Only",
|
|
154
|
+
hidden: selectedItems.some((x) => x.position != "Developer"),
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
label: "Other (TextInput)",
|
|
158
|
+
action: async () => {
|
|
159
|
+
//
|
|
160
|
+
},
|
|
161
|
+
subComponent: () => (
|
|
162
|
+
<GridFormSubComponentTextInput placeholder={"Other"} maxLength={5} required defaultValue={""} />
|
|
163
|
+
),
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
label: "Other (TextArea)",
|
|
167
|
+
action: async ({ menuOption }) => {
|
|
168
|
+
// eslint-disable-next-line no-console
|
|
169
|
+
console.log(`Sub selected value was ${JSON.stringify(menuOption.subValue)}`);
|
|
170
|
+
await wait(500);
|
|
171
|
+
},
|
|
172
|
+
subComponent: () => (
|
|
173
|
+
<GridFormSubComponentTextArea placeholder={"Other"} maxLength={5} required defaultValue={""} />
|
|
174
|
+
),
|
|
175
|
+
},
|
|
176
|
+
] as MenuOption<ITestRow>[];
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
),
|
|
181
|
+
GridPopoverMenu(
|
|
182
|
+
{
|
|
183
|
+
editable: () => false,
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
editorParams: {
|
|
187
|
+
options: async () => {
|
|
188
|
+
return [];
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
),
|
|
193
|
+
],
|
|
194
|
+
[],
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
const [rowData] = useState([
|
|
198
|
+
{ id: 1000, position: "Tester", age: 30, desc: "Tests application", dd: "1" },
|
|
199
|
+
{ id: 1001, position: "Developer", age: 12, desc: "Develops application", dd: "2" },
|
|
200
|
+
{ id: 1002, position: "Manager", age: 65, desc: "Manages", dd: "3" },
|
|
201
|
+
]);
|
|
202
|
+
|
|
203
|
+
return (
|
|
204
|
+
<Grid
|
|
205
|
+
{...props}
|
|
206
|
+
selectable={true}
|
|
207
|
+
externalSelectedItems={externalSelectedItems}
|
|
208
|
+
setExternalSelectedItems={setExternalSelectedItems}
|
|
209
|
+
columnDefs={columnDefs}
|
|
210
|
+
rowData={rowData}
|
|
211
|
+
domLayout={"autoHeight"}
|
|
212
|
+
autoSelectFirstRow={true}
|
|
213
|
+
/>
|
|
214
|
+
);
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
export const GridKeyboardInteractions = GridKeyboardInteractionsTemplate.bind({});
|
|
218
|
+
GridKeyboardInteractions.play = async ({ canvasElement }) => {
|
|
219
|
+
// Ensure first row/cell is selected on render
|
|
220
|
+
await waitFor(async () => {
|
|
221
|
+
const activeCell = canvasElement.ownerDocument.activeElement;
|
|
222
|
+
expect(activeCell).toHaveClass("ag-cell-focus");
|
|
223
|
+
expect(activeCell).toHaveAttribute("aria-colindex", "1");
|
|
224
|
+
expect(activeCell?.parentElement).toHaveAttribute("row-index", "0");
|
|
225
|
+
});
|
|
226
|
+
userEvent.keyboard("{arrowdown}{arrowdown}");
|
|
227
|
+
userEvent.keyboard("{arrowright}{arrowright}{arrowright}{arrowright}{arrowright}{arrowright}{arrowright}");
|
|
228
|
+
|
|
229
|
+
// Test enter post focus
|
|
230
|
+
const test = async (fn: () => any, colId: string, rowId: string) => {
|
|
231
|
+
userEvent.keyboard("{Enter}");
|
|
232
|
+
await wait(1000);
|
|
233
|
+
userEvent.keyboard("{arrowdown}{arrowdown}");
|
|
234
|
+
fn();
|
|
235
|
+
await waitFor(async () => {
|
|
236
|
+
expect(multiEditAction).toHaveBeenCalled();
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
await waitFor(async () => {
|
|
240
|
+
const activeCell = canvasElement.ownerDocument.activeElement;
|
|
241
|
+
expect(activeCell).toHaveClass("ag-cell-focus");
|
|
242
|
+
expect(activeCell).toHaveAttribute("aria-colindex", colId);
|
|
243
|
+
expect(activeCell?.parentElement).toHaveAttribute("row-index", rowId);
|
|
244
|
+
});
|
|
245
|
+
await wait(1000);
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
await test(() => userEvent.keyboard("{Enter}"), "8", "2");
|
|
249
|
+
await test(() => userEvent.tab(), "9", "2");
|
|
250
|
+
userEvent.tab({ shift: true });
|
|
251
|
+
await test(() => userEvent.tab({ shift: true }), "7", "2");
|
|
252
|
+
|
|
253
|
+
userEvent.keyboard("{Enter}");
|
|
254
|
+
await wait(250);
|
|
255
|
+
expect(eAction).not.toHaveBeenCalled();
|
|
256
|
+
|
|
257
|
+
userEvent.keyboard("e");
|
|
258
|
+
await waitFor(async () => {
|
|
259
|
+
expect(eAction).toHaveBeenCalled();
|
|
260
|
+
});
|
|
261
|
+
};
|
package/src/stories/grid/{GridPopoutBearing.stories.tsx → GridPopoverEditBearing.stories.tsx}
RENAMED
|
@@ -42,7 +42,7 @@ interface ITestRow {
|
|
|
42
42
|
bearing: string | number | null;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
const
|
|
45
|
+
const GridPopoverEditBearingTemplate: ComponentStory<typeof Grid> = (props: GridProps) => {
|
|
46
46
|
const [externalSelectedItems, setExternalSelectedItems] = useState<any[]>([]);
|
|
47
47
|
const columnDefs: ColDefT<ITestRow>[] = useMemo(
|
|
48
48
|
() => [
|
|
@@ -57,8 +57,8 @@ const GridReadOnlyTemplate: ComponentStory<typeof Grid> = (props: GridProps) =>
|
|
|
57
57
|
field: "bearingCorrection",
|
|
58
58
|
headerName: "Bearing correction",
|
|
59
59
|
cellRendererParams: {
|
|
60
|
-
warning: (
|
|
61
|
-
info: (
|
|
60
|
+
warning: ({ data }) => data.id == 1002 && "Testers are testing",
|
|
61
|
+
info: ({ data }) => data.id == 1001 && "Developers are developing",
|
|
62
62
|
},
|
|
63
63
|
},
|
|
64
64
|
{
|
|
@@ -108,4 +108,4 @@ const GridReadOnlyTemplate: ComponentStory<typeof Grid> = (props: GridProps) =>
|
|
|
108
108
|
);
|
|
109
109
|
};
|
|
110
110
|
|
|
111
|
-
export const
|
|
111
|
+
export const _GridPopoverEditBearing = GridPopoverEditBearingTemplate.bind({});
|
package/src/stories/grid/{GridPopoutEditDropDown.stories.tsx → GridPopoverEditDropDown.stories.tsx}
RENAMED
|
@@ -14,6 +14,7 @@ import { ColDefT, GridCell } from "../../components/GridCell";
|
|
|
14
14
|
import { GridPopoverEditDropDown } from "../../components/gridPopoverEdit/GridPopoverEditDropDown";
|
|
15
15
|
import { GridFormSubComponentTextInput } from "../../components/gridForm/GridFormSubComponentTextInput";
|
|
16
16
|
import { GridPopoverMenu } from "../../components/gridPopoverEdit/GridPopoverMenu";
|
|
17
|
+
import { GridFormSubComponentTextArea } from "../../components/gridForm/GridFormSubComponentTextArea";
|
|
17
18
|
|
|
18
19
|
export default {
|
|
19
20
|
title: "Components / Grids",
|
|
@@ -234,9 +235,16 @@ const GridEditDropDownTemplate: ComponentStory<typeof Grid> = (props: GridProps)
|
|
|
234
235
|
},
|
|
235
236
|
{
|
|
236
237
|
value: "oth",
|
|
237
|
-
label: "Other",
|
|
238
|
+
label: "Other text input",
|
|
238
239
|
subComponent: () => (
|
|
239
|
-
<GridFormSubComponentTextInput placeholder={"Other..."} defaultValue={""} required={true} />
|
|
240
|
+
<GridFormSubComponentTextInput placeholder={"Other..."} defaultValue={"a"} required={true} />
|
|
241
|
+
),
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
value: "oth",
|
|
245
|
+
label: "Other text area",
|
|
246
|
+
subComponent: () => (
|
|
247
|
+
<GridFormSubComponentTextArea placeholder={"Other..."} defaultValue={"b"} required={true} />
|
|
240
248
|
),
|
|
241
249
|
},
|
|
242
250
|
];
|
|
File without changes
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import "@linzjs/lui/dist/scss/base.scss";
|
|
2
|
+
import "@linzjs/lui/dist/fonts";
|
|
3
|
+
|
|
4
|
+
import { useRef } from "react";
|
|
5
|
+
import { ComponentMeta, ComponentStory } from "@storybook/react/dist/ts3.9/client/preview/types-6-3";
|
|
6
|
+
import {
|
|
7
|
+
GridFormDropDown,
|
|
8
|
+
GridFormDropDownProps,
|
|
9
|
+
GridPopoutEditDropDownSelectedItem,
|
|
10
|
+
} from "../../../components/gridForm/GridFormDropDown";
|
|
11
|
+
import { GridContextProvider } from "../../../contexts/GridContextProvider";
|
|
12
|
+
import { GridPopoverContext, GridPopoverContextType } from "contexts/GridPopoverContext";
|
|
13
|
+
import { GridFormSubComponentTextInput } from "../../../components/gridForm/GridFormSubComponentTextInput";
|
|
14
|
+
import { userEvent, within } from "@storybook/testing-library";
|
|
15
|
+
import { expect, jest } from "@storybook/jest";
|
|
16
|
+
|
|
17
|
+
export default {
|
|
18
|
+
title: "GridForm / Interactions",
|
|
19
|
+
component: GridFormDropDown,
|
|
20
|
+
args: {},
|
|
21
|
+
} as ComponentMeta<typeof GridFormDropDown>;
|
|
22
|
+
|
|
23
|
+
const updateValue = jest
|
|
24
|
+
.fn<void, [saveFn: (selectedRows: any[]) => Promise<boolean>, _tabDirection: 1 | 0 | -1]>()
|
|
25
|
+
.mockImplementation((saveFn: (selectedRows: any[]) => Promise<boolean>, _tabDirection: 1 | 0 | -1) => saveFn([]));
|
|
26
|
+
|
|
27
|
+
const onSelectedItem = jest
|
|
28
|
+
.fn<Promise<void>, [GridPopoutEditDropDownSelectedItem<any>]>()
|
|
29
|
+
.mockImplementation(async () => undefined);
|
|
30
|
+
|
|
31
|
+
const Template: ComponentStory<typeof GridFormDropDown> = (props) => {
|
|
32
|
+
const config: GridFormDropDownProps<any> = {
|
|
33
|
+
filtered: "local",
|
|
34
|
+
onSelectedItem,
|
|
35
|
+
options: [
|
|
36
|
+
{ label: "Enabled", value: 1 },
|
|
37
|
+
{ label: "Disabled", value: 0, disabled: true },
|
|
38
|
+
{
|
|
39
|
+
label: "Sub menu",
|
|
40
|
+
value: 0,
|
|
41
|
+
subComponent: () => (
|
|
42
|
+
<GridFormSubComponentTextInput placeholder={"Text input"} maxLength={5} required defaultValue={""} />
|
|
43
|
+
),
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
};
|
|
47
|
+
const anchorRef = useRef<HTMLHeadingElement>(null);
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<div className={"react-menu-inline-test"}>
|
|
51
|
+
<GridContextProvider>
|
|
52
|
+
<div>
|
|
53
|
+
<h6 ref={anchorRef}>Interaction test</h6>
|
|
54
|
+
<GridPopoverContext.Provider
|
|
55
|
+
value={
|
|
56
|
+
{
|
|
57
|
+
anchorRef: anchorRef,
|
|
58
|
+
updateValue,
|
|
59
|
+
data: { value: "" },
|
|
60
|
+
value: "",
|
|
61
|
+
field: "value",
|
|
62
|
+
selectedRows: [],
|
|
63
|
+
} as any as GridPopoverContextType<any>
|
|
64
|
+
}
|
|
65
|
+
>
|
|
66
|
+
<GridFormDropDown {...props} {...config} />
|
|
67
|
+
</GridPopoverContext.Provider>
|
|
68
|
+
</div>
|
|
69
|
+
</GridContextProvider>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const GridFormDropDownInteractions_ = Template.bind({});
|
|
75
|
+
GridFormDropDownInteractions_.play = async ({ canvasElement }) => {
|
|
76
|
+
const canvas = within(canvasElement);
|
|
77
|
+
|
|
78
|
+
const getOption = (name: string) => canvas.findByRole("menuitem", { name });
|
|
79
|
+
|
|
80
|
+
// Check enabled menu handles click
|
|
81
|
+
const enabledMenuOption = await getOption("Enabled");
|
|
82
|
+
expect(enabledMenuOption).toBeInTheDocument();
|
|
83
|
+
|
|
84
|
+
userEvent.click(enabledMenuOption);
|
|
85
|
+
expect(updateValue).toHaveBeenCalled();
|
|
86
|
+
expect(onSelectedItem).toHaveBeenCalled();
|
|
87
|
+
|
|
88
|
+
// Check disabled menu ignores click
|
|
89
|
+
updateValue.mockClear();
|
|
90
|
+
onSelectedItem.mockClear();
|
|
91
|
+
const disabledMenuOption = await getOption("Disabled");
|
|
92
|
+
userEvent.click(disabledMenuOption);
|
|
93
|
+
expect(updateValue).not.toHaveBeenCalled();
|
|
94
|
+
expect(onSelectedItem).not.toHaveBeenCalled();
|
|
95
|
+
|
|
96
|
+
// Check sub menu works
|
|
97
|
+
const subTextInput = await getOption("Sub menu...");
|
|
98
|
+
expect(subTextInput).toBeInTheDocument();
|
|
99
|
+
|
|
100
|
+
expect(canvas.queryByPlaceholderText("Text input")).not.toBeInTheDocument();
|
|
101
|
+
|
|
102
|
+
userEvent.click(subTextInput);
|
|
103
|
+
const textInput = await canvas.findByPlaceholderText("Text input");
|
|
104
|
+
expect(textInput).toBeInTheDocument();
|
|
105
|
+
expect(await canvas.findByText("Must not be empty")).toBeInTheDocument();
|
|
106
|
+
|
|
107
|
+
userEvent.type(textInput, "Hello");
|
|
108
|
+
expect(await canvas.findByText("Press enter or tab to save")).toBeInTheDocument();
|
|
109
|
+
|
|
110
|
+
// Test tab to save
|
|
111
|
+
updateValue.mockClear();
|
|
112
|
+
userEvent.tab();
|
|
113
|
+
expect(updateValue).toHaveBeenCalledWith(expect.anything(), 1); // 1 = Tab
|
|
114
|
+
|
|
115
|
+
// Test shift+tab to save
|
|
116
|
+
updateValue.mockClear();
|
|
117
|
+
userEvent.tab({ shift: true });
|
|
118
|
+
expect(updateValue).toHaveBeenCalledWith(expect.anything(), -1); // -1 = Shift + tab
|
|
119
|
+
|
|
120
|
+
// Test escape to not save
|
|
121
|
+
updateValue.mockClear();
|
|
122
|
+
userEvent.type(textInput, "{Escape}");
|
|
123
|
+
expect(updateValue).not.toHaveBeenCalled();
|
|
124
|
+
|
|
125
|
+
// Test invalid value doesn't save
|
|
126
|
+
updateValue.mockClear();
|
|
127
|
+
userEvent.clear(textInput);
|
|
128
|
+
userEvent.type(textInput, "{Enter}");
|
|
129
|
+
expect(updateValue).not.toHaveBeenCalled();
|
|
130
|
+
|
|
131
|
+
// Test filter
|
|
132
|
+
const filterText = await canvas.findByPlaceholderText("Filter...");
|
|
133
|
+
userEvent.type(filterText, "ena");
|
|
134
|
+
expect(canvas.queryByText("Enabled")).toBeInTheDocument();
|
|
135
|
+
expect(canvas.queryByText("Disabled")).not.toBeInTheDocument();
|
|
136
|
+
expect(canvas.queryByText("Sub menu...")).not.toBeInTheDocument();
|
|
137
|
+
};
|
package/src/stories/grid/gridFormInteraction/GridFormEditBearingCorrectionInteraction.stories.tsx
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
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 { GridFormEditBearing } from "../../../components/gridForm/GridFormEditBearing";
|
|
6
|
+
import { GridContextProvider } from "../../../contexts/GridContextProvider";
|
|
7
|
+
import { GridPopoverContext, GridPopoverContextType } from "contexts/GridPopoverContext";
|
|
8
|
+
import { useRef } from "react";
|
|
9
|
+
import { GridPopoverEditBearingCorrectionEditorParams } from "../../../components/gridPopoverEdit/GridPopoverEditBearing";
|
|
10
|
+
import { userEvent, within } from "@storybook/testing-library";
|
|
11
|
+
import { expect, jest } from "@storybook/jest";
|
|
12
|
+
|
|
13
|
+
export default {
|
|
14
|
+
title: "GridForm / Interactions",
|
|
15
|
+
component: GridFormEditBearing,
|
|
16
|
+
args: {},
|
|
17
|
+
} as ComponentMeta<typeof GridFormEditBearing>;
|
|
18
|
+
|
|
19
|
+
const updateValue = jest.fn();
|
|
20
|
+
|
|
21
|
+
const Template: ComponentStory<typeof GridFormEditBearing> = (props) => {
|
|
22
|
+
const anchorRef = useRef<HTMLHeadingElement>(null);
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div className={"react-menu-inline-test"}>
|
|
26
|
+
<GridContextProvider>
|
|
27
|
+
<h6 ref={anchorRef}>Interaction Test</h6>
|
|
28
|
+
<GridPopoverContext.Provider
|
|
29
|
+
value={
|
|
30
|
+
{
|
|
31
|
+
anchorRef,
|
|
32
|
+
value: null,
|
|
33
|
+
updateValue,
|
|
34
|
+
} as any as GridPopoverContextType<any>
|
|
35
|
+
}
|
|
36
|
+
>
|
|
37
|
+
<GridFormEditBearing {...props} {...GridPopoverEditBearingCorrectionEditorParams} />
|
|
38
|
+
</GridPopoverContext.Provider>
|
|
39
|
+
</GridContextProvider>
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const GridFormEditBearingCorrectionInteractions_ = Template.bind({});
|
|
45
|
+
GridFormEditBearingCorrectionInteractions_.play = async ({ canvasElement }) => {
|
|
46
|
+
const canvas = within(canvasElement);
|
|
47
|
+
|
|
48
|
+
expect(await canvas.findByText("Press enter or tab to save")).toBeInTheDocument();
|
|
49
|
+
|
|
50
|
+
const inputField = canvas.getByPlaceholderText("Enter bearing correction");
|
|
51
|
+
|
|
52
|
+
// Test formatting null
|
|
53
|
+
expect(await canvas.findByText("–")).toBeInTheDocument();
|
|
54
|
+
|
|
55
|
+
// Test formatting a bearing
|
|
56
|
+
expect(inputField).toBeInTheDocument();
|
|
57
|
+
userEvent.type(inputField, "1.2345");
|
|
58
|
+
expect(await canvas.findByText("+1° 23' 45.0\"")).toBeInTheDocument();
|
|
59
|
+
|
|
60
|
+
// Test enter to save
|
|
61
|
+
updateValue.mockClear();
|
|
62
|
+
userEvent.type(inputField, "{Enter}");
|
|
63
|
+
expect(updateValue).toHaveBeenCalledWith(expect.anything(), 0); // 0 = Enter
|
|
64
|
+
|
|
65
|
+
// Test tab to save
|
|
66
|
+
updateValue.mockClear();
|
|
67
|
+
userEvent.tab();
|
|
68
|
+
expect(updateValue).toHaveBeenCalledWith(expect.anything(), 1); // 1 = Tab
|
|
69
|
+
|
|
70
|
+
// Test shift+tab to save
|
|
71
|
+
updateValue.mockClear();
|
|
72
|
+
userEvent.tab({ shift: true });
|
|
73
|
+
expect(updateValue).toHaveBeenCalledWith(expect.anything(), -1); // -1 = Shift + tab
|
|
74
|
+
|
|
75
|
+
// Test escape not to save
|
|
76
|
+
updateValue.mockClear();
|
|
77
|
+
userEvent.type(inputField, "{Escape}");
|
|
78
|
+
expect(updateValue).not.toHaveBeenCalled();
|
|
79
|
+
|
|
80
|
+
// Test invalid value doesn't save
|
|
81
|
+
updateValue.mockClear();
|
|
82
|
+
userEvent.type(inputField, "xxx");
|
|
83
|
+
expect(await canvas.findByText("?")).toBeInTheDocument();
|
|
84
|
+
|
|
85
|
+
expect(canvas.getByText("Bearing must be a number in D.MMSSS format")).toBeInTheDocument();
|
|
86
|
+
userEvent.type(inputField, "{Enter}");
|
|
87
|
+
expect(updateValue).not.toHaveBeenCalled();
|
|
88
|
+
userEvent.tab();
|
|
89
|
+
expect(updateValue).not.toHaveBeenCalled();
|
|
90
|
+
userEvent.tab({ shift: true });
|
|
91
|
+
expect(updateValue).not.toHaveBeenCalled();
|
|
92
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
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 { GridFormEditBearing } from "../../../components/gridForm/GridFormEditBearing";
|
|
6
|
+
import { GridContextProvider } from "../../../contexts/GridContextProvider";
|
|
7
|
+
import { GridPopoverContext, GridPopoverContextType } from "contexts/GridPopoverContext";
|
|
8
|
+
import { useRef } from "react";
|
|
9
|
+
import { GridPopoverEditBearingEditorParams } from "../../../components/gridPopoverEdit/GridPopoverEditBearing";
|
|
10
|
+
import { userEvent, within } from "@storybook/testing-library";
|
|
11
|
+
import { expect, jest } from "@storybook/jest";
|
|
12
|
+
|
|
13
|
+
export default {
|
|
14
|
+
title: "GridForm / Interactions",
|
|
15
|
+
component: GridFormEditBearing,
|
|
16
|
+
args: {},
|
|
17
|
+
} as ComponentMeta<typeof GridFormEditBearing>;
|
|
18
|
+
|
|
19
|
+
const updateValue = jest.fn();
|
|
20
|
+
|
|
21
|
+
const Template: ComponentStory<typeof GridFormEditBearing> = (props) => {
|
|
22
|
+
const anchorRef = useRef<HTMLHeadingElement>(null);
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div className={"react-menu-inline-test"}>
|
|
26
|
+
<GridContextProvider>
|
|
27
|
+
<h6 ref={anchorRef}>Interaction Test</h6>
|
|
28
|
+
<GridPopoverContext.Provider
|
|
29
|
+
value={
|
|
30
|
+
{
|
|
31
|
+
anchorRef,
|
|
32
|
+
value: null,
|
|
33
|
+
updateValue,
|
|
34
|
+
} as any as GridPopoverContextType<any>
|
|
35
|
+
}
|
|
36
|
+
>
|
|
37
|
+
<GridFormEditBearing {...props} {...GridPopoverEditBearingEditorParams} />
|
|
38
|
+
</GridPopoverContext.Provider>
|
|
39
|
+
</GridContextProvider>
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const GridFormEditBearingInteractions_ = Template.bind({});
|
|
45
|
+
GridFormEditBearingInteractions_.play = async ({ canvasElement }) => {
|
|
46
|
+
const canvas = within(canvasElement);
|
|
47
|
+
|
|
48
|
+
expect(await canvas.findByText("Press enter or tab to save")).toBeInTheDocument();
|
|
49
|
+
|
|
50
|
+
const inputField = canvas.getByPlaceholderText("Enter bearing");
|
|
51
|
+
|
|
52
|
+
// Test formatting null
|
|
53
|
+
expect(await canvas.findByText("–")).toBeInTheDocument();
|
|
54
|
+
|
|
55
|
+
// Test formatting a bearing
|
|
56
|
+
expect(inputField).toBeInTheDocument();
|
|
57
|
+
userEvent.type(inputField, "1.2345");
|
|
58
|
+
expect(await canvas.findByText("1° 23' 45\"")).toBeInTheDocument();
|
|
59
|
+
|
|
60
|
+
// Test enter to save
|
|
61
|
+
updateValue.mockClear();
|
|
62
|
+
userEvent.type(inputField, "{Enter}");
|
|
63
|
+
expect(updateValue).toHaveBeenCalledWith(expect.anything(), 0); // 0 = Enter
|
|
64
|
+
|
|
65
|
+
// Test tab to save
|
|
66
|
+
updateValue.mockClear();
|
|
67
|
+
userEvent.tab();
|
|
68
|
+
expect(updateValue).toHaveBeenCalledWith(expect.anything(), 1); // 1 = Tab
|
|
69
|
+
|
|
70
|
+
// Test shift+tab to save
|
|
71
|
+
updateValue.mockClear();
|
|
72
|
+
userEvent.tab({ shift: true });
|
|
73
|
+
expect(updateValue).toHaveBeenCalledWith(expect.anything(), -1); // -1 = Shift + tab
|
|
74
|
+
|
|
75
|
+
// Test escape not to save
|
|
76
|
+
updateValue.mockClear();
|
|
77
|
+
userEvent.type(inputField, "{Escape}");
|
|
78
|
+
expect(updateValue).not.toHaveBeenCalled();
|
|
79
|
+
|
|
80
|
+
// Test invalid value doesn't save
|
|
81
|
+
updateValue.mockClear();
|
|
82
|
+
userEvent.type(inputField, "xxx");
|
|
83
|
+
expect(await canvas.findByText("?")).toBeInTheDocument();
|
|
84
|
+
expect(canvas.getByText("Bearing must be a number in D.MMSSS format")).toBeInTheDocument();
|
|
85
|
+
userEvent.type(inputField, "{Enter}");
|
|
86
|
+
expect(updateValue).not.toHaveBeenCalled();
|
|
87
|
+
userEvent.tab();
|
|
88
|
+
expect(updateValue).not.toHaveBeenCalled();
|
|
89
|
+
userEvent.tab({ shift: true });
|
|
90
|
+
expect(updateValue).not.toHaveBeenCalled();
|
|
91
|
+
};
|