Browse Source

Add isVisible to Property in StyleManager (#6526)

* Trigger `component:styleUpdate` also on the component itself

* Up

* Add type getter to the Component

* Add isVisible property to Property class in StyleManager

* Fix unstylable

* Remove type getter
pull/6530/head
Artur Arseniev 1 year ago
committed by GitHub
parent
commit
398ea3799a
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 9
      packages/core/src/dom_components/model/Component.ts
  2. 8
      packages/core/src/dom_components/types.ts
  3. 4
      packages/core/src/style_manager/index.ts
  4. 53
      packages/core/src/style_manager/model/Property.ts
  5. 18
      packages/core/test/specs/style_manager/model/Sectors.ts

9
packages/core/src/dom_components/model/Component.ts

@ -225,6 +225,10 @@ export default class Component extends StyleableModel<ComponentProperties> {
return this.frame?.getPage(); return this.frame?.getPage();
} }
getType() {
return this.get('type') || 'default';
}
preInit() {} preInit() {}
/** /**
@ -449,12 +453,11 @@ export default class Component extends StyleableModel<ComponentProperties> {
const { em } = this; const { em } = this;
if (!em) return; if (!em) return;
const event = 'component:styleUpdate';
const styleKeys = keys(newStyles); const styleKeys = keys(newStyles);
const pros = { style: newStyles }; const pros = { style: newStyles };
em.trigger(event, this, pros); this.emitWithEditor(ComponentsEvents.styleUpdate, this, pros);
styleKeys.forEach((key) => em.trigger(`${event}:${key}`, this, pros)); styleKeys.forEach((key) => this.emitWithEditor(`${ComponentsEvents.styleUpdateProperty}${key}`, this, pros));
const collectionsStateMap = this.collectionsStateMap; const collectionsStateMap = this.collectionsStateMap;
const allParentCollectionIds = Object.keys(collectionsStateMap); const allParentCollectionIds = Object.keys(collectionsStateMap);

8
packages/core/src/dom_components/types.ts

@ -53,6 +53,14 @@ export enum ComponentsEvents {
update = 'component:update', update = 'component:update',
updateInside = 'component:update-inside', updateInside = 'component:update-inside',
/**
* @event `component:styleUpdate` Component related styles are updated, the component is passed as an argument to the callback.
* @example
* editor.on('component:styleUpdate', (component) => { ... });
*/
styleUpdate = 'component:styleUpdate',
styleUpdateProperty = 'component:styleUpdate:',
/** /**
* @event `component:select` Component selected. * @event `component:select` Component selected.
* @example * @example

4
packages/core/src/style_manager/index.ts

@ -805,9 +805,9 @@ export default class StyleManager extends ItemManagerModule<
props.forEach((prop) => { props.forEach((prop) => {
const isVisible = prop.__checkVisibility({ const isVisible = prop.__checkVisibility({
target: lastTarget, target: lastTarget,
sector,
component, component,
// @ts-ignore sectors: sectors.models,
sectors,
}); });
prop.set('visible', isVisible); prop.set('visible', isVisible);
}); });

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

@ -1,4 +1,4 @@
import { isUndefined, isString, isArray, result, keys, each, includes, any } from 'underscore'; import { isUndefined, isString, isArray, result, keys, each, includes, isFunction } from 'underscore';
import { Model } from '../../common'; import { Model } from '../../common';
import Component from '../../dom_components/model/Component'; import Component from '../../dom_components/model/Component';
import EditorModel from '../../editor/model/Editor'; import EditorModel from '../../editor/model/Editor';
@ -6,6 +6,14 @@ import { capitalize, camelCase, hasWin } from '../../utils/mixins';
import Sector from './Sector'; import Sector from './Sector';
import PropertyComposite from './PropertyComposite'; import PropertyComposite from './PropertyComposite';
import { StyleProps } from '../../domain_abstract/model/StyleableModel'; import { StyleProps } from '../../domain_abstract/model/StyleableModel';
import { StyleTarget } from '..';
export type IsVisibleFn = (props: {
property: Property;
sector: Sector;
target: StyleTarget;
component?: Component;
}) => boolean | void;
/** @private */ /** @private */
export interface PropertyProps { export interface PropertyProps {
@ -33,6 +41,17 @@ export interface PropertyProps {
opts: any; opts: any;
}) => any; }) => any;
/**
* Pass a custom function to check if the property should be visible.
*
* @example
* isVisible: ({ component }) => {
* // Show the property only if the selected component is an image
* return component?.is('image');
* }
*/
isVisible?: IsVisibleFn;
/** /**
* If true, the property will be forced to be full width * If true, the property will be forced to be full width
*/ */
@ -56,9 +75,9 @@ export interface PropertyProps {
* Specifies dependency on other properties of the selected object. * Specifies dependency on other properties of the selected object.
* Property is shown only when all conditions are matched. * Property is shown only when all conditions are matched.
* *
* example: { display: ['flex', 'block'], position: ['absolute'] }; * @example
* in this case the property is only shown when display is * // in this case the property is only shown when display is of value 'flex' or 'block' AND position is 'absolute'
* of value 'flex' or 'block' AND position is 'absolute' * requires: { display: ['flex', 'block'], position: ['absolute'] };
*/ */
requires?: Record<string, any>; requires?: Record<string, any>;
@ -81,6 +100,10 @@ export type OptionsUpdate = {
export type OptionsStyle = { camelCase?: boolean }; export type OptionsStyle = { camelCase?: boolean };
export interface PropertyPropsCustom extends PropertyProps {
[key: string]: any;
}
type PartialPropertyProps = Partial<PropertyProps>; type PartialPropertyProps = Partial<PropertyProps>;
/** /**
@ -98,7 +121,7 @@ type PartialPropertyProps = Partial<PropertyProps>;
* ``` * ```
* *
*/ */
export default class Property<T extends Record<string, any> = PropertyProps> extends Model<T> { export default class Property<T extends PropertyPropsCustom = PropertyPropsCustom> extends Model<T> {
em!: EditorModel; em!: EditorModel;
parent?: Property; parent?: Property;
@ -528,19 +551,31 @@ export default class Property<T extends Record<string, any> = PropertyProps> ext
}; };
} }
__checkVisibility({ target, component, sectors }: { target: any; component?: Component; sectors?: Sector[] }) { __checkVisibility({
target,
component,
sector,
sectors,
}: {
target: StyleTarget;
sector: Sector;
component?: Component;
sectors?: Sector[];
}) {
const trg = component || target; const trg = component || target;
if (!trg) return false; if (!trg) return false;
const id = this.getId(); const id = this.getId();
const property = this.getName(); const property = this.getName();
const toRequire = this.get('toRequire'); const { requires, requiresParent, toRequire, isVisible } = this.attributes;
const requires = this.get('requires');
const requiresParent = this.get('requiresParent');
const unstylable = trg.get('unstylable'); const unstylable = trg.get('unstylable');
const stylableReq = trg.get('stylable-require'); const stylableReq = trg.get('stylable-require');
let stylable = trg.get('stylable'); let stylable = trg.get('stylable');
if (isFunction(isVisible)) {
return !!isVisible({ property: this, sector, target, component });
}
// Stylable could also be an array indicating with which property // Stylable could also be an array indicating with which property
// the target could be styled // the target could be styled
if (isArray(stylable)) { if (isArray(stylable)) {

18
packages/core/test/specs/style_manager/model/Sectors.ts

@ -86,5 +86,23 @@ describe('Sectors', () => {
expect(prop.isVisible()).toBe(isVisible); expect(prop.isVisible()).toBe(isVisible);
}); });
}); });
test('Property with isVisible', () => {
const cmp = domc.addComponent({ tagName: 'span' });
em.setSelected(cmp);
s2.getProperty('color')?.set({
isVisible: ({ component }) => component?.tagName !== 'span',
});
sm.__upSel();
[s1, s2].forEach((sector) => expect(sector.isVisible()).toBe(true));
s2.getProperties().forEach((prop) => {
const isVisible = prop.getName() !== 'color';
expect(prop.isVisible()).toBe(isVisible);
});
});
}); });
}); });

Loading…
Cancel
Save