From 88a8d17ba4a1500743780e217241911b477630f3 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Fri, 26 May 2023 12:19:19 +0400 Subject: [PATCH] Add `disableTextInnerChilds` option to Components module configuration --- src/dom_components/config/config.ts | 16 +++++++++++++ src/dom_components/model/ComponentText.ts | 28 +++++++++++++++++++++++ src/dom_components/model/Components.ts | 2 ++ src/dom_components/model/types.ts | 5 ++++ src/navigator/index.ts | 2 +- 5 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/dom_components/config/config.ts b/src/dom_components/config/config.ts index eb95566c6..56da8668e 100644 --- a/src/dom_components/config/config.ts +++ b/src/dom_components/config/config.ts @@ -1,3 +1,5 @@ +import Component from '../model/Component'; + export interface DomComponentsConfig { stylePrefix?: string; @@ -12,6 +14,19 @@ export interface DomComponentsConfig { */ draggableComponents?: boolean; + /** + * Experimental: Disable text inner components. + * With this option, you're able to decide which inner component inside text should be + * disabled (eg. no select, no hover, no layer visibility) once edited. + * @default false + * @example + * // disable all inner childs + * disableTextInnerChilds: true, + * // disable all except link components + * disableTextInnerChilds: (child) => !child.is('link'), + */ + disableTextInnerChilds?: boolean | ((cmp: Component) => boolean | void); + /** * You can setup a custom component definition processor before adding it into the editor. * It might be useful to transform custom objects (es. some framework specific JSX) to GrapesJS component one. @@ -44,6 +59,7 @@ export default { stylePrefix: 'comp-', components: [], draggableComponents: true, + disableTextInnerChilds: false, processor: undefined, voidElements: [ 'area', diff --git a/src/dom_components/model/ComponentText.ts b/src/dom_components/model/ComponentText.ts index 66f645f5f..810a24459 100644 --- a/src/dom_components/model/ComponentText.ts +++ b/src/dom_components/model/ComponentText.ts @@ -1,3 +1,4 @@ +import { isFunction } from 'underscore'; import Component from './Component'; export default class ComponentText extends Component { @@ -10,4 +11,31 @@ export default class ComponentText extends Component { editable: true, }; } + + initialize(props: any, opts: any) { + super.initialize(props, opts); + this.__checkInnerChilds(); + } + + __checkInnerChilds() { + const { disableTextInnerChilds } = this.em.Components.config; + if (disableTextInnerChilds) { + const disableChild = (child: Component) => { + if (!child.isInstanceOf('textnode')) { + child.set({ + locked: true, + layerable: false, + }); + } + }; + + if (isFunction(disableTextInnerChilds)) { + this.forEachChild(child => { + disableTextInnerChilds(child) && disableChild(child); + }); + } else { + this.forEachChild(disableChild); + } + } + } } diff --git a/src/dom_components/model/Components.ts b/src/dom_components/model/Components.ts index 1829b27f9..660fdc80e 100644 --- a/src/dom_components/model/Components.ts +++ b/src/dom_components/model/Components.ts @@ -6,6 +6,7 @@ import EditorModel from '../../editor/model/Editor'; import ComponentManager from '..'; import CssRule from '../../css_composer/model/CssRule'; import { ComponentAdd, ComponentProperties } from './types'; +import ComponentText from './ComponentText'; export const getComponentIds = (cmp?: Component | Component[] | Components, res: string[] = []) => { if (!cmp) return []; @@ -131,6 +132,7 @@ Component> { this.reset(newCmps, opts as any); em?.trigger('component:content', parent, opts, input); + (parent as ComponentText).__checkInnerChilds?.(); } removeChildren(removed: Component, coll?: Components, opts: any = {}) { diff --git a/src/dom_components/model/types.ts b/src/dom_components/model/types.ts index 56f4279e2..5b87882b0 100644 --- a/src/dom_components/model/types.ts +++ b/src/dom_components/model/types.ts @@ -106,6 +106,11 @@ export interface ComponentProperties { * @defaultValue true */ hoverable?: boolean; + /** + * Disable the selection of the component and its children in the canvas. + * @default false + */ + locked?: boolean; /** * This property is used by the HTML exporter as void elements don't have closing tags, eg. `
`, `
`, etc. Default: `false` */ diff --git a/src/navigator/index.ts b/src/navigator/index.ts index d3c2afbc1..4ce72c34b 100644 --- a/src/navigator/index.ts +++ b/src/navigator/index.ts @@ -223,7 +223,7 @@ export default class LayerManager extends Module { * @returns {Boolean} */ isLocked(component: Component): boolean { - return component.get('locked'); + return !!component.get('locked'); } /**