Browse Source

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

pull/1775/head
Artur Arseniev 7 years ago
parent
commit
b7820d1bd5
  1. 2
      docs/modules/Style-manager.md
  2. 4
      index.html
  3. 10
      src/commands/view/SelectComponent.js
  4. 16
      src/editor/config/config.js
  5. 14
      src/style_manager/model/Property.js
  6. 122
      src/style_manager/model/PropertyFactory.js
  7. 42
      src/style_manager/view/PropertyView.js
  8. 5
      src/utils/mixins.js
  9. 153
      test/specs/style_manager/model/Models.js

2
docs/modules/Style-manager.md

@ -13,7 +13,7 @@ Coming soon
Here you can find all the available built-in properties that you can use inside Style Manager via `buildProps`:
`float`, `position`, `text-align`, `display`, `font-family`, `font-weight`, `border`, `border-style`, `border-color`, `border-width`, `box-shadow`, `background-repeat`, `background-position`, `background-attachment`, `background-size`, `transition`, `transition-duration`, `transition-property`, `transition-timing-function`, `top`, `right`, `bottom`, `left`, `margin`, `margin-top`, `margin-right`, `margin-bottom`, `margin-left`, `padding`, `padding-top`, `padding-right`, `padding-bottom`, `padding-left`, `width`, `heigth`, `min-width`, `min-heigth`, `max-width`, `max-heigth`, `font-size`, `letter-spacing`, `line-height`, `text-shadow`, `border-radius`, `border-top-left-radius`, `border-top-right-radius`, `border-bottom-left-radius`, `border-bottom-right-radius`, `perspective`, `transform`, `transform-rotate-x`, `transform-rotate-y`, `transform-rotate-z`, `transform-scale-x`, `transform-scale-y`, `transform-scale-z`, `color`, `background-color`, `background`, `background-image`, `cursor`
`float`, `position`, `text-align`, `display`, `font-family`, `font-weight`, `border`, `border-style`, `border-color`, `border-width`, `box-shadow`, `background-repeat`, `background-position`, `background-attachment`, `background-size`, `transition`, `transition-duration`, `transition-property`, `transition-timing-function`, `top`, `right`, `bottom`, `left`, `margin`, `margin-top`, `margin-right`, `margin-bottom`, `margin-left`, `padding`, `padding-top`, `padding-right`, `padding-bottom`, `padding-left`, `width`, `height`, `min-width`, `min-height`, `max-width`, `max-height`, `font-size`, `letter-spacing`, `line-height`, `text-shadow`, `border-radius`, `border-top-left-radius`, `border-top-right-radius`, `border-bottom-left-radius`, `border-bottom-right-radius`, `perspective`, `transform`, `transform-rotate-x`, `transform-rotate-y`, `transform-rotate-z`, `transform-scale-x`, `transform-scale-y`, `transform-scale-z`, `color`, `background-color`, `background`, `background-image`, `cursor`, `flex-direction`, `flex-wrap`, `justify-content`, `align-items`, `align-content`, `order`, `flex-basis`, `flex-grow`, `flex-shrink`, `align-self`, `overflow`, `overflow-x`, `overflow-y`
Example usage:
```js

4
index.html

@ -91,6 +91,10 @@
name: 'General',
open: false,
buildProps: ['float', 'display', 'position', 'top', 'right', 'left', 'bottom']
},{
name: 'Flex',
open: false,
buildProps: ['flex-direction', 'flex-wrap', 'justify-content', 'align-items', 'align-content', 'order', 'flex-basis', 'flex-grow', 'flex-shrink', 'align-self']
},{
name: 'Dimension',
open: false,

10
src/commands/view/SelectComponent.js

@ -350,7 +350,7 @@ module.exports = {
* @private
*/
initResize(elem) {
const em = this.em;
const { em, canvas } = this;
const editor = em ? em.get('Editor') : '';
const config = em ? em.get('Config') : '';
const pfx = config.stylePrefix || '';
@ -444,7 +444,13 @@ module.exports = {
const style = modelToStyle.getStyle();
if (!onlyHeight) {
style[keyWidth] = autoWidth ? 'auto' : `${rect.w}${unitWidth}`;
const padding = 10;
const frameOffset = canvas.getCanvasView().getFrameOffset();
const width =
rect.w < frameOffset.width - padding
? rect.w
: frameOffset.width - padding;
style[keyWidth] = autoWidth ? 'auto' : `${width}${unitWidth}`;
}
if (!onlyWidth) {

16
src/editor/config/config.js

@ -223,6 +223,22 @@ module.exports = {
'bottom'
]
},
{
name: 'Flex',
open: false,
buildProps: [
'flex-direction',
'flex-wrap',
'justify-content',
'align-items',
'align-content',
'order',
'flex-basis',
'flex-grow',
'flex-shrink',
'align-self'
]
},
{
name: 'Dimension',
open: false,

14
src/style_manager/model/Property.js

@ -26,7 +26,19 @@ const Property = require('backbone').Model.extend(
// Use case:
// you can add all SVG CSS properties with toRequire as true
// and then require them on SVG Components
toRequire: 0
toRequire: 0,
// Specifies dependency on other properties of the selected object.
// Property is shown only when all conditions are matched.
//
// example: { display: ['flex', 'block'], position: ['absolute'] };
// in this case the property is only shown when display is
// of value 'flex' or 'block' AND position is 'absolute'
requires: null,
// Specifies dependency on properties of the parent of the selected object.
// Property is shown only when all conditions are matched.
requiresParent: null
},
initialize(props = {}, opts = {}) {

122
src/style_manager/model/PropertyFactory.js

@ -40,6 +40,7 @@ module.exports = () => ({
case 'height':
case 'max-height':
case 'min-height':
case 'flex-basis':
obj.fixedValues = ['initial', 'inherit', 'auto'];
break;
case 'font-size':
@ -72,6 +73,12 @@ module.exports = () => ({
obj.type = 'radio';
break;
case 'display':
case 'flex-direction':
case 'flex-wrap':
case 'justify-content':
case 'align-items':
case 'align-content':
case 'align-self':
case 'font-family':
case 'font-weight':
case 'border-style':
@ -84,6 +91,8 @@ module.exports = () => ({
case 'transition-timing-function':
case 'cursor':
case 'overflow':
case 'overflow-x':
case 'overflow-y':
obj.type = 'select';
break;
case 'top':
@ -128,6 +137,10 @@ module.exports = () => ({
case 'transform-scale-x':
case 'transform-scale-y':
case 'transform-scale-z':
case 'order':
case 'flex-grow':
case 'flex-shrink':
case 'flex-basis':
obj.type = 'integer';
break;
case 'margin':
@ -166,6 +179,24 @@ module.exports = () => ({
case 'display':
obj.defaults = 'block';
break;
case 'flex-direction':
obj.defaults = 'row';
break;
case 'flex-wrap':
obj.defaults = 'nowrap';
break;
case 'justify-content':
obj.defaults = 'flex-start';
break;
case 'align-items':
obj.defaults = 'stretch';
break;
case 'align-content':
obj.defaults = 'stretch';
break;
case 'align-self':
obj.defaults = 'auto';
break;
case 'position':
obj.defaults = 'static';
break;
@ -192,6 +223,8 @@ module.exports = () => ({
case 'transform-rotate-x':
case 'transform-rotate-y':
case 'transform-rotate-z':
case 'order':
case 'flex-grow':
obj.defaults = 0;
break;
case 'border-top-left-radius':
@ -203,6 +236,7 @@ module.exports = () => ({
case 'transform-scale-x':
case 'transform-scale-y':
case 'transform-scale-z':
case 'flex-shrink':
obj.defaults = 1;
break;
case 'box-shadow-blur':
@ -216,6 +250,7 @@ module.exports = () => ({
case 'height':
case 'background-size':
case 'cursor':
case 'flex-basis':
obj.defaults = 'auto';
break;
case 'font-family':
@ -266,10 +301,36 @@ module.exports = () => ({
obj.defaults = 'ease';
break;
case 'overflow':
case 'overflow-x':
case 'overflow-y':
obj.defaults = 'visible';
break;
}
/*
* Add styleable dependency on other properties. Allows properties to be
* dynamically hidden or shown based on values of other properties.
*
* Property will be styleable if all of the properties (keys) in the
* requires object have any of the values specified in the array.
*/
switch (prop) {
case 'flex-direction':
case 'flex-wrap':
case 'justify-content':
case 'align-items':
case 'align-content':
obj.requires = { display: ['flex'] };
break;
case 'order':
case 'flex-basis':
case 'flex-grow':
case 'flex-shrink':
case 'align-self':
obj.requiresParent = { display: ['flex'] };
break;
}
// Units
switch (prop) {
case 'top':
@ -294,6 +355,9 @@ module.exports = () => ({
case 'width':
obj.units = ['px', '%', 'vw'];
break;
case 'flex-basis':
obj.units = ['px', '%', 'vw', 'vh'];
break;
case 'text-shadow-v':
case 'text-shadow-h':
case 'text-shadow-blur':
@ -352,6 +416,7 @@ module.exports = () => ({
case 'box-shadow-blur':
case 'transition-duration':
case 'perspective':
case 'flex-basis':
obj.min = 0;
break;
}
@ -407,9 +472,64 @@ module.exports = () => ({
{ value: 'block' },
{ value: 'inline' },
{ value: 'inline-block' },
{ value: 'flex' },
{ value: 'none' }
];
break;
case 'flex-direction':
obj.list = [
{ value: 'row' },
{ value: 'row-reverse' },
{ value: 'column' },
{ value: 'column-reverse' }
];
break;
case 'flex-wrap':
obj.list = [
{ value: 'nowrap' },
{ value: 'wrap' },
{ value: 'wrap-reverse' }
];
break;
case 'justify-content':
obj.list = [
{ value: 'flex-start' },
{ value: 'flex-end' },
{ value: 'center' },
{ value: 'space-between' },
{ value: 'space-around' },
{ value: 'space-evenly' }
];
break;
case 'align-items':
obj.list = [
{ value: 'flex-start' },
{ value: 'flex-end' },
{ value: 'center' },
{ value: 'baseline' },
{ value: 'stretch' }
];
break;
case 'align-content':
obj.list = [
{ value: 'flex-start' },
{ value: 'flex-end' },
{ value: 'center' },
{ value: 'space-between' },
{ value: 'space-around' },
{ value: 'stretch' }
];
break;
case 'align-self':
obj.list = [
{ value: 'auto' },
{ value: 'flex-start' },
{ value: 'flex-end' },
{ value: 'center' },
{ value: 'baseline' },
{ value: 'stretch' }
];
break;
case 'position':
obj.list = [
{ value: 'static' },
@ -552,6 +672,8 @@ module.exports = () => ({
];
break;
case 'overflow':
case 'overflow-x':
case 'overflow-y':
obj.list = [
{ value: 'visible' },
{ value: 'hidden' },

42
src/style_manager/view/PropertyView.js

@ -1,6 +1,7 @@
import Backbone from 'backbone';
import { bindAll, isArray, isUndefined, debounce } from 'underscore';
import { camelCase } from 'utils/mixins';
import { includes, each } from 'underscore';
const clearProp = 'data-clear-style';
@ -70,6 +71,15 @@ module.exports = Backbone.View.extend({
em && em.on(`update:component:style:${this.property}`, this.targetUpdated);
//em && em.on(`styleable:change:${this.property}`, this.targetUpdated);
// Listening to changes of properties in this.requires, so that styleable
// changes based on other properties are propagated
const requires = model.get('requires');
requires &&
Object.keys(requires).forEach(property => {
em && em.on(`component:styleUpdate:${property}`, this.targetUpdated);
});
this.listenTo(
this.propTarget,
'update styleManager:update',
@ -406,6 +416,10 @@ module.exports = Backbone.View.extend({
const toRequire = model.get('toRequire');
const unstylable = trg.get('unstylable');
const stylableReq = trg.get('stylable-require');
const requires = model.get('requires');
const requiresParent = model.get('requiresParent');
const sectors = this.sector ? this.sector.collection : null;
const selected = this.em ? this.em.getSelected() : null;
let stylable = trg.get('stylable');
// Stylable could also be an array indicating with which property
@ -427,6 +441,34 @@ module.exports = Backbone.View.extend({
(stylableReq.indexOf(id) >= 0 || stylableReq.indexOf(property) >= 0));
}
// Check if the property is available based on other property's values
if (sectors && requires) {
const properties = Object.keys(requires);
sectors.each(sector => {
sector.get('properties').each(model => {
if (includes(properties, model.id)) {
const values = requires[model.id];
stylable = stylable && includes(values, model.get('value'));
}
});
});
}
// Check if the property is available based on parent's property values
if (requiresParent) {
const parent = selected && selected.parent();
const parentEl = parent && parent.getEl();
if (parentEl) {
const styles = window.getComputedStyle(parentEl);
each(requiresParent, (values, property) => {
stylable =
stylable && styles[property] && includes(values, styles[property]);
});
} else {
stylable = false;
}
}
return stylable;
},

5
src/utils/mixins.js

@ -126,7 +126,8 @@ const getModel = (el, $) => {
* @param {Event} ev
* @return {Event}
*/
const getPointerEvent = (ev) => ev.touches && ev.touches[0] ? ev.touches[0] : ev;
const getPointerEvent = ev =>
ev.touches && ev.touches[0] ? ev.touches[0] : ev;
export {
on,
@ -140,5 +141,5 @@ export {
shallowDiff,
normalizeFloat,
getPointerEvent,
getUnitFromValue,
getUnitFromValue
};

153
test/specs/style_manager/model/Models.js

@ -60,6 +60,7 @@ module.exports = {
{ value: 'block' },
{ value: 'inline' },
{ value: 'inline-block' },
{ value: 'flex' },
{ value: 'none' }
]
});
@ -369,12 +370,121 @@ module.exports = {
{ value: 'block' },
{ value: 'inline' },
{ value: 'inline-block' },
{ value: 'flex' },
{ value: 'none' }
]
}
]);
});
test('Build flex-direction', () => {
expect(obj.build('flex-direction')).toEqual([
{
property: 'flex-direction',
type: 'select',
defaults: 'row',
list: [
{ value: 'row' },
{ value: 'row-reverse' },
{ value: 'column' },
{ value: 'column-reverse' }
],
requires: { display: ['flex'] }
}
]);
});
test('Build flex-wrap', () => {
expect(obj.build('flex-wrap')).toEqual([
{
property: 'flex-wrap',
type: 'select',
defaults: 'nowrap',
list: [
{ value: 'nowrap' },
{ value: 'wrap' },
{ value: 'wrap-reverse' }
],
requires: { display: ['flex'] }
}
]);
});
test('Build justify-content', () => {
expect(obj.build('justify-content')).toEqual([
{
property: 'justify-content',
type: 'select',
defaults: 'flex-start',
list: [
{ value: 'flex-start' },
{ value: 'flex-end' },
{ value: 'center' },
{ value: 'space-between' },
{ value: 'space-around' },
{ value: 'space-evenly' }
],
requires: { display: ['flex'] }
}
]);
});
test('Build align-items', () => {
expect(obj.build('align-items')).toEqual([
{
property: 'align-items',
type: 'select',
defaults: 'stretch',
list: [
{ value: 'flex-start' },
{ value: 'flex-end' },
{ value: 'center' },
{ value: 'baseline' },
{ value: 'stretch' }
],
requires: { display: ['flex'] }
}
]);
});
test('Build align-content', () => {
expect(obj.build('align-content')).toEqual([
{
property: 'align-content',
type: 'select',
defaults: 'stretch',
list: [
{ value: 'flex-start' },
{ value: 'flex-end' },
{ value: 'center' },
{ value: 'space-between' },
{ value: 'space-around' },
{ value: 'stretch' }
],
requires: { display: ['flex'] }
}
]);
});
test('Build align-self', () => {
expect(obj.build('align-self')).toEqual([
{
property: 'align-self',
type: 'select',
defaults: 'auto',
list: [
{ value: 'auto' },
{ value: 'flex-start' },
{ value: 'flex-end' },
{ value: 'center' },
{ value: 'baseline' },
{ value: 'stretch' }
],
requiresParent: { display: ['flex'] }
}
]);
});
test('Build position', () => {
expect(obj.build('position')).toEqual([
{
@ -431,6 +541,19 @@ module.exports = {
expect(obj.build('max-width')).toEqual([res]);
});
test('Build flex-basis', () => {
var res = {
type: 'integer',
units: ['px', '%', 'vw', 'vh'],
defaults: 'auto',
fixedValues: ['initial', 'inherit', 'auto'],
requiresParent: { display: ['flex'] },
min: 0
};
res.property = 'flex-basis';
expect(obj.build('flex-basis')).toEqual([res]);
});
test('Build height family', () => {
var res = {
type: 'integer',
@ -1032,6 +1155,36 @@ module.exports = {
};
expect(obj.build('overflow')).toEqual([res]);
});
test('Build overflow-x', () => {
var res = {
type: 'select',
property: 'overflow-x',
defaults: 'visible',
list: [
{ value: 'visible' },
{ value: 'hidden' },
{ value: 'scroll' },
{ value: 'auto' }
]
};
expect(obj.build('overflow-x')).toEqual([res]);
});
test('Build overflow-y', () => {
var res = {
type: 'select',
property: 'overflow-y',
defaults: 'visible',
list: [
{ value: 'visible' },
{ value: 'hidden' },
{ value: 'scroll' },
{ value: 'auto' }
]
};
expect(obj.build('overflow-y')).toEqual([res]);
});
});
}
};

Loading…
Cancel
Save