@linzjs/step-ag-grid 32.2.0 → 32.3.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/src/lui/TextInputFormatted.d.ts +1 -0
- package/dist/src/lui/TextInputFormatted.test.d.ts +1 -0
- package/dist/src/utils/textValidator.d.ts +1 -0
- package/dist/step-ag-grid.cjs +34 -4
- package/dist/step-ag-grid.cjs.map +1 -1
- package/dist/step-ag-grid.esm.js +34 -5
- package/dist/step-ag-grid.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/gridForm/GridFormSubComponentTextInput.tsx +6 -1
- package/src/components/gridForm/GridFormTextInput.tsx +6 -1
- package/src/lui/TextInputFormatted.test.tsx +22 -0
- package/src/lui/TextInputFormatted.tsx +11 -1
- package/src/utils/textValidator.test.ts +45 -1
- package/src/utils/textValidator.ts +21 -0
package/package.json
CHANGED
|
@@ -2,7 +2,11 @@ import { ReactElement, useCallback, useContext, useEffect } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { GridSubComponentContext } from '../../contexts/GridSubComponentContext';
|
|
4
4
|
import { TextInputFormatted } from '../../lui/TextInputFormatted';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
TextInputValidator,
|
|
7
|
+
textInputValidatorPropsToSummary,
|
|
8
|
+
TextInputValidatorProps,
|
|
9
|
+
} from '../../utils/textValidator';
|
|
6
10
|
import { CellEditorCommon } from '../GridCell';
|
|
7
11
|
import { GridBaseRow } from '../types';
|
|
8
12
|
|
|
@@ -41,6 +45,7 @@ export const GridFormSubComponentTextInput = <TData extends GridBaseRow>(
|
|
|
41
45
|
placeholder={props.placeholder}
|
|
42
46
|
style={{ width: '100%' }}
|
|
43
47
|
allowTabToSave={true}
|
|
48
|
+
validationSummary={textInputValidatorPropsToSummary(props)}
|
|
44
49
|
/>
|
|
45
50
|
);
|
|
46
51
|
};
|
|
@@ -2,7 +2,11 @@ import { useCallback, useMemo, useState } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { useGridPopoverContext } from '../../contexts/GridPopoverContext';
|
|
4
4
|
import { TextInputFormatted } from '../../lui/TextInputFormatted';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
TextInputValidator,
|
|
7
|
+
textInputValidatorPropsToSummary,
|
|
8
|
+
TextInputValidatorProps,
|
|
9
|
+
} from '../../utils/textValidator';
|
|
6
10
|
import { CellEditorCommon } from '../GridCell';
|
|
7
11
|
import { useGridPopoverHook } from '../GridPopoverHook';
|
|
8
12
|
import { GridBaseRow } from '../types';
|
|
@@ -63,6 +67,7 @@ export const GridFormTextInput = <TData extends GridBaseRow>(props: GridFormText
|
|
|
63
67
|
style={{ width: props.width ?? 240 }}
|
|
64
68
|
placeholder={props.placeholder ?? 'Type here'}
|
|
65
69
|
helpText={helpText}
|
|
70
|
+
validationSummary={textInputValidatorPropsToSummary(props)}
|
|
66
71
|
/>
|
|
67
72
|
</div>,
|
|
68
73
|
);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { cleanup, render, screen } from '@testing-library/react';
|
|
2
|
+
import { afterEach, describe, expect, test } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import { TextInputFormatted } from './TextInputFormatted';
|
|
5
|
+
|
|
6
|
+
describe('TextInputFormatted', () => {
|
|
7
|
+
afterEach(() => {
|
|
8
|
+
cleanup();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test('sets data-validationsummary attribute from validationSummary prop', () => {
|
|
12
|
+
render(<TextInputFormatted value={''} onChange={() => {}} validationSummary={'required,maxLength=10'} />);
|
|
13
|
+
|
|
14
|
+
expect(screen.getByRole('textbox').getAttribute('data-validationsummary')).toBe('required,maxLength=10');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test('omits data-validationsummary attribute when validationSummary prop is not set', () => {
|
|
18
|
+
render(<TextInputFormatted value={''} onChange={() => {}} />);
|
|
19
|
+
|
|
20
|
+
expect(screen.getByRole('textbox').hasAttribute('data-validationsummary')).toBe(false);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -15,6 +15,7 @@ export interface LuiTextInputProps extends DetailedHTMLProps<InputHTMLAttributes
|
|
|
15
15
|
error?: ReactElement | string | boolean | null;
|
|
16
16
|
formatted?: string;
|
|
17
17
|
allowTabToSave?: boolean;
|
|
18
|
+
validationSummary?: string;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export const TextInputFormatted = (props: LuiTextInputProps): ReactElement => {
|
|
@@ -32,13 +33,22 @@ export const TextInputFormatted = (props: LuiTextInputProps): ReactElement => {
|
|
|
32
33
|
type={'text'}
|
|
33
34
|
spellCheck={true}
|
|
34
35
|
defaultValue={props.value}
|
|
35
|
-
{...omit(props, [
|
|
36
|
+
{...omit(props, [
|
|
37
|
+
'error',
|
|
38
|
+
'value',
|
|
39
|
+
'helpText',
|
|
40
|
+
'formatted',
|
|
41
|
+
'className',
|
|
42
|
+
'allowTabToSave',
|
|
43
|
+
'validationSummary',
|
|
44
|
+
])}
|
|
36
45
|
className={'LuiTextInput-input'}
|
|
37
46
|
onMouseEnter={(e) => {
|
|
38
47
|
e.currentTarget.focus();
|
|
39
48
|
props.onMouseEnter?.(e);
|
|
40
49
|
}}
|
|
41
50
|
data-allowtabtosave={props.allowTabToSave}
|
|
51
|
+
data-validationsummary={props.validationSummary}
|
|
42
52
|
/>
|
|
43
53
|
<span className={'LuiTextInput-formatted'}>{props.formatted}</span>
|
|
44
54
|
</span>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, expect, test, vi } from 'vitest';
|
|
2
2
|
|
|
3
3
|
import { GridBaseRow } from '../components/types';
|
|
4
|
-
import { TextInputValidator, TextInputValidatorProps } from './textValidator';
|
|
4
|
+
import { textInputValidatorPropsToSummary, TextInputValidator, TextInputValidatorProps } from './textValidator';
|
|
5
5
|
|
|
6
6
|
describe('TextInputValidator', () => {
|
|
7
7
|
test('number format', () => {
|
|
@@ -115,3 +115,47 @@ describe('TextInputValidator', () => {
|
|
|
115
115
|
expect(TextInputValidator({ maxBytes: 2 }, 'a–', { id: 0 }, {})).toBe('Must be no longer than 2 bytes');
|
|
116
116
|
});
|
|
117
117
|
});
|
|
118
|
+
|
|
119
|
+
describe('textInputValidatorPropsToSummary', () => {
|
|
120
|
+
test('empty props gives empty summary', () => {
|
|
121
|
+
expect(textInputValidatorPropsToSummary({})).toBe('');
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('required', () => {
|
|
125
|
+
expect(textInputValidatorPropsToSummary({ required: true })).toBe('required');
|
|
126
|
+
expect(textInputValidatorPropsToSummary({ required: false })).toBe('');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test('maxLength and maxBytes', () => {
|
|
130
|
+
expect(textInputValidatorPropsToSummary({ maxLength: 10 })).toBe('maxLength=10');
|
|
131
|
+
expect(textInputValidatorPropsToSummary({ maxBytes: 20 })).toBe('maxBytes=20');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test('invalid callback', () => {
|
|
135
|
+
expect(textInputValidatorPropsToSummary({ invalid: () => null })).toBe('invalid');
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test('numberFormat fields', () => {
|
|
139
|
+
expect(
|
|
140
|
+
textInputValidatorPropsToSummary({
|
|
141
|
+
numberFormat: { precision: 3, scale: 2, gtMin: 0, geMin: 1, ltMax: 100, leMax: 99, notZero: true },
|
|
142
|
+
}),
|
|
143
|
+
).toBe('precision=3,scale=2,gtMin=0,geMin=1,ltMax=100,leMax=99,notZero');
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test('numberFormat with no set fields contributes nothing', () => {
|
|
147
|
+
expect(textInputValidatorPropsToSummary({ numberFormat: {} })).toBe('');
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test('combines multiple props in order', () => {
|
|
151
|
+
expect(
|
|
152
|
+
textInputValidatorPropsToSummary({
|
|
153
|
+
required: true,
|
|
154
|
+
maxLength: 10,
|
|
155
|
+
maxBytes: 20,
|
|
156
|
+
invalid: () => null,
|
|
157
|
+
numberFormat: { scale: 2 },
|
|
158
|
+
}),
|
|
159
|
+
).toBe('required,maxLength=10,maxBytes=20,invalid,scale=2');
|
|
160
|
+
});
|
|
161
|
+
});
|
|
@@ -81,3 +81,24 @@ export const TextInputValidator = <TData extends GridBaseRow>(
|
|
|
81
81
|
}
|
|
82
82
|
return null;
|
|
83
83
|
};
|
|
84
|
+
|
|
85
|
+
export const textInputValidatorPropsToSummary = <TData extends GridBaseRow>(
|
|
86
|
+
props: TextInputValidatorProps<TData>,
|
|
87
|
+
): string => {
|
|
88
|
+
const parts: string[] = [];
|
|
89
|
+
if (props.required) parts.push('required');
|
|
90
|
+
if (props.maxLength != null) parts.push(`maxLength=${props.maxLength}`);
|
|
91
|
+
if (props.maxBytes != null) parts.push(`maxBytes=${props.maxBytes}`);
|
|
92
|
+
if (props.invalid) parts.push('invalid');
|
|
93
|
+
const nf = props.numberFormat;
|
|
94
|
+
if (nf) {
|
|
95
|
+
if (nf.precision != null) parts.push(`precision=${nf.precision}`);
|
|
96
|
+
if (nf.scale != null) parts.push(`scale=${nf.scale}`);
|
|
97
|
+
if (nf.gtMin != null) parts.push(`gtMin=${nf.gtMin}`);
|
|
98
|
+
if (nf.geMin != null) parts.push(`geMin=${nf.geMin}`);
|
|
99
|
+
if (nf.ltMax != null) parts.push(`ltMax=${nf.ltMax}`);
|
|
100
|
+
if (nf.leMax != null) parts.push(`leMax=${nf.leMax}`);
|
|
101
|
+
if (nf.notZero) parts.push('notZero');
|
|
102
|
+
}
|
|
103
|
+
return parts.join(',');
|
|
104
|
+
};
|