Browse Source

Allow custom parseValue to StyleManager properties (#6820)

pull/6814/merge
Artur Arseniev 5 days ago
committed by GitHub
parent
commit
361cb9af35
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 11
      packages/core/src/style_manager/config/config.ts
  2. 36
      packages/core/src/style_manager/model/Property.ts
  3. 18
      packages/core/src/style_manager/model/PropertyStack.ts
  4. 36
      packages/core/test/specs/style_manager/model/Models.ts

11
packages/core/src/style_manager/config/config.ts

@ -1,4 +1,5 @@
import { PropertyTypes } from '..';
import type { PropertyParseValue } from '../model/Property';
import { SectorProperties } from '../model/Sector';
export interface StyleManagerConfig {
@ -7,6 +8,16 @@ export interface StyleManagerConfig {
*/
sectors?: (Omit<SectorProperties, 'properties'> & { properties?: (string | PropertyTypes)[] })[];
/**
* Pass a custom function to parse property values globally.
*
* @example
* parseValue: ({ value, parse }) => {
* return value.startsWith('var(--') ? { value, unit: '' } : parse();
* }
*/
parseValue?: PropertyParseValue;
/**
* Specify the element to use as a container, string (query) or HTMLElement.
* With the empty value, nothing will be rendered.

36
packages/core/src/style_manager/model/Property.ts

@ -1,6 +1,7 @@
import { isUndefined, isString, isArray, result, keys, each, includes, isFunction } from 'underscore';
import { Model } from '../../common';
import Component from '../../dom_components/model/Component';
import type Editor from '../../editor';
import EditorModel from '../../editor/model/Editor';
import { capitalize, camelCase, hasWin } from '../../utils/mixins';
import Sector from './Sector';
@ -15,6 +16,13 @@ export type IsVisibleFn = (props: {
component?: Component;
}) => boolean | void;
export type PropertyParseValue<T extends PropertyPropsCustom = PropertyPropsCustom> = (props: {
property: Property<T>;
editor?: Editor;
parse: () => Partial<T>;
value: string;
}) => Partial<T>;
/** @private */
export interface PropertyProps {
name?: string;
@ -33,6 +41,15 @@ export interface PropertyProps {
fixedValues?: string[];
className?: string;
extend?: string;
/**
* Pass a custom function to parse the property value.
*
* @example
* parseValue: ({ value, parse }) => {
* return value.startsWith('var(--') ? { value, unit: '' } : parse();
* }
*/
parseValue?: PropertyParseValue;
onChange?: (data: {
property: Property;
from: PartialPropertyProps;
@ -373,7 +390,20 @@ export default class Property<T extends PropertyPropsCustom = PropertyPropsCusto
}
__parseValue(value: string, opts: any) {
return this.parseValue(value, opts);
return this.__parseValueCustom(value, () => this.parseValue(value, opts));
}
__parseValueCustom(value: string, parse: () => Partial<T>) {
const customValueParser = this.get('parseValue') || this.em?.Styles.getConfig().parseValue;
return customValueParser
? customValueParser({
property: this,
editor: this.em?.getEditor(),
parse,
value,
})
: parse();
}
__getClearProps() {
@ -388,11 +418,11 @@ export default class Property<T extends PropertyPropsCustom = PropertyPropsCusto
* @private
*/
setValue(value: string, complete = true, opts = {}) {
const parsed = this.parseValue(value);
const parsed = this.__parseValue(value, { complete });
const avoidStore = !complete;
// @ts-ignore
!avoidStore && this.set({ value: undefined }, { avoidStore, silent: true });
this.set(parsed, { avoidStore, ...opts });
this.set(parsed as any, { avoidStore, ...opts });
}
/**

18
packages/core/src/style_manager/model/PropertyStack.ts

@ -452,14 +452,16 @@ export default class PropertyStack extends PropertyComposite<PropertyStackProps>
}
__parseValue(value: string) {
const result = this.parseValue(value);
result.__layers = value
.split(VALUES_REG)
.map((v) => v.trim())
.map((v) => this.__parseLayer(v))
.filter(Boolean);
return result;
return this.__parseValueCustom(value, () => {
const result = this.parseValue(value);
result.__layers = value
.split(VALUES_REG)
.map((v) => v.trim())
.map((v) => this.__parseLayer(v))
.filter(Boolean);
return result;
});
}
__parseLayer(value: string) {

36
packages/core/test/specs/style_manager/model/Models.ts

@ -250,4 +250,40 @@ describe('PropertyNumber', () => {
expect(obj.parseValue('200px')).toEqual(result);
expect(obj.parseValue('95px')).toEqual({ value: 95, unit: 'px' });
});
test('supports per-property parseValue overrides', () => {
obj = new PropertyNumber({
units: ['px'],
property: 'width',
parseValue: ({ value, parse }) => (value.startsWith('var(--') ? { value, unit: '' } : parse()),
});
expect(obj.__parseValue('var(--size)', {})).toEqual({ value: 'var(--size)', unit: '' });
expect(obj.__parseValue('20px', {})).toEqual({ value: 20, unit: 'px' });
});
test('supports global styleManager parseValue overrides', () => {
const em = new Editor({
styleManager: {
parseValue: ({ value, parse }) => (value.startsWith('var(--') ? { value, unit: '' } : parse()),
},
});
const sm = em.Styles;
sm.onLoad();
sm.addSector('test', {
name: 'Test',
properties: [{ type: 'number', property: 'width', units: ['px'] }],
});
obj = sm.getProperty('test', 'width') as PropertyNumber;
obj.upValue('var(--size)', { noTarget: true });
expect(obj.get('value')).toEqual('var(--size)');
expect(obj.get('unit')).toEqual('');
obj.upValue('20px', { noTarget: true });
expect(obj.get('value')).toEqual(20);
expect(obj.get('unit')).toEqual('px');
em.destroy();
});
});

Loading…
Cancel
Save