Browse Source

Merge branch 'dev' of https://github.com/amirrahmani76/grapesjs into amirrahmani76-dev

pull/5642/head
Artur Arseniev 2 years ago
parent
commit
00b1685de8
  1. 20
      .vscode/launch.json
  2. 24
      .vscode/settings.json
  3. 2
      dist/css/grapes.min.css
  4. 8
      src/abstract/ModuleCategories.ts
  5. 10
      src/abstract/ModuleCategory.ts
  6. 41
      src/abstract/ModuleCategoryView.ts
  7. 4
      src/block_manager/index.ts
  8. 4
      src/block_manager/model/Block.ts
  9. 6
      src/block_manager/view/BlocksView.ts
  10. 4
      src/index.ts
  11. 30
      src/styles/scss/_gjs_traits.scss
  12. 18
      src/trait_manager/index.ts
  13. 13
      src/trait_manager/model/Trait.ts
  14. 8
      src/trait_manager/view/TraitView.ts
  15. 134
      src/trait_manager/view/TraitsView.ts

20
.vscode/launch.json

@ -0,0 +1,20 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "msedge",
"request": "launch",
"name": "Launch Edge against localhost",
"url": "http://localhost:8080",
"webRoot": "${workspaceFolder}/src/trait_managerindex.ts",
"sourceMapPathOverrides": {
"meteor://💻app/*": "${workspaceFolder}/*",
"webpack:///./~/*": "${workspaceFolder}/node_modules/*",
"webpack://?:*/*": "${workspaceFolder}/*"
}
}
]
}

24
.vscode/settings.json

@ -0,0 +1,24 @@
{
"grammarly.selectors": [
{
"language": "markdown",
"scheme": "file",
"pattern": "c:\\Users\\amirmohammad.r\\Desktop\\pr\\Grapesjs.md"
},
{
"language": "markdown",
"scheme": "file",
"pattern": "c:\\Users\\amirmohammad.r\\Desktop\\pr\\Grapesjs.md"
},
{
"language": "markdown",
"scheme": "file",
"pattern": "c:\\Users\\amirmohammad.r\\Desktop\\pr\\Grapesjs.md"
},
{
"language": "markdown",
"scheme": "file",
"pattern": "c:\\Users\\amirmohammad.r\\Desktop\\pr\\Grapesjs.md"
}
]
}

2
dist/css/grapes.min.css

File diff suppressed because one or more lines are too long

8
src/block_manager/model/Categories.ts → src/abstract/ModuleCategories.ts

@ -1,11 +1,11 @@
import { isArray, isString } from 'underscore';
import { AddOptions, Collection } from '../../common';
import { normalizeKey } from '../../utils/mixins';
import Category, { BlockCategoryProperties } from './Category';
import { AddOptions, Collection } from '../common';
import { normalizeKey } from '../utils/mixins';
import Category, { CategoryProperties } from './ModuleCategory';
export default class Categories extends Collection<Category> {
/** @ts-ignore */
add(model: (BlockCategoryProperties | Category)[] | BlockCategoryProperties | Category, opts?: AddOptions) {
add(model: (CategoryProperties | Category)[] | CategoryProperties | Category, opts?: AddOptions) {
const models = isArray(model) ? model : [model];
models.forEach(md => md && (md.id = normalizeKey(`${md.id}`)));
return super.add(model, opts);

10
src/block_manager/model/Category.ts → src/abstract/ModuleCategory.ts

@ -1,7 +1,7 @@
import { Model } from '../../common';
import CategoryView from '../view/CategoryView';
import { Model } from '../common';
import CategoryView from './ModuleCategoryView';
export interface BlockCategoryProperties {
export interface CategoryProperties {
/**
* Category id.
*/
@ -26,14 +26,14 @@ export interface BlockCategoryProperties {
attributes?: Record<string, any>;
}
export default class Category extends Model<BlockCategoryProperties> {
export default class Category extends Model<CategoryProperties> {
view?: CategoryView;
defaults() {
return {
id: '',
label: '',
open: true,
open: false,
attributes: {},
};
}

41
src/block_manager/view/CategoryView.ts → src/abstract/ModuleCategoryView.ts

@ -1,11 +1,12 @@
import { View } from '../../common';
import EditorModel from '../../editor/model/Editor';
import html from '../../utils/html';
import Category from '../model/Category';
import { View } from '../common';
import EditorModel from '../editor/model/Editor';
import html from '../utils/html';
import Category from './ModuleCategory';
export interface CategoryViewConfig {
em: EditorModel;
pStylePrefix?: string;
stylePrefix?: string;
}
export default class CategoryView extends View<Category> {
@ -17,7 +18,8 @@ export default class CategoryView extends View<Category> {
iconClass: string;
activeClass: string;
iconEl?: HTMLElement;
blocksEl?: HTMLElement;
typeEl?: HTMLElement;
catName: string;
events() {
return {
@ -25,13 +27,13 @@ export default class CategoryView extends View<Category> {
};
}
template({ pfx, label }: { pfx: string; label: string }) {
template({ pfx, label, catName }: { pfx: string; label: string; catName: string }) {
return html`
<div class="${pfx}title" data-title>
<i class="${pfx}caret-icon"></i>
${label}
</div>
<div class="${pfx}blocks-c"></div>
<div class="${pfx}${catName}s-c"></div>
`;
}
@ -40,17 +42,18 @@ export default class CategoryView extends View<Category> {
return this.model.get('attributes') || {};
}
constructor(o: any, config: CategoryViewConfig) {
constructor(o: any, config: CategoryViewConfig, catName: string) {
super(o);
this.config = config;
const pfx = config.pStylePrefix || '';
this.em = config.em;
this.catName = catName;
this.pfx = pfx;
this.caretR = 'fa fa-caret-right';
this.caretD = 'fa fa-caret-down';
this.iconClass = `${pfx}caret-icon`;
this.activeClass = `${pfx}open`;
this.className = `${pfx}block-category`;
this.className = `${pfx}${catName}-category`;
this.listenTo(this.model, 'change:open', this.updateVisibility);
this.model.view = this;
}
@ -63,13 +66,13 @@ export default class CategoryView extends View<Category> {
open() {
this.$el.addClass(this.activeClass);
this.getIconEl()!.className = `${this.iconClass} ${this.caretD}`;
this.getBlocksEl()!.style.display = '';
this.getTypeEl()!.style.display = '';
}
close() {
this.$el.removeClass(this.activeClass);
this.getIconEl()!.className = `${this.iconClass} ${this.caretR}`;
this.getBlocksEl()!.style.display = 'none';
this.getTypeEl()!.style.display = 'none';
}
toggle() {
@ -85,22 +88,22 @@ export default class CategoryView extends View<Category> {
return this.iconEl;
}
getBlocksEl() {
if (!this.blocksEl) {
this.blocksEl = this.el.querySelector(`.${this.pfx}blocks-c`)!;
getTypeEl() {
if (!this.typeEl) {
this.typeEl = this.el.querySelector(`.${this.pfx}${this.catName}s-c`)!;
}
return this.blocksEl;
return this.typeEl;
}
append(el: HTMLElement) {
this.getBlocksEl().appendChild(el);
this.getTypeEl().appendChild(el);
}
render() {
const { em, el, $el, model, pfx } = this;
const label = em.t(`blockManager.categories.${model.id}`) || model.get('label');
el.innerHTML = this.template({ pfx, label });
const { em, el, $el, model, pfx, catName } = this;
const label = em.t(`${catName}Manager.categories.${model.id}`) || model.get('label');
el.innerHTML = this.template({ pfx, label, catName });
$el.addClass(this.className!);
$el.css({ order: model.get('order')! });
this.updateVisibility();

4
src/block_manager/index.ts

@ -34,8 +34,8 @@ import EditorModel from '../editor/model/Editor';
import defaults, { BlockManagerConfig } from './config/config';
import Block, { BlockProperties } from './model/Block';
import Blocks from './model/Blocks';
import Categories from './model/Categories';
import Category from './model/Category';
import Categories from '../abstract/ModuleCategories';
import Category from '../abstract/ModuleCategory';
import { BlocksEvents } from './types';
import BlocksView from './view/BlocksView';

4
src/block_manager/model/Block.ts

@ -1,7 +1,7 @@
import { Model } from '../../common';
import { isFunction } from 'underscore';
import Editor from '../../editor';
import { BlockCategoryProperties } from './Category';
import { CategoryProperties } from '../../abstract/ModuleCategory';
import { ComponentDefinition } from '../../dom_components/model/types';
/** @private */
@ -23,7 +23,7 @@ export interface BlockProperties {
* Block category, eg. `Basic blocks`
* @default ''
*/
category?: string | BlockCategoryProperties;
category?: string | CategoryProperties;
/**
* If true, triggers the `active` event on the dropped component.
* @default false

6
src/block_manager/view/BlocksView.ts

@ -4,9 +4,9 @@ import { View } from '../../common';
import Component from '../../dom_components/model/Component';
import EditorModel from '../../editor/model/Editor';
import Block from '../model/Block';
import Categories from '../model/Categories';
import Categories from '../../abstract/ModuleCategories';
import BlockView from './BlockView';
import CategoryView from './CategoryView';
import CategoryView from '../../abstract/ModuleCategoryView';
export interface BlocksViewConfig {
em: EditorModel;
@ -152,7 +152,7 @@ export default class BlocksView extends View {
model.set('category', catModel, { silent: true });
if (!catView && categories) {
catView = new CategoryView({ model: catModel }, config).render();
catView = new CategoryView({ model: catModel }, config, 'block').render();
renderedCategories.set(catId, catView);
categories.appendChild(catView.el);
}

4
src/index.ts

@ -97,8 +97,8 @@ export type { default as Asset } from './asset_manager/model/Asset';
export type { default as Assets } from './asset_manager/model/Assets';
export type { default as Block } from './block_manager/model/Block';
export type { default as Blocks } from './block_manager/model/Blocks';
export type { default as Categories } from './block_manager/model/Categories';
export type { default as Category } from './block_manager/model/Category';
export type { default as Categories } from './abstract/ModuleCategories';
export type { default as Category } from './abstract/ModuleCategory';
export type { default as Canvas } from './canvas/model/Canvas';
export type { default as CanvasSpot } from './canvas/model/CanvasSpot';
export type { default as CanvasSpots } from './canvas/model/CanvasSpots';

30
src/styles/scss/_gjs_traits.scss

@ -1,3 +1,31 @@
.#{$app-prefix}traits-c {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
}
.#{$app-prefix}trait-categories {
display: flex;
flex-direction: column;
}
.#{$app-prefix}trait-category {
width: 100%;
&.#{$app-prefix}open {
@extend .#{$app-prefix}category-open;
}
.#{$app-prefix}title {
@extend .#{$app-prefix}category-title;
}
.#{$app-prefix}caret-icon {
margin-right: 5px;
}
}
.#{$app-prefix} {
&traits-label {
border-bottom: 1px solid var(--gjs-main-dark-color);
@ -45,4 +73,4 @@
text-overflow: ellipsis;
overflow: hidden;
}
}
}

18
src/trait_manager/index.ts

@ -12,6 +12,9 @@ import TraitButtonView from './view/TraitButtonView';
import EditorModel from '../editor/model/Editor';
import Component from '../dom_components/model/Component';
import Trait from './model/Trait';
import Traits from './model/Traits';
import Category from '../abstract/ModuleCategory';
import Categories from '../abstract/ModuleCategories';
export const evAll = 'trait';
export const evPfx = `${evAll}:`;
@ -43,7 +46,13 @@ export default class TraitManager extends Module<TraitManagerConfig & { pStylePr
types: { [id: string]: { new (o: any): TraitView } };
model: Model;
__ctn?: any;
traits: Traits;
traitsVisible: Traits;
categories: Categories;
TraitsView = TraitsView;
Category = Category;
Categories = Categories;
events = {
all: evAll,
@ -66,6 +75,13 @@ export default class TraitManager extends Module<TraitManagerConfig & { pStylePr
const model = new Model();
this.model = model;
this.types = typesDef;
const ppfx = this.config.pStylePrefix;
ppfx && (this.config.stylePrefix = `${ppfx}${this.config.stylePrefix}`);
// Global traits collection
this.traits = new Traits([], { em });
this.traitsVisible = new Traits(this.traits.models, { em });
this.categories = new Categories();
const upAll = debounce(() => this.__upSel(), 0);
model.listenTo(em, 'component:toggled', upAll);
@ -149,6 +165,7 @@ export default class TraitManager extends Module<TraitManagerConfig & { pStylePr
render() {
let { view, em } = this;
const { categories } = this;
const config = this.getConfig();
const el = view && view.el;
view = new TraitsView(
@ -157,6 +174,7 @@ export default class TraitManager extends Module<TraitManagerConfig & { pStylePr
collection: [],
editor: em,
config,
categories,
},
this.getTypes()
);

13
src/trait_manager/model/Trait.ts

@ -5,6 +5,7 @@ import Editor from '../../editor';
import EditorModel from '../../editor/model/Editor';
import TraitView from '../view/TraitView';
import { isDef } from '../../utils/mixins';
import { CategoryProperties } from '../../abstract/ModuleCategory';
/** @private */
export interface TraitProperties {
@ -18,13 +19,19 @@ export interface TraitProperties {
* The name of the trait used as a key for the attribute/property.
* By default, the name is used as attribute name or property in case `changeProp` in enabled.
*/
name: string;
name?: string;
/**
* Trait id, eg. `my-trait-id`.
* If not specified, the `name` will be used as id.
*/
id?: string;
id?: string | number;
/**
* Trait category.
* @default ''
*/
category?: string | CategoryProperties;
/**
* The trait label to show for the rendered trait.
@ -80,6 +87,7 @@ type TraitOption = {
* @property {String} type Trait type, defines how the trait should rendered. Possible values: `text` (default), `number`, `select`, `checkbox`, `color`, `button`
* @property {String} label The trait label to show for the rendered trait.
* @property {String} name The name of the trait used as a key for the attribute/property. By default, the name is used as attribute name or property in case `changeProp` in enabled.
* @property {String} [category=''] Trait category.
* @property {Boolean} changeProp If `true` the trait value is applied on component
*
*/
@ -99,6 +107,7 @@ export default class Trait extends Model<TraitProperties> {
value: '',
default: '',
placeholder: '',
category: '',
changeProp: false,
options: [],
};

8
src/trait_manager/view/TraitView.ts

@ -48,11 +48,11 @@ export default class TraitView extends View<Trait> {
const { type } = model.attributes;
this.config = config;
this.em = config.em;
this.ppfx = config.pStylePrefix || '';
this.pfx = this.ppfx + config.stylePrefix || '';
this.pfx = this.config.stylePrefix || '';
this.ppfx = this.config.pStylePrefix || '';
this.target = target;
const { ppfx } = this;
this.clsField = `${ppfx}field ${ppfx}field-${type}`;
this.className = this.pfx + 'trait';
this.clsField = `${this.ppfx}field ${this.ppfx}field-${type}`;
const evToListen: [string, any][] = [
['change:value', this.onValueChange],
['remove', this.removeView],

134
src/trait_manager/view/TraitsView.ts

@ -1,12 +1,26 @@
import DomainViews from '../../domain_abstract/view/DomainViews';
import EditorModel from '../../editor/model/Editor';
import TraitView from './TraitView';
import CategoryView from '../../abstract/ModuleCategoryView';
import Categories from '../../abstract/ModuleCategories';
import Trait from '../model/Trait';
import { isObject, isString } from 'underscore';
export default class TraitsView extends DomainViews {
reuseView = true;
em: EditorModel;
pfx: string;
ppfx: string;
categories: Categories;
renderedCategories = new Map<string, CategoryView>();
noCatClass: string;
traitContClass: string;
catsClass: string;
catsEl?: HTMLElement;
traitsEl?: HTMLElement;
itemView?: any;
itemType: any;
rendered?: boolean;
constructor(o: any = {}, itemsView: any) {
super(o);
@ -14,11 +28,14 @@ export default class TraitsView extends DomainViews {
const config = o.config || {};
const em = o.editor;
this.config = config;
this.em = em;
this.ppfx = config.pStylePrefix || '';
this.pfx = this.ppfx + config.stylePrefix || '';
this.className = `${this.pfx}traits`;
this.categories = o.categories || '';
this.noCatClass = `${this.ppfx}traits-no-cat`;
this.traitContClass = `${this.ppfx}traits-c`;
this.catsClass = `${this.ppfx}trait-categories`;
this.listenTo(em, 'component:toggled', this.updatedCollection);
this.updatedCollection();
}
@ -28,13 +45,122 @@ export default class TraitsView extends DomainViews {
* @private
*/
updatedCollection() {
const { ppfx, className, em } = this;
const { ppfx, em } = this;
const comp = em.getSelected();
this.el.className = `${className} ${ppfx}one-bg ${ppfx}two-color`;
this.el.className = `${this.traitContClass}s ${ppfx}one-bg ${ppfx}two-color`;
// @ts-ignore
this.collection = comp ? comp.traits : [];
this.collection = comp ? comp.get('traits') : [];
this.render();
}
/**
* Add new model to the collection
* @param {Model} model
* @private
*/
addTo(model: Trait) {
this.add(model);
}
/**
* Render new model inside the view
* @param {Model} model
* @param {Object} fragment Fragment collection
* @private
* */
add(model: Trait, fragment?: DocumentFragment) {
const { config, renderedCategories } = this;
var itemView = this.itemView;
const typeField = model.get(this.itemType);
if (this.itemsView && this.itemsView[typeField]) {
itemView = this.itemsView[typeField];
}
const view = new itemView({
config,
model,
attributes: model.get('attributes'),
});
const rendered = view.render().el;
let category = model.get('category');
// Check for categories
if (category && this.categories && !config.ignoreCategories) {
if (isString(category)) {
category = {
id: category,
label: category,
};
} else if (isObject(category) && !category.id) {
category.id = category.label;
}
const catModel = this.categories.add(category);
const catId = catModel.get('id')!;
const categories = this.getCategoriesEl();
let catView = renderedCategories.get(catId);
//@ts-ignore
model.set('category', catModel, { silent: true });
if (!catView && categories) {
catView = new CategoryView(
{
model: catModel,
},
config,
'trait'
).render();
renderedCategories.set(catId, catView);
categories.appendChild(catView.el);
}
catView && catView.append(rendered);
return;
}
fragment ? fragment.appendChild(rendered) : this.append(rendered);
}
getCategoriesEl() {
if (!this.catsEl) {
this.catsEl = this.el.querySelector(`.${this.catsClass}`)!;
}
return this.catsEl;
}
getTraitsEl() {
if (!this.traitsEl) {
this.traitsEl = this.el.querySelector(`.${this.noCatClass} .${this.traitContClass}`)!;
}
return this.traitsEl;
}
append(el: HTMLElement | DocumentFragment) {
let traits = this.getTraitsEl();
traits && traits.appendChild(el);
}
render() {
const ppfx = this.ppfx;
const frag = document.createDocumentFragment();
delete this.catsEl;
delete this.traitsEl;
this.renderedCategories = new Map();
this.el.innerHTML = `
<div class="${this.catsClass}"></div>
<div class="${this.noCatClass}">
<div class="${this.traitContClass}"></div>
</div>
`;
if (this.collection.length) {
this.collection.each(model => this.add(model, frag));
}
this.append(frag);
const cls = `${this.traitContClass}s ${ppfx}one-bg ${ppfx}two-color`;
this.$el.addClass(cls);
this.rendered = true;
return this;
}
}
// @ts-ignore

Loading…
Cancel
Save