Browse Source

Movr PropertyComposite to TS

ts-style-manager
Artur Arseniev 3 years ago
parent
commit
d604032d50
  1. 11
      src/style_manager/model/Property.ts
  2. 105
      src/style_manager/model/PropertyComposite.ts
  3. 68
      src/style_manager/model/PropertyFactory.ts

11
src/style_manager/model/Property.ts

@ -68,6 +68,13 @@ export interface PropertyProps {
__p?: any;
}
export type OptionsUpdate = {
partial?: boolean;
noTarget?: boolean;
__up?: boolean;
__clear?: boolean;
};
type PartialPropertyProps = Partial<PropertyProps>;
/**
@ -164,7 +171,7 @@ export default class Property<T extends Record<string, any> = PropertyProps> ext
sm?.addStyleTargets({ ...style, __p: !!opts.avoidStore }, opts);
}
_up(props: Partial<T>, opts: any = {}) {
_up(props: Partial<T>, opts: OptionsUpdate = {}) {
if (opts.noTarget) opts.__up = true;
const { partial, ...rest } = opts;
// @ts-ignore
@ -285,7 +292,7 @@ export default class Property<T extends Record<string, any> = PropertyProps> ext
* @param {Boolean} [opts.partial=false] If `true` the update on targets won't be considered complete (not stored in UndoManager)
* @param {Boolean} [opts.noTarget=false] If `true` the change won't be propagated to selected targets.
*/
upValue(value: string, opts = {}) {
upValue(value: string, opts: OptionsUpdate = {}) {
const parsed = value === null || value === '' ? this.__getClearProps() : this.__parseValue(value, opts);
return this._up(parsed as Partial<T>, opts);
}

105
src/style_manager/model/PropertyComposite.js → src/style_manager/model/PropertyComposite.ts

@ -1,8 +1,42 @@
import { isString, isUndefined, keys } from 'underscore';
import Property from './Property';
import Property, { OptionsUpdate, PropertyProps } from './Property';
import Properties from './Properties';
import { camelCase } from '../../utils/mixins';
export const isNumberType = type => type === 'integer' || type === 'number';
export const isNumberType = (type: string) => type === 'integer' || type === 'number';
type StyleProps = Record<string, string>;
type OptionByName = { byName?: boolean };
/** @private */
export interface PropertyCompositeProps extends PropertyProps {
detached?: boolean;
/**
* Array of sub properties, eg. `[{ type: 'number', property: 'margin-top' }, ...]`
*/
properties: PropertyProps[];
/**
* Value used to split property values, default `" "`.
*/
separator: string;
/**
* Value used to join property values, default `" "`.
*/
join?: string;
/**
* Custom logic for getting property values from the target style object.
*/
fromStyle?: (style: StyleProps, data: { property: Property; name: string; separator: RegExp }) => Record<string, any>;
/**
* Custom logic for creating the CSS style object to apply on selected targets.
*/
toStyle?: (values: Record<string, any>, data: { join: string; name: string; property: Property }) => StyleProps;
}
/**
*
@ -38,7 +72,7 @@ export const isNumberType = type => type === 'integer' || type === 'number';
* }
* ```
*/
export default class PropertyComposite extends Property {
export default class PropertyComposite extends Property<PropertyCompositeProps> {
defaults() {
return {
...Property.getDefaults(),
@ -53,22 +87,30 @@ export default class PropertyComposite extends Property {
}
initialize(props = {}, opts = {}) {
// @ts-ignore
Property.callParentInit(Property, this, props, opts);
const { em } = this;
const properties = new Properties(this.get('properties') || [], {
em,
parentProp: this,
});
this.set('properties', properties, { silent: 1 });
this.set('properties', properties, { silent: true });
this.listenTo(properties, 'change', this.__upProperties);
// @ts-ignore
Property.callInit(this, props, opts);
}
get properties(): Property[] {
// @ts-ignore
return this.get('properties')! || [];
}
/**
* Get properties.
* @returns {Array<[Property]>}
*/
getProperties() {
getProperties(): Property[] {
// @ts-ignore
return [...this.get('properties').models];
}
@ -77,8 +119,8 @@ export default class PropertyComposite extends Property {
* @param {String} id Property id.
* @returns {[Property]|null}
*/
getProperty(id) {
return this.get('properties').filter(prop => prop.getId() === id || prop.getName() === id)[0] || null;
getProperty(id: string): Property | undefined {
return this.properties.filter(prop => prop.getId() === id || prop.getName() === id)[0];
}
/**
@ -86,7 +128,8 @@ export default class PropertyComposite extends Property {
* @param {Number} index
* @returns {[Property]|null}
*/
getPropertyAt(index) {
getPropertyAt(index: number) {
// @ts-ignore
return this.get('properties').at(index);
}
@ -108,12 +151,12 @@ export default class PropertyComposite extends Property {
* console.log(property.getValues());
* // { 'margin-top': '10px', 'margin-right': '20px', ... };
*/
getValues({ byName } = {}) {
getValues({ byName }: { byName?: boolean } = {}) {
return this.getProperties().reduce((res, prop) => {
const key = byName ? prop.getName() : prop.getId();
res[key] = `${prop.__getFullValue()}`;
return res;
}, {});
}, {} as Record<string, any>);
}
/**
@ -139,12 +182,12 @@ export default class PropertyComposite extends Property {
* @returns {Object} Style object
* @private
*/
getStyleFromProps(opts = {}) {
getStyleFromProps(opts: { camelCase?: boolean } = {}) {
const name = this.getName();
const join = this.__getJoin();
const toStyle = this.get('toStyle');
let values = this.getValues();
let style = {};
let style: StyleProps = {};
if (toStyle) {
style = toStyle(values, { join, name, property: this });
@ -171,7 +214,7 @@ export default class PropertyComposite extends Property {
...this.getProperties().reduce((acc, prop) => {
acc[prop.getName()] = '';
return acc;
}, {}),
}, {} as StyleProps),
};
}
@ -179,7 +222,7 @@ export default class PropertyComposite extends Property {
? Object.keys(style).reduce((res, key) => {
res[camelCase(key)] = style[key];
return res;
}, {})
}, {} as StyleProps)
: style;
}
@ -187,7 +230,7 @@ export default class PropertyComposite extends Property {
return new RegExp(`${this.get('separator')}(?![^\\(]*\\))`);
}
__upProperties(p, opts = {}) {
__upProperties(p: this, opts: any = {}) {
if (opts.__up || opts.__clearIn) return;
const parentProp = this.__getParentProp();
@ -196,7 +239,7 @@ export default class PropertyComposite extends Property {
this.__upTargetsStyleProps(opts, p);
}
__upTargetsStyleProps(opts = {}, prop) {
__upTargetsStyleProps(opts = {}, prop?: Property) {
let style = this.getStyleFromProps();
if (this.isDetached() && prop) {
@ -207,27 +250,27 @@ export default class PropertyComposite extends Property {
this.__upTargetsStyle(style, opts);
}
_up(props, opts = {}) {
_up(props: Partial<PropertyCompositeProps>, opts: OptionsUpdate = {}) {
this.__setProperties(this.__getSplitValue(props.value), opts);
return Property.prototype._up.call(this, props, opts);
return Property.prototype._up.call(this, props, opts) as this;
}
getStyle(opts) {
getStyle(opts?: { camelCase?: boolean }) {
return this.getStyleFromProps(opts);
}
__getFullValue(opts = {}) {
__getFullValue(opts: any = {}) {
if (this.isDetached() || opts.__clear) return '';
return this.getStyleFromProps()[this.getName()] || '';
}
__getJoin() {
const join = this.get('join');
return isString(join) ? join : this.get('separator');
const join = this.get('join')!;
return isString(join) ? join : this.get('separator')!;
}
__styleHasProps(style = {}) {
__styleHasProps(style: StyleProps = {}) {
const name = this.getName();
const props = this.getProperties();
const nameProps = props.map(prop => prop.getName());
@ -235,22 +278,22 @@ export default class PropertyComposite extends Property {
return allNameProps.some(prop => !isUndefined(style[prop]) && style[prop] !== '');
}
__splitValue(value, sep) {
__splitValue(value: string, sep: string | RegExp) {
return value
.split(sep)
.map(value => value.trim())
.filter(Boolean);
}
__splitStyleName(style, name, sep) {
__splitStyleName(style: StyleProps, name: string, sep: string | RegExp) {
return this.__splitValue(style[name] || '', sep);
}
__getSplitValue(value = '', { byName } = {}) {
__getSplitValue(value = '', { byName }: OptionByName = {}) {
const props = this.getProperties();
const props4Nums = props.length === 4 && props.every(prop => isNumberType(prop.getType()));
const values = this.__splitValue(value, this.getSplitSeparator());
const result = {};
const result: StyleProps = {};
props.forEach((prop, i) => {
const value = values[i];
@ -271,7 +314,7 @@ export default class PropertyComposite extends Property {
return result;
}
__getPropsFromStyle(style = {}, opts = {}) {
__getPropsFromStyle(style: StyleProps = {}, opts: OptionByName = {}) {
if (!this.__styleHasProps(style)) return null;
const { byName } = opts;
@ -296,7 +339,7 @@ export default class PropertyComposite extends Property {
return result;
}
__setProperties(values = {}, opts = {}) {
__setProperties(values: Record<string, any> = {}, opts: OptionsUpdate = {}) {
this.getProperties().forEach(prop => {
const value = values[prop.getId()];
prop.__getFullValue() !== value && prop.upValue(value, opts);
@ -314,7 +357,7 @@ export default class PropertyComposite extends Property {
return Property.prototype.clear.call(this);
}
hasValue(opts) {
hasValue(opts: Parameters<Property['hasValue']>[0]) {
return this.getProperties().some(prop => prop.hasValue(opts));
}
@ -322,7 +365,7 @@ export default class PropertyComposite extends Property {
return this.__getFullValue();
}
__canClearProp(prop) {
__canClearProp(prop: Property) {
return this.isDetached() && prop.hasValue({ noParent: true });
}
}

68
src/style_manager/model/PropertyFactory.js → src/style_manager/model/PropertyFactory.ts

@ -1,8 +1,55 @@
import { isFunction, isString } from 'underscore';
const getOptions = items => items.map(item => ({ id: item }));
type Option = {
id: string;
label?: string;
};
type Property = Record<string, any>;
const getOptions = (items: string[]): Option[] => items.map(item => ({ id: item }));
export default class PropertyFactory {
props: Record<string, Property | undefined> = {};
typeNumber: string;
typeColor: string;
typeRadio: string;
typeSelect: string;
typeFile: string;
typeSlider: string;
typeComposite: string;
typeStack: string;
unitsSize: string[];
unitsSizeNoPerc: string[];
unitsTime: string[];
unitsAngle: string[];
fixedValues: string[];
optsBgSize: Option[];
optsBgAttach: Option[];
optsBgRepeat: Option[];
optsWrap: Option[];
optsOverflow: Option[];
optsDir: Option[];
opstDisplay: Option[];
optsTransitFn: Option[];
optsCursor: Option[];
optsFloat: Option[];
optsPos: Option[];
optsTextAlign: Option[];
optsFlexAlign: Option[];
optsJustCont: Option[];
optsAlignCont: Option[];
optsAlignSelf: Option[];
optsTransitProp: Option[];
optsBorderStyle: Option[];
optsBgPos: Option[];
optsWeight: Option[];
optsShadowType: Option[];
optsFonts: Option[];
fixedFontSizes: string[];
fixedLetSpace: string[];
requireFlex: Record<string, any>;
constructor() {
this.typeNumber = 'number';
this.typeColor = 'color';
@ -122,10 +169,10 @@ export default class PropertyFactory {
this.init();
}
__sub(items) {
__sub(items: (string | Property)[]) {
return () =>
items.map(p => {
if (isString(p)) return this.get(p);
if (isString(p)) return this.get(p)!;
const { extend, ...rest } = p;
return {
...this.get(extend),
@ -451,17 +498,18 @@ export default class PropertyFactory {
],
},
],
].forEach(([prop, def, from]) => {
].forEach(arr => {
const [prop, def, from] = arr as [string, Property, string];
this.add(prop, def || {}, { from });
});
return this;
}
add(property, def = {}, opts = {}) {
add(property: string, def = {}, opts: { from?: string } = {}) {
const from = opts.from || '';
const fromRes = this.props[from || property] || {};
const result = { ...fromRes, property, ...def };
const result: Property = { ...fromRes, property, ...def };
if (result.properties && isFunction(result.properties)) {
result.properties = result.properties();
}
@ -469,8 +517,8 @@ export default class PropertyFactory {
return result;
}
get(prop) {
return this.props[prop] || null;
get(prop: string) {
return this.props[prop];
}
/**
@ -478,8 +526,8 @@ export default class PropertyFactory {
* @param {Array<string>|string} props Array of properties name
* @return {Array<Object>}
*/
build(props) {
const result = [];
build(props: string | string[]) {
const result: Property[] = [];
const propsArr = isString(props) ? [props] : props;
propsArr.forEach(prop => {
Loading…
Cancel
Save