diff --git a/src/code_manager/model/HtmlGenerator.ts b/src/code_manager/model/HtmlGenerator.ts
index bee317723..8a7ad32c5 100644
--- a/src/code_manager/model/HtmlGenerator.ts
+++ b/src/code_manager/model/HtmlGenerator.ts
@@ -39,7 +39,7 @@ export default class HTMLGenerator extends Model {
id &&
id[0] === 'i' && // all autogenerated IDs start with 'i'
!mod.get('script') && // if the component has script, we have to leave the ID
- !mod.get('attributes').id && // id is not intentionally in attributes
+ !mod.get('attributes')!.id && // id is not intentionally in attributes
idRules.indexOf(id) < 0 // we shouldn't have any rule with this ID
) {
delete attrs.id;
diff --git a/src/common/index.ts b/src/common/index.ts
index 5ab18b2c4..56401f96b 100644
--- a/src/common/index.ts
+++ b/src/common/index.ts
@@ -7,3 +7,7 @@ export type SetOptions = Backbone.ModelSetOptions & { avoidStore?: boolean };
export type AddOptions = Backbone.AddOptions;
export type RemoveOptions = Backbone.Silenceable;
+
+export type ObjectAny = Record;
+
+export type ObjectStrings = Record;
diff --git a/src/css_composer/index.ts b/src/css_composer/index.ts
index 1cabda8f9..c88dd17cd 100644
--- a/src/css_composer/index.ts
+++ b/src/css_composer/index.ts
@@ -379,7 +379,7 @@ export default class CssComposer extends ItemManagerModule {
+import Selector from '../../selector_manager/model/Selector';
+import Selectors from '../../selector_manager/model/Selectors';
+import Traits from '../../trait_manager/model/Traits';
+import EditorModel from '../../editor/model/Editor';
+import {
+ ComponentAdd,
+ ComponentDefinition,
+ ComponentDefinitionDefined,
+ ComponentOptions,
+ ComponentProperties,
+ DragMode,
+ SymbolToUpOptions,
+ ToHTMLOptions,
+} from './types';
+import Frame from '../../canvas/model/Frame';
+import { DomComponentsConfig } from '../config/config';
+import ComponentView from '../view/ComponentView';
+import { AddOptions, ObjectAny, ObjectStrings, SetOptions } from '../../common';
+import CssRule, { CssRuleProperties } from '../../css_composer/model/CssRule';
+import { TraitProperties } from '../../trait_manager/model/Trait';
+
+const escapeRegExp = (str: string) => {
return str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&');
};
-const avoidInline = em => em && em.getConfig().avoidInlineStyle;
+const avoidInline = (em: EditorModel) => em && em.getConfig().avoidInlineStyle;
export const eventDrag = 'component:drag';
export const keySymbols = '__symbols';
@@ -93,7 +110,8 @@ export const keyUpdateInside = `${keyUpdate}-inside`;
*
* @module docsjs.Component
*/
-export default class Component extends StyleableModel {
+export default class Component extends StyleableModel {
+ // @ts-ignore
get defaults() {
return {
tagName: 'div',
@@ -139,6 +157,14 @@ export default class Component extends StyleableModel {
};
}
+ get classes() {
+ return this.get('classes')!;
+ }
+
+ get traits() {
+ return this.get('traits')!;
+ }
+
/**
* Hook method, called once the model is created
*/
@@ -150,25 +176,37 @@ export default class Component extends StyleableModel {
* @param {*} value Property value, if triggered after some property update
* @param {*} previous Property previous value, if triggered after some property update
*/
- updated(property, value, previous) {}
+ updated(property: string, value: any, previous: any) {}
/**
* Hook method, called once the model has been removed
*/
removed() {}
- initialize(props = {}, opt = {}) {
+ em!: EditorModel;
+ opt!: ComponentOptions;
+ config!: DomComponentsConfig;
+ ccid!: string;
+ views!: ComponentView[];
+ view?: ComponentView;
+ frame?: Frame;
+ rule?: CssRule;
+ prevColl?: Components;
+ __hasUm?: boolean;
+ __symbReady?: boolean;
+
+ initialize(props = {}, opt: ComponentOptions = {}) {
bindAll(this, '__upSymbProps', '__upSymbCls', '__upSymbComps');
const em = opt.em;
// Propagate properties from parent if indicated
const parent = this.parent();
- const parentAttr = parent && parent.attributes;
+ const parentAttr = parent?.attributes;
const propagate = this.get('propagate');
propagate && this.set('propagate', isArray(propagate) ? propagate : [propagate]);
if (parentAttr && parentAttr.propagate && !propagate) {
- const newAttr = {};
+ const newAttr: Partial = {};
const toPropagate = parentAttr.propagate;
toPropagate.forEach(prop => (newAttr[prop] = parent.get(prop)));
newAttr.propagate = toPropagate;
@@ -176,13 +214,13 @@ export default class Component extends StyleableModel {
}
// Check void elements
- if (opt && opt.config && opt.config.voidElements.indexOf(this.get('tagName')) >= 0) {
+ if (opt && opt.config && opt.config.voidElements!.indexOf(this.get('tagName')!) >= 0) {
this.set('void', true);
}
opt.em = em;
this.opt = opt;
- this.em = em;
+ this.em = em!;
this.frame = opt.frame;
this.config = opt.config || {};
this.set('attributes', {
@@ -226,14 +264,14 @@ export default class Component extends StyleableModel {
}
}
- __postAdd(opts = {}) {
+ __postAdd(opts: { recursive?: boolean } = {}) {
const { em } = this;
- const um = em && em.get('UndoManager');
+ const um = em?.UndoManager;
const comps = this.components();
if (um && !this.__hasUm) {
um.add(comps);
um.add(this.getSelectors());
- this.__hasUm = 1;
+ this.__hasUm = true;
}
opts.recursive && comps.map(c => c.__postAdd(opts));
}
@@ -248,8 +286,8 @@ export default class Component extends StyleableModel {
}
}
- __onChange(m, opts) {
- const changed = this.changedAttributes();
+ __onChange(m: any, opts: any) {
+ const changed = this.changedAttributes() || {};
keys(changed).forEach(prop => this.emitUpdate(prop));
['status', 'open', 'toolbar', 'traits'].forEach(name => delete changed[name]);
// Propagate component prop changes
@@ -259,17 +297,17 @@ export default class Component extends StyleableModel {
}
}
- __changesUp(opts) {
+ __changesUp(opts: any) {
const { em, frame } = this;
[frame, em].forEach(md => md && md.changesUp(opts));
}
- __propSelfToParent(props) {
+ __propSelfToParent(props: any) {
this.trigger(keyUpdate, props);
this.__propToParent(props);
}
- __propToParent(props) {
+ __propToParent(props: any) {
const parent = this.parent();
parent && parent.trigger(keyUpdateInside, props);
}
@@ -286,7 +324,7 @@ export default class Component extends StyleableModel {
* component.is('image')
* // -> false
*/
- is(type) {
+ is(type: string) {
return !!(this.get('type') == type);
}
@@ -313,7 +351,7 @@ export default class Component extends StyleableModel {
* @param {String} value Drag mode, options: 'absolute' | 'translate'
* @returns {this}
*/
- setDragMode(value) {
+ setDragMode(value?: DragMode) {
return this.set('dmode', value);
}
@@ -326,10 +364,10 @@ export default class Component extends StyleableModel {
* component.find('div > .class');
* // -> [Component, Component, ...]
*/
- find(query) {
- const result = [];
- const $els = this.view.$el.find(query);
- $els.each(i => {
+ find(query: string) {
+ const result: Component[] = [];
+ const $els = this.view?.$el.find(query);
+ $els?.each(i => {
const $el = $els.eq(i);
const model = $el.data('model');
model && result.push(model);
@@ -348,9 +386,9 @@ export default class Component extends StyleableModel {
* const allImages = component.findType('image');
* console.log(allImages[0]) // prints the first found component
*/
- findType(type) {
- const result = [];
- const find = components =>
+ findType(type: string) {
+ const result: Component[] = [];
+ const find = (components: Components) =>
components.forEach(item => {
item.is(type) && result.push(item);
find(item.components());
@@ -368,9 +406,9 @@ export default class Component extends StyleableModel {
* component.closest('div.some-class');
* // -> Component
*/
- closest(query) {
- const result = this.view.$el.closest(query);
- return result.length && result.data('model');
+ closest(query: string) {
+ const result = this.view?.$el.closest(query);
+ return result?.length ? (result.data('model') as Component) : undefined;
}
/**
@@ -383,7 +421,7 @@ export default class Component extends StyleableModel {
* const Section = component.closestType('section');
* console.log(Section);
*/
- closestType(type) {
+ closestType(type: string) {
let parent = this.parent();
while (parent && !parent.is(type)) {
@@ -399,10 +437,10 @@ export default class Component extends StyleableModel {
* @param {Component} component Component to check
* @returns {Boolean}
*/
- contains(component) {
+ contains(component: Component) {
let result = !1;
if (!component) return result;
- const contains = components => {
+ const contains = (components: Components) => {
!result &&
components.forEach(item => {
if (item === component) result = !0;
@@ -429,7 +467,7 @@ export default class Component extends StyleableModel {
* component.replaceWith('Some new content
');
* // -> Component
*/
- replaceWith(el) {
+ replaceWith(el: Component) {
const coll = this.collection;
const at = coll.indexOf(this);
coll.remove(this);
@@ -440,8 +478,8 @@ export default class Component extends StyleableModel {
* Emit changes for each updated attribute
* @private
*/
- attrUpdated(m, v, opts = {}) {
- const attrs = this.get('attributes');
+ attrUpdated(m: any, v: any, opts: any = {}) {
+ const attrs = this.get('attributes')!;
// Handle classes
const classes = attrs.class;
classes && this.setClass(classes);
@@ -453,7 +491,7 @@ export default class Component extends StyleableModel {
delete attrs.style;
const attrPrev = { ...this.previous('attributes') };
- const diff = shallowDiff(attrPrev, this.get('attributes'));
+ const diff = shallowDiff(attrPrev, this.get('attributes')!);
keys(diff).forEach(pr => this.trigger(`change:attributes:${pr}`, this, diff[pr], opts));
}
@@ -465,7 +503,7 @@ export default class Component extends StyleableModel {
* @example
* component.setAttributes({ id: 'test', 'data-key': 'value' });
*/
- setAttributes(attrs, opts = {}) {
+ setAttributes(attrs: ObjectAny, opts: SetOptions = {}) {
this.set('attributes', { ...attrs }, opts);
return this;
}
@@ -478,7 +516,7 @@ export default class Component extends StyleableModel {
* @example
* component.addAttributes({ 'data-key': 'value' });
*/
- addAttributes(attrs, opts = {}) {
+ addAttributes(attrs: ObjectAny, opts: SetOptions = {}) {
return this.setAttributes(
{
...this.getAttributes({ noClass: true }),
@@ -497,7 +535,7 @@ export default class Component extends StyleableModel {
* component.removeAttributes('some-attr');
* component.removeAttributes(['some-attr1', 'some-attr2']);
*/
- removeAttributes(attrs = [], opts = {}) {
+ removeAttributes(attrs: string[] = [], opts: SetOptions = {}) {
const attrArr = Array.isArray(attrs) ? attrs : [attrs];
const compAttr = this.getAttributes();
attrArr.map(i => delete compAttr[i]);
@@ -508,14 +546,14 @@ export default class Component extends StyleableModel {
* Get the style of the component
* @return {Object}
*/
- getStyle(options = {}, optsAdd = {}) {
+ getStyle(options: any = {}, optsAdd: any = {}) {
const em = this.em;
const prop = isString(options) ? options : '';
const opts = prop ? optsAdd : options;
if (em && em.getConfig().avoidInlineStyle && !opts.inline) {
const state = em.get('state');
- const cc = em.get('CssComposer');
+ const cc = em.Css;
const rule = cc.getIdRule(this.getId(), { state, ...opts });
this.rule = rule;
@@ -534,9 +572,8 @@ export default class Component extends StyleableModel {
* @example
* component.setStyle({ color: 'red' });
*/
- setStyle(prop = {}, opts = {}) {
- const em = this.em;
- const { opt } = this;
+ setStyle(prop: ObjectStrings = {}, opts: any = {}) {
+ const { opt, em } = this;
if (em && em.getConfig().avoidInlineStyle && !opt.temporary && !opts.inline) {
const style = this.get('style') || {};
@@ -547,9 +584,10 @@ export default class Component extends StyleableModel {
const propOrig = this.getStyle(opts);
this.rule = cc.setIdRule(this.getId(), prop, { ...opts, state });
const diff = shallowDiff(propOrig, prop);
- this.set('style', '', { silent: 1 });
+ this.set('style', '', { silent: true });
keys(diff).forEach(pr => this.trigger(`change:style:${pr}`));
} else {
+ // @ts-ignore
prop = super.setStyle.apply(this, arguments);
}
@@ -560,9 +598,9 @@ export default class Component extends StyleableModel {
* Return all component's attributes
* @return {Object}
*/
- getAttributes(opts = {}) {
+ getAttributes(opts: { noClass?: boolean; noStyle?: boolean } = {}) {
const { em } = this;
- const classes = [];
+ const classes: string[] = [];
const attributes = { ...this.get('attributes') };
const sm = em && em.get('SelectorManager');
const id = this.getId();
@@ -571,7 +609,7 @@ export default class Component extends StyleableModel {
if (opts.noClass) {
delete attributes.class;
} else {
- this.get('classes').forEach(cls => classes.push(isString(cls) ? cls : cls.get('name')));
+ this.classes.forEach(cls => classes.push(isString(cls) ? cls : cls.get('name')));
classes.length && (attributes.class = classes.join(' '));
}
@@ -618,9 +656,9 @@ export default class Component extends StyleableModel {
* model.addClass(['class1', 'class2']);
* // -> [SelectorObject, ...]
*/
- addClass(classes) {
- const added = this.em.get('SelectorManager').addClass(classes);
- return this.get('classes').add(added);
+ addClass(classes: string | string[]) {
+ const added = this.em.Selectors.addClass(classes);
+ return this.classes.add(added);
}
/**
@@ -633,8 +671,8 @@ export default class Component extends StyleableModel {
* model.setClass(['class1', 'class2']);
* // -> [SelectorObject, ...]
*/
- setClass(classes) {
- this.get('classes').reset();
+ setClass(classes: string | string[]) {
+ this.classes.reset();
return this.addClass(classes);
}
@@ -648,10 +686,10 @@ export default class Component extends StyleableModel {
* model.removeClass(['class1', 'class2']);
* // -> [SelectorObject, ...]
*/
- removeClass(classes) {
- const removed = [];
+ removeClass(classes: string | string[]) {
+ const removed: Selector[] = [];
classes = isArray(classes) ? classes : [classes];
- const selectors = this.get('classes');
+ const selectors = this.classes;
const type = Selector.TYPE_CLASS;
classes.forEach(classe => {
@@ -675,7 +713,7 @@ export default class Component extends StyleableModel {
return classStr ? classStr.split(' ') : [];
}
- __logSymbol(type, toUp, opts = {}) {
+ __logSymbol(type: string, toUp: Component[], opts: any = {}) {
const symbol = this.__getSymbol();
const symbols = this.__getSymbols();
if (!symbol && !symbols) return;
@@ -685,7 +723,7 @@ export default class Component extends StyleableModel {
__initSymb() {
if (this.__symbReady) return;
this.on('change', this.__upSymbProps);
- this.__symbReady = 1;
+ this.__symbReady = true;
}
__isSymbol() {
@@ -704,7 +742,7 @@ export default class Component extends StyleableModel {
__isSymbolNested() {
if (!this.__isSymbolOrInst() || this.__isSymbolTop()) return false;
- const symbTopSelf = (this.__isSymbol() ? this : this.__getSymbol()).__getSymbTop();
+ const symbTopSelf = (this.__isSymbol() ? this : this.__getSymbol())!.__getSymbTop();
const symbTop = this.__getSymbTop();
const symbTopMain = symbTop.__isSymbol() ? symbTop : symbTop.__getSymbol();
return symbTopMain !== symbTopSelf;
@@ -715,7 +753,7 @@ export default class Component extends StyleableModel {
return em ? em.get('DomComponents').allById() : {};
}
- __getSymbol() {
+ __getSymbol(): Component | undefined {
let symb = this.get(keySymbol);
if (symb && isString(symb)) {
const ref = this.__getAllById()[symb];
@@ -729,7 +767,7 @@ export default class Component extends StyleableModel {
return symb;
}
- __getSymbols() {
+ __getSymbols(): Component[] | undefined {
let symbs = this.get(keySymbols);
if (symbs && isArray(symbs)) {
symbs.forEach((symb, idx) => {
@@ -749,17 +787,14 @@ export default class Component extends StyleableModel {
return ovrd === true || (isArray(ovrd) && props.some(p => ovrd.indexOf(p) >= 0));
}
- __getSymbToUp(opts = {}) {
- let result = [];
- const { em } = this;
+ __getSymbToUp(opts: SymbolToUpOptions = {}) {
+ let result: Component[] = [];
const { changed } = opts;
- const symbEnabled = em && em.config.symbols;
if (
opts.fromInstance ||
opts.noPropagate ||
opts.fromUndo ||
- !symbEnabled ||
// Avoid updating others if the current component has override
(changed && this.__isSymbOvrd(changed))
) {
@@ -777,8 +812,8 @@ export default class Component extends StyleableModel {
return result;
}
- __getSymbTop(opts) {
- let result = this;
+ __getSymbTop(opts?: any) {
+ let result: Component = this;
let parent = this.parent(opts);
while (parent && (parent.__isSymbol() || parent.__getSymbol())) {
@@ -789,8 +824,8 @@ export default class Component extends StyleableModel {
return result;
}
- __upSymbProps(m, opts = {}) {
- const changed = this.changedAttributes();
+ __upSymbProps(m: any, opts: SymbolToUpOptions = {}) {
+ const changed = this.changedAttributes() || {};
const attrs = changed.attributes || {};
delete changed.status;
delete changed.open;
@@ -819,17 +854,17 @@ export default class Component extends StyleableModel {
}
}
- __upSymbCls(m, c, opts = {}) {
+ __upSymbCls(m: any, c: any, opts = {}) {
const toUp = this.__getSymbToUp(opts);
this.__logSymbol('classes', toUp, { opts });
toUp.forEach(child => {
- // This will propagate the change up to __upSymbProps
+ // @ts-ignore This will propagate the change up to __upSymbProps
child.set('classes', this.get('classes'), { fromInstance: this });
});
this.__changesUp(opts);
}
- __upSymbComps(m, c, o) {
+ __upSymbComps(m: Component, c: Components, o: any) {
const optUp = o || c || {};
const { fromInstance, fromUndo } = optUp;
const toUpOpts = { fromInstance, fromUndo };
@@ -841,14 +876,17 @@ export default class Component extends StyleableModel {
...toUpOpts,
changed: 'components:reset',
});
- this.__logSymbol('reset', toUp, { components: m.models });
+ // @ts-ignore
+ const cmps = m.models as Component[];
+ this.__logSymbol('reset', toUp, { components: cmps });
toUp.forEach(symb => {
- const newMods = m.models.map(mod => mod.clone({ symbol: 1 }));
+ const newMods = cmps.map(mod => mod.clone({ symbol: true }));
+ // @ts-ignore
symb.components().reset(newMods, { fromInstance: this, ...c });
});
// Add
} else if (o.add) {
- let addedInstances = [];
+ let addedInstances: Component[] = [];
const isMainSymb = !!this.__getSymbols();
const toUp = this.__getSymbToUp({
...toUpOpts,
@@ -874,7 +912,7 @@ export default class Component extends StyleableModel {
const addedTop = addedInst.__getSymbTop({ prev: 1 });
return symbTop && addedTop && addedTop === symbTop;
})[0];
- const toAppend = symbPrev || m.clone({ symbol: 1, symbolInv: isMainSymb });
+ const toAppend = symbPrev || m.clone({ symbol: true, symbolInv: isMainSymb });
symb.append(toAppend, { fromInstance: this, ...o });
});
// Remove
@@ -885,7 +923,7 @@ export default class Component extends StyleableModel {
!o.temporary &&
symb.set(
keySymbols,
- symb.__getSymbols().filter(i => i !== m)
+ symb.__getSymbols()!.filter(i => i !== m)
);
// Propagate remove only if the component is an inner symbol
@@ -895,15 +933,15 @@ export default class Component extends StyleableModel {
const parent = m.parent();
const opts = { fromInstance: m, ...o };
const isSymbNested = m.__isSymbolNested();
- let toUpFn = symb => {
+ let toUpFn = (symb: Component) => {
const symbPrnt = symb.parent();
symbPrnt && !symbPrnt.__isSymbOvrd(changed) && symb.remove(opts);
};
// Check if the parent allows the removing
- let toUp = !parent.__isSymbOvrd(changed) ? m.__getSymbToUp(toUpOpts) : [];
+ let toUp = !parent?.__isSymbOvrd(changed) ? m.__getSymbToUp(toUpOpts) : [];
if (isSymbNested) {
- toUp = parent.__getSymbToUp({ ...toUpOpts, changed });
+ toUp = parent?.__getSymbToUp({ ...toUpOpts, changed })!;
toUpFn = symb => {
const toRemove = symb.components().at(index);
toRemove && toRemove.remove({ fromInstance: parent, ...opts });
@@ -923,9 +961,9 @@ export default class Component extends StyleableModel {
this.__changesUp(optUp);
}
- initClasses(m, c, opts = {}) {
+ initClasses(m?: any, c?: any, opts: any = {}) {
const event = 'change:classes';
- const attrCls = this.get('attributes').class || [];
+ const attrCls = this.get('attributes')!.class || [];
const toListen = [this, event, this.initClasses];
const cls = this.get('classes') || attrCls;
const clsArr = isString(cls) ? cls.split(' ') : cls;
@@ -935,6 +973,7 @@ export default class Component extends StyleableModel {
this.set('classes', selectors, opts);
selectors.add(classes);
selectors.on('add remove reset', this.__upSymbCls);
+ // @ts-ignore
this.listenTo(...toListen);
return this;
}
@@ -945,24 +984,25 @@ export default class Component extends StyleableModel {
this.stopListening(...toListen);
// Have to add components after the init, otherwise the parent
// is not visible
- const comps = new Components(null, this.opt);
+ const comps = new Components([], this.opt);
comps.parent = this;
const components = this.get('components');
const addChild = !this.opt.avoidChildren;
this.set('components', comps);
addChild && components && comps.add(isFunction(components) ? components(this) : components, this.opt);
comps.on('add remove reset', this.__upSymbComps);
+ // @ts-ignore
this.listenTo(...toListen);
return this;
}
- initTraits(changed) {
+ initTraits(changed?: any) {
const { em } = this;
const event = 'change:traits';
this.off(event, this.initTraits);
this.__loadTraits();
const attrs = { ...this.get('attributes') };
- const traits = this.get('traits');
+ const traits = this.traits;
traits.each(trait => {
if (!trait.get('changeProp')) {
const name = trait.get('name');
@@ -979,7 +1019,7 @@ export default class Component extends StyleableModel {
initScriptProps() {
if (this.opt.temporary) return;
const prop = 'script-props';
- const toListen = [`change:${prop}`, this.initScriptProps];
+ const toListen: any = [`change:${prop}`, this.initScriptProps];
this.off(...toListen);
const prevProps = this.previous(prop) || [];
const newProps = this.get(prop) || [];
@@ -987,10 +1027,11 @@ export default class Component extends StyleableModel {
const newPropsEv = newProps.map(e => `change:${e}`).join(' ');
prevPropsEv && this.off(prevPropsEv, this.__scriptPropsChange);
newPropsEv && this.on(newPropsEv, this.__scriptPropsChange);
+ // @ts-ignore
this.on(...toListen);
}
- __scriptPropsChange(m, v, opts = {}) {
+ __scriptPropsChange(m: any, v: any, opts: any = {}) {
if (opts.avoidStore) return;
this.trigger('rerender');
}
@@ -1011,7 +1052,7 @@ export default class Component extends StyleableModel {
* // append at specific index (eg. at the beginning)
* someComponent.append(otherComponent, { at: 0 });
*/
- append(components, opts = {}) {
+ append(components: ComponentAdd, opts: AddOptions = {}): Component[] {
const compArr = isArray(components) ? [...components] : [components];
const toAppend = compArr.map(comp => {
if (isString(comp)) {
@@ -1040,14 +1081,17 @@ export default class Component extends StyleableModel {
* console.log(collection.length);
* // -> 2
*/
- components(components, opts = {}) {
- const coll = this.get('components');
+ components(
+ components?: T,
+ opts: any = {}
+ ): undefined extends T ? Components : Component[] {
+ const coll = this.get('components')!;
if (isUndefined(components)) {
- return coll;
+ return coll as any;
} else {
- coll.reset(null, opts);
- return components ? this.append(components, opts) : [];
+ coll.reset(undefined, opts);
+ return components ? this.append(components, opts) : ([] as any);
}
}
@@ -1061,8 +1105,8 @@ export default class Component extends StyleableModel {
* // Return second child
* component.getChildAt(1);
*/
- getChildAt(index) {
- return this.components().at(index || 0) || null;
+ getChildAt(index: number) {
+ return this.components().at(index || 0) || undefined;
}
/**
@@ -1081,7 +1125,7 @@ export default class Component extends StyleableModel {
* * @return {this}
*/
empty(opts = {}) {
- this.components().reset(null, opts);
+ this.components().reset(undefined, opts);
return this;
}
@@ -1092,7 +1136,7 @@ export default class Component extends StyleableModel {
* component.parent();
* // -> Component
*/
- parent(opts = {}) {
+ parent(opts: any = {}): Component | undefined {
const coll = this.collection || (opts.prev && this.prevColl);
return coll ? coll.parent : null;
}
@@ -1101,7 +1145,7 @@ export default class Component extends StyleableModel {
* Return all parents of the component.
* @returns {Array}
*/
- parents() {
+ parents(): Component[] {
const parent = this.parent();
return parent ? [parent].concat(parent.parents()) : [];
}
@@ -1150,12 +1194,12 @@ export default class Component extends StyleableModel {
}
}
- __loadTraits(tr, opts = {}) {
- let traitsI = tr || this.get('traits');
+ __loadTraits(tr?: Traits | TraitProperties[], opts = {}) {
+ let traitsI = tr || this.traits;
if (!(traitsI instanceof Traits)) {
- traitsI = isFunction(traitsI) ? traitsI(this) : traitsI;
- const traits = new Traits([], this.opt);
+ traitsI = (isFunction(traitsI) ? traitsI(this) : traitsI) as TraitProperties[];
+ const traits = new Traits([], this.opt as any);
traits.setTarget(this);
if (traitsI.length) {
@@ -1179,7 +1223,7 @@ export default class Component extends StyleableModel {
*/
getTraits() {
this.__loadTraits();
- return [...this.get('traits').models];
+ return [...this.traits.models];
}
/**
@@ -1191,8 +1235,9 @@ export default class Component extends StyleableModel {
* console.log(traits);
* // [Trait, ...]
*/
- setTraits(traits) {
+ setTraits(traits: TraitProperties[]) {
const tr = isArray(traits) ? traits : [traits];
+ // @ts-ignore
this.set({ traits: tr });
return this.getTraits();
}
@@ -1205,7 +1250,7 @@ export default class Component extends StyleableModel {
* const traitTitle = component.getTrait('title');
* traitTitle && traitTitle.set('label', 'New label');
*/
- getTrait(id) {
+ getTrait(id: string) {
return (
this.getTraits().filter(trait => {
return trait.get('id') === id || trait.get('name') === id;
@@ -1224,7 +1269,7 @@ export default class Component extends StyleableModel {
* options: [ 'Option 1', 'Option 2' ],
* });
*/
- updateTrait(id, props) {
+ updateTrait(id: string, props: Partial) {
const trait = this.getTrait(id);
trait && trait.set(props);
this.em?.trigger('component:toggled');
@@ -1240,9 +1285,9 @@ export default class Component extends StyleableModel {
* const traitTitle = component.getTraitIndex('title');
* console.log(traitTitle); // 1
*/
- getTraitIndex(id) {
+ getTraitIndex(id: string) {
const trait = this.getTrait(id);
- return trait ? this.get('traits').indexOf(trait) : -1;
+ return trait ? this.traits.indexOf(trait) : -1;
}
/**
@@ -1253,10 +1298,10 @@ export default class Component extends StyleableModel {
* component.removeTrait('title');
* component.removeTrait(['title', 'id']);
*/
- removeTrait(id) {
+ removeTrait(id: string | string[]) {
const ids = isArray(id) ? id : [id];
const toRemove = ids.map(id => this.getTrait(id));
- const traits = this.get('traits');
+ const { traits } = this;
const removed = toRemove.length ? traits.remove(toRemove) : [];
this.em?.trigger('component:toggled');
return isArray(removed) ? removed : [removed];
@@ -1275,9 +1320,9 @@ export default class Component extends StyleableModel {
* });
* component.addTrait(['title', {...}, ...]);
*/
- addTrait(trait, opts = {}) {
+ addTrait(trait: Parameters[0], opts: AddOptions = {}) {
this.__loadTraits();
- const added = this.get('traits').add(trait, opts);
+ const added = this.traits.add(trait, opts);
this.em?.trigger('component:toggled');
return isArray(added) ? added : [added];
}
@@ -1288,13 +1333,14 @@ export default class Component extends StyleableModel {
* @return {Array}
* @private
*/
- normalizeClasses(arr) {
- const res = [];
+ normalizeClasses(arr: string[]): Selector[] {
+ const res: Selector[] = [];
const { em } = this;
- const clm = em && em.get('SelectorManager');
- if (!clm) return;
+ const clm = em?.Selectors;
+ if (!clm) return [];
+ // @ts-ignore
if (arr.models) return [...arr.models];
- arr.forEach(val => res.push(clm.add(val)));
+ arr.forEach(val => res.push(clm.add(val) as Selector));
return res;
}
@@ -1302,35 +1348,42 @@ export default class Component extends StyleableModel {
* Override original clone method
* @private
*/
- clone(opt = {}) {
+ clone(opt: { symbol?: boolean; symbolInv?: boolean } = {}) {
const em = this.em;
const attr = { ...this.attributes };
const opts = { ...this.opt };
const id = this.getId();
- const cssc = em && em.get('CssComposer');
+ const cssc = em?.Css;
attr.attributes = { ...attr.attributes };
delete attr.attributes.id;
+ // @ts-ignore
attr.components = [];
+ // @ts-ignore
attr.classes = [];
+ // @ts-ignore
attr.traits = [];
if (this.__isSymbolTop()) {
- opt.symbol = 1;
+ opt.symbol = true;
}
- this.get('components').each((md, i) => {
+ this.get('components')!.each((md, i) => {
+ // @ts-ignore
attr.components[i] = md.clone({ ...opt, _inner: 1 });
});
- this.get('traits').each((md, i) => {
+ this.get('traits')!.each((md, i) => {
+ // @ts-ignore
attr.traits[i] = md.clone();
});
- this.get('classes').each((md, i) => {
+ this.get('classes')!.each((md, i) => {
+ // @ts-ignore
attr.classes[i] = md.get('name');
});
attr.status = '';
+ // @ts-ignore
opts.collection = null;
-
+ // @ts-ignore
const cloned = new this.constructor(attr, opts);
// Clone component specific rules
@@ -1338,6 +1391,7 @@ export default class Component extends StyleableModel {
const rulesToClone = cssc ? cssc.getRules(`#${id}`) : [];
rulesToClone.forEach(rule => {
const newRule = rule.clone();
+ // @ts-ignore
newRule.set('selectors', [newId]);
cssc.getAll().add(newRule);
});
@@ -1353,13 +1407,13 @@ export default class Component extends StyleableModel {
cloned.set(keySymbols, 0);
} else if (symbol) {
// Contains already a reference to a symbol
- symbol.set(keySymbols, [...symbol.__getSymbols(), cloned]);
+ symbol.set(keySymbols, [...symbol.__getSymbols()!, cloned]);
cloned.__initSymb();
} else if (opt.symbol) {
// Request to create a symbol
if (this.__isSymbol()) {
// Already a symbol, cloned should be an instance
- this.set(keySymbols, [...symbols, cloned]);
+ this.set(keySymbols, [...symbols!, cloned]);
cloned.set(keySymbol, this);
cloned.__initSymb();
} else if (opt.symbolInv) {
@@ -1390,7 +1444,7 @@ export default class Component extends StyleableModel {
const { em } = this;
const { type, tagName, name } = this.attributes;
const defName = type || tagName;
- const nameTag = !type && tagName;
+ const nameTag = !type ? tagName : '';
const i18nPfx = 'domComponents.names.';
const i18nName = name && em?.t(`${i18nPfx}${name}`);
const i18nNameTag = nameTag && em?.t(`${i18nPfx}${nameTag}`);
@@ -1445,7 +1499,7 @@ export default class Component extends StyleableModel {
* });
* // ->
*/
- toHTML(opts = {}) {
+ toHTML(opts: ToHTMLOptions = {}) {
const model = this;
const attrs = [];
const customTag = opts.tag;
@@ -1508,11 +1562,11 @@ export default class Component extends StyleableModel {
* @param {Object} [opts={}] Same options of `toHTML`
* @returns {String} HTML string
*/
- getInnerHTML(opts) {
+ getInnerHTML(opts?: ToHTMLOptions) {
return this.__innerHTML(opts);
}
- __innerHTML(opts = {}) {
+ __innerHTML(opts: ToHTMLOptions = {}) {
const cmps = this.components();
return !cmps.length ? this.get('content') : cmps.map(c => c.toHTML(opts)).join('');
}
@@ -1534,7 +1588,7 @@ export default class Component extends StyleableModel {
* @return {Object}
* @private
*/
- toJSON(opts = {}) {
+ toJSON(opts: ObjectAny = {}): ComponentDefinition {
const obj = Model.prototype.toJSON.call(this, opts);
obj.attributes = this.getAttributes();
delete obj.attributes.class;
@@ -1565,8 +1619,8 @@ export default class Component extends StyleableModel {
/**
* Return an object containing only changed props
*/
- getChangedProps(res) {
- const obj = res || Model.prototype.toJSON.apply(this);
+ getChangedProps(res: Partial): Partial {
+ const obj: any = res || Model.prototype.toJSON.apply(this);
const defaults = result(this, 'defaults');
forEach(defaults, (value, key) => {
@@ -1598,7 +1652,7 @@ export default class Component extends StyleableModel {
* Return the component id
* @return {String}
*/
- getId() {
+ getId(): string {
let attrs = this.get('attributes') || {};
return attrs.id || this.ccid || this.cid;
}
@@ -1608,7 +1662,7 @@ export default class Component extends StyleableModel {
* @param {String} id
* @return {this}
*/
- setId(id, opts) {
+ setId(id: string, opts?: SetOptions & { idUpdate?: boolean }) {
const attrs = { ...this.get('attributes') };
attrs.id = id;
this.set('attributes', attrs, opts);
@@ -1632,7 +1686,7 @@ export default class Component extends StyleableModel {
* @param {Frame} frame Get View of a specific frame
* @return {ComponentView}
*/
- getView(frame) {
+ getView(frame?: Frame) {
let { view, views } = this;
if (frame) {
@@ -1653,7 +1707,7 @@ export default class Component extends StyleableModel {
return scrProps.reduce((acc, prop) => {
acc[prop] = modelProps[prop];
return acc;
- }, {});
+ }, {} as Partial);
}
/**
@@ -1663,7 +1717,7 @@ export default class Component extends StyleableModel {
* @return {string}
* @private
*/
- getScriptString(script) {
+ getScriptString(script?: string | Function) {
let scr = script || this.get('script');
if (!scr) {
@@ -1696,17 +1750,18 @@ export default class Component extends StyleableModel {
return scr;
}
- emitUpdate(property, ...args) {
+ emitUpdate(property?: string, ...args: any[]) {
const { em } = this;
const event = keyUpdate + (property ? `:${property}` : '');
const item = property && this.get(property);
+ // @ts-ignore
property && this.updated(property, item, property && this.previous(property), ...args);
this.trigger(event, ...args);
em && em.trigger(event, this, ...args);
- ['components', 'classes'].indexOf(property) >= 0 &&
+ ['components', 'classes'].indexOf(property!) >= 0 &&
this.__propSelfToParent({
component: this,
- changed: { [property]: item },
+ changed: { [property!]: item },
options: args[2] || args[1] || {},
});
}
@@ -1720,7 +1775,7 @@ export default class Component extends StyleableModel {
* // do something with component
* })
*/
- onAll(clb) {
+ onAll(clb: (cmp: Component) => void) {
if (isFunction(clb)) {
clb(this);
this.components().forEach(model => model.onAll(clb));
@@ -1732,7 +1787,7 @@ export default class Component extends StyleableModel {
* Remove the component
* @return {this}
*/
- remove(opts = {}) {
+ remove(opts: any = {}) {
const { em } = this;
const coll = this.collection;
const remove = () => {
@@ -1759,12 +1814,12 @@ export default class Component extends StyleableModel {
* const dest = editor.getWrapper();
* editor.getSelected().move(dest, { at: 0 });
*/
- move(component, opts = {}) {
+ move(component: Component, opts: AddOptions = {}) {
if (component) {
const { at } = opts;
const index = this.index();
const sameParent = component === this.parent();
- const sameIndex = index === at || index === at - 1;
+ const sameIndex = index === at || index === at! - 1;
if (!sameParent || !sameIndex) {
if (sameParent && at && at > index) {
@@ -1790,8 +1845,8 @@ export default class Component extends StyleableModel {
* newTextExt.isInstanceOf('text-ext'); // true
* newTextExt.isInstanceOf('text'); // true
*/
- isInstanceOf(type) {
- const cmp = this.em?.get('DomComponents').getType(type)?.model;
+ isInstanceOf(type: string) {
+ const cmp = this.em?.Components.getType(type)?.model;
if (!cmp) return false;
@@ -1812,7 +1867,7 @@ export default class Component extends StyleableModel {
* innerComponent.isChildOf(newTextComponent); // true
* innerComponent.isChildOf('text'); // true
*/
- isChildOf(component) {
+ isChildOf(component: string | Component) {
const byType = isString(component);
let parent = this.parent();
@@ -1851,18 +1906,18 @@ export default class Component extends StyleableModel {
return this;
}
- _getStyleRule({ id } = {}) {
+ _getStyleRule({ id }: { id?: string } = {}) {
const { em } = this;
const idS = id || this.getId();
return em && em.get('CssComposer').getIdRule(idS);
}
- _getStyleSelector(opts) {
+ _getStyleSelector(opts?: { id?: string }) {
const rule = this._getStyleRule(opts);
return rule && rule.get('selectors').at(0);
}
- _idUpdated(m, v, opts = {}) {
+ _idUpdated(m: any, v: any, opts: { idUpdate?: boolean } = {}) {
if (opts.idUpdate) return;
const { ccid } = this;
@@ -1872,7 +1927,7 @@ export default class Component extends StyleableModel {
// If the ID already exists I need to rollback to the old one
if (list[id] || (!id && idPrev)) {
- return this.setId(idPrev, { idUpdate: 1 });
+ return this.setId(idPrev, { idUpdate: true });
}
// Remove the old ID reference and add the new one
@@ -1884,11 +1939,123 @@ export default class Component extends StyleableModel {
const selector = this._getStyleSelector({ id: idPrev });
selector && selector.set({ name: id, label: id });
}
+
+ static getDefaults() {
+ return result(this.prototype, 'defaults');
+ }
+
+ static isComponent(el: HTMLElement) {
+ return { tagName: toLowerCase(el.tagName) };
+ }
+
+ static ensureInList(model: Component) {
+ const list = Component.getList(model);
+ const id = model.getId();
+ const current = list[id];
+
+ if (!current) {
+ // Insert in list
+ list[id] = model;
+ } else if (current !== model) {
+ // Create new ID
+ const nextId = Component.getIncrementId(id, list);
+ model.setId(nextId);
+ list[nextId] = model;
+ }
+
+ model.components().forEach(i => Component.ensureInList(i));
+ }
+
+ static createId(model: Component, opts: any = {}) {
+ const list = Component.getList(model);
+ const { idMap = {} } = opts;
+ let { id } = model.get('attributes')!;
+ let nextId;
+
+ if (id) {
+ nextId = Component.getIncrementId(id, list, opts);
+ model.setId(nextId);
+ if (id !== nextId) idMap[id] = nextId;
+ } else {
+ nextId = Component.getNewId(list);
+ }
+
+ list[nextId] = model;
+ return nextId;
+ }
+
+ static getNewId(list: ObjectAny) {
+ const count = Object.keys(list).length;
+ // Testing 1000000 components with `+ 2` returns 0 collisions
+ const ilen = count.toString().length + 2;
+ const uid = (Math.random() + 1.1).toString(36).slice(-ilen);
+ let newId = `i${uid}`;
+
+ while (list[newId]) {
+ newId = Component.getNewId(list);
+ }
+
+ return newId;
+ }
+
+ static getIncrementId(id: string, list: ObjectAny, opts: { keepIds?: string[] } = {}) {
+ const { keepIds = [] } = opts;
+ let counter = 1;
+ let newId = id;
+
+ if (keepIds.indexOf(id) < 0) {
+ while (list[newId]) {
+ counter++;
+ newId = `${id}-${counter}`;
+ }
+ }
+
+ return newId;
+ }
+
+ static getList(model: Component) {
+ const { opt = {} } = model;
+ // @ts-ignore
+ const { domc, em } = opt;
+ const dm = domc || em?.Components;
+ return dm ? dm.componentsById : {};
+ }
+
+ static checkId(
+ components: ComponentDefinitionDefined[],
+ styles: { selectors: string[] }[] = [],
+ list: ObjectAny = {},
+ opts: { keepIds?: string[] } = {}
+ ) {
+ const comps = isArray(components) ? components : [components];
+ const { keepIds = [] } = opts;
+ comps.forEach(comp => {
+ comp.attributes;
+ const { attributes = {}, components } = comp;
+ const { id } = attributes;
+
+ // Check if we have collisions with current components
+ if (id && list[id] && keepIds.indexOf(id) < 0) {
+ const newId = Component.getIncrementId(id, list);
+ attributes.id = newId;
+ // Update passed styles
+ isArray(styles) &&
+ styles.forEach(style => {
+ const { selectors } = style;
+ selectors.forEach((sel, idx) => {
+ if (sel === `#${id}`) selectors[idx] = `#${newId}`;
+ });
+ });
+ }
+
+ components && Component.checkId(components, styles, list, opts);
+ });
+ }
}
-Component.getDefaults = function () {
- return result(this.prototype, 'defaults');
-};
+// Component.getDefaults = function () {
+// return result(this.prototype, 'defaults');
+// };
/**
* Detect if the passed element is a valid component.
@@ -1898,27 +2065,27 @@ Component.getDefaults = function () {
* @return {Object}
* @private
*/
-Component.isComponent = el => {
- return { tagName: toLowerCase(el.tagName) };
-};
-
-Component.ensureInList = model => {
- const list = Component.getList(model);
- const id = model.getId();
- const current = list[id];
-
- if (!current) {
- // Insert in list
- list[id] = model;
- } else if (current !== model) {
- // Create new ID
- const nextId = Component.getIncrementId(id, list);
- model.setId(nextId);
- list[nextId] = model;
- }
-
- model.components().forEach(i => Component.ensureInList(i));
-};
+// Component.isComponent = el => {
+// return { tagName: toLowerCase(el.tagName) };
+// };
+
+// Component.ensureInList = model => {
+// const list = Component.getList(model);
+// const id = model.getId();
+// const current = list[id];
+
+// if (!current) {
+// // Insert in list
+// list[id] = model;
+// } else if (current !== model) {
+// // Create new ID
+// const nextId = Component.getIncrementId(id, list);
+// model.setId(nextId);
+// list[nextId] = model;
+// }
+
+// model.components().forEach(i => Component.ensureInList(i));
+// };
/**
* Relying simply on the number of components becomes a problem when you
@@ -1927,52 +2094,52 @@ Component.ensureInList = model => {
* @return {string}
* @private
*/
-Component.createId = (model, opts = {}) => {
- const list = Component.getList(model);
- const { idMap = {} } = opts;
- let { id } = model.get('attributes');
- let nextId;
-
- if (id) {
- nextId = Component.getIncrementId(id, list, opts);
- model.setId(nextId);
- if (id !== nextId) idMap[id] = nextId;
- } else {
- nextId = Component.getNewId(list);
- }
-
- list[nextId] = model;
- return nextId;
-};
-
-Component.getNewId = list => {
- const count = Object.keys(list).length;
- // Testing 1000000 components with `+ 2` returns 0 collisions
- const ilen = count.toString().length + 2;
- const uid = (Math.random() + 1.1).toString(36).slice(-ilen);
- let newId = `i${uid}`;
-
- while (list[newId]) {
- newId = Component.getNewId(list);
- }
-
- return newId;
-};
-
-Component.getIncrementId = (id, list, opts = {}) => {
- const { keepIds = [] } = opts;
- let counter = 1;
- let newId = id;
-
- if (keepIds.indexOf(id) < 0) {
- while (list[newId]) {
- counter++;
- newId = `${id}-${counter}`;
- }
- }
-
- return newId;
-};
+// Component.createId = (model, opts = {}) => {
+// const list = Component.getList(model);
+// const { idMap = {} } = opts;
+// let { id } = model.get('attributes');
+// let nextId;
+
+// if (id) {
+// nextId = Component.getIncrementId(id, list, opts);
+// model.setId(nextId);
+// if (id !== nextId) idMap[id] = nextId;
+// } else {
+// nextId = Component.getNewId(list);
+// }
+
+// list[nextId] = model;
+// return nextId;
+// };
+
+// Component.getNewId = list => {
+// const count = Object.keys(list).length;
+// // Testing 1000000 components with `+ 2` returns 0 collisions
+// const ilen = count.toString().length + 2;
+// const uid = (Math.random() + 1.1).toString(36).slice(-ilen);
+// let newId = `i${uid}`;
+
+// while (list[newId]) {
+// newId = Component.getNewId(list);
+// }
+
+// return newId;
+// };
+
+// Component.getIncrementId = (id, list, opts = {}) => {
+// const { keepIds = [] } = opts;
+// let counter = 1;
+// let newId = id;
+
+// if (keepIds.indexOf(id) < 0) {
+// while (list[newId]) {
+// counter++;
+// newId = `${id}-${counter}`;
+// }
+// }
+
+// return newId;
+// };
/**
* The list of components is taken from the Components module.
@@ -1980,12 +2147,12 @@ Component.getIncrementId = (id, list, opts = {}) => {
* not ok, as it was shared between multiple editor instances
* @private
*/
-Component.getList = model => {
- const { opt = {} } = model;
- const { domc, em } = opt;
- const dm = domc || (em && em.get('DomComponents'));
- return dm ? dm.componentsById : {};
-};
+// Component.getList = model => {
+// const { opt = {} } = model;
+// const { domc, em } = opt;
+// const dm = domc || (em && em.get('DomComponents'));
+// return dm ? dm.componentsById : {};
+// };
/**
* This method checks, for each parsed component and style object
@@ -1993,27 +2160,27 @@ Component.getList = model => {
* This method is used in Components.js just after the parsing
* @private
*/
-Component.checkId = (components, styles = [], list = {}, opts = {}) => {
- const comps = isArray(components) ? components : [components];
- const { keepIds = [] } = opts;
- comps.forEach(comp => {
- const { attributes = {}, components } = comp;
- const { id } = attributes;
-
- // Check if we have collisions with current components
- if (id && list[id] && keepIds.indexOf(id) < 0) {
- const newId = Component.getIncrementId(id, list);
- attributes.id = newId;
- // Update passed styles
- isArray(styles) &&
- styles.forEach(style => {
- const { selectors } = style;
- selectors.forEach((sel, idx) => {
- if (sel === `#${id}`) selectors[idx] = `#${newId}`;
- });
- });
- }
-
- components && Component.checkId(components, styles, list, opts);
- });
-};
+// Component.checkId = (components, styles = [], list = {}, opts = {}) => {
+// const comps = isArray(components) ? components : [components];
+// const { keepIds = [] } = opts;
+// comps.forEach(comp => {
+// const { attributes = {}, components } = comp;
+// const { id } = attributes;
+
+// // Check if we have collisions with current components
+// if (id && list[id] && keepIds.indexOf(id) < 0) {
+// const newId = Component.getIncrementId(id, list);
+// attributes.id = newId;
+// // Update passed styles
+// isArray(styles) &&
+// styles.forEach(style => {
+// const { selectors } = style;
+// selectors.forEach((sel, idx) => {
+// if (sel === `#${id}`) selectors[idx] = `#${newId}`;
+// });
+// });
+// }
+
+// components && Component.checkId(components, styles, list, opts);
+// });
+// };
diff --git a/src/dom_components/model/types.ts b/src/dom_components/model/types.ts
new file mode 100644
index 000000000..6821c16f4
--- /dev/null
+++ b/src/dom_components/model/types.ts
@@ -0,0 +1,231 @@
+import Frame from '../../canvas/model/Frame';
+import EditorModel from '../../editor/model/Editor';
+import Selectors from '../../selector_manager/model/Selectors';
+import { TraitProperties } from '../../trait_manager/model/Trait';
+import Traits from '../../trait_manager/model/Traits';
+import { DomComponentsConfig } from '../config/config';
+import Component from './Component';
+import Components from './Components';
+
+export type DragMode = 'translate' | 'absolute';
+
+export interface ComponentProperties {
+ /**
+ * Component type, eg. `text`, `image`, `video`, etc.
+ * @defaultValue ''
+ */
+ type?: string;
+ /**
+ * HTML tag of the component, eg. `span`. Default: `div`
+ * @defaultValue 'div'
+ */
+ tagName?: string;
+ /**
+ * Key-value object of the component's attributes, eg. `{ title: 'Hello' }` Default: `{}`
+ * @defaultValue {}
+ */
+ attributes?: Record;
+ /**
+ * Name of the component. Will be used, for example, in Layers and badges
+ * @defaultValue ''
+ */
+ name?: string;
+ /**
+ * When `true` the component is removable from the canvas, default: `true`
+ * @defaultValue true
+ */
+ removable?: boolean;
+ /**
+ * Indicates if it's possible to drag the component inside others.
+ You can also specify a query string to indentify elements,
+ eg. `'.some-class[title=Hello], [data-gjs-type=column]'` means you can drag the component only inside elements
+ containing `some-class` class and `Hello` title, and `column` components. In the case of a function, target and destination components are passed as arguments, return a Boolean to indicate if the drag is possible. Default: `true`
+ * @defaultValue true
+ */
+ draggable?: boolean | string | ((...params: any[]) => any);
+ /**
+ * Indicates if it's possible to drop other components inside. You can use
+ a query string as with `draggable`. In the case of a function, target and destination components are passed as arguments, return a Boolean to indicate if the drop is possible. Default: `true`
+ * @defaultValue true
+ */
+ droppable?: boolean | string | ((...params: any[]) => any);
+ /**
+ * Set to false if you don't want to see the badge (with the name) over the component. Default: `true`
+ * @defaultValue true
+ */
+ badgable?: boolean;
+ /**
+ * True if it's possible to style the component.
+ You can also indicate an array of CSS properties which is possible to style, eg. `['color', 'width']`, all other properties
+ will be hidden from the style manager. Default: `true`
+ * @defaultValue true
+ */
+ stylable?: boolean | String[];
+ ///**
+ // * Indicate an array of style properties to show up which has been marked as `toRequire`. Default: `[]`
+ // * @defaultValue []
+ // */
+ //`stylable-require`?: String[];
+ /**
+ * Indicate an array of style properties which should be hidden from the style manager. Default: `[]`
+ * @defaultValue []
+ */
+ unstylable?: String[];
+ /**
+ * It can be highlighted with 'dotted' borders if true. Default: `true`
+ * @defaultValue true
+ */
+ highlightable?: boolean;
+ /**
+ * True if it's possible to clone the component. Default: `true`
+ * @defaultValue true
+ */
+ copyable?: boolean;
+ /**
+ * Indicates if it's possible to resize the component. It's also possible to pass an object as [options for the Resizer](https://github.com/artf/grapesjs/blob/master/src/utils/Resizer.js). Default: `false`
+ */
+ resizable?: boolean;
+ /**
+ * Allow to edit the content of the component (used on Text components). Default: `false`
+ */
+ editable?: boolean;
+ /**
+ * Set to `false` if you need to hide the component inside Layers. Default: `true`
+ * @defaultValue true
+ */
+ layerable?: boolean;
+ /**
+ * Allow component to be selected when clicked. Default: `true`
+ * @defaultValue true
+ */
+ selectable?: boolean;
+ /**
+ * Shows a highlight outline when hovering on the element if `true`. Default: `true`
+ * @defaultValue true
+ */
+ hoverable?: boolean;
+ /**
+ * This property is used by the HTML exporter as void elements don't have closing tags, eg. `
`, `
`, etc. Default: `false`
+ */
+ void?: boolean;
+ /**
+ * Component default style, eg. `{ width: '100px', height: '100px', 'background-color': 'red' }`
+ * @defaultValue {}
+ */
+ style?: any;
+ /**
+ * Component related styles, eg. `.my-component-class { color: red }`
+ * @defaultValue ''
+ */
+ styles?: string;
+ /**
+ * Content of the component (not escaped) which will be appended before children rendering. Default: `''`
+ * @defaultValue ''
+ */
+ content?: string;
+ /**
+ * Component's icon, this string will be inserted before the name (in Layers and badge), eg. it can be an HTML string ''. Default: `''`
+ * @defaultValue ''
+ */
+ icon?: string;
+ /**
+ * Component's javascript. More about it [here](/modules/Components-js.html). Default: `''`
+ * @defaultValue ''
+ */
+ script?: string | ((...params: any[]) => any);
+ ///**
+ // * You can specify javascript available only in export functions (eg. when you get the HTML).
+ //If this property is defined it will overwrite the `script` one (in export functions). Default: `''`
+ // * @defaultValue ''
+ // */
+ //script-export?: string | ((...params: any[]) => any);
+ /**
+ * Component's traits. More about it [here](/modules/Traits.html). Default: `['id', 'title']`
+ * @defaultValue ''
+ */
+ traits?: Traits;
+ /**
+ * Indicates an array of properties which will be inhereted by all NEW appended children.
+ For example if you create a component likes this: `{ removable: false, draggable: false, propagate: ['removable', 'draggable'] }`
+ and append some new component inside, the new added component will get the exact same properties indicated in the `propagate` array (and the `propagate` property itself). Default: `[]`
+ * @defaultValue []
+ */
+ propagate?: (keyof ComponentProperties)[];
+ /**
+ * Set an array of items to show up inside the toolbar when the component is selected (move, clone, delete).
+ Eg. `toolbar: [ { attributes: {class: 'fa fa-arrows'}, command: 'tlb-move' }, ... ]`.
+ By default, when `toolbar` property is falsy the editor will add automatically commands `core:component-exit` (select parent component, added if there is one), `tlb-move` (added if `draggable`) , `tlb-clone` (added if `copyable`), `tlb-delete` (added if `removable`).
+ */
+ toolbar?: object[];
+ ///**
+ // * Children components. Default: `null`
+ // */
+ components?: Components;
+
+ classes?: Selectors;
+ dmode?: DragMode;
+ 'script-props'?: string[];
+ [key: string]: any;
+}
+
+export interface SymbolToUpOptions {
+ changed?: string;
+ fromInstance?: boolean;
+ noPropagate?: boolean;
+ fromUndo?: boolean;
+}
+
+export interface ComponentDefinition extends Omit {
+ /**
+ * Children components.
+ */
+ components?: string | ComponentDefinition | (string | ComponentDefinition)[];
+ traits?: (Partial | string)[];
+ [key: string]: unknown;
+}
+
+export interface ComponentDefinitionDefined extends Omit {
+ /**
+ * Children components.
+ */
+ components: ComponentDefinitionDefined[];
+ traits: Partial[];
+ [key: string]: any;
+}
+
+export interface ComponentModelProperties extends ComponentProperties {
+ [key: string]: any;
+}
+
+export type ComponentAdd = Component | ComponentDefinition | ComponentDefinition[] | string;
+
+export type ToHTMLOptions = {
+ /**
+ * Custom tagName.
+ */
+ tag?: string;
+
+ /**
+ * Include component properties as `data-gjs-*` attributes. This allows you to have re-importable HTML.
+ */
+ withProps?: boolean;
+
+ /**
+ * In case the attribute value contains a `"` char, instead of escaping it (`attr="value ""`), the attribute will be quoted using single quotes (`attr='value "'`).
+ */
+ altQuoteAttr?: boolean;
+
+ /**
+ * You can pass an object of custom attributes to replace with the current ones
+ * or you can even pass a function to generate attributes dynamically.
+ */
+ attributes?: Record | ((component: Component, attr: Record) => Record);
+};
+
+export interface ComponentOptions {
+ em?: EditorModel;
+ config?: DomComponentsConfig;
+ frame?: Frame;
+ temporary?: boolean;
+ avoidChildren?: boolean;
+}
diff --git a/src/selector_manager/index.ts b/src/selector_manager/index.ts
index e95ff6220..d110f8aad 100644
--- a/src/selector_manager/index.ts
+++ b/src/selector_manager/index.ts
@@ -298,7 +298,7 @@ export default class SelectorManager extends ItemManagerModule(name: T, type?: number): T extends string[] ? Selector[] : Selector {
+ get(name: T, type?: number): T extends string[] ? Selector[] : Selector | undefined {
// Keep support for arrays but avoid it in docs
if (isArray(name)) {
const result: Selector[] = [];
diff --git a/src/style_manager/index.ts b/src/style_manager/index.ts
index 882d59bcf..61d7de340 100644
--- a/src/style_manager/index.ts
+++ b/src/style_manager/index.ts
@@ -553,7 +553,10 @@ export default class StyleManager extends ItemManagerModule<
const id = model.getId();
rule = cssC.getIdRule(id, opts);
!rule && !skipAdd && (rule = cssC.setIdRule(id, {}, opts));
- if (model.is('wrapper')) rule.set('wrapper', 1, addOpts);
+ if (model.is('wrapper')) {
+ // @ts-ignore
+ rule!.set('wrapper', 1, addOpts);
+ }
}
rule && (model = rule);
diff --git a/src/trait_manager/model/Traits.ts b/src/trait_manager/model/Traits.ts
index dd1898a07..7af932595 100644
--- a/src/trait_manager/model/Traits.ts
+++ b/src/trait_manager/model/Traits.ts
@@ -34,7 +34,7 @@ export default class Traits extends Collection {
}
// @ts-ignore
- add(models: string | Trait | (string | Trait)[], opt: AddOptions) {
+ add(models: string | Trait | TraitProperties | (string | Trait | TraitProperties)[], opt?: AddOptions) {
const em = this.em;
// Use TraitFactory if necessary