Browse Source

Merge branch 'dev' into components-dynamic-values

pull/6351/head
mohamed yahia 2 years ago
committed by GitHub
parent
commit
770a316453
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      packages/core/package.json
  2. 13
      packages/core/src/dom_components/model/Components.ts
  3. 7
      packages/core/src/dom_components/view/ComponentImageView.ts
  4. 5
      packages/core/src/dom_components/view/ComponentTextView.ts
  5. 2
      packages/core/src/dom_components/view/ComponentView.ts
  6. 12
      packages/core/src/rich_text_editor/config/config.ts
  7. 23
      packages/core/src/rich_text_editor/index.ts
  8. 16
      packages/core/test/specs/dom_components/view/ComponentView.ts

2
packages/core/package.json

@ -1,7 +1,7 @@
{
"name": "grapesjs",
"description": "Free and Open Source Web Builder Framework",
"version": "0.22.3",
"version": "0.22.4",
"author": "Artur Arseniev",
"license": "BSD-3-Clause",
"homepage": "http://grapesjs.com",

13
packages/core/src/dom_components/model/Components.ts

@ -63,15 +63,20 @@ const getComponentsFromDefs = (
}
}
// Here `result` might be a Component
const cmp = isFunction(result.components) ? (result as unknown as Component) : null;
if (components) {
const newComponents = getComponentsFromDefs(components, all);
const newComponents = getComponentsFromDefs(components, all, opts);
if (isFunction(result.components)) {
const cmps = result.components();
cmps.length > 0 && cmps.reset(newComponents, opts);
if (cmp) {
cmp.components().reset(newComponents, opts);
} else {
result.components = newComponents;
}
} else if (cmp) {
// The component already exists but the parsed one is without components
cmp.components().reset([], opts);
}
return result;

7
packages/core/src/dom_components/view/ComponentImageView.ts

@ -95,9 +95,12 @@ export default class ComponentImageView<TComp extends ComponentImage = Component
}
onError() {
const fallback = this.model.getSrcResult({ fallback: true });
const { model, el } = this;
const fallback = model.getSrcResult({ fallback: true });
if (fallback) {
this.el.src = fallback;
// Remove srcset to prevent error loop on src update #6332
if (el.srcset) el.srcset = '';
el.src = fallback;
}
}

5
packages/core/src/dom_components/view/ComponentTextView.ts

@ -71,7 +71,7 @@ export default class ComponentTextView<TComp extends ComponentText = ComponentTe
* Enable element content editing
* @private
* */
async onActive(ev: Event) {
async onActive(ev: MouseEvent) {
const { rte, em } = this;
const { result, delegate } = this.canActivate();
@ -91,7 +91,8 @@ export default class ComponentTextView<TComp extends ComponentText = ComponentTe
if (rte) {
try {
this.activeRte = await rte.enable(this, this.activeRte!, { event: ev });
const view = this;
this.activeRte = await rte.enable(view, this.activeRte!, { event: ev, view });
} catch (err) {
em.logError(err as any);
}

2
packages/core/src/dom_components/view/ComponentView.ts

@ -241,7 +241,7 @@ TComp> {
const hoveredCls = `${ppfx}hovered`;
const noPointerCls = `${ppfx}no-pointer`;
const pointerInitCls = `${ppfx}pointer-init`;
const toRemove = [selectedCls, selectedParentCls, freezedCls, hoveredCls, noPointerCls];
const toRemove = [selectedCls, selectedParentCls, freezedCls, hoveredCls, noPointerCls, pointerInitCls];
const selCls = extHl && !opts.noExtHl ? '' : selectedCls;
this.$el.removeClass(toRemove.join(' '));
const actualCls = el.getAttribute('class') || '';

12
packages/core/src/rich_text_editor/config/config.ts

@ -1,6 +1,12 @@
import ComponentTextView from '../../dom_components/view/ComponentTextView';
import Editor from '../../editor';
import RichTextEditor from '../model/RichTextEditor';
export interface CustomRteOptions {
event?: MouseEvent;
view: ComponentTextView;
}
export interface CustomRTE<T = any> {
/**
* If true, the returned HTML content will be parsed into Components, allowing
@ -11,16 +17,16 @@ export interface CustomRTE<T = any> {
/**
* Create or enable the custom RTE.
*/
enable: (el: HTMLElement, rte: T | undefined) => T | Promise<T>;
enable: (el: HTMLElement, rte: T | undefined, opts: CustomRteOptions) => T | Promise<T>;
/**
* Disable the custom RTE.
*/
disable: (el: HTMLElement, rte: T) => any | Promise<any>;
disable: (el: HTMLElement, rte: T, opts: CustomRteOptions) => any | Promise<any>;
/**
* Get HTML content from the custom RTE.
* If not specified, it will use the innerHTML of the element (passed also as `content` in options).
*/
getContent?: (el: HTMLElement, rte: T | undefined) => string | Promise<string>;
getContent?: (el: HTMLElement, rte: T | undefined, opts: CustomRteOptions) => string | Promise<string>;
/**
* Destroy the custom RTE.
* Will be triggered on editor destroy.

23
packages/core/src/rich_text_editor/index.ts

@ -40,14 +40,14 @@
import { debounce, isFunction, isString } from 'underscore';
import { Module } from '../abstract';
import { Debounced, DisableOptions, Model } from '../common';
import ComponentView from '../dom_components/view/ComponentView';
import EditorModel from '../editor/model/Editor';
import { createEl, cx, on, removeEl } from '../utils/dom';
import { hasWin, isDef } from '../utils/mixins';
import defConfig, { CustomRTE, RichTextEditorConfig } from './config/config';
import defConfig, { CustomRTE, CustomRteOptions, RichTextEditorConfig } from './config/config';
import RichTextEditor, { RichTextEditorAction } from './model/RichTextEditor';
import CanvasEvents from '../canvas/types';
import { ComponentsEvents } from '../dom_components/types';
import ComponentTextView from '../dom_components/view/ComponentTextView';
export type RichTextEditorEvent = 'rte:enable' | 'rte:disable' | 'rte:custom';
@ -64,7 +64,7 @@ const events = {
};
interface ModelRTE {
currentView?: ComponentView;
currentView?: ComponentTextView;
}
export interface RteDisableResult {
@ -360,13 +360,13 @@ export default class RichTextEditorModule extends Module<RichTextEditorConfig &
* @param {Object} rte The instance of already defined RTE
* @private
* */
async enable(view: ComponentView, rte: RichTextEditor, opts: any = {}) {
async enable(view: ComponentTextView, rte: RichTextEditor, opts: CustomRteOptions) {
this.lastEl = view.el;
const { customRte, em } = this;
const el = view.getChildrenContainer();
this.toolbar.style.display = '';
const rteInst = await (customRte ? customRte.enable(el, rte) : this.initRte(el).enable(opts));
const rteInst = await (customRte ? customRte.enable(el, rte, opts) : this.initRte(el).enable(opts));
if (em) {
setTimeout(this.updatePosition.bind(this), 0);
@ -380,13 +380,14 @@ export default class RichTextEditorModule extends Module<RichTextEditorConfig &
return rteInst;
}
async getContent(view: ComponentView, rte: RichTextEditor) {
async getContent(view: ComponentTextView, rte: RichTextEditor) {
const { customRte } = this;
const el = view.getChildrenContainer();
if (customRte && rte && isFunction(customRte.getContent)) {
return await customRte.getContent(view.el, rte);
return await customRte.getContent(el, rte, { view });
} else {
return view.getChildrenContainer().innerHTML;
return el.innerHTML;
}
}
@ -404,15 +405,13 @@ export default class RichTextEditorModule extends Module<RichTextEditorConfig &
* @param {Object} rte The instance of already defined RTE
* @private
* */
async disable(view: ComponentView, rte?: RichTextEditor, opts: DisableOptions = {}) {
async disable(view: ComponentTextView, rte?: RichTextEditor, opts: DisableOptions = {}) {
let result: RteDisableResult = {};
const { em } = this;
const customRte = this.customRte;
// @ts-ignore
const el = view.getChildrenContainer();
if (customRte) {
const res = await customRte.disable(el, rte);
const res = await customRte.disable(view.getChildrenContainer(), rte, { ...opts, view });
if (res) {
result = res;
}

16
packages/core/test/specs/dom_components/view/ComponentView.ts

@ -143,4 +143,20 @@ describe('ComponentView', () => {
const result = model.getAttributes();
expect(result.class).toEqual(undefined);
});
test('updateStatus removes previous classes and adds new ones', () => {
model.addClass('selected');
model.set('locked', true);
view.updateStatus();
expect(view.el.getAttribute('class')).toEqual('no-pointer');
model.set('locked', false);
view.updateStatus();
expect(view.el.getAttribute('class')).toEqual('pointer-init');
model.set('locked');
view.updateStatus();
expect(view.el.getAttribute('class')).toEqual('');
});
});

Loading…
Cancel
Save