packageDocumentation module import * as React from "react" ; import { UnitProps , UnitsProvider } from "@itwin/core-quantity" ; import { CommonProps } from "@itwin/core-react" ; import { Input , Select , SelectOption } from "@itwin/itwinui-react" ; internal export interface UnitDescrProps extends CommonProps { name : string ; parentUnitName ? : string ; label : string ; index : number ; unitsProvider : UnitsProvider ; readonly ? : boolean ; onUnitChange : ( value : string , index : number ) => void ; onLabelChange : ( value : string , index : number ) => void ; } async function getUnitConversionData ( possibleUnits , toUnit , unitsProvider ) { const unitConversionEntries = possibleUnits . map ( async ( unit ) => { const conversion = await unitsProvider . getConversion ( unit , toUnit ) ; return { conversion , unitProps : unit } ; } ) ; return unitConversionEntries ; } async function getPossibleUnits ( parentUnit , unitsProvider , ensureCompatibleComposite ) { const phenomenon = parentUnit . phenomenon ; const possibleUnits = await unitsProvider . getUnitsByFamily ( phenomenon ) ; if ( ! ensureCompatibleComposite ) return possibleUnits ; const conversionPromises = await getUnitConversionData ( possibleUnits , parentUnit , unitsProvider ) ; const conversionEntries = await Promise . all ( conversionPromises ) ; return conversionEntries . filter ( ( entry ) => ( ( entry . unitProps . system === parentUnit . system ) && ( entry . conversion . factor < 1 ) ) ) . sort ( ( a , b ) => b . conversion . factor - a . conversion . factor ) . map ( ( value ) => value . unitProps ) ; } function getUnitName ( fullUnitName ) { const nameParts = fullUnitName . split ( /[.:]/ ) ; if ( nameParts . length > 0 ) return nameParts [ nameParts . length - 1 ] ; throw Error ( "Bad unit name encountered" ) ; } internal export function UnitDescr ( props ) { const { name , label , parentUnitName , index , onUnitChange , onLabelChange , readonly , unitsProvider } = props ; const [ unitOptions , setUnitOptions ] = React . useState < SelectOption < string > [ ] > ( [ { value : name , label : getUnitName ( name ) } ] ) ; const [ currentUnit , setCurrentUnit ] = React . useState ( { name , label } ) ; const isMounted = React . useRef ( false ) ; React . useEffect ( ( ) => { isMounted . current = true ; return ( ) => { isMounted . current = false ; } ; } ) ; React . useEffect ( ( ) => { async function fetchAllowableUnitSelections ( ) { const currentUnitProps = await unitsProvider . findUnitByName ( name ) ; const parentUnit = await unitsProvider . findUnitByName ( parentUnitName ? parentUnitName : name ) ; if ( parentUnit && currentUnitProps ) { let potentialSubUnit ; const potentialUnits = await getPossibleUnits ( parentUnit , unitsProvider , index !== 0 ) ; if ( index < 3 ) { const potentialSubUnits = await getPossibleUnits ( currentUnitProps , unitsProvider , true ) ; if ( potentialSubUnits . length ) potentialSubUnit = potentialSubUnits [ 0 ] ; } const options = ( potentialUnits . length > 0 ) ? potentialUnits . map ( ( unitValue ) => { return { value : `${ unitValue . name }:${ unitValue . label }` , label : getUnitName ( unitValue . name ) } ; } ) . sort ( ( a , b ) => a . label . localeCompare ( b . label ) ) : [ { value : `${ currentUnitProps . name }:${ currentUnitProps . label }` , label : getUnitName ( name ) } ] ; if ( potentialSubUnit ) { options . push ( { value : `ADDSUBUNIT:${ potentialSubUnit . name }:${ potentialSubUnit . label }` , label : "Add sub-unit" } ) ; } if ( index !== 0 ) options . push ( { value : "REMOVEUNIT" , label : "Remove" } ) ; if ( isMounted . current ) { setUnitOptions ( options ) ; setCurrentUnit ( currentUnitProps ) ; } } } fetchAllowableUnitSelections ( ) ; } , [ index , label , name , parentUnitName , unitsProvider ] ) ; const handleOnUnitChange = React . useCallback ( ( newValue ) => { onUnitChange && onUnitChange ( newValue , index ) ; } , [ index , onUnitChange ] ) ; const handleOnLabelChange = React . useCallback ( ( e ) => { e . preventDefault ( ) ; onLabelChange && onLabelChange ( e . target . value , index ) ; } , [ index , onLabelChange ] ) ; return ( < > < Select options = { unitOptions } data - testid = { `unit-${ currentUnit . name }` } value = { `${ currentUnit . name }:${ currentUnit . label }` } onChange = { handleOnUnitChange } disabled = { readonly } size = "small" / > < Input data - testid = { `unit-label-${ currentUnit . name }` } value = { label } onChange = { handleOnLabelChange } size = "small" / > < />); }