From f64a2635b753a1d1a2d5bcacf5734b77dbc955ee Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Sat, 25 Sep 2021 16:06:01 +0200 Subject: [PATCH] Add support to component related styles --- docs/api/pages.md | 53 ++++++++++++++++-------- docs/modules/Blocks.md | 2 +- src/commands/view/ComponentStyleClear.js | 27 ++++++------ src/css_composer/index.js | 19 ++++++--- src/css_composer/model/CssRule.js | 2 + src/dom_components/model/Component.js | 7 ++++ src/dom_components/model/Components.js | 5 +++ 7 files changed, 77 insertions(+), 38 deletions(-) diff --git a/docs/api/pages.md b/docs/api/pages.md index a5252506f..1144cf830 100644 --- a/docs/api/pages.md +++ b/docs/api/pages.md @@ -38,21 +38,24 @@ const pageManager = editor.Pages; * [add][1] * [get][2] * [getAll][3] -* [getMain][4] -* [remove][5] -* [select][6] -* [getSelected][7] +* [getAllWrappers][4] +* [getMain][5] +* [remove][6] +* [select][7] +* [getSelected][8] [Page]: page.html +[Component]: component.html + ## add Add new page ### Parameters -* `props` **[Object][8]** Page properties -* `opts` **[Object][8]?** Options (optional, default `{}`) +* `props` **[Object][9]** Page properties +* `opts` **[Object][9]?** Options (optional, default `{}`) ### Examples @@ -72,7 +75,7 @@ Remove page ### Parameters -* `page` **([String][9] | [Page])** Page or page id +* `page` **([String][10] | [Page])** Page or page id * `opts` (optional, default `{}`) ### Examples @@ -92,7 +95,7 @@ Get page by id ### Parameters -* `id` **[String][9]** Page id +* `id` **[String][10]** Page id ### Examples @@ -124,7 +127,21 @@ Get all pages const arrayOfPages = pageManager.getAll(); ``` -Returns **[Array][10]<[Page]>** +Returns **[Array][11]<[Page]>** + +## getAllWrappers + +Get wrapper components (aka body) from all pages and frames. + +### Examples + +```javascript +// Get all the `image` components from the project +const wrappers = pageManager.getAllWrappers(); +const allImages = wrappers.map(wrp => wrp.findType('image')).flat(); +``` + +Returns **[Array][11]<[Component]>** ## select @@ -132,7 +149,7 @@ Change the selected page. This will switch the page rendered in canvas ### Parameters -* `page` **([String][9] | [Page])** Page or page id +* `page` **([String][10] | [Page])** Page or page id * `opts` (optional, default `{}`) ### Examples @@ -164,16 +181,18 @@ Returns **[Page]** [3]: #getall -[4]: #getmain +[4]: #getallwrappers + +[5]: #getmain -[5]: #remove +[6]: #remove -[6]: #select +[7]: #select -[7]: #getselected +[8]: #getselected -[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object +[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object -[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String +[10]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String -[10]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array +[11]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array diff --git a/docs/modules/Blocks.md b/docs/modules/Blocks.md index 9e6786c7d..5f2710856 100644 --- a/docs/modules/Blocks.md +++ b/docs/modules/Blocks.md @@ -225,7 +225,7 @@ Don't put non serializable properties, like functions, in your blocks, keep them This will work, but if you try to save and reload a stored project, those will disappear. ### Avoid styles -Don't put styles in your blocks. +Don't put styles in your blocks, keep them in your components. ```js // Your block { diff --git a/src/commands/view/ComponentStyleClear.js b/src/commands/view/ComponentStyleClear.js index d6354353a..fd53a76c6 100644 --- a/src/commands/view/ComponentStyleClear.js +++ b/src/commands/view/ComponentStyleClear.js @@ -1,25 +1,22 @@ -import { isArray } from 'underscore'; +import { isArray, flatten } from 'underscore'; export default { - run(ed, sender, opts = {}) { + run(ed, s, opts = {}) { const { target } = opts; - const dc = ed.DomComponents; + let toRemove = []; + + if (!target.get('styles')) return toRemove; + + // Find all components in the project, of the target component type const type = target.get('type'); - const len = dc.getWrapper().findType(type).length; - const toRemove = []; + const wrappers = ed.Pages.getAllWrappers(); + const len = flatten(wrappers.map(wrp => wrp.findType(type))).length; + // Remove component related styles only if there are no more components + // of that type in the project if (!len) { const rules = ed.CssComposer.getAll(); - let toClear = target.get('style-signature'); - toClear = isArray(toClear) ? toClear : [toClear]; - - rules.forEach(rule => { - const selector = rule.selectorsToString(); - toClear.forEach(part => { - part && selector.indexOf(part) >= 0 && toRemove.push(rule); - }); - }); - + toRemove = rules.filter(rule => rule.get('group') === `cmp:${type}`); rules.remove(toRemove); } diff --git a/src/css_composer/index.js b/src/css_composer/index.js index 90ee36bc1..6f448b64f 100644 --- a/src/css_composer/index.js +++ b/src/css_composer/index.js @@ -27,7 +27,8 @@ * @module CssComposer */ -import { isArray, isUndefined } from 'underscore'; +import { isArray, isString, isUndefined, each } from 'underscore'; +import { isObject } from 'utils/mixins'; import defaults from './config/config'; import CssRule from './model/CssRule'; import CssRules from './model/CssRules'; @@ -243,14 +244,20 @@ export default () => { /** * Add a raw collection of rule objects * This method overrides styles, in case, of already defined rule - * @param {Array} data Array of rule objects, eg . [{selectors: ['class1'], style: {....}}, ..] + * @param {String|Array} data CSS string or an array of rule objects, eg. [{selectors: ['class1'], style: {....}}, ..] * @param {Object} opts Options + * @param {Object} props Additional properties to add on rules * @return {Array} * @private */ - addCollection(data, opts = {}) { - var result = []; - var d = data instanceof Array ? data : [data]; + addCollection(data, opts = {}, props = {}) { + const result = []; + + if (isString(data)) { + data = em.get('Parser').parseCss(data); + } + + const d = data instanceof Array ? data : [data]; for (var i = 0, l = d.length; i < l; i++) { var rule = d[i] || {}; @@ -271,6 +278,8 @@ export default () => { var updateStyle = !modelExists || !opts.avoidUpdateStyle; const style = rule.style || {}; + isObject(props) && model.set(props, opts); + if (updateStyle) { let styleUpdate = opts.extend ? { ...model.get('style'), ...style } diff --git a/src/css_composer/model/CssRule.js b/src/css_composer/model/CssRule.js index f1f331c3f..dc40f7b23 100644 --- a/src/css_composer/model/CssRule.js +++ b/src/css_composer/model/CssRule.js @@ -40,6 +40,8 @@ export default class CssRule extends Model.extend(Styleable) { // Used in view important: 0, + group: '', + _undo: true }; } diff --git a/src/dom_components/model/Component.js b/src/dom_components/model/Component.js index 88fdc10f4..54c7b5acd 100644 --- a/src/dom_components/model/Component.js +++ b/src/dom_components/model/Component.js @@ -176,6 +176,13 @@ export default class Component extends Model.extend(Styleable) { }); if (!opt.temporary) { + // Add component styles + const cssc = em && em.get('CssComposer'); + const { styles, type } = this.attributes; + if (styles && cssc) { + cssc.addCollection(styles, {}, { group: `cmp:${type}` }); + } + this.__postAdd(); this.init(); this.__isSymbolOrInst() && this.__initSymb(); diff --git a/src/dom_components/model/Components.js b/src/dom_components/model/Components.js index b5d085ea5..f0c28d5ac 100644 --- a/src/dom_components/model/Components.js +++ b/src/dom_components/model/Components.js @@ -82,6 +82,11 @@ export default Backbone.Collection.extend({ sels.remove(rulesRemoved.map(rule => rule.getSelectors().at(0))); if (!removed.opt.temporary) { + const hasStyles = removed.get('styles'); + const cm = em.get('Commands'); + em.get('Commands').run('core:component-style-clear', { + target: removed + }); // Deprecate 'style-signature' // const cm = em.get('Commands'); // const hasSign = removed.get('style-signature');