@linzjs/step-ag-grid 8.4.3 → 10.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/GridCell.d.ts +1 -1
- package/dist/src/components/gridForm/GridFormMultiSelect.d.ts +5 -4
- 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 +58858 -1100
- package/dist/step-ag-grid.esm.js.map +1 -1
- package/package.json +45 -47
- package/src/components/Grid.tsx +29 -27
- package/src/components/GridCell.tsx +1 -1
- package/src/components/gridForm/GridFormDropDown.tsx +2 -2
- package/src/components/gridForm/GridFormMultiSelect.tsx +12 -6
- package/src/components/gridForm/GridFormSubComponentTextArea.tsx +0 -1
- package/src/components/gridForm/GridFormSubComponentTextInput.tsx +0 -1
- package/src/lui/TextAreaInput.tsx +1 -1
- package/src/lui/TextInputFormatted.tsx +1 -1
- package/src/react-menu3/components/ControlledMenu.tsx +19 -6
- package/src/react-menu3/hooks/useMenuState.ts +1 -1
- 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} +0 -0
- package/src/stories/grid/{GridPopoutEditMultiSelect.stories.tsx → GridPopoverEditMultiSelect.stories.tsx} +0 -0
- package/src/stories/grid/gridFormInteraction/GridFormDropDownInteraction.stories.tsx +10 -1
- package/src/stories/grid/gridFormInteraction/GridFormEditBearingCorrectionInteraction.stories.tsx +1 -1
- package/src/stories/grid/gridFormInteraction/GridFormEditBearingInteraction.stories.tsx +1 -1
- package/src/stories/grid/gridFormInteraction/GridFormMultiSelectInteraction.stories.tsx +153 -0
- package/src/stories/grid/gridFormInteraction/GridFormPopoverMenuInteraction.stories.tsx +1 -1
- package/src/stories/grid/gridFormInteraction/GridFormTextAreaInteraction.stories.tsx +1 -1
- package/src/stories/grid/gridFormInteraction/GridFormTextInputInteraction.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
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": "
|
|
5
|
+
"version": "10.0.0",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"aggrid",
|
|
8
8
|
"ag-grid",
|
|
@@ -28,22 +28,20 @@
|
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
30
|
"@linzjs/lui": ">=17",
|
|
31
|
-
"ag-grid-community": ">=27",
|
|
32
|
-
"ag-grid-react": ">=27",
|
|
33
31
|
"lodash-es": ">=4",
|
|
34
32
|
"react": ">=17",
|
|
35
33
|
"react-dom": ">=17"
|
|
36
34
|
},
|
|
37
35
|
"dependencies": {
|
|
38
36
|
"@linzjs/lui": ">=17",
|
|
39
|
-
"ag-grid-community": "
|
|
40
|
-
"ag-grid-react": "
|
|
37
|
+
"ag-grid-community": "^28.2.1",
|
|
38
|
+
"ag-grid-react": "^28.2.1",
|
|
41
39
|
"debounce-promise": "^3.1.2",
|
|
42
40
|
"lodash-es": ">=4",
|
|
43
41
|
"matcher": "^5.0.0",
|
|
44
42
|
"react": ">=17",
|
|
45
43
|
"react-dom": ">=17",
|
|
46
|
-
"react-transition-state": "^
|
|
44
|
+
"react-transition-state": "^2.0.2",
|
|
47
45
|
"uuid": "^9.0.0"
|
|
48
46
|
},
|
|
49
47
|
"scripts": {
|
|
@@ -81,76 +79,76 @@
|
|
|
81
79
|
]
|
|
82
80
|
},
|
|
83
81
|
"devDependencies": {
|
|
84
|
-
"@rollup/plugin-commonjs": "^
|
|
85
|
-
"@rollup/plugin-json": "^
|
|
82
|
+
"@rollup/plugin-commonjs": "^24.0.1",
|
|
83
|
+
"@rollup/plugin-json": "^6.0.0",
|
|
86
84
|
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
87
|
-
"@semantic-release/changelog": "^6.0.
|
|
85
|
+
"@semantic-release/changelog": "^6.0.2",
|
|
88
86
|
"@semantic-release/git": "^10.0.1",
|
|
89
|
-
"@storybook/addon-
|
|
90
|
-
"@storybook/addon-essentials": "^6.5.
|
|
91
|
-
"@storybook/
|
|
92
|
-
"@storybook/addon-links": "^6.5.13",
|
|
87
|
+
"@storybook/addon-interactions": "^6.5.16",
|
|
88
|
+
"@storybook/addon-essentials": "^6.5.16",
|
|
89
|
+
"@storybook/builder-webpack5": "^6.5.16",
|
|
93
90
|
"@storybook/jest": "^0.0.10",
|
|
94
|
-
"@storybook/
|
|
95
|
-
"@storybook/
|
|
91
|
+
"@storybook/manager-webpack5": "^6.5.16",
|
|
92
|
+
"@storybook/preset-create-react-app": "^4.1.2",
|
|
93
|
+
"@storybook/react": "^6.5.16",
|
|
94
|
+
"@storybook/test-runner": "^0.9.4",
|
|
96
95
|
"@storybook/testing-library": "^0.0.13",
|
|
97
|
-
"@testing-library/dom": "^8.
|
|
96
|
+
"@testing-library/dom": "^8.20.0",
|
|
98
97
|
"@testing-library/jest-dom": "^5.16.5",
|
|
99
98
|
"@testing-library/react": "^12.1.5",
|
|
100
99
|
"@testing-library/user-event": "^13.5.0",
|
|
101
|
-
"@types/debounce-promise": "^3.1.
|
|
102
|
-
"@types/jest": "^29.
|
|
100
|
+
"@types/debounce-promise": "^3.1.6",
|
|
101
|
+
"@types/jest": "^29.4.0",
|
|
103
102
|
"@types/lodash-es": "^4.17.6",
|
|
104
|
-
"@types/node": "^18.
|
|
105
|
-
"@types/react": "^17.0.
|
|
103
|
+
"@types/node": "^18.13.0",
|
|
104
|
+
"@types/react": "^17.0.53",
|
|
106
105
|
"@types/react-dom": "^17.0.18",
|
|
107
|
-
"@types/uuid": "^
|
|
108
|
-
"@typescript-eslint/parser": "^5.
|
|
109
|
-
"babel-jest": "^29.
|
|
106
|
+
"@types/uuid": "^9.0.0",
|
|
107
|
+
"@typescript-eslint/parser": "^5.51.0",
|
|
108
|
+
"babel-jest": "^29.4.2",
|
|
110
109
|
"babel-preset-react-app": "^10.0.1",
|
|
111
|
-
"chromatic": "^6.
|
|
110
|
+
"chromatic": "^6.17.0",
|
|
112
111
|
"conventional-changelog-conventionalcommits": "^5.0.0",
|
|
113
|
-
"eslint": "^8.
|
|
114
|
-
"eslint-config-prettier": "^8.
|
|
112
|
+
"eslint": "^8.33.0",
|
|
113
|
+
"eslint-config-prettier": "^8.6.0",
|
|
115
114
|
"eslint-config-react-app": "^7.0.1",
|
|
116
|
-
"eslint-plugin-deprecation": "^1.3.
|
|
117
|
-
"eslint-plugin-import": "^2.
|
|
118
|
-
"eslint-plugin-jest": "^27.1
|
|
119
|
-
"eslint-plugin-jsx-a11y": "^6.
|
|
115
|
+
"eslint-plugin-deprecation": "^1.3.3",
|
|
116
|
+
"eslint-plugin-import": "^2.27.5",
|
|
117
|
+
"eslint-plugin-jest": "^27.2.1",
|
|
118
|
+
"eslint-plugin-jsx-a11y": "^6.7.1",
|
|
120
119
|
"eslint-plugin-prettier": "^4.2.1",
|
|
121
|
-
"eslint-plugin-react": "^7.
|
|
120
|
+
"eslint-plugin-react": "^7.32.2",
|
|
122
121
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
123
|
-
"eslint-plugin-testing-library": "^5.
|
|
124
|
-
"jest": "^29.
|
|
122
|
+
"eslint-plugin-testing-library": "^5.10.1",
|
|
123
|
+
"jest": "^29.4.2",
|
|
125
124
|
"jest-canvas-mock": "^2.4.0",
|
|
126
|
-
"jest-environment-jsdom": "^29.
|
|
125
|
+
"jest-environment-jsdom": "^29.4.2",
|
|
127
126
|
"jest-expect-message": "^1.1.3",
|
|
128
|
-
"mkdirp": "^1.
|
|
127
|
+
"mkdirp": "^2.1.3",
|
|
129
128
|
"npm-run-all": "^4.1.5",
|
|
130
|
-
"postcss": "^8.4.
|
|
131
|
-
"postcss-loader": "^7.0.
|
|
132
|
-
"postcss-scss": "^4.0.
|
|
133
|
-
"prettier": "^2.
|
|
129
|
+
"postcss": "^8.4.21",
|
|
130
|
+
"postcss-loader": "^7.0.2",
|
|
131
|
+
"postcss-scss": "^4.0.6",
|
|
132
|
+
"prettier": "^2.8.4",
|
|
134
133
|
"react-app-polyfill": "^3.0.0",
|
|
135
134
|
"react-scripts": "^5.0.1",
|
|
136
|
-
"rollup": "^3.
|
|
135
|
+
"rollup": "^3.14.0",
|
|
137
136
|
"rollup-plugin-copy": "^3.4.0",
|
|
138
137
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
139
138
|
"rollup-plugin-postcss": "^4.0.2",
|
|
140
139
|
"rollup-plugin-typescript2": "^0.34.1",
|
|
141
|
-
"sass": "^1.
|
|
142
|
-
"sass-loader": "
|
|
140
|
+
"sass": "^1.58.0",
|
|
141
|
+
"sass-loader": "^13.2.0",
|
|
143
142
|
"semantic-release": "^19.0.5",
|
|
144
|
-
"
|
|
145
|
-
"
|
|
146
|
-
"stylelint": "^
|
|
147
|
-
"stylelint-config-prettier": "^9.0.3",
|
|
143
|
+
"style-loader": "^3.3.1",
|
|
144
|
+
"stylelint": "^14.16.1",
|
|
145
|
+
"stylelint-config-prettier": "^9.0.4",
|
|
148
146
|
"stylelint-config-recommended-scss": "^8.0.0",
|
|
149
147
|
"stylelint-config-standard": "^29.0.0",
|
|
150
148
|
"stylelint-prettier": "^2.0.0",
|
|
151
149
|
"stylelint-scss": "^4.3.0",
|
|
152
150
|
"tsconfig-paths-webpack-plugin": "^4.0.0",
|
|
153
|
-
"typescript": "^4.
|
|
151
|
+
"typescript": "^4.9.5"
|
|
154
152
|
},
|
|
155
153
|
"babel": {
|
|
156
154
|
"presets": [
|
package/src/components/Grid.tsx
CHANGED
|
@@ -340,33 +340,35 @@ export const Grid = (params: GridProps): JSX.Element => {
|
|
|
340
340
|
/>
|
|
341
341
|
</div>
|
|
342
342
|
)}
|
|
343
|
-
<
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
343
|
+
<div style={{ flex: 1 }}>
|
|
344
|
+
<AgGridReact
|
|
345
|
+
animateRows={params.animateRows}
|
|
346
|
+
rowClassRules={params.rowClassRules}
|
|
347
|
+
defaultColDef={params.defaultColDef}
|
|
348
|
+
getRowId={(params) => `${params.data.id}`}
|
|
349
|
+
suppressRowClickSelection={true}
|
|
350
|
+
rowSelection={params.rowSelection ?? "multiple"}
|
|
351
|
+
suppressBrowserResizeObserver={true}
|
|
352
|
+
colResizeDefault={"shift"}
|
|
353
|
+
onFirstDataRendered={sizeColumnsToFit}
|
|
354
|
+
onGridSizeChanged={sizeColumnsToFit}
|
|
355
|
+
suppressClickEdit={true}
|
|
356
|
+
onCellKeyPress={onCellKeyPress}
|
|
357
|
+
onCellClicked={onCellClicked}
|
|
358
|
+
onCellDoubleClicked={onCellDoubleClick}
|
|
359
|
+
onCellEditingStarted={refreshSelectedRows}
|
|
360
|
+
domLayout={params.domLayout}
|
|
361
|
+
columnDefs={columnDefs}
|
|
362
|
+
rowData={params.rowData}
|
|
363
|
+
noRowsOverlayComponent={noRowsOverlayComponent}
|
|
364
|
+
onGridReady={onGridReady}
|
|
365
|
+
onSortChanged={ensureSelectedRowIsVisible}
|
|
366
|
+
postSortRows={params.postSortRows ?? postSortRows}
|
|
367
|
+
onSelectionChanged={synchroniseExternalStateToGridSelection}
|
|
368
|
+
onColumnMoved={params.onColumnMoved}
|
|
369
|
+
alwaysShowVerticalScroll={params.alwaysShowVerticalScroll}
|
|
370
|
+
/>
|
|
371
|
+
</div>
|
|
370
372
|
</div>
|
|
371
373
|
);
|
|
372
374
|
};
|
|
@@ -44,7 +44,7 @@ export const GridCellRenderer = (props: ICellRendererParams) => {
|
|
|
44
44
|
{colDef.cellRendererParams?.originalCellRenderer ? (
|
|
45
45
|
<colDef.cellRendererParams.originalCellRenderer {...props} />
|
|
46
46
|
) : (
|
|
47
|
-
<span title={props.valueFormatted}>{props.valueFormatted}</span>
|
|
47
|
+
<span title={props.valueFormatted ?? undefined}>{props.valueFormatted}</span>
|
|
48
48
|
)}
|
|
49
49
|
</div>
|
|
50
50
|
{fnOrVar(colDef.editable, props) && rendererParams?.rightHoverElement && (
|
|
@@ -11,6 +11,7 @@ import { GridSubComponentContext } from "../../contexts/GridSubComponentContext"
|
|
|
11
11
|
import { ClickEvent } from "../../react-menu3/types";
|
|
12
12
|
import { FormError } from "../../lui/FormError";
|
|
13
13
|
import { isNotEmpty } from "../../utils/util";
|
|
14
|
+
import { textMatch } from "../../utils/textMatcher";
|
|
14
15
|
|
|
15
16
|
export interface GridPopoutEditDropDownSelectedItem<RowType> {
|
|
16
17
|
// Note the row that was clicked on will be first
|
|
@@ -136,8 +137,7 @@ export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormDro
|
|
|
136
137
|
console.error("Cannot filter non-string labels", option);
|
|
137
138
|
return undefined;
|
|
138
139
|
}
|
|
139
|
-
|
|
140
|
-
return str.toLowerCase().indexOf(filter.toLowerCase()) !== -1 ? option : undefined;
|
|
140
|
+
return textMatch((option.label as string) || "", filter) ? option : undefined;
|
|
141
141
|
})
|
|
142
142
|
.filter((r) => r !== undefined),
|
|
143
143
|
);
|
|
@@ -41,6 +41,11 @@ export interface GridFormMultiSelectGroup {
|
|
|
41
41
|
filter?: string;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
export interface GridFormMultiSelectSaveProps<RowType extends GridBaseRow> {
|
|
45
|
+
selectedRows: RowType[];
|
|
46
|
+
selectedOptions: MultiSelectOption[];
|
|
47
|
+
}
|
|
48
|
+
|
|
44
49
|
export interface GridFormMultiSelectProps<RowType extends GridBaseRow> extends CellEditorCommon {
|
|
45
50
|
className?:
|
|
46
51
|
| "GridMultiSelect-containerSmall"
|
|
@@ -54,7 +59,7 @@ export interface GridFormMultiSelectProps<RowType extends GridBaseRow> extends C
|
|
|
54
59
|
filterHelpText?: string | ((filter: string, options: MultiSelectOption[]) => string | undefined);
|
|
55
60
|
noOptionsMessage?: string;
|
|
56
61
|
onSelectFilter?: (props: { filter: string; options: MultiSelectOption[] }) => void;
|
|
57
|
-
onSave?: (props:
|
|
62
|
+
onSave?: (props: GridFormMultiSelectSaveProps<RowType>) => Promise<boolean>;
|
|
58
63
|
headers?: GridFormMultiSelectGroup[];
|
|
59
64
|
options: MultiSelectOption[] | ((selectedRows: RowType[]) => Promise<MultiSelectOption[]> | MultiSelectOption[]);
|
|
60
65
|
invalid?: (selectedRows: RowType[], selectedOptions: MultiSelectOption[]) => boolean;
|
|
@@ -164,11 +169,12 @@ export const GridFormMultiSelect = <RowType extends GridBaseRow>(props: GridForm
|
|
|
164
169
|
filterPlaceholder={props.filterPlaceholder}
|
|
165
170
|
/>
|
|
166
171
|
)}
|
|
167
|
-
{headerGroups &&
|
|
168
|
-
|
|
169
|
-
{
|
|
170
|
-
|
|
171
|
-
|
|
172
|
+
{headerGroups &&
|
|
173
|
+
(isEmpty(headerGroups) || !toPairs(headerGroups).some(([_, options]) => !isEmpty(options))) && (
|
|
174
|
+
<MenuItem key={"noOptions"} className={"GridMultiSelect-noOptions"} disabled={true}>
|
|
175
|
+
{props.noOptionsMessage ?? "No Options"}
|
|
176
|
+
</MenuItem>
|
|
177
|
+
)}
|
|
172
178
|
{headerGroups && !isEmpty(headerGroups) && (
|
|
173
179
|
<div className={"GridFormMultiSelect-options"}>
|
|
174
180
|
{headers.map((header, index) => {
|
|
@@ -38,7 +38,6 @@ export const GridFormSubComponentTextInput = <RowType extends GridBaseRow>(
|
|
|
38
38
|
error={invalid()}
|
|
39
39
|
onChange={(e) => setValue(e.target.value)}
|
|
40
40
|
helpText={helpText}
|
|
41
|
-
autoFocus={true}
|
|
42
41
|
placeholder={props.placeholder}
|
|
43
42
|
style={{ width: "100%" }}
|
|
44
43
|
allowTabToSave={true}
|
|
@@ -40,7 +40,7 @@ export const TextAreaInput = (props: LuiTextAreaInputProps) => {
|
|
|
40
40
|
{/* wrapper div used for error styling */}
|
|
41
41
|
<textarea
|
|
42
42
|
rows={5}
|
|
43
|
-
{...omit(props, ["error", "value", "helpText", "formatted", "className"])}
|
|
43
|
+
{...omit(props, ["error", "value", "helpText", "formatted", "className", "allowTabToSave"])}
|
|
44
44
|
id={id}
|
|
45
45
|
value={props.value ?? ""}
|
|
46
46
|
spellCheck={true}
|
|
@@ -26,7 +26,7 @@ export const TextInputFormatted = (props: LuiTextInputProps): JSX.Element => {
|
|
|
26
26
|
type={"text"}
|
|
27
27
|
spellCheck={true}
|
|
28
28
|
defaultValue={props.value}
|
|
29
|
-
{...omit(props, ["error", "value", "helpText", "formatted", "className"])}
|
|
29
|
+
{...omit(props, ["error", "value", "helpText", "formatted", "className", "allowTabToSave"])}
|
|
30
30
|
className={"LuiTextInput-input"}
|
|
31
31
|
onMouseEnter={(e) => {
|
|
32
32
|
e.currentTarget.focus();
|
|
@@ -127,6 +127,25 @@ export const ControlledMenuFr = (
|
|
|
127
127
|
return;
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
+
const invokeSave = (reason: string) => {
|
|
131
|
+
if (!saveButtonRef?.current) return;
|
|
132
|
+
saveButtonRef.current?.setAttribute("data-reason", reason);
|
|
133
|
+
saveButtonRef?.current?.click();
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const allowTabToSave = activeElement.getAttribute("data-allowtabtosave") == "true";
|
|
137
|
+
if (allowTabToSave) {
|
|
138
|
+
if (isDown) {
|
|
139
|
+
ev.preventDefault();
|
|
140
|
+
ev.stopPropagation();
|
|
141
|
+
lastTabDownEl.current = activeElement;
|
|
142
|
+
} else {
|
|
143
|
+
lastTabDownEl.current == activeElement &&
|
|
144
|
+
invokeSave(ev.shiftKey ? CloseReason.TAB_BACKWARD : CloseReason.TAB_FORWARD);
|
|
145
|
+
}
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
130
149
|
const inputElsIterator = thisDocument.querySelectorAll<HTMLElement>(".szh-menu--state-open input,textarea");
|
|
131
150
|
let inputEls: HTMLElement[] = [];
|
|
132
151
|
inputElsIterator.forEach((el) => inputEls.push(el));
|
|
@@ -138,12 +157,6 @@ export const ControlledMenuFr = (
|
|
|
138
157
|
|
|
139
158
|
const isTextArea = activeElement.nodeName === "TEXTAREA";
|
|
140
159
|
const suppressEnterAutoSave = activeElement.getAttribute("data-disableenterautosave") == "true" || isTextArea;
|
|
141
|
-
const allowTabToSave = activeElement.getAttribute("data-allowtabtosave") == "true";
|
|
142
|
-
const invokeSave = (reason: string) => {
|
|
143
|
-
if (!saveButtonRef?.current) return;
|
|
144
|
-
saveButtonRef.current?.setAttribute("data-reason", reason);
|
|
145
|
-
saveButtonRef?.current?.click();
|
|
146
|
-
};
|
|
147
160
|
|
|
148
161
|
switch (activeElement.nodeName) {
|
|
149
162
|
case "TEXTAREA":
|
|
@@ -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
|
File without changes
|