diff --git a/docs/.vuepress/components/DemoStyle.vue b/docs/.vuepress/components/DemoStyle.vue
new file mode 100644
index 000000000..716525f3f
--- /dev/null
+++ b/docs/.vuepress/components/DemoStyle.vue
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
Hello World Component!
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/.vuepress/components/demos/utils.js b/docs/.vuepress/components/demos/utils.js
index 9ccee893a..d53dcd6ac 100644
--- a/docs/.vuepress/components/demos/utils.js
+++ b/docs/.vuepress/components/demos/utils.js
@@ -29,6 +29,47 @@ var blockManager = {
]
};
+var styleManager = {
+ sectors: [{
+ name: 'Dimension',
+ open: false,
+ // Use built-in properties
+ buildProps: ['width', 'min-height', 'padding'],
+ // Use `properties` to define/override single property
+ properties: [
+ {
+ // Type of the input,
+ // options: integer | radio | select | color | slider | file | composite | stack
+ type: 'integer',
+ name: 'The width', // Label for the property
+ property: 'width', // CSS property (if buildProps contains it will be extended)
+ units: ['px', '%'], // Units, available only for 'integer' types
+ defaults: 'auto', // Default value
+ min: 0, // Min value, available only for 'integer' types
+ }
+ ]
+ },{
+ name: 'Extra',
+ open: false,
+ buildProps: ['background-color', 'box-shadow', 'custom-prop'],
+ properties: [
+ {
+ id: 'custom-prop',
+ name: 'Custom Label',
+ property: 'font-size',
+ type: 'select',
+ defaults: '32px',
+ // List of options, available only for 'select' and 'radio' types
+ options: [
+ { value: '12px', name: 'Tiny' },
+ { value: '18px', name: 'Medium' },
+ { value: '32px', name: 'Big' },
+ ],
+ }
+ ]
+ }]
+};
+
var panelTop = { id: 'panel-top' };
var panelBasicActions = {
id: 'panel-basic',
@@ -78,6 +119,54 @@ var panelSidebar = {
keyWidth: 'flex-basis',
},
};
+var panelSwitcher = {
+ id: 'panel-switcher',
+ buttons: [
+ {
+ id: 'show-layers',
+ active: true,
+ label: 'Layers',
+ command: {
+ getRowEl(editor) { return editor.getContainer().parentNode.parentNode; },
+ getLayersEl(row) { return row.querySelector('.layers-container') },
+ getStyleEl(row) { return row.querySelector('.styles-container') },
+
+ run(editor, sender) {
+ const row = this.getRowEl(editor);
+ const lmEl = this.getLayersEl(row);
+ lmEl.style.display = '';
+ },
+ stop(editor, sender) {
+ const row = this.getRowEl(editor);
+ const lmEl = this.getLayersEl(row);
+ lmEl.style.display = 'none';
+ sender && sender.set('active', false);
+ },
+ },
+ }, {
+ id: 'show-style',
+ label: 'Styles',
+ active: true,
+ command: {
+ getRowEl(editor) { return editor.getContainer().parentNode.parentNode; },
+ getLayersEl(row) { return row.querySelector('.layers-container') },
+ getStyleEl(row) { return row.querySelector('.styles-container') },
+
+ run(editor, sender) {
+ const row = this.getRowEl(editor);
+ const smEl = this.getStyleEl(row);
+ smEl.style.display = '';
+ },
+ stop(editor, sender) {
+ const row = this.getRowEl(editor);
+ const smEl = this.getStyleEl(row);
+ smEl.style.display = 'none';
+ sender && sender.set('active', false);
+ },
+ },
+ }
+ ],
+};
var gjsConfigStart = {
// Indicate where to init the editor. It's also possible to pass an HTMLElement
@@ -111,11 +200,21 @@ var gjsConfigLayers = Object.assign({}, gjsConfigBlocks, {
panels: { defaults: [panelSidebar] }
});
+var gjsConfigStyle = Object.assign({}, gjsConfigBlocks, {
+ container: '#gjs5',
+ blockManager: Object.assign({}, blockManager, { appendTo: '#blocks5' }),
+ layerManager: { appendTo: '#layers-container5', scrollLayers: 0 },
+ styleManager: Object.assign({}, styleManager, { appendTo: '#styles-container5' }),
+});
+
module.exports = {
gjsConfigStart,
gjsConfigBlocks,
gjsConfigPanels,
gjsConfigLayers,
+ gjsConfigStyle,
panelTop,
panelBasicActions,
+ panelSidebar,
+ panelSwitcher,
};
diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js
index 6b1839f21..d69ffd60d 100644
--- a/docs/.vuepress/config.js
+++ b/docs/.vuepress/config.js
@@ -84,6 +84,7 @@ module.exports = {
['/modules/Components', 'Component Manager'],
['/modules/Components-js', 'Components & JS'],
['/modules/Traits', 'Trait Manager'],
+ ['/modules/Style-manager', 'Style Manager'],
['/modules/Storage', 'Storag Manager'],
['/modules/Plugins', 'Plugins'],
]
diff --git a/docs/getting-started.md b/docs/getting-started.md
index 664d04a44..bddfcfc83 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -274,15 +274,139 @@ const editor = grapesjs.init({
## Style Manager
-An important step in any web project is the style definition and with the built-in style manager module you're able to do it easily and quickly.
-The style manager is composed by style properties and are grouped by sectors, let's see how to define a basic set of them.
+Once you have defined the structure of the template probably the next step is the ability to style it. To meet this need GrapesJS includes the Style Manager module which is composed by CSS style properties and sectors. To make it more clear, let's see how to define a basic set.
--- show how to render SM and show style for width, height, padding, Typography, shadows
+Let's start from adding one more panel inside the `panel__right` and another one in `panel__top` which will contain a Layer/Style Manager switcher
-Now any component could be defined with its own style, you can add any other CSS property to your sectors and configure it by your needs. To get more about style manager extension check out this guide.
+```html{3,11}
+
+
+
+```
+```css
+.panel__switcher {
+ position: initial;
+}
+```
+```js
+const editor = grapesjs.init({
+ // ...
+ panels: {
+ defaults: [
+ // ...
+ {
+ id: 'panel-switcher',
+ el: '.panel__switcher',
+ buttons: [{
+ id: 'show-layers',
+ active: true,
+ label: 'Layers',
+ command: 'commandShowLayers',
+ }, {
+ id: 'show-style',
+ active: true,
+ label: 'Styles',
+ command: 'commandShowStyle',
+ }],
+ }
+ ]
+ },
+ styleManager: {
+ appendTo: '.styles-container',
+ sectors: [{
+ name: 'Dimension',
+ open: false,
+ // Use built-in properties
+ buildProps: ['width', 'min-height', 'padding'],
+ // Use `properties` to define/override single property
+ properties: [
+ {
+ // Type of the input,
+ // options: integer | radio | select | color | slider | file | composite | stack
+ type: 'integer',
+ name: 'The width', // Label for the property
+ property: 'width', // CSS property (if buildProps contains it will be extended)
+ units: ['px', '%'], // Units, available only for 'integer' types
+ defaults: 'auto', // Default value
+ min: 0, // Min value, available only for 'integer' types
+ }
+ ]
+ },{
+ name: 'Extra',
+ open: false,
+ buildProps: ['background-color', 'box-shadow', 'custom-prop'],
+ properties: [
+ {
+ id: 'custom-prop',
+ name: 'Custom Label',
+ property: 'font-size',
+ type: 'select',
+ defaults: '32px',
+ // List of options, available only for 'select' and 'radio' types
+ options: [
+ { value: '12px', name: 'Tiny' },
+ { value: '18px', name: 'Medium' },
+ { value: '32px', name: 'Big' },
+ ],
+ }
+ ]
+ }]
+ },
+});
+
+// Define commands
+editor.Commands.add('commandShowLayers', {
+ getRowEl(editor) { return editor.getContainer().closest('.editor-row'); },
+ getLayersEl(row) { return row.querySelector('.layers-container') },
+
+ run(editor, sender) {
+ const lmEl = this.getLayersEl(this.getRowEl(editor));
+ lmEl.style.display = '';
+ },
+ stop(editor, sender) {
+ const lmEl = this.getLayersEl(this.getRowEl(editor));
+ lmEl.style.display = 'none';
+ sender && sender.set('active', false);
+ },
+});
+editor.Commands.add('commandShowStyle', {
+ getRowEl(editor) { return editor.getContainer().closest('.editor-row'); },
+ getStyleEl(row) { return row.querySelector('.styles-container') },
+
+ run(editor, sender) {
+ const smEl = this.getStyleEl(this.getRowEl(editor));
+ smEl.style.display = '';
+ },
+ stop(editor, sender) {
+ const smEl = this.getStyleEl(this.getRowEl(editor));
+ smEl.style.display = 'none';
+ sender && sender.set('active', false);
+ },
+});
+```
+
+
+
+
+
+Now any component could be defined with its own style, you can add any other CSS property to your sectors and configure it by your needs.
+
+
## Traits
Most of them time you would style your components and you would place them somewhere in the structure, but sometimes your components might need custom attributes or even behaviours
diff --git a/docs/modules/Style-manager.md b/docs/modules/Style-manager.md
new file mode 100644
index 000000000..32fb41ff6
--- /dev/null
+++ b/docs/modules/Style-manager.md
@@ -0,0 +1,31 @@
+---
+title: Style Manager
+---
+
+# Style Manager
+
+Coming soon
+
+[[toc]]
+
+
+## Built-in properties
+
+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`
+
+Example usage:
+```js
+...
+ styleManager : {
+ sectors: [{
+ name: 'Dimension',
+ buildProps: ['width', 'min-height']
+ },{
+ name: 'Extra',
+ buildProps: ['background-color', 'box-shadow']
+ }]
+ }
+...
+```
diff --git a/src/panels/view/ButtonView.js b/src/panels/view/ButtonView.js
index d8b0c9f05..cdaf49488 100644
--- a/src/panels/view/ButtonView.js
+++ b/src/panels/view/ButtonView.js
@@ -82,7 +82,7 @@ module.exports = Backbone.View.extend({
} else if (cmdIsFunc) {
command = commands.create({ run: commandName });
} else if (commandName !== null && isObject(commandName)) {
- command = commandName;
+ command = commands.create(commandName);
}
if (model.get('active')) {