UNPKG

@itwin/presentation-components

Version:

React components based on iTwin.js Presentation library

107 lines 4.43 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ Object.defineProperty(exports, "__esModule", { value: true }); exports.getPersistenceUnitRoundingError = getPersistenceUnitRoundingError; exports.getDecimalRoundingError = getDecimalRoundingError; const core_quantity_1 = require("@itwin/core-quantity"); /** * Finds rounding error for entered value and converts it to persistence unit. * @internal */ function getPersistenceUnitRoundingError(numberStr, parser) { const tokens = core_quantity_1.Parser.parseQuantitySpecification(numberStr, parser.format); const enteredUnit = tokens.length > 0 && tokens[tokens.length - 1].isString ? tokens[tokens.length - 1].value : undefined; const precisionStr = getPrecision(numberStr, parser.format); if (!precisionStr) { return undefined; } // convert precision to persistence unit const parseResult = parser.parseToQuantityValue(enteredUnit ? `${precisionStr}${enteredUnit}` : precisionStr); return parseResult.ok ? parseResult.value : undefined; } /** @internal */ function getDecimalRoundingError(numStr) { const precision = getDecimalPrecision(numStr); return precision ? Number(precision) : undefined; } function getPrecision(numberStr, format) { // use decimal precision if number contains decimal separator if (numberStr.includes(getLocalizedDecimalSeparator())) { return getDecimalPrecision(numberStr); } // use fractional precision if number contains fraction separator if (numberStr.includes("/")) { return getFractionalPrecision(numberStr); } // if number does not have decimal or fraction separator use precision based on format type. // TODO: this might not be correct in all cases. For example: // if format is `Fractional` but entered value is `2 m` precision should be `0.5 m` but we will get ` 1/16 m` if (format.type === core_quantity_1.FormatType.Decimal) { return getDecimalPrecision(numberStr); } if (format.type === core_quantity_1.FormatType.Fractional) { return getFractionalPrecision(numberStr); } return undefined; } let localeSpecificDecimalSeparator; function getLocalizedDecimalSeparator() { if (localeSpecificDecimalSeparator !== undefined) { return localeSpecificDecimalSeparator; } localeSpecificDecimalSeparator = "."; const matches = (12345.6789).toLocaleString().match(/345(.*)67/); if (matches && matches.length > 1) { localeSpecificDecimalSeparator = matches[1]; } return localeSpecificDecimalSeparator; } function getFractionalPrecision(numStr) { const digitsAfterFraction = parseDigitsAfterSymbol(numStr, "/"); if (digitsAfterFraction.result !== "success") { return digitsAfterFraction.result === "noSymbol" ? "1/2" : undefined; } return `1/${Number(digitsAfterFraction.value) * 2}`; } function getDecimalPrecision(numStr) { const separator = getLocalizedDecimalSeparator(); const digitsAfterSeparator = parseDigitsAfterSymbol(numStr, separator); if (digitsAfterSeparator.result !== "success") { return digitsAfterSeparator.result === "noSymbol" ? "0.5" : undefined; } return `${0.5 * Math.pow(10, -digitsAfterSeparator.value.length)}`; } function parseDigitsAfterSymbol(numStr, symbol) { let lastDigitIndex = -1; for (let i = numStr.length - 1; i >= 0; i--) { if (isDigit(numStr[i])) { lastDigitIndex = i; break; } } if (lastDigitIndex === -1) { return { result: "noNumber" }; } let symbolIndex = -1; // find symbol position in the number for (let i = lastDigitIndex - 1; i >= 0; i--) { if (numStr[i] === symbol) { symbolIndex = i; break; } if (!isDigit(numStr[i])) { break; } } if (symbolIndex === -1) { return { result: "noSymbol" }; } return { result: "success", value: numStr.substring(symbolIndex + 1, lastDigitIndex + 1) }; } function isDigit(char) { return Number.isFinite(parseInt(char, 10)); } //# sourceMappingURL=Utils.js.map