import { toKebabCase , evaluate } from '../../esl-utils/misc/format' ; import type { ESLBaseElement } from '../core/esl-base-element' ; /** HTML attribute to object property mapping configuration */ interface JsonAttrDescriptor < T > { /** HTML attribute name. Uses kebab-cased variable name by default */ name ? : string ; /** Create getter only */ readonly ? : boolean ; /** Use data-* attribute */ dataAttr ? : boolean ; /** Default property value. Used if no attribute is present on the element. Empty string by default. */ defaultValue ? : T ; } function buildJsonAttrDescriptor < T > ( attrName , readOnly , defaultValue ) { function get ( ) { const attrContent = ( this . getAttribute ( attrName ) || '' ) . trim ( ) ; return evaluate ( attrContent , defaultValue ) ; } function set ( value ) { if ( typeof value !== 'object' ) { console . error ( 'Can not set json value: value should be object' ) ; } try { if ( value ) { const serializedValue = JSON . stringify ( value ) ; this . setAttribute ( attrName , serializedValue ) ; } else { this . removeAttribute ( attrName ) ; } } catch ( e ) { console . error ( '[ESL] jsonAttr: Can not set json value ' , e ) ; } } return readOnly ? { get } : { get , set } ; } const buildAttrName = ( propName , dataAttr ) : string => dataAttr ? `data-${ toKebabCase ( propName ) }` : toKebabCase ( propName ) ; param config - mapping configuration. See  JsonAttrDescriptor export const jsonAttr = < T > ( config = { } ) : PropertyDecorator => { config = Object . assign ( { defaultValue : { } } , config ) ; return ( target , propName ) : void => { const attrName = buildAttrName ( config . name || propName , ! ! config . dataAttr ) ; Object . defineProperty ( target , propName , buildJsonAttrDescriptor ( attrName , ! ! config . readonly , config . defaultValue ) ) ; } ; } ;