Browse Source

Add __getPropsFromStyle to composite type

up-style-manager
Artur Arseniev 4 years ago
parent
commit
f16db52120
  1. 2
      src/style_manager/index.js
  2. 63
      src/style_manager/model/PropertyComposite.js
  3. 69
      src/style_manager/model/PropertyStack.js
  4. 86
      test/specs/style_manager/model/Properties.js

2
src/style_manager/index.js

@ -594,7 +594,9 @@ export default () => {
const value = style[name];
const hasVal = propDef(value);
const isStack = prop.getType() === 'stack';
const isComposite = prop.getType() === 'composite';
let newLayers = isStack ? prop.__getLayersFromStyle(style) : [];
// let newProps = isComposite ? prop.__getPropsFromStyle(style) : {};
let newValue = hasVal ? value : null;
let parentTarget = null;

63
src/style_manager/model/PropertyComposite.js

@ -1,4 +1,4 @@
import { isString } from 'underscore';
import { isString, isUndefined } from 'underscore';
import Property from './Property';
export default Property.extend({
@ -92,17 +92,19 @@ export default Property.extend({
return isString(join) ? join : this.get('separator');
},
// TODO remove
__getFromStyle(style = {}) {
let result = {};
const fromStyle = this.get('fromStyle');
const sep = this.getSplitSeparator();
const name = this.getName();
if (fromStyle) {
result = fromStyle(style);
result = fromStyle(style, { property: this, separator: sep });
} else {
const name = this.getName();
const value = style[name];
if (value) {
const values = value.split(this.getSplitSeparator());
const values = value.split(sep);
this.getProperties().forEach((prop, i) => {
const len = values.length;
// Try to get value from a shorthand:
@ -123,6 +125,59 @@ export default Property.extend({
return result;
},
__styleHasProps(style = {}) {
const name = this.getName();
const props = this.getProperties();
const nameProps = props.map(prop => prop.getName());
const allNameProps = [name, ...nameProps];
return allNameProps.some(prop => !isUndefined(style[prop]) && style[prop] !== '');
},
__splitStyleName(style, name, sep) {
return (style[name] || '')
.split(sep)
.map(value => value.trim())
.filter(Boolean);
},
__getPropsFromStyle(style = {}) {
if (!this.__styleHasProps(style)) return null;
const props = this.getProperties();
const sep = this.getSplitSeparator();
const fromStyle = this.get('fromStyle');
let result = fromStyle ? fromStyle(style, { property: this, separator: sep }) : {};
if (!fromStyle) {
const props4Nums = props.length === 4 && props.every(prop => prop.getType() === 'integer');
// Get props from the main property
const values = this.__splitStyleName(style, this.getName(), sep);
props.forEach((prop, i) => {
const value = values[i];
let res = !isUndefined(value) ? value : prop.getDefaultValue();
if (props4Nums) {
// Try to get value from a shorthand:
// 11px -> 11px 11px 11px 11xp
// 11px 22px -> 11px 22px 11px 22xp
const len = values.length;
res = values[i] || values[(i % len) + (len != 1 && len % 2 ? 1 : 0)] || res;
}
result[prop.getId()] = res || '';
});
// Get props from the inner properties
props.forEach(prop => {
const value = style[prop.getName()];
if (!isUndefined(value) && value !== '') result[prop.getId()] = value;
});
}
return result;
},
clear() {
this.getProperties().map(p => p.clear({ __clearIn: !this.isDetached() }));
return Property.prototype.clear.call(this);

69
src/style_manager/model/PropertyStack.js

@ -7,13 +7,6 @@ import { camelCase } from 'utils/mixins';
const VALUES_REG = /,(?![^\(]*\))/;
const PARTS_REG = /\s(?![^(]*\))/;
const splitStyleName = (style, name, sep) => {
return (style[name] || '')
.split(sep)
.map(value => value.trim())
.filter(Boolean);
};
export default Property.extend({
defaults: {
...Property.prototype.defaults,
@ -141,45 +134,39 @@ export default Property.extend({
},
__getLayersFromStyle(style = {}) {
if (!this.__styleHasProps(style)) return null;
const name = this.getName();
const props = this.getProperties();
const nameProps = props.map(prop => prop.getName());
const allNameProps = [name, ...nameProps];
const hasProps = allNameProps.some(prop => !isUndefined(style[prop]) && style[prop] !== '');
if (!hasProps) {
return null;
} else {
const sep = this.getLayerSeparator();
const fromStyle = this.get('fromStyle');
let result = fromStyle ? fromStyle(style, { property: this, separatorLayers: sep }) : [];
if (!fromStyle) {
// Get layers from the main property
const layers = splitStyleName(style, name, sep)
.map(value => value.split(this.getSplitSeparator()))
.map(parts => {
const result = {};
props.forEach((prop, i) => {
const value = parts[i];
result[prop.getId()] = !isUndefined(value) ? value : prop.getDefaultValue();
});
return result;
const sep = this.getLayerSeparator();
const fromStyle = this.get('fromStyle');
let result = fromStyle ? fromStyle(style, { property: this, separatorLayers: sep }) : [];
if (!fromStyle) {
// Get layers from the main property
const layers = this.__splitStyleName(style, name, sep)
.map(value => value.split(this.getSplitSeparator()))
.map(parts => {
const result = {};
props.forEach((prop, i) => {
const value = parts[i];
result[prop.getId()] = !isUndefined(value) ? value : prop.getDefaultValue();
});
// Get layers from the inner properties
props.forEach(prop => {
const id = prop.getId();
splitStyleName(style, prop.getName(), sep)
.map(value => ({ [id]: value || prop.getDefaultValue() }))
.forEach((inLayer, i) => {
layers[i] = layers[i] ? { ...layers[i], ...inLayer } : inLayer;
});
return result;
});
result = layers;
}
return isArray(result) ? result : [result];
// Get layers from the inner properties
props.forEach(prop => {
const id = prop.getId();
this.__splitStyleName(style, prop.getName(), sep)
.map(value => ({ [id]: value || prop.getDefaultValue() }))
.forEach((inLayer, i) => {
layers[i] = layers[i] ? { ...layers[i], ...inLayer } : inLayer;
});
});
result = layers;
}
return isArray(result) ? result : [result];
},
hasValue(opts) {

86
test/specs/style_manager/model/Properties.js

@ -34,7 +34,10 @@ describe('StyleManager properties logic', () => {
describe('Composite type', () => {
const propTest = 'padding';
const propInTest = 'padding-top';
const propATest = `${propTest}-top`;
const propBTest = `${propTest}-right`;
const propCTest = `${propTest}-bottom`;
const propDTest = `${propTest}-left`;
let compTypeProp;
let compTypePropInn;
@ -49,7 +52,7 @@ describe('StyleManager properties logic', () => {
],
});
compTypeProp = obj.getProperty(sectorTest, propTest);
compTypePropInn = compTypeProp.getProperty(propInTest);
compTypePropInn = compTypeProp.getProperty(propATest);
em.setSelected(cmp);
obj.__upSel();
});
@ -72,11 +75,86 @@ describe('StyleManager properties logic', () => {
expect(obj.getLastSelected()).toBe(rule1);
});
test('Properties correctly reflect on rule update', () => {
compTypeProp.set('detached', false);
rule1.setStyle({ padding: '1px 2px 3px 4px' });
obj.__upSel();
[
[propATest, '1px'],
[propBTest, '2px'],
[propCTest, '3px'],
[propDTest, '4px'],
].forEach(item => {
expect(compTypeProp.getProperty(item[0]).getFullValue()).toBe(item[1]);
});
});
test('getPropsFromStyle returns correct values', () => {
expect(
compTypeProp.__getPropsFromStyle({
[propTest]: '1px 2px 3px 4px',
[propCTest]: '33px',
[propBTest]: '22%',
})
).toEqual({
[propATest]: '1px',
[propBTest]: '22%',
[propCTest]: '33px',
[propDTest]: '4px',
});
// Split correctly props in 4 numeric values
expect(
compTypeProp.__getPropsFromStyle({
[propTest]: '111px',
[propCTest]: '33px',
[propBTest]: '22%',
})
).toEqual({
[propATest]: '111px',
[propBTest]: '22%',
[propCTest]: '33px',
[propDTest]: '111px',
});
// Resolves correctly with values from inner properties
expect(
compTypeProp.__getPropsFromStyle({
color: 'red',
[propCTest]: '33px',
})
).toEqual({
[propATest]: '0',
[propBTest]: '0',
[propCTest]: '33px',
[propDTest]: '0',
});
// null if no properties are found
expect(compTypeProp.__getPropsFromStyle({ color: 'red' })).toEqual(null);
});
test('Update on properties reflects to the rule correctly', () => {
compTypeProp.set('detached', false);
rule1.setStyle({ padding: '1px 2px 3px 4px' });
obj.__upSel();
compTypeProp.getProperty(propCTest).upValue('50%');
obj.__upSel();
expect(rule1.getStyle()).toEqual({
__p: false,
padding: '1px 2px 50% 4px',
[propATest]: '',
[propBTest]: '',
[propCTest]: '',
[propDTest]: '',
});
});
test('Updating inner property, it reflects on the rule', () => {
compTypePropInn.upValue('55%');
const style = rule1.getStyle();
const otherProps = Object.keys(style).filter(p => p.indexOf('padding') >= 0 && p !== propInTest);
expect(style[propInTest]).toBe('55%');
const otherProps = Object.keys(style).filter(p => p.indexOf('padding') >= 0 && p !== propATest);
expect(style[propATest]).toBe('55%');
expect(compTypeProp.hasValue()).toBe(true);
expect(compTypePropInn.hasValue()).toBe(true);
otherProps.forEach(prop => {

Loading…
Cancel
Save