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
fix-resizeobserver-recursion-in-framewrapview
Artur Arseniev 9 months 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();
}
getType() {
return this.get('type') || 'default';
}
preInit() {}
/**
@ -449,12 +453,11 @@ export default class Component extends StyleableModel<ComponentProperties> {
const { em } = this;
if (!em) return;
const event = 'component:styleUpdate';
const styleKeys = keys(newStyles);
const pros = { style: newStyles };
em.trigger(event, this, pros);
styleKeys.forEach((key) => em.trigger(`${event}:${key}`, this, pros));
this.emitWithEditor(ComponentsEvents.styleUpdate, this, pros);
styleKeys.forEach((key) => this.emitWithEditor(`${ComponentsEvents.styleUpdateProperty}${key}`, this, pros));
const collectionsStateMap = this.collectionsStateMap;
const allParentCollectionIds = Object.keys(collectionsStateMap);

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

@ -53,6 +53,14 @@ export enum ComponentsEvents {
update = 'component:update',
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.
* @example

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

@ -805,9 +805,9 @@ export default class StyleManager extends ItemManagerModule<
props.forEach((prop) => {
const isVisible = prop.__checkVisibility({
target: lastTarget,
sector,
component,
// @ts-ignore
sectors,
sectors: sectors.models,
});
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 Component from '../../dom_components/model/Component';
import EditorModel from '../../editor/model/Editor';
@ -6,6 +6,14 @@ import { capitalize, camelCase, hasWin } from '../../utils/mixins';
import Sector from './Sector';
import PropertyComposite from './PropertyComposite';
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 */
export interface PropertyProps {
@ -33,6 +41,17 @@ export interface PropertyProps {
opts: 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
*/
@ -56,9 +75,9 @@ export interface PropertyProps {
* Specifies dependency on other properties of the selected object.
* Property is shown only when all conditions are matched.
*
* example: { display: ['flex', 'block'], position: ['absolute'] };
* in this case the property is only shown when display is
* of value 'flex' or 'block' AND position is 'absolute'
* @example
* // in this case the property is only shown when display is of value 'flex' or 'block' AND position is 'absolute'
* requires: { display: ['flex', 'block'], position: ['absolute'] };
*/
requires?: Record<string, any>;
@ -81,6 +100,10 @@ export type OptionsUpdate = {
export type OptionsStyle = { camelCase?: boolean };
export interface PropertyPropsCustom extends PropertyProps {
[key: string]: any;
}
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;
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;
if (!trg) return false;
const id = this.getId();
const property = this.getName();
const toRequire = this.get('toRequire');
const requires = this.get('requires');
const requiresParent = this.get('requiresParent');
const { requires, requiresParent, toRequire, isVisible } = this.attributes;
const unstylable = trg.get('unstylable');
const stylableReq = trg.get('stylable-require');
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
// the target could be styled
if (isArray(stylable)) {

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

@ -86,5 +86,23 @@ describe('Sectors', () => {
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