import { prepareInterceptor } from './interceptor' ; import { clearUISelection } from './selection' ; const UIValue = Symbol ( 'Displayed value in UI' ) ; const InitialValue = Symbol ( 'Initial value to compare on blur' ) ; const TrackChanges = Symbol ( 'Track programmatic changes for React workaround' ) ; type Value = { [ UIValue ] ? : typeof UIValue ; toString ( ) : string ; } ; declare global { interface Element { [ UIValue ] ? : string ; [ InitialValue ] ? : string ; [ TrackChanges ] ? : string [ ] ; } } function valueInterceptor ( this , v ) { const isUI = typeof v === 'object' && v [ UIValue ] ; this [ UIValue ] = isUI ? String ( v ) : undefined ; if ( ! isUI ) { trackValue ( this , String ( v ) ) ; this [ InitialValue ] = String ( v ) ; clearUISelection ( this ) ; } return { applyNative : ! ! isUI , realArgs : String ( v ) , } ; } export function prepareValueInterceptor ( element ) { prepareInterceptor ( element , 'value' , valueInterceptor ) ; } export function setUIValue ( element , value ) { element . value = { [ UIValue ] : UIValue , toString : ( ) => value , } as unknown as string ; } export function getUIValue ( element ) { return element [ UIValue ] === undefined ? element . value : String ( element [ UIValue ] ) ; } export function setInitialValue ( element ) { element [ InitialValue ] = element . value ; } export function getInitialValue ( element ) { return element [ InitialValue ] ; } export function startTrackValue ( element ) { element [ TrackChanges ] = [ ] ; } function trackValue ( element , v ) { element [ TrackChanges ] ?. push ( v ) ; } export function endTrackValue ( element ) { const tracked = element [ TrackChanges ] ; element [ TrackChanges ] = undefined ; return tracked ; }