Wrappers for the Nested Properties and Collections
For the nested properties like Selectable.colors.normalColor or properties in collections wrappers should be create manually.
Widget with Nested Field
public class WidgetWithNestedField : MonoBehaviour
{
        [Serializable]
        public class Data
        {
                public string Name;
                // nested property cannot be automatically accessed
                public Sprite Icon;
        }
        public Data WidgetData = new Data();
        public void UpdateData()
        {
                // update game objects which display WidgetData
        }
}
Wrapper for the Widget with Nested Field
public class WidgetWithNestedFieldWrapper : Wrapper<Sprite, WidgetWithNestedField>
{
        public WidgetWithNestedFieldWrapper()
        {
                Name = string.Format("{0}.{1}", nameof(WidgetWithNestedField.WidgetData), nameof(WidgetWithNestedField.Data.Icon));
        }
        protected override Sprite Get(WidgetWithNestedField widget) => widget.WidgetData?.Icon;
        protected override void Set(WidgetWithNestedField widget, Sprite value)
        {
                widget.WidgetData.Icon = value;
                widget.UpdateData();
        }
        protected override bool ShouldAttachValue(WidgetWithNestedField widget) => Get(widget) != null;
        [PropertiesRegistry, Preserve]
        public static void AddWrappers()
        {
                PropertyWrappers<Sprite>.Add(new WidgetWithNestedFieldWrapper());
        }
}
Widget with Collections
public class WidgetWithList : MonoBehaviour
{
        [Serializable]
        public class Data
        {
                public string Name;
                public Sprite Icon;
        }
        // properties in collections cannot be automatically accessed
        public List<Data> WidgetData = new List<Data>();
        public void UpdateData(int index)
        {
                // update game objects that display WidgetData[index]
        }
}
Wrapper for the Widget with Collections
public class WidgetWithListWrapper : Wrapper<Sprite, WidgetWithList>
{
        readonly int index;
        public WidgetWithListWrapper(int index)
        {
                this.index = index;
                Name = string.Format("{0}[{1}].{2}", nameof(WidgetWithList.WidgetData), index, nameof(WidgetWithList.Data.Icon));
        }
        protected override Sprite Get(WidgetWithList widget) => Active(widget) ? widget.WidgetData[index].Icon : null;
        protected override void Set(WidgetWithList widget, Sprite value)
        {
                if (Active(widget))
                {
                        widget.WidgetData[index].Icon = value;
                        widget.UpdateData(index);
                }
        }
        protected override bool Active(WidgetWithList widget) => index < widget.WidgetData.Count;
        protected override bool ShouldAttachValue(WidgetWithList widget) => Get(widget) != null;
        [PropertiesRegistry, Preserve]
        public static void AddWrappers()
        {
                // 20 is the maximum supported size of the WidgetData array and can be changed
                for (var i = 0; i < 20; i++)
                {
                        PropertyWrappers<Sprite>.Add(new WidgetWithListWrapper(i));
                }
        }
}