├── .gitignore ├── LICENSE ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── src ├── blocks.ts └── index.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | private/ 3 | node_modules/ 4 | dist/ 5 | .eslintrc 6 | .npmrc 7 | *.log 8 | _index.html 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-current, Artur Arseniev 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | - Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | - Redistributions in binary form must reproduce the above copyright notice, this 10 | list of conditions and the following disclaimer in the documentation and/or 11 | other materials provided with the distribution. 12 | - Neither the name "GrapesJS" nor the names of its contributors may be 13 | used to endorse or promote products derived from this software without 14 | specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 23 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GrapesJS Blocks Flexbox 2 | 3 | This plugin adds the Flexbox block which allows creating easily flexible and responsive columns 4 | 5 | [Demo](https://codepen.io/artf/full/qpWBRW/) 6 | 7 | 8 | ## Summary 9 | 10 | * Plugin name: `grapesjs-blocks-flexbox` 11 | * Blocks 12 | * `flexbox` 13 | 14 | 15 | 16 | 17 | 18 | ## Options 19 | 20 | |Option|Description|Default| 21 | |-|-|- 22 | |`stylePrefix`|Classes prefix|`''`| 23 | |`flexboxBlock`|Use this to extend the default flexbox block|`{}`| 24 | |`labelRow`|Row label|`Row`| 25 | |`labelColumn`|Column label|`Column`| 26 | 27 | 28 | 29 | 30 | 31 | ## Download 32 | 33 | * CDN 34 | * `https://unpkg.com/grapesjs-blocks-flexbox` 35 | * NPM 36 | * `npm i grapesjs-blocks-flexbox` 37 | * GIT 38 | * `git clone https://github.com/GrapesJS/blocks-flexbox.git` 39 | 40 | 41 | 42 | 43 | 44 | ## Usage 45 | 46 | ```html 47 | 48 | 49 | 50 | 51 |
52 | 53 | 65 | ``` 66 | 67 | 68 | 69 | 70 | 71 | ## Development 72 | 73 | Clone the repository 74 | 75 | ```sh 76 | $ git clone https://github.com/GrapesJS/blocks-flexbox.git 77 | $ cd blocks-flexbox 78 | ``` 79 | 80 | Install dependencies 81 | 82 | ```sh 83 | $ npm i 84 | ``` 85 | 86 | Start the dev server 87 | 88 | ```sh 89 | $ npm start 90 | ``` 91 | 92 | 93 | 94 | 95 | 96 | ## License 97 | 98 | BSD 3-Clause 99 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | GrapesJS Flexbox 6 | 7 | 8 | 15 | 16 | 17 | 18 |
19 |
20 | This is a demo content from index.html. For the development, you shouldn't edit this file, instead you can 21 | copy and rename it to _index.html, on next server start the new file will be served, and it will be ignored by git. 22 |
23 |
24 | 25 | 26 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grapesjs-blocks-flexbox", 3 | "version": "1.0.1", 4 | "description": "Add the flexbox block", 5 | "main": "dist/index.js", 6 | "files": [ 7 | "dist" 8 | ], 9 | "scripts": { 10 | "build": "grapesjs-cli build", 11 | "start": "grapesjs-cli serve" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/GrapesJS/blocks-flexbox.git" 16 | }, 17 | "keywords": [ 18 | "grapesjs", 19 | "plugin", 20 | "flexbox", 21 | "wysiwyg" 22 | ], 23 | "author": "Artur Arseniev", 24 | "license": "BSD-3-Clause", 25 | "devDependencies": { 26 | "grapesjs": "^0.21.2", 27 | "grapesjs-cli": "^4.1.1" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/blocks.ts: -------------------------------------------------------------------------------- 1 | import type { Editor } from 'grapesjs'; 2 | import { PluginOptions } from '.'; 3 | 4 | export default (editor: Editor, opt: PluginOptions = {}) => { 5 | const bm = editor.BlockManager; 6 | const stylePrefix = opt.stylePrefix; 7 | const clsRow = `${stylePrefix}row`; 8 | const clsCell = `${stylePrefix}cell`; 9 | const labelRow = opt.labelRow; 10 | const labelCell = opt.labelColumn; 11 | 12 | const attrsToString = (attrs: Record) => { 13 | const result = []; 14 | 15 | for (let key in attrs) { 16 | let value = attrs[key]; 17 | const toParse = value instanceof Array || value instanceof Object; 18 | value = toParse ? JSON.stringify(value) : value; 19 | result.push(`${key}=${toParse ? `'${value}'` : `"${value}"`}`); 20 | } 21 | 22 | return result.length ? ` ${result.join(' ')}` : ''; 23 | } 24 | 25 | // Flex elements do not react on width style change therefore I use 26 | // 'flex-basis' as keyWidth for the resizer on columns 27 | const keyWidth = 'flex-basis'; 28 | const step = 0.2; 29 | const minDim = 1; 30 | const currentUnit = 1; 31 | const resizerBtm = { tl: 0, tc: 0, tr: 0, cl: 0, cr:0, bl:0, br: 0, minDim }; 32 | const resizerRight = { ...resizerBtm, cr: 1, bc: 0, keyWidth, currentUnit, minDim, step }; 33 | const rowAttr = { 34 | class: clsRow, 35 | 'data-gjs-droppable': `.${clsCell}`, 36 | 'data-gjs-resizable': resizerBtm, 37 | 'data-gjs-custom-name': labelRow, 38 | }; 39 | 40 | const colAttr = { 41 | class: clsCell, 42 | 'data-gjs-draggable': `.${clsRow}`, 43 | 'data-gjs-resizable': resizerRight, 44 | 'data-gjs-custom-name': labelCell, 45 | // X Flex 46 | 'data-gjs-unstylable': ['width'], 47 | 'data-gjs-stylable-require': ['flex-basis'], 48 | }; 49 | 50 | const privateCls = [`.${clsRow}`, `.${clsCell}`]; 51 | editor.on('selector:add', selector => 52 | privateCls.indexOf(selector.getFullName()) >= 0 && selector.set('private', 1)) 53 | 54 | const label = 'Flexbox'; 55 | const category = 'Basic'; 56 | const attrsRow = attrsToString(rowAttr); 57 | const attrsCell = attrsToString(colAttr); 58 | const styleRow = ` 59 | .${clsRow} { 60 | display: flex; 61 | justify-content: flex-start; 62 | align-items: stretch; 63 | flex-wrap: nowrap; 64 | padding: 10px; 65 | } 66 | @media (max-width: 768px) { 67 | .${clsRow} { 68 | flex-wrap: wrap; 69 | } 70 | } 71 | `; 72 | const styleClm = ` 73 | .${clsCell} { 74 | min-height: 75px; 75 | flex-grow: 1; 76 | flex-basis: 100%; 77 | }`; 78 | 79 | bm.add('flexbox', { 80 | label, 81 | category, 82 | attributes: { class: 'gjs-fonts gjs-f-b2' }, 83 | content: ` 84 |
85 |
86 |
87 |
88 | 92 | `, 93 | ...opt.flexboxBlock 94 | }); 95 | } 96 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import type { BlockProperties, Plugin } from 'grapesjs'; 2 | import loadBlocks from './blocks'; 3 | 4 | export interface PluginOptions { 5 | /** 6 | * Use this to extend the default flexbox block. 7 | * @default {} 8 | */ 9 | flexboxBlock?: Partial; 10 | 11 | /** 12 | * Classes prefix. 13 | * @default '' 14 | */ 15 | stylePrefix?: string; 16 | 17 | /** 18 | * Row label. 19 | * @default 'Row' 20 | */ 21 | labelRow?: string; 22 | 23 | /** 24 | * Column label. 25 | * @default 'Column' 26 | */ 27 | labelColumn?: string; 28 | }; 29 | 30 | const plugin: Plugin = (editor, opts = {}) => { 31 | const options: Required = { 32 | flexboxBlock: {}, 33 | stylePrefix: '', 34 | labelRow: 'Row', 35 | labelColumn: 'Column', 36 | ...opts, 37 | }; 38 | 39 | loadBlocks(editor, options); 40 | }; 41 | 42 | export default plugin; 43 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/grapesjs-cli/dist/template/tsconfig.json", 3 | "include": ["src"] 4 | } --------------------------------------------------------------------------------