@itwin/components-react 5.20.0 → 5.21.1

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 CHANGED
@@ -1,5 +1,21 @@
1
1
  # Change Log - @itwin/components-react
2
2
 
3
+ ## 5.21.1
4
+
5
+ ### Patch Changes
6
+
7
+ - @itwin/core-react@5.21.1
8
+
9
+ ## 5.21.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 43acfb9: Added `onBlur` and `onFocus` callbacks to `FormattedNumericInput`
14
+
15
+ ### Patch Changes
16
+
17
+ - @itwin/core-react@5.21.0
18
+
3
19
  ## 5.20.0
4
20
 
5
21
  ### Patch Changes
@@ -2,12 +2,13 @@
2
2
  * @module PropertyEditors
3
3
  */
4
4
  import * as React from "react";
5
+ import { Input } from "@itwin/itwinui-react";
5
6
  import type { NumericValue } from "../values/Values.js";
6
7
  /**
7
8
  * Props for FormattedNumericInput component.
8
9
  * @beta
9
10
  */
10
- interface FormattedNumericInputProps {
11
+ interface FormattedNumericInputProps extends Pick<React.ComponentPropsWithoutRef<typeof Input>, "onBlur" | "onFocus"> {
11
12
  value: NumericValue;
12
13
  onChange: (value: NumericValue) => void;
13
14
  parseValue: (value: string) => number | undefined;
@@ -19,6 +20,6 @@ interface FormattedNumericInputProps {
19
20
  * A numeric input that allows to pass custom parsing/formatting logic to handle values with units etc.
20
21
  * @beta
21
22
  */
22
- export declare function FormattedNumericInput({ onChange, value, parseValue, formatValue, disabled, size, }: FormattedNumericInputProps): React.JSX.Element;
23
+ export declare function FormattedNumericInput({ onChange, value, parseValue, formatValue, disabled, size, ...props }: FormattedNumericInputProps): React.JSX.Element;
23
24
  export {};
24
25
  //# sourceMappingURL=FormattedNumericInput.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FormattedNumericInput.d.ts","sourceRoot":"","sources":["../../../../src/components-react/new-editors/editors/FormattedNumericInput.tsx"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAIxD;;;GAGG;AACH,UAAU,0BAA0B;IAClC,KAAK,EAAE,YAAY,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACxC,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAClD,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,KAAK,EACL,UAAU,EACV,WAAW,EACX,QAAQ,EACR,IAAI,GACL,EAAE,0BAA0B,qBAgB5B"}
1
+ {"version":3,"file":"FormattedNumericInput.d.ts","sourceRoot":"","sources":["../../../../src/components-react/new-editors/editors/FormattedNumericInput.tsx"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAIxD;;;GAGG;AACH,UAAU,0BACR,SAAQ,IAAI,CACV,KAAK,CAAC,wBAAwB,CAAC,OAAO,KAAK,CAAC,EAC5C,QAAQ,GAAG,SAAS,CACrB;IACD,KAAK,EAAE,YAAY,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACxC,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAClD,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,KAAK,EACL,UAAU,EACV,WAAW,EACX,QAAQ,EACR,IAAI,EACJ,GAAG,KAAK,EACT,EAAE,0BAA0B,qBAgB5B"}
@@ -11,7 +11,7 @@ import { Input } from "@itwin/itwinui-react";
11
11
  * A numeric input that allows to pass custom parsing/formatting logic to handle values with units etc.
12
12
  * @beta
13
13
  */
14
- export function FormattedNumericInput({ onChange, value, parseValue, formatValue, disabled, size, }) {
14
+ export function FormattedNumericInput({ onChange, value, parseValue, formatValue, disabled, size, ...props }) {
15
15
  const { currentValue, inputProps } = useParsedNumberInput({
16
16
  initialValue: value.rawValue,
17
17
  parseValue,
@@ -24,7 +24,7 @@ export function FormattedNumericInput({ onChange, value, parseValue, formatValue
24
24
  React.useEffect(() => {
25
25
  onChangeRef.current(currentValue);
26
26
  }, [currentValue]);
27
- return React.createElement(Input, { disabled: disabled, size: size, ...inputProps });
27
+ return React.createElement(Input, { ...props, ...inputProps, disabled: disabled, size: size });
28
28
  }
29
29
  function useParsedNumberInput({ initialValue, formatValue, parseValue, }) {
30
30
  const [state, setState] = React.useState(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"FormattedNumericInput.js","sourceRoot":"","sources":["../../../../src/components-react/new-editors/editors/FormattedNumericInput.tsx"],"names":[],"mappings":"AAAA;;;gGAGgG;AAChG;;GAEG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAkB7C;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,EACpC,QAAQ,EACR,KAAK,EACL,UAAU,EACV,WAAW,EACX,QAAQ,EACR,IAAI,GACuB;IAC3B,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,oBAAoB,CAAC;QACxD,YAAY,EAAE,KAAK,CAAC,QAAQ;QAC5B,UAAU;QACV,WAAW;KACZ,CAAC,CAAC;IACH,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC3C,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,WAAW,CAAC,OAAO,GAAG,QAAQ,CAAC;IACjC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACpC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;IAEnB,OAAO,oBAAC,KAAK,IAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,KAAM,UAAU,GAAI,CAAC;AACnE,CAAC;AAED,SAAS,oBAAoB,CAAC,EAC5B,YAAY,EACZ,WAAW,EACX,UAAU,GAKX;IAMC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAQ,GAAG,EAAE;QACnD,OAAO;YACL,KAAK,EAAE;gBACL,QAAQ,EAAE,YAAY;gBACtB,YAAY,EACV,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE;aAC9D;YACD,WAAW,EAAE,WAAW,CAAC,YAAY,IAAI,MAAM,CAAC;SACjD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,QAAQ,CAAC,CAAC,SAAS,EAAE,EAAE;YACrB,OAAO;gBACL,GAAG,SAAS;gBACZ,KAAK,EAAE;oBACL,GAAG,SAAS,CAAC,KAAK;oBAClB,YAAY,EACV,SAAS,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS;wBACpC,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC;wBACvC,CAAC,CAAC,EAAE;iBACT;gBACD,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC;aACjC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElB,MAAM,YAAY,GAAG,CAAC,CAAsC,EAAE,EAAE;QAC9D,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QAChC,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QAEtC,QAAQ,CAAC,CAAC,SAAS,EAAE,EAAE;YACrB,OAAO;gBACL,GAAG,SAAS;gBACZ,KAAK,EAAE;oBACL,GAAG,SAAS,CAAC,KAAK;oBAClB,QAAQ;oBACR,YAAY,EAAE,QAAQ;iBACvB;aACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,OAAO;QACL,YAAY,EAAE,KAAK,CAAC,KAAK;QACzB,UAAU,EAAE;YACV,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,YAAY;YAC/B,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,QAAQ,EAAE,YAAY;SACvB;KACF,CAAC;AACJ,CAAC;AAED,oBAAoB","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n/** @packageDocumentation\n * @module PropertyEditors\n */\n\nimport * as React from \"react\";\nimport { Input } from \"@itwin/itwinui-react\";\nimport type { NumericValue } from \"../values/Values.js\";\n\n/* v8 ignore start */\n\n/**\n * Props for FormattedNumericInput component.\n * @beta\n */\ninterface FormattedNumericInputProps {\n value: NumericValue;\n onChange: (value: NumericValue) => void;\n parseValue: (value: string) => number | undefined;\n formatValue: (num: number) => string;\n disabled?: boolean;\n size?: \"small\" | \"large\";\n}\n\n/**\n * A numeric input that allows to pass custom parsing/formatting logic to handle values with units etc.\n * @beta\n */\nexport function FormattedNumericInput({\n onChange,\n value,\n parseValue,\n formatValue,\n disabled,\n size,\n}: FormattedNumericInputProps) {\n const { currentValue, inputProps } = useParsedNumberInput({\n initialValue: value.rawValue,\n parseValue,\n formatValue,\n });\n const onChangeRef = React.useRef(onChange);\n React.useEffect(() => {\n onChangeRef.current = onChange;\n }, [onChange]);\n\n React.useEffect(() => {\n onChangeRef.current(currentValue);\n }, [currentValue]);\n\n return <Input disabled={disabled} size={size} {...inputProps} />;\n}\n\nfunction useParsedNumberInput({\n initialValue,\n formatValue,\n parseValue,\n}: {\n initialValue: number | undefined;\n parseValue: (value: string) => number | undefined;\n formatValue: (num: number) => string;\n}) {\n interface State {\n value: NumericValue;\n placeholder: string;\n }\n\n const [state, setState] = React.useState<State>(() => {\n return {\n value: {\n rawValue: initialValue,\n displayValue:\n initialValue !== undefined ? formatValue(initialValue) : \"\",\n },\n placeholder: formatValue(initialValue ?? 123.45),\n };\n });\n\n React.useEffect(() => {\n setState((prevState) => {\n return {\n ...prevState,\n value: {\n ...prevState.value,\n displayValue:\n prevState.value.rawValue !== undefined\n ? formatValue(prevState.value.rawValue)\n : \"\",\n },\n placeholder: formatValue(123.45),\n };\n });\n }, [formatValue]);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n const rawValue = parseValue(newValue);\n\n setState((prevState) => {\n return {\n ...prevState,\n value: {\n ...prevState.value,\n rawValue,\n displayValue: newValue,\n },\n };\n });\n };\n\n return {\n currentValue: state.value,\n inputProps: {\n value: state.value.displayValue,\n placeholder: state.placeholder,\n onChange: handleChange,\n },\n };\n}\n\n/* v8 ignore stop */\n"]}
1
+ {"version":3,"file":"FormattedNumericInput.js","sourceRoot":"","sources":["../../../../src/components-react/new-editors/editors/FormattedNumericInput.tsx"],"names":[],"mappings":"AAAA;;;gGAGgG;AAChG;;GAEG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAsB7C;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,EACpC,QAAQ,EACR,KAAK,EACL,UAAU,EACV,WAAW,EACX,QAAQ,EACR,IAAI,EACJ,GAAG,KAAK,EACmB;IAC3B,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,oBAAoB,CAAC;QACxD,YAAY,EAAE,KAAK,CAAC,QAAQ;QAC5B,UAAU;QACV,WAAW;KACZ,CAAC,CAAC;IACH,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC3C,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,WAAW,CAAC,OAAO,GAAG,QAAQ,CAAC;IACjC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACpC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;IAEnB,OAAO,oBAAC,KAAK,OAAK,KAAK,KAAM,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,GAAI,CAAC;AAC9E,CAAC;AAED,SAAS,oBAAoB,CAAC,EAC5B,YAAY,EACZ,WAAW,EACX,UAAU,GAKX;IAMC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAQ,GAAG,EAAE;QACnD,OAAO;YACL,KAAK,EAAE;gBACL,QAAQ,EAAE,YAAY;gBACtB,YAAY,EACV,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE;aAC9D;YACD,WAAW,EAAE,WAAW,CAAC,YAAY,IAAI,MAAM,CAAC;SACjD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,QAAQ,CAAC,CAAC,SAAS,EAAE,EAAE;YACrB,OAAO;gBACL,GAAG,SAAS;gBACZ,KAAK,EAAE;oBACL,GAAG,SAAS,CAAC,KAAK;oBAClB,YAAY,EACV,SAAS,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS;wBACpC,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC;wBACvC,CAAC,CAAC,EAAE;iBACT;gBACD,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC;aACjC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElB,MAAM,YAAY,GAAG,CAAC,CAAsC,EAAE,EAAE;QAC9D,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QAChC,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QAEtC,QAAQ,CAAC,CAAC,SAAS,EAAE,EAAE;YACrB,OAAO;gBACL,GAAG,SAAS;gBACZ,KAAK,EAAE;oBACL,GAAG,SAAS,CAAC,KAAK;oBAClB,QAAQ;oBACR,YAAY,EAAE,QAAQ;iBACvB;aACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,OAAO;QACL,YAAY,EAAE,KAAK,CAAC,KAAK;QACzB,UAAU,EAAE;YACV,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,YAAY;YAC/B,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,QAAQ,EAAE,YAAY;SACvB;KACF,CAAC;AACJ,CAAC;AAED,oBAAoB","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n/** @packageDocumentation\n * @module PropertyEditors\n */\n\nimport * as React from \"react\";\nimport { Input } from \"@itwin/itwinui-react\";\nimport type { NumericValue } from \"../values/Values.js\";\n\n/* v8 ignore start */\n\n/**\n * Props for FormattedNumericInput component.\n * @beta\n */\ninterface FormattedNumericInputProps\n extends Pick<\n React.ComponentPropsWithoutRef<typeof Input>,\n \"onBlur\" | \"onFocus\"\n > {\n value: NumericValue;\n onChange: (value: NumericValue) => void;\n parseValue: (value: string) => number | undefined;\n formatValue: (num: number) => string;\n disabled?: boolean;\n size?: \"small\" | \"large\";\n}\n\n/**\n * A numeric input that allows to pass custom parsing/formatting logic to handle values with units etc.\n * @beta\n */\nexport function FormattedNumericInput({\n onChange,\n value,\n parseValue,\n formatValue,\n disabled,\n size,\n ...props\n}: FormattedNumericInputProps) {\n const { currentValue, inputProps } = useParsedNumberInput({\n initialValue: value.rawValue,\n parseValue,\n formatValue,\n });\n const onChangeRef = React.useRef(onChange);\n React.useEffect(() => {\n onChangeRef.current = onChange;\n }, [onChange]);\n\n React.useEffect(() => {\n onChangeRef.current(currentValue);\n }, [currentValue]);\n\n return <Input {...props} {...inputProps} disabled={disabled} size={size} />;\n}\n\nfunction useParsedNumberInput({\n initialValue,\n formatValue,\n parseValue,\n}: {\n initialValue: number | undefined;\n parseValue: (value: string) => number | undefined;\n formatValue: (num: number) => string;\n}) {\n interface State {\n value: NumericValue;\n placeholder: string;\n }\n\n const [state, setState] = React.useState<State>(() => {\n return {\n value: {\n rawValue: initialValue,\n displayValue:\n initialValue !== undefined ? formatValue(initialValue) : \"\",\n },\n placeholder: formatValue(initialValue ?? 123.45),\n };\n });\n\n React.useEffect(() => {\n setState((prevState) => {\n return {\n ...prevState,\n value: {\n ...prevState.value,\n displayValue:\n prevState.value.rawValue !== undefined\n ? formatValue(prevState.value.rawValue)\n : \"\",\n },\n placeholder: formatValue(123.45),\n };\n });\n }, [formatValue]);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n const rawValue = parseValue(newValue);\n\n setState((prevState) => {\n return {\n ...prevState,\n value: {\n ...prevState.value,\n rawValue,\n displayValue: newValue,\n },\n };\n });\n };\n\n return {\n currentValue: state.value,\n inputProps: {\n value: state.value.displayValue,\n placeholder: state.placeholder,\n onChange: handleChange,\n },\n };\n}\n\n/* v8 ignore stop */\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/components-react",
3
- "version": "5.20.0",
3
+ "version": "5.21.1",
4
4
  "description": "A react component library of iTwin.js UI data-oriented components",
5
5
  "type": "module",
6
6
  "types": "./lib/components-react.d.ts",
@@ -40,7 +40,7 @@
40
40
  "@itwin/itwinui-react": "^3.15.0",
41
41
  "react": "^18.0.0 || ^19.0.0",
42
42
  "react-dom": "^18.0.0 || ^19.0.0",
43
- "@itwin/core-react": "5.20.0"
43
+ "@itwin/core-react": "5.21.1"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@itwin/appui-abstract": "^5.1.0",
@@ -55,8 +55,8 @@
55
55
  "@testing-library/user-event": "^14.6.1",
56
56
  "@types/linkify-it": "~2.1.0",
57
57
  "@types/lodash": "^4.14.0",
58
- "@types/react": "^19.2.0",
59
- "@types/react-dom": "^19.2.0",
58
+ "@types/react": "^19.2.7",
59
+ "@types/react-dom": "^19.2.3",
60
60
  "@types/react-window": "^1.8.2",
61
61
  "@vitest/coverage-v8": "^3.0.6",
62
62
  "cpx2": "^3.0.0",
@@ -67,15 +67,15 @@
67
67
  "jsdom": "^24.0.0",
68
68
  "npm-run-all": "^4.1.5",
69
69
  "raf": "^3.4.0",
70
- "react": "^19.2.0",
71
- "react-dom": "^19.2.0",
70
+ "react": "^19.2.1",
71
+ "react-dom": "^19.2.1",
72
72
  "rimraf": "^6.1.0",
73
73
  "ts-node": "^10.8.2",
74
74
  "typemoq": "^2.1.0",
75
75
  "typescript": "~5.6.2",
76
76
  "upath": "^2.0.1",
77
77
  "vitest": "^3.2.4",
78
- "@itwin/core-react": "5.20.0"
78
+ "@itwin/core-react": "5.21.1"
79
79
  },
80
80
  "dependencies": {
81
81
  "@itwin/itwinui-icons-react": "^2.8.0",