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. `
`, `