@itwin/presentation-components
Version:
React components based on iTwin.js Presentation library
97 lines • 4.3 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import { useEffect, useRef, useState } from "react";
import { assert } from "@itwin/core-bentley";
import { IModelApp } from "@itwin/core-frontend";
import { KoqPropertyValueFormatter } from "@itwin/presentation-common";
import { getPersistenceUnitRoundingError } from "./Utils.js";
const PLACEHOLDER_RAW_VALUE = 12.34;
/**
* Custom hook that manages state for quantity values input.
* @internal
*/
export function useQuantityValueInput({ initialRawValue, schemaContext, koqName }) {
const initialRawValueRef = useRef(initialRawValue);
const [{ quantityValue, placeholder }, setState] = useState(() => ({
quantityValue: {
rawValue: initialRawValueRef.current,
formattedValue: "",
roundingError: undefined,
},
placeholder: "",
}));
const { formatter, parser } = useFormatterAndParser(koqName, schemaContext);
useEffect(() => {
if (!formatter || !parser) {
return;
}
setState((prev) => {
const newPlaceholder = formatter.applyFormatting(initialRawValueRef.current ?? PLACEHOLDER_RAW_VALUE);
const newFormattedValue = prev.quantityValue.rawValue !== undefined ? formatter.applyFormatting(prev.quantityValue.rawValue) : "";
const roundingError = getPersistenceUnitRoundingError(newFormattedValue, parser);
return {
...prev,
quantityValue: {
...prev.quantityValue,
formattedValue: newFormattedValue,
roundingError,
},
placeholder: newPlaceholder,
};
});
}, [formatter, parser]);
const onChange = (e) => {
assert(parser !== undefined); // input should be disabled if parser is `undefined`
const newValue = e.currentTarget.value;
const parseResult = parser.parseToQuantityValue(newValue);
const roundingError = getPersistenceUnitRoundingError(newValue, parser);
setState((prev) => ({
...prev,
quantityValue: {
formattedValue: newValue,
rawValue: parseResult.ok ? parseResult.value : undefined,
roundingError: parseResult.ok ? roundingError : undefined,
},
}));
};
return {
quantityValue,
inputProps: {
onChange,
placeholder,
value: quantityValue.formattedValue,
disabled: !formatter || !parser,
},
};
}
function useFormatterAndParser(koqName, schemaContext) {
const [state, setState] = useState();
useEffect(() => {
const findFormatterAndParser = async () => {
// eslint-disable-next-line @typescript-eslint/no-deprecated
const koqFormatter = new KoqPropertyValueFormatter(schemaContext, undefined, IModelApp.formatsProvider);
const formatterSpec = await koqFormatter.getFormatterSpec({ koqName, unitSystem: IModelApp.quantityFormatter.activeUnitSystem });
const parserSpec = await koqFormatter.getParserSpec({ koqName, unitSystem: IModelApp.quantityFormatter.activeUnitSystem });
if (formatterSpec && parserSpec) {
setState({ formatterSpec, parserSpec });
return;
}
setState(undefined);
};
void findFormatterAndParser();
const listeners = [IModelApp.quantityFormatter.onActiveFormattingUnitSystemChanged.addListener(findFormatterAndParser)];
if (IModelApp.formatsProvider) {
listeners.push(IModelApp.formatsProvider.onFormatsChanged.addListener(findFormatterAndParser));
}
return () => {
listeners.forEach((listener) => listener());
};
}, [koqName, schemaContext]);
return {
formatter: state?.formatterSpec,
parser: state?.parserSpec,
};
}
//# sourceMappingURL=UseQuantityValueInput.js.map