@patternfly/react-core 4.262.0 → 4.264.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/CHANGELOG.md +28 -0
- package/dist/esm/components/Button/Button.d.ts.map +1 -1
- package/dist/esm/components/Button/Button.js +1 -1
- package/dist/esm/components/Button/Button.js.map +1 -1
- package/dist/esm/components/NumberInput/NumberInput.d.ts +1 -1
- package/dist/esm/components/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/esm/components/NumberInput/NumberInput.js +0 -1
- package/dist/esm/components/NumberInput/NumberInput.js.map +1 -1
- package/dist/esm/components/Spinner/Spinner.d.ts +2 -0
- package/dist/esm/components/Spinner/Spinner.d.ts.map +1 -1
- package/dist/esm/components/Spinner/Spinner.js +2 -2
- package/dist/esm/components/Spinner/Spinner.js.map +1 -1
- package/dist/esm/components/Tabs/Tab.d.ts +4 -2
- package/dist/esm/components/Tabs/Tab.d.ts.map +1 -1
- package/dist/esm/components/Tabs/Tab.js +6 -7
- package/dist/esm/components/Tabs/Tab.js.map +1 -1
- package/dist/esm/components/Tabs/TabAction.d.ts +20 -0
- package/dist/esm/components/Tabs/TabAction.d.ts.map +1 -0
- package/dist/esm/components/Tabs/TabAction.js +17 -0
- package/dist/esm/components/Tabs/TabAction.js.map +1 -0
- package/dist/esm/components/Tabs/Tabs.d.ts +1 -1
- package/dist/esm/components/Tabs/Tabs.d.ts.map +1 -1
- package/dist/esm/components/Tabs/index.d.ts +1 -0
- package/dist/esm/components/Tabs/index.d.ts.map +1 -1
- package/dist/esm/components/Tabs/index.js +1 -0
- package/dist/esm/components/Tabs/index.js.map +1 -1
- package/dist/esm/helpers/Popper/Popper.d.ts.map +1 -1
- package/dist/esm/helpers/Popper/Popper.js +6 -3
- package/dist/esm/helpers/Popper/Popper.js.map +1 -1
- package/dist/js/components/Button/Button.d.ts.map +1 -1
- package/dist/js/components/Button/Button.js +1 -1
- package/dist/js/components/Button/Button.js.map +1 -1
- package/dist/js/components/NumberInput/NumberInput.d.ts +1 -1
- package/dist/js/components/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/js/components/NumberInput/NumberInput.js +0 -1
- package/dist/js/components/NumberInput/NumberInput.js.map +1 -1
- package/dist/js/components/Spinner/Spinner.d.ts +2 -0
- package/dist/js/components/Spinner/Spinner.d.ts.map +1 -1
- package/dist/js/components/Spinner/Spinner.js +2 -2
- package/dist/js/components/Spinner/Spinner.js.map +1 -1
- package/dist/js/components/Tabs/Tab.d.ts +4 -2
- package/dist/js/components/Tabs/Tab.d.ts.map +1 -1
- package/dist/js/components/Tabs/Tab.js +6 -7
- package/dist/js/components/Tabs/Tab.js.map +1 -1
- package/dist/js/components/Tabs/TabAction.d.ts +20 -0
- package/dist/js/components/Tabs/TabAction.d.ts.map +1 -0
- package/dist/js/components/Tabs/TabAction.js +20 -0
- package/dist/js/components/Tabs/TabAction.js.map +1 -0
- package/dist/js/components/Tabs/Tabs.d.ts +1 -1
- package/dist/js/components/Tabs/Tabs.d.ts.map +1 -1
- package/dist/js/components/Tabs/index.d.ts +1 -0
- package/dist/js/components/Tabs/index.d.ts.map +1 -1
- package/dist/js/components/Tabs/index.js +1 -0
- package/dist/js/components/Tabs/index.js.map +1 -1
- package/dist/js/helpers/Popper/Popper.d.ts.map +1 -1
- package/dist/js/helpers/Popper/Popper.js +6 -3
- package/dist/js/helpers/Popper/Popper.js.map +1 -1
- package/dist/styles/assets/pficon/pficon.scss +12 -0
- package/dist/styles/assets/pficon/pficon.woff +0 -0
- package/dist/styles/assets/pficon/pficon.woff2 +0 -0
- package/dist/styles/base-no-reset.css +10 -0
- package/dist/styles/base.css +10 -0
- package/dist/umd/react-core.min.css +1331 -1162
- package/dist/umd/react-core.min.js +2 -2
- package/package.json +6 -6
- package/src/components/Button/Button.tsx +1 -0
- package/src/components/Button/__tests__/__snapshots__/Button.test.tsx.snap +1 -1
- package/src/components/NumberInput/NumberInput.tsx +1 -2
- package/src/components/NumberInput/__tests__/NumberInput.test.tsx +4 -4
- package/src/components/NumberInput/examples/NumberInput.md +2 -0
- package/src/components/NumberInput/examples/NumberInputCustomStep.tsx +4 -4
- package/src/components/NumberInput/examples/NumberInputCustomStepAndThreshold.tsx +4 -5
- package/src/components/NumberInput/examples/NumberInputDefault.tsx +5 -5
- package/src/components/NumberInput/examples/NumberInputDisabled.tsx +5 -5
- package/src/components/NumberInput/examples/NumberInputUnit.tsx +10 -10
- package/src/components/NumberInput/examples/NumberInputUnitThreshold.tsx +16 -6
- package/src/components/NumberInput/examples/NumberInputVaryingSizes.tsx +11 -11
- package/src/components/NumberInput/examples/NumberInputWithStatus.tsx +5 -6
- package/src/components/Popover/__tests__/__snapshots__/Popover.test.tsx.snap +3 -1
- package/src/components/SearchInput/__tests__/__snapshots__/SearchInput.test.tsx.snap +3 -1
- package/src/components/Spinner/Spinner.tsx +4 -1
- package/src/components/Spinner/examples/Spinner.md +4 -0
- package/src/components/Spinner/examples/SpinnerInline.tsx +29 -0
- package/src/components/Tabs/Tab.tsx +17 -16
- package/src/components/Tabs/TabAction.tsx +57 -0
- package/src/components/Tabs/Tabs.tsx +1 -1
- package/src/components/Tabs/__tests__/Tab.test.tsx +10 -0
- package/src/components/Tabs/__tests__/__snapshots__/Tab.test.tsx.snap +45 -0
- package/src/components/Tabs/examples/Tabs.md +64 -20
- package/src/components/Tabs/examples/TabsHelp.tsx +61 -0
- package/src/components/Tabs/examples/TabsHelpAndClose.tsx +84 -0
- package/src/components/Tabs/index.ts +1 -0
- package/src/components/Tooltip/__tests__/__snapshots__/Tooltip.test.tsx.snap +3 -1
- package/src/demos/Tabs.md +0 -10
- package/src/demos/examples/DashboardWrapper.js +1 -0
- package/src/demos/examples/Tabs/ModalTabs.tsx +3 -3
- package/src/demos/examples/Tabs/NestedTabs.tsx +11 -3
- package/src/demos/examples/Tabs/NestedUnindentedTabs.tsx +25 -40
- package/src/demos/examples/Tabs/TabsAndTable.tsx +9 -52
- package/src/helpers/Popper/Popper.tsx +13 -3
- package/src/demos/examples/Tabs/GrayTabs.tsx +0 -152
- package/src/demos/examples/Tabs/TabsAndTablesAutoWidthTabs.tsx +0 -442
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@patternfly/react-core",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.264.0",
|
|
4
4
|
"description": "This library provides a set of common React components for use with the PatternFly reference implementation.",
|
|
5
5
|
"main": "dist/js/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -44,16 +44,16 @@
|
|
|
44
44
|
"generate": "node scripts/copyStyles.js"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@patternfly/react-icons": "^4.
|
|
48
|
-
"@patternfly/react-styles": "^4.
|
|
49
|
-
"@patternfly/react-tokens": "^4.
|
|
47
|
+
"@patternfly/react-icons": "^4.93.0",
|
|
48
|
+
"@patternfly/react-styles": "^4.92.0",
|
|
49
|
+
"@patternfly/react-tokens": "^4.94.0",
|
|
50
50
|
"focus-trap": "6.9.2",
|
|
51
51
|
"react-dropzone": "9.0.0",
|
|
52
52
|
"tippy.js": "5.1.2",
|
|
53
53
|
"tslib": "^2.0.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@patternfly/patternfly": "4.
|
|
56
|
+
"@patternfly/patternfly": "4.221.2",
|
|
57
57
|
"@rollup/plugin-commonjs": "^21.0.0",
|
|
58
58
|
"@rollup/plugin-node-resolve": "^13.0.0",
|
|
59
59
|
"@rollup/plugin-replace": "^3.0.0",
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
"react": "^16.8 || ^17 || ^18",
|
|
71
71
|
"react-dom": "^16.8 || ^17 || ^18"
|
|
72
72
|
},
|
|
73
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "e1f95ce96852165dd4d102cd87c6b49288f01eff"
|
|
74
74
|
}
|
|
@@ -172,6 +172,7 @@ const ButtonBase: React.FunctionComponent<ButtonProps> = ({
|
|
|
172
172
|
<span className={css(styles.buttonProgress)}>
|
|
173
173
|
<Spinner
|
|
174
174
|
size={spinnerSize.md}
|
|
175
|
+
isInline={isInline}
|
|
175
176
|
aria-valuetext={spinnerAriaValueText}
|
|
176
177
|
aria-label={spinnerAriaLabel}
|
|
177
178
|
aria-labelledby={spinnerAriaLabelledBy}
|
|
@@ -10,7 +10,7 @@ import { TextInput } from '../TextInput';
|
|
|
10
10
|
|
|
11
11
|
export interface NumberInputProps extends React.HTMLProps<HTMLDivElement> {
|
|
12
12
|
/** Value of the number input */
|
|
13
|
-
value?: number |
|
|
13
|
+
value?: number | '';
|
|
14
14
|
/** Additional classes added to the number input */
|
|
15
15
|
className?: string;
|
|
16
16
|
/** Sets the width of the number input to a number of characters */
|
|
@@ -89,7 +89,6 @@ export const NumberInput: React.FunctionComponent<NumberInputProps> = ({
|
|
|
89
89
|
plusBtnProps,
|
|
90
90
|
...props
|
|
91
91
|
}: NumberInputProps) => {
|
|
92
|
-
value = value || 0;
|
|
93
92
|
const numberInputUnit = <div className={css(styles.numberInputUnit)}>{unit}</div>;
|
|
94
93
|
const keyDownHandler =
|
|
95
94
|
inputProps && inputProps.onKeyDown ? inputProps.onKeyDown : defaultKeyDownHandler({ inputName, onMinus, onPlus });
|
|
@@ -195,22 +195,22 @@ describe('numberInput', () => {
|
|
|
195
195
|
expect(input).toHaveDisplayValue('47.01');
|
|
196
196
|
});
|
|
197
197
|
|
|
198
|
-
test('renders 0 if no value passed', () => {
|
|
198
|
+
test('renders 0 (default value) if no value passed', () => {
|
|
199
199
|
render(<NumberInput />);
|
|
200
200
|
const input = screen.getByRole('spinbutton');
|
|
201
201
|
expect(input).toHaveDisplayValue('0');
|
|
202
202
|
});
|
|
203
203
|
|
|
204
|
-
test('renders 0 if undefined value passed', () => {
|
|
204
|
+
test('renders 0 (default value) if undefined value passed', () => {
|
|
205
205
|
render(<NumberInput value={undefined} />);
|
|
206
206
|
const input = screen.getByRole('spinbutton');
|
|
207
207
|
expect(input).toHaveDisplayValue('0');
|
|
208
208
|
});
|
|
209
209
|
|
|
210
|
-
test('renders
|
|
210
|
+
test('renders nothing if null value passed', () => {
|
|
211
211
|
render(<NumberInput value={null} />);
|
|
212
212
|
const input = screen.getByRole('spinbutton');
|
|
213
|
-
expect(input).toHaveDisplayValue('
|
|
213
|
+
expect(input).toHaveDisplayValue('');
|
|
214
214
|
});
|
|
215
215
|
|
|
216
216
|
test('does not throw an error if onChange is passed via inputProps as well as the onChange prop', () => {
|
|
@@ -19,6 +19,8 @@ propComponents: ['NumberInput']
|
|
|
19
19
|
|
|
20
20
|
### With unit and thresholds
|
|
21
21
|
|
|
22
|
+
To enable a user entered value to snap to the nearest threshold if the entered input is out of bounds, define the blur event handler.
|
|
23
|
+
|
|
22
24
|
```ts file="./NumberInputUnitThreshold.tsx"
|
|
23
25
|
```
|
|
24
26
|
|
|
@@ -2,16 +2,16 @@ import React from 'react';
|
|
|
2
2
|
import { NumberInput } from '@patternfly/react-core';
|
|
3
3
|
|
|
4
4
|
export const NumberInputCustomStep: React.FunctionComponent = () => {
|
|
5
|
-
const [value, setValue] = React.useState(90);
|
|
5
|
+
const [value, setValue] = React.useState<number | ''>(90);
|
|
6
6
|
const step = 3;
|
|
7
7
|
|
|
8
8
|
const stepper = (stepValue: number) => {
|
|
9
|
-
setValue(value + stepValue);
|
|
9
|
+
setValue((value || 0) + stepValue);
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
const onChange = (event: React.FormEvent<HTMLInputElement>) => {
|
|
13
|
-
const
|
|
14
|
-
setValue(
|
|
13
|
+
const value = (event.target as HTMLInputElement).value;
|
|
14
|
+
setValue(value === '' ? value : +value);
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
return (
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { NumberInput } from '@patternfly/react-core';
|
|
3
3
|
|
|
4
4
|
export const NumberInputCustomStepAndThreshold: React.FunctionComponent = () => {
|
|
5
|
-
const [value, setValue] = React.useState(90);
|
|
5
|
+
const [value, setValue] = React.useState<number | ''>(90);
|
|
6
6
|
const minValue = 90;
|
|
7
7
|
const maxValue = 100;
|
|
8
8
|
const step = 3;
|
|
@@ -19,13 +19,12 @@ export const NumberInputCustomStepAndThreshold: React.FunctionComponent = () =>
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
const stepper = (stepValue: number) => {
|
|
22
|
-
setValue(value + stepValue);
|
|
22
|
+
setValue((value || 0) + stepValue);
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
const onChange = (event: React.FormEvent<HTMLInputElement>) => {
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
setValue(newValue);
|
|
26
|
+
const value = (event.target as HTMLInputElement).value;
|
|
27
|
+
setValue(value === '' ? value : +value);
|
|
29
28
|
};
|
|
30
29
|
|
|
31
30
|
const onBlur = (event: React.FormEvent<HTMLInputElement>) => {
|
|
@@ -2,20 +2,20 @@ import React from 'react';
|
|
|
2
2
|
import { NumberInput } from '@patternfly/react-core';
|
|
3
3
|
|
|
4
4
|
export const NumberInputDefault: React.FunctionComponent = () => {
|
|
5
|
-
const [value, setValue] = React.useState(90);
|
|
5
|
+
const [value, setValue] = React.useState<number | ''>(90);
|
|
6
6
|
|
|
7
7
|
const onMinus = () => {
|
|
8
|
-
const newValue = value - 1;
|
|
8
|
+
const newValue = (value || 0) - 1;
|
|
9
9
|
setValue(newValue);
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
const onChange = (event: React.FormEvent<HTMLInputElement>) => {
|
|
13
|
-
const
|
|
14
|
-
setValue(
|
|
13
|
+
const value = (event.target as HTMLInputElement).value;
|
|
14
|
+
setValue(value === '' ? value : +value);
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
const onPlus = () => {
|
|
18
|
-
const newValue = value + 1;
|
|
18
|
+
const newValue = (value || 0) + 1;
|
|
19
19
|
setValue(newValue);
|
|
20
20
|
};
|
|
21
21
|
|
|
@@ -2,22 +2,22 @@ import React from 'react';
|
|
|
2
2
|
import { NumberInput } from '@patternfly/react-core';
|
|
3
3
|
|
|
4
4
|
export const NumberInputDisabled: React.FunctionComponent = () => {
|
|
5
|
-
const [value, setValue] = React.useState(100);
|
|
5
|
+
const [value, setValue] = React.useState<number | ''>(100);
|
|
6
6
|
const minValue = 0;
|
|
7
7
|
const maxValue = 100;
|
|
8
8
|
|
|
9
9
|
const onMinus = () => {
|
|
10
|
-
const newValue = value - 1;
|
|
10
|
+
const newValue = (value || 0) - 1;
|
|
11
11
|
setValue(newValue);
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
const onChange = (event: React.FormEvent<HTMLInputElement>) => {
|
|
15
|
-
const
|
|
16
|
-
setValue(
|
|
15
|
+
const value = (event.target as HTMLInputElement).value;
|
|
16
|
+
setValue(value === '' ? value : +value);
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
const onPlus = () => {
|
|
20
|
-
const newValue = value + 1;
|
|
20
|
+
const newValue = (value || 0) + 1;
|
|
21
21
|
setValue(newValue);
|
|
22
22
|
};
|
|
23
23
|
|
|
@@ -2,26 +2,26 @@ import React from 'react';
|
|
|
2
2
|
import { NumberInput } from '@patternfly/react-core';
|
|
3
3
|
|
|
4
4
|
export const NumberInputUnit: React.FunctionComponent = () => {
|
|
5
|
-
const [value1, setValue1] = React.useState(90);
|
|
6
|
-
const [value2, setValue2] = React.useState(Number((1.0).toFixed(2)));
|
|
5
|
+
const [value1, setValue1] = React.useState<number | ''>(90);
|
|
6
|
+
const [value2, setValue2] = React.useState<number | ''>(Number((1.0).toFixed(2)));
|
|
7
7
|
|
|
8
|
-
const onMinus1 = () => setValue1(value1 - 1);
|
|
8
|
+
const onMinus1 = () => setValue1((value1 || 0) - 1);
|
|
9
9
|
const onChange1 = (event: React.FormEvent<HTMLInputElement>) => {
|
|
10
|
-
const
|
|
11
|
-
setValue1(
|
|
10
|
+
const value = (event.target as HTMLInputElement).value;
|
|
11
|
+
setValue1(value === '' ? value : +value);
|
|
12
12
|
};
|
|
13
|
-
const onPlus1 = () => setValue1(value1 + 1);
|
|
13
|
+
const onPlus1 = () => setValue1((value1 || 0) + 1);
|
|
14
14
|
|
|
15
15
|
const onMinus2 = () => {
|
|
16
|
-
const newValue = Number((value2 - 0.01).toFixed(2));
|
|
16
|
+
const newValue = Number(((value2 || 0) - 0.01).toFixed(2));
|
|
17
17
|
setValue2(newValue);
|
|
18
18
|
};
|
|
19
19
|
const onChange2 = (event: React.FormEvent<HTMLInputElement>) => {
|
|
20
|
-
const
|
|
21
|
-
setValue2(
|
|
20
|
+
const value = (event.target as HTMLInputElement).value;
|
|
21
|
+
setValue2(value === '' ? value : +value);
|
|
22
22
|
};
|
|
23
23
|
const onPlus2 = () => {
|
|
24
|
-
const newValue = Number((value2 + 0.01).toFixed(2));
|
|
24
|
+
const newValue = Number(((value2 || 0) + 0.01).toFixed(2));
|
|
25
25
|
setValue2(newValue);
|
|
26
26
|
};
|
|
27
27
|
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { NumberInput } from '@patternfly/react-core';
|
|
3
3
|
|
|
4
4
|
export const NumberInputUnitThreshold: React.FunctionComponent = () => {
|
|
5
|
-
const [value, setValue] = React.useState(0);
|
|
5
|
+
const [value, setValue] = React.useState<number | ''>(0);
|
|
6
6
|
const minValue = 0;
|
|
7
7
|
const maxValue = 10;
|
|
8
8
|
|
|
@@ -18,18 +18,27 @@ export const NumberInputUnitThreshold: React.FunctionComponent = () => {
|
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
const onMinus = () => {
|
|
21
|
-
const newValue = normalizeBetween(value - 1, minValue, maxValue);
|
|
21
|
+
const newValue = normalizeBetween((value as number) - 1, minValue, maxValue);
|
|
22
22
|
setValue(newValue);
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
const onChange = (event: React.FormEvent<HTMLInputElement>) => {
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
const value = (event.target as HTMLInputElement).value;
|
|
27
|
+
setValue(value === '' ? value : +value);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const onBlur = (event: React.FocusEvent<HTMLInputElement>) => {
|
|
31
|
+
const blurVal = +event.target.value;
|
|
32
|
+
|
|
33
|
+
if (blurVal < minValue) {
|
|
34
|
+
setValue(minValue);
|
|
35
|
+
} else if (blurVal > maxValue) {
|
|
36
|
+
setValue(maxValue);
|
|
37
|
+
}
|
|
29
38
|
};
|
|
30
39
|
|
|
31
40
|
const onPlus = () => {
|
|
32
|
-
const newValue = normalizeBetween(value + 1, minValue, maxValue);
|
|
41
|
+
const newValue = normalizeBetween((value as number) + 1, minValue, maxValue);
|
|
33
42
|
setValue(newValue);
|
|
34
43
|
};
|
|
35
44
|
|
|
@@ -43,6 +52,7 @@ export const NumberInputUnitThreshold: React.FunctionComponent = () => {
|
|
|
43
52
|
max={maxValue}
|
|
44
53
|
onMinus={onMinus}
|
|
45
54
|
onChange={onChange}
|
|
55
|
+
onBlur={onBlur}
|
|
46
56
|
onPlus={onPlus}
|
|
47
57
|
inputName="input"
|
|
48
58
|
inputAriaLabel="number input"
|
|
@@ -2,25 +2,25 @@ import React from 'react';
|
|
|
2
2
|
import { NumberInput } from '@patternfly/react-core';
|
|
3
3
|
|
|
4
4
|
export const NumberInputVaryingSizes: React.FunctionComponent = () => {
|
|
5
|
-
const [input1Value, setInput1Value] = React.useState(1);
|
|
6
|
-
const [input2Value, setInput2Value] = React.useState(1234567890);
|
|
7
|
-
const [input3Value, setInput3Value] = React.useState(5);
|
|
8
|
-
const [input4Value, setInput4Value] = React.useState(12345);
|
|
5
|
+
const [input1Value, setInput1Value] = React.useState<number | ''>(1);
|
|
6
|
+
const [input2Value, setInput2Value] = React.useState<number | ''>(1234567890);
|
|
7
|
+
const [input3Value, setInput3Value] = React.useState<number | ''>(5);
|
|
8
|
+
const [input4Value, setInput4Value] = React.useState<number | ''>(12345);
|
|
9
9
|
|
|
10
10
|
const onChange = (
|
|
11
11
|
event: React.FormEvent<HTMLInputElement>,
|
|
12
|
-
updateFunction: React.Dispatch<React.SetStateAction<number>>
|
|
12
|
+
updateFunction: React.Dispatch<React.SetStateAction<number | ''>>
|
|
13
13
|
) => {
|
|
14
|
-
const
|
|
15
|
-
updateFunction(
|
|
14
|
+
const value = (event.target as HTMLInputElement).value;
|
|
15
|
+
updateFunction(value === '' ? value : +value);
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
const onMinus = (value, updateFunction: React.Dispatch<React.SetStateAction<number>>) => {
|
|
19
|
-
updateFunction(value - 1);
|
|
18
|
+
const onMinus = (value: number | '', updateFunction: React.Dispatch<React.SetStateAction<number | ''>>) => {
|
|
19
|
+
updateFunction((value || 0) - 1);
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
const onPlus = (value, updateFunction: React.Dispatch<React.SetStateAction<number>>) => {
|
|
23
|
-
updateFunction(value + 1);
|
|
22
|
+
const onPlus = (value: number | '', updateFunction: React.Dispatch<React.SetStateAction<number | ''>>) => {
|
|
23
|
+
updateFunction((value || 0) + 1);
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
return (
|
|
@@ -9,22 +9,21 @@ export const NumberInputWithStatus: React.FunctionComponent = () => {
|
|
|
9
9
|
const [value, setValue] = React.useReducer((state, newVal) => Math.max(min, Math.min(max, Number(newVal))), 5);
|
|
10
10
|
|
|
11
11
|
const onPlus = () => {
|
|
12
|
-
const newVal = value + 1;
|
|
12
|
+
const newVal = (value || 0) + 1;
|
|
13
13
|
setValue(newVal);
|
|
14
14
|
validate(newVal);
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
const onMinus = () => {
|
|
18
|
-
const newVal = value - 1;
|
|
18
|
+
const newVal = (value || 0) - 1;
|
|
19
19
|
setValue(newVal);
|
|
20
20
|
validate(newVal);
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
const onChange = (event: React.FormEvent<HTMLInputElement>) => {
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
validate(newVal);
|
|
24
|
+
const value = (event.target as HTMLInputElement).value;
|
|
25
|
+
setValue(value === '' ? value : +value);
|
|
26
|
+
validate(value);
|
|
28
27
|
};
|
|
29
28
|
|
|
30
29
|
const validate = newVal => {
|
|
@@ -20,6 +20,8 @@ export interface SpinnerProps extends Omit<React.HTMLProps<HTMLSpanElement>, 'si
|
|
|
20
20
|
isSVG?: boolean;
|
|
21
21
|
/** Diameter of spinner set as CSS variable */
|
|
22
22
|
diameter?: string;
|
|
23
|
+
/** @beta Indicates the spinner is inline and the size should inherit the text font size. This will override the size prop. */
|
|
24
|
+
isInline?: boolean;
|
|
23
25
|
/** Accessible label to describe what is loading */
|
|
24
26
|
'aria-label'?: string;
|
|
25
27
|
/** Id of element which describes what is being loaded */
|
|
@@ -33,6 +35,7 @@ export const Spinner: React.FunctionComponent<SpinnerProps> = ({
|
|
|
33
35
|
'aria-valuetext': ariaValueText = 'Loading...',
|
|
34
36
|
isSVG = false,
|
|
35
37
|
diameter,
|
|
38
|
+
isInline = false,
|
|
36
39
|
'aria-label': ariaLabel,
|
|
37
40
|
'aria-labelledBy': ariaLabelledBy,
|
|
38
41
|
...props
|
|
@@ -41,7 +44,7 @@ export const Spinner: React.FunctionComponent<SpinnerProps> = ({
|
|
|
41
44
|
|
|
42
45
|
return (
|
|
43
46
|
<Component
|
|
44
|
-
className={css(styles.spinner, styles.modifiers[size], className)}
|
|
47
|
+
className={css(styles.spinner, isInline ? styles.modifiers.inline : styles.modifiers[size], className)}
|
|
45
48
|
role="progressbar"
|
|
46
49
|
aria-valuetext={ariaValueText}
|
|
47
50
|
{...(isSVG && { viewBox: '0 0 100 100' })}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Spinner, Text, TextContent } from '@patternfly/react-core';
|
|
3
|
+
|
|
4
|
+
export const SpinnerInline: React.FunctionComponent = () => (
|
|
5
|
+
<React.Fragment>
|
|
6
|
+
<TextContent>
|
|
7
|
+
<Text component="h1">
|
|
8
|
+
Heading
|
|
9
|
+
<Spinner isInline isSVG aria-label="Spinner in a heading" />
|
|
10
|
+
</Text>
|
|
11
|
+
<Text component="p">
|
|
12
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit Sed hendrerit nisi in cursus maximus.
|
|
13
|
+
</Text>
|
|
14
|
+
<Text component="h2">
|
|
15
|
+
Second level
|
|
16
|
+
<Spinner isInline isSVG aria-label="spinner in a subheading" />
|
|
17
|
+
</Text>
|
|
18
|
+
<Text component="p">
|
|
19
|
+
Curabitur accumsan turpis pharetra blandit. Quisque condimentum maximus mi,{' '}
|
|
20
|
+
<Spinner isInline isSVG aria-label="Spinner in a paragraph" /> sit amet commodo arcu rutrum id. Proin pretium
|
|
21
|
+
urna vel cursus venenatis. Suspendisse potenti.
|
|
22
|
+
</Text>
|
|
23
|
+
<small>
|
|
24
|
+
Sometimes you need small text
|
|
25
|
+
<Spinner isInline isSVG aria-label="Spinner in a small element" />
|
|
26
|
+
</small>
|
|
27
|
+
</TextContent>
|
|
28
|
+
</React.Fragment>
|
|
29
|
+
);
|
|
@@ -5,10 +5,12 @@ import { TabButton } from './TabButton';
|
|
|
5
5
|
import { TabsContext } from './TabsContext';
|
|
6
6
|
import { css } from '@patternfly/react-styles';
|
|
7
7
|
import { Tooltip } from '../Tooltip';
|
|
8
|
-
import { Button } from '../Button';
|
|
9
8
|
import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
|
|
9
|
+
import { TabAction } from './TabAction';
|
|
10
10
|
|
|
11
|
-
export interface TabProps
|
|
11
|
+
export interface TabProps
|
|
12
|
+
extends Omit<React.HTMLProps<HTMLAnchorElement | HTMLButtonElement>, 'title' | 'action'>,
|
|
13
|
+
OUIAProps {
|
|
12
14
|
/** content rendered inside the Tab content area. */
|
|
13
15
|
children?: React.ReactNode;
|
|
14
16
|
/** additional classes added to the Tab */
|
|
@@ -39,6 +41,8 @@ export interface TabProps extends Omit<React.HTMLProps<HTMLAnchorElement | HTMLB
|
|
|
39
41
|
closeButtonAriaLabel?: string;
|
|
40
42
|
/** @beta Flag indicating the close button should be disabled */
|
|
41
43
|
isCloseDisabled?: boolean;
|
|
44
|
+
/** @beta Actions rendered beside the tab content */
|
|
45
|
+
actions?: React.ReactNode;
|
|
42
46
|
/** Value to set the data-ouia-component-id for the tab button.*/
|
|
43
47
|
ouiaId?: number | string;
|
|
44
48
|
}
|
|
@@ -59,6 +63,7 @@ const TabBase: React.FunctionComponent<TabProps> = ({
|
|
|
59
63
|
tooltip,
|
|
60
64
|
closeButtonAriaLabel,
|
|
61
65
|
isCloseDisabled = false,
|
|
66
|
+
actions,
|
|
62
67
|
...props
|
|
63
68
|
}: TabProps) => {
|
|
64
69
|
const preventedEvents = inoperableEvents.reduce(
|
|
@@ -117,26 +122,22 @@ const TabBase: React.FunctionComponent<TabProps> = ({
|
|
|
117
122
|
className={css(
|
|
118
123
|
styles.tabsItem,
|
|
119
124
|
eventKey === localActiveKey && styles.modifiers.current,
|
|
120
|
-
handleTabClose && styles.modifiers.action,
|
|
121
|
-
|
|
125
|
+
(handleTabClose || actions) && styles.modifiers.action,
|
|
126
|
+
(isDisabled || isAriaDisabled) && styles.modifiers.disabled,
|
|
122
127
|
childClassName
|
|
123
128
|
)}
|
|
124
129
|
role="presentation"
|
|
125
130
|
>
|
|
126
131
|
{tooltip ? <Tooltip {...tooltip.props}>{tabButton}</Tooltip> : tabButton}
|
|
132
|
+
{actions && actions}
|
|
127
133
|
{handleTabClose !== undefined && (
|
|
128
|
-
<
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
<span className={css(styles.tabsItemCloseIcon)}>
|
|
136
|
-
<TimesIcon />
|
|
137
|
-
</span>
|
|
138
|
-
</Button>
|
|
139
|
-
</span>
|
|
134
|
+
<TabAction
|
|
135
|
+
aria-label={closeButtonAriaLabel || 'Close tab'}
|
|
136
|
+
onClick={(event: any) => handleTabClose(event, eventKey, tabContentRef)}
|
|
137
|
+
isDisabled={isCloseDisabled}
|
|
138
|
+
>
|
|
139
|
+
<TimesIcon />
|
|
140
|
+
</TabAction>
|
|
140
141
|
)}
|
|
141
142
|
</li>
|
|
142
143
|
);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { css } from '@patternfly/react-styles';
|
|
3
|
+
import styles from '@patternfly/react-styles/css/components/Tabs/tabs';
|
|
4
|
+
import { Button } from '../Button';
|
|
5
|
+
import { getOUIAProps, OUIAProps } from '../../helpers';
|
|
6
|
+
|
|
7
|
+
export interface TabActionProps extends Omit<React.HTMLProps<HTMLButtonElement>, 'ref' | 'type'>, OUIAProps {
|
|
8
|
+
/** Content rendered in the tab action */
|
|
9
|
+
children?: React.ReactNode;
|
|
10
|
+
/** Additional classes added to the tab action span */
|
|
11
|
+
className?: string;
|
|
12
|
+
/** Click callback for tab action button */
|
|
13
|
+
onClick?: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
|
14
|
+
/** Flag indicating if the tab action is a help action */
|
|
15
|
+
isHelpAction?: boolean;
|
|
16
|
+
/** Flag indicating if the tab action is disabled */
|
|
17
|
+
isDisabled?: boolean;
|
|
18
|
+
/** Accessible label for the tab action */
|
|
19
|
+
'aria-label'?: string;
|
|
20
|
+
/** @hide Callback for the section ref */
|
|
21
|
+
innerRef?: React.Ref<any>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const TabActionBase: React.FunctionComponent<TabActionProps> = ({
|
|
25
|
+
children,
|
|
26
|
+
className,
|
|
27
|
+
onClick,
|
|
28
|
+
isHelpAction,
|
|
29
|
+
isDisabled,
|
|
30
|
+
'aria-label': ariaLabel = 'Tab action',
|
|
31
|
+
innerRef,
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
33
|
+
ouiaId,
|
|
34
|
+
ouiaSafe,
|
|
35
|
+
...props
|
|
36
|
+
}: TabActionProps) => (
|
|
37
|
+
<span className={css(styles.tabsItemAction, isHelpAction && styles.modifiers.help, className)}>
|
|
38
|
+
<Button
|
|
39
|
+
ref={innerRef}
|
|
40
|
+
type="button"
|
|
41
|
+
variant="plain"
|
|
42
|
+
aria-label={ariaLabel}
|
|
43
|
+
onClick={onClick}
|
|
44
|
+
isDisabled={isDisabled}
|
|
45
|
+
{...getOUIAProps(TabAction.displayName, ouiaId, ouiaSafe)}
|
|
46
|
+
{...props}
|
|
47
|
+
>
|
|
48
|
+
<span className={css(styles.tabsItemActionIcon)}>{children}</span>
|
|
49
|
+
</Button>
|
|
50
|
+
</span>
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
export const TabAction = React.forwardRef((props: TabActionProps, ref: React.Ref<HTMLElement>) => (
|
|
54
|
+
<TabActionBase {...props} innerRef={ref} />
|
|
55
|
+
));
|
|
56
|
+
|
|
57
|
+
TabAction.displayName = 'TabAction';
|
|
@@ -42,7 +42,7 @@ export interface TabsProps extends Omit<React.HTMLProps<HTMLElement | HTMLDivEle
|
|
|
42
42
|
defaultActiveKey?: number | string;
|
|
43
43
|
/** Callback to handle tab selection */
|
|
44
44
|
onSelect?: (event: React.MouseEvent<HTMLElement, MouseEvent>, eventKey: number | string) => void;
|
|
45
|
-
/** @beta Callback to handle tab closing */
|
|
45
|
+
/** @beta Callback to handle tab closing and adds a basic close button to all tabs. This is overridden by the tab actions property. */
|
|
46
46
|
onClose?: (event: React.MouseEvent<HTMLElement, MouseEvent>, eventKey: number | string) => void;
|
|
47
47
|
/** @beta Callback for the add button. Passing this property inserts the add button */
|
|
48
48
|
onAdd?: () => void;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { render } from '@testing-library/react';
|
|
3
3
|
import { Tab } from '../Tab';
|
|
4
|
+
import { TabAction } from '../TabAction';
|
|
4
5
|
import { TabTitleText } from '../TabTitleText';
|
|
5
6
|
|
|
6
7
|
test('should not render anything', () => {
|
|
@@ -11,3 +12,12 @@ test('should not render anything', () => {
|
|
|
11
12
|
);
|
|
12
13
|
expect(asFragment()).toMatchSnapshot();
|
|
13
14
|
});
|
|
15
|
+
|
|
16
|
+
test('renders tab action', () => {
|
|
17
|
+
const { asFragment } = render(
|
|
18
|
+
<Tab eventKey={1} title={<TabTitleText>"Tab item 2"</TabTitleText>} actions={<TabAction>test</TabAction>}>
|
|
19
|
+
Tab 2 section
|
|
20
|
+
</Tab>
|
|
21
|
+
);
|
|
22
|
+
expect(asFragment()).toMatchSnapshot();
|
|
23
|
+
});
|