├── .gitignore ├── LICENSE ├── README.md ├── elements ├── cssVariablesButton │ ├── cssVariablesButton │ │ ├── component.js │ │ ├── editor.css │ │ ├── index.js │ │ ├── public │ │ │ ├── css-variables-button-preview.png │ │ │ ├── css-variables-button-thumbnail.png │ │ │ └── src │ │ │ │ ├── init.less │ │ │ │ ├── mixins.less │ │ │ │ ├── styles.less │ │ │ │ └── variables.less │ │ ├── settings.json │ │ └── styles.css │ ├── manifest.json │ ├── package.json │ └── public │ │ └── dist │ │ └── element.bundle.js ├── demoGrid │ ├── demoGrid │ │ ├── component.js │ │ ├── editor.css │ │ ├── index.js │ │ ├── public │ │ │ ├── preview.png │ │ │ └── thumbnail.png │ │ ├── settings.json │ │ └── styles.css │ ├── manifest.json │ ├── package.json │ └── public │ │ └── dist │ │ └── element.bundle.js ├── demoGridItem │ ├── demoGridItem │ │ ├── component.js │ │ ├── index.js │ │ ├── settings.json │ │ └── styles.css │ ├── manifest.json │ ├── package.json │ └── public │ │ └── dist │ │ └── element.bundle.js ├── imageGalleryWithTestZoom │ ├── ci │ │ ├── phpcs.phar │ │ └── ruleset.xml │ ├── imageGalleryWithTestZoom │ │ ├── component.js │ │ ├── cssMixins │ │ │ ├── imageGalleryColumns.pcss │ │ │ └── imageGalleryGap.pcss │ │ ├── editor.css │ │ ├── index.js │ │ ├── public │ │ │ ├── close.png │ │ │ ├── default-skin │ │ │ │ ├── default-skin.css │ │ │ │ ├── default-skin.png │ │ │ │ ├── default-skin.svg │ │ │ │ └── preloader.gif │ │ │ ├── dist │ │ │ │ ├── dist │ │ │ │ │ ├── photoswipe-init.min.js │ │ │ │ │ └── photoswipeInit.min.js │ │ │ │ ├── lightbox.min.js │ │ │ │ ├── photoswipe-init.min.js │ │ │ │ ├── photoswipe-ui-default.min.js │ │ │ │ └── photoswipe.min.js │ │ │ ├── icon.png │ │ │ ├── image-1.png │ │ │ ├── image-2.png │ │ │ ├── image-3.png │ │ │ ├── image-gallery-preview.png │ │ │ ├── image-gallery-thumbnail.png │ │ │ ├── js │ │ │ │ └── lib │ │ │ │ │ ├── lightbox.js │ │ │ │ │ └── photoswipe │ │ │ │ │ ├── photoswipe-ui-default.js │ │ │ │ │ ├── photoswipe.css │ │ │ │ │ ├── photoswipe.js │ │ │ │ │ └── photoswipeInit.js │ │ │ ├── loading.gif │ │ │ ├── next.png │ │ │ ├── prev.png │ │ │ └── webpack.config.js │ │ ├── settings.json │ │ └── styles.css │ ├── manifest.json │ ├── package.json │ └── public │ │ └── dist │ │ └── element.bundle.js ├── imageSlider │ ├── imageSlider │ │ ├── component.js │ │ ├── editor.css │ │ ├── index.js │ │ ├── public │ │ │ ├── dist │ │ │ │ └── imageSlider.min.js │ │ │ ├── image-slide-1.png │ │ │ ├── image-slide-2.png │ │ │ ├── image-slide-3.png │ │ │ ├── image-slider-preview.png │ │ │ ├── image-slider-thumbnail.png │ │ │ ├── js │ │ │ │ └── imageSlider.js │ │ │ └── webpack.config.js │ │ ├── settings.json │ │ └── styles.css │ ├── manifest.json │ ├── package.json │ └── public │ │ └── dist │ │ └── element.bundle.js ├── logoSuperTest │ ├── ci │ │ ├── phpcs.phar │ │ └── ruleset.xml │ ├── logoSuperTest │ │ ├── LogoSuperTestShortcodes.php │ │ ├── component.js │ │ ├── editor.css │ │ ├── index.js │ │ ├── public │ │ │ ├── logo-element-preview.png │ │ │ ├── logo-element-thumbnail.png │ │ │ └── src │ │ │ │ ├── init.less │ │ │ │ └── styles.less │ │ ├── settings.json │ │ └── styles.css │ ├── manifest.json │ ├── package.json │ └── public │ │ └── dist │ │ └── element.bundle.js ├── textTest │ ├── ci │ │ ├── phpcs.phar │ │ └── ruleset.xml │ ├── manifest.json │ ├── package.json │ ├── public │ │ └── dist │ │ │ └── element.bundle.js │ └── textTest │ │ ├── component.js │ │ ├── editor.css │ │ ├── index.js │ │ ├── public │ │ ├── text-element-preview.png │ │ └── text-element-thumbnail.png │ │ └── settings.json └── verticalChart │ ├── manifest.json │ ├── package.json │ ├── public │ └── dist │ │ └── element.bundle.js │ └── verticalChart │ ├── bar.js │ ├── component.js │ ├── cssMixins │ ├── barBackgroundColor.pcss │ ├── barThickness.pcss │ └── barValue.pcss │ ├── editor.css │ ├── index.js │ ├── public │ ├── dist │ │ └── countUpStarter.min.js │ ├── js │ │ └── countUpStarter.js │ ├── vertical-chart-preview.png │ ├── vertical-chart-thumbnail.png │ └── webpack.config.js │ ├── settings.json │ └── styles.css └── index.php /.gitignore: -------------------------------------------------------------------------------- 1 | # cache files for sublime text 2 | *.tmlanguage.cache 3 | *.tmPreferences.cache 4 | *.stTheme.cache 5 | 6 | # workspace files are user-specific 7 | *.sublime-workspace 8 | 9 | # project files should be checked into the repository, unless a significant 10 | # proportion of contributors will probably not be using SublimeText 11 | *.sublime-project 12 | 13 | # VIM 14 | .*.swo 15 | .*.swp 16 | tags 17 | # NetBeans 18 | nbproject 19 | # CVS 20 | CVS 21 | .cvsignore 22 | # TextMate 23 | .#* 24 | # PHP Storm, other java IDE's 25 | .idea 26 | # OS X 27 | .DS_Store 28 | ._* 29 | # Windows 30 | Thumbs.db 31 | # VS Code 32 | .vscode 33 | 34 | elements/**/node_modules 35 | node_modules 36 | npm-debug.log 37 | yarn.lock 38 | elements/**/public/dist/runtime.bundle.js 39 | elements/**/public/dist/vendor.bundle.js -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Demo plugin with custom elements for Visual Composer Website Builder 2 | 3 | This is a Demo (example) plugin for developers to showcase custom elements. It acts as a sandbox for developers. To see it in action download and install it on your WordPress instance along with the [Visual Composer Website Builder](https://github.com/VisualComposer/builder) plugin. 4 | 5 | ### Requirements 6 | - node > 8.0, recommended latest 7 | - PHP > 5.4, recommended latest (7.2) 8 | 9 | ## Installation 10 | - Clone this repository `git clone https://github.com/VisualComposer/vcwb-demo-element-example-plugin.git` to wp-content/plugins directory 11 | - Go to the plugin page in your wp admin area and activate the plugin 12 | - That's it. You can open the editor and find new plugin elements here. 13 | 14 | ## Element update 15 | - Run `yarn install` in the element directory 16 | - Build via `yarn build` in the element directory 17 | - Once an element is built it will appear in the Visual Composer editor 18 | 19 | ## What is an element? 20 | An element is the independent part of the system which represents HTML based block with the ability to output media and dynamic content. 21 | 22 | ## How does it work? 23 | The editor works with elements as [React components](https://reactjs.org/docs/react-component.html). These components must be built with [webpack](https://webpack.js.org/) and enqueued by API. 24 | Every element has a preview image, thumbnail image, category and React-based component. 25 | 26 | ### Element content 27 | Each element contains 28 | - manifest.json - describes element data, preview image, thumbnail image, category and PHP files 29 | - package.json - yarn install/update files for required node modules 30 | - webpack.config files to build a component with webpack 31 | 32 | Directory {tag} (must be renamed to the element tag name): 33 | - cssMixins directory – cssMixin.pcss: POSTCSS file that holds mixin for custom generated style 34 | - public directory – may contain custom CSS, JS, and images for public view 35 | - index.js - the main file, build with webpack 36 | - component.js - ReactJS component contains Visual Composer editor component. NOTE: This component is used only in the editor, not the View Page 37 | - settings.json - Describes element attributes 38 | - *.php files - Required PHP files(must be described in ../manifest.json) 39 | - editor.css - CSS file which will be used only in the editor 40 | - style.css - CSS file which will be used on the frontend to display content 41 | 42 | ### Commands 43 | ``` 44 | yarn install // Install all the element dependencies 45 | yarn build // Builds development build 46 | yarn watch // Watches & Builds development version on file modification 47 | yarn build-production // Builds the minified build 48 | 49 | lessc elementName/public/src/init.less elementName/styles.css // compile LESS source file to CSS output 50 | ../../node_modules/.bin/webpack --config=webpack.config.js -p // minify JS file for public use inside elementName/public folder 51 | ``` 52 | 53 | ### Resources for Visual Composer API: 54 | - [API Documentation](https://visualcomposer.com/help/api/) 55 | - [Custom Element & Add-on Development](https://visualcomposer.com/blog/visual-composer-api-custom-elements-and-add-ons/) 56 | - [Theme Integration](https://visualcomposer.com/blog/visual-composer-theme-integration/) 57 | - [Staging Environment](https://visualcomposer.com/blog/visual-composer-on-staging/) 58 | -------------------------------------------------------------------------------- /elements/cssVariablesButton/cssVariablesButton/component.js: -------------------------------------------------------------------------------- 1 | // Basic Button element copy 2 | // This element is re-created without PCSS mixins 3 | // Dynamic styles are handled with CSS Properties (Variables) 4 | // CSS variables are defined in the styles.css file (source file is public/src/styles.less) 5 | 6 | // NOTE: CSS Properties (Variables) are not supported by older browsers 7 | // Please see more at: https://caniuse.com/#search=CSS%20Variables%20(Custom%20Properties) 8 | 9 | import React from 'react' 10 | import vcCake from 'vc-cake' 11 | 12 | const vcvAPI = vcCake.getService('api') 13 | 14 | export default class CssVariablesButton extends vcvAPI.elementComponent { 15 | // Blend and convert colors 16 | // https://github.com/PimpTrizkit/PJs/wiki/12.-Shade,-Blend-and-Convert-a-Web-Color-(pSBC.js)#stackoverflow-archive-begin 17 | /* eslint-disable */ 18 | pSBC (p,c0,c1,l) { 19 | let r,g,b,P,f,t,h,i=parseInt,m=Math.round,a=typeof(c1)=="string"; 20 | if(typeof(p)!="number"||p<-1||p>1||typeof(c0)!="string"||(c0[0]!='r'&&c0[0]!='#')||(c1&&!a))return null; 21 | if(!this.pSBCr)this.pSBCr=(d)=>{ 22 | let n=d.length,x={}; 23 | if(n>9){ 24 | [r,g,b,a]=d=d.split(","),n=d.length; 25 | if(n<3||n>4)return null; 26 | x.r=i(r[3]=="a"?r.slice(5):r.slice(4)),x.g=i(g),x.b=i(b),x.a=a?parseFloat(a):-1 27 | }else{ 28 | if(n==8||n==6||n<4)return null; 29 | if(n<6)d="#"+d[1]+d[1]+d[2]+d[2]+d[3]+d[3]+(n>4?d[4]+d[4]:""); 30 | d=i(d.slice(1),16); 31 | if(n==9||n==5)x.r=d>>24&255,x.g=d>>16&255,x.b=d>>8&255,x.a=m((d&255)/0.255)/1000; 32 | else x.r=d>>16,x.g=d>>8&255,x.b=d&255,x.a=-1 33 | }return x}; 34 | h=c0.length>9,h=a?c1.length>9?true:c1=="c"?!h:false:h,f=this.pSBCr(c0),P=p<0,t=c1&&c1!="c"?this.pSBCr(c1):P?{r:0,g:0,b:0,a:-1}:{r:255,g:255,b:255,a:-1},p=P?p*-1:p,P=1-p; 35 | if(!f||!t)return null; 36 | if(l)r=m(P*f.r+p*t.r),g=m(P*f.g+p*t.g),b=m(P*f.b+p*t.b); 37 | else r=m((P*f.r**2+p*t.r**2)**0.5),g=m((P*f.g**2+p*t.g**2)**0.5),b=m((P*f.b**2+p*t.b**2)**0.5); 38 | a=f.a,t=t.a,f=a>=0||t>=0,a=f?a<0?t:t<0?a:a*P+t*p:0; 39 | if(h)return"rgb"+(f?"a(":"(")+r+","+g+","+b+(f?","+m(a*1000)/1000:"")+")"; 40 | else return"#"+(4294967296+r*16777216+g*65536+b*256+(f?m(a*255):0)).toString(16).slice(1,f?undefined:-2) 41 | } 42 | /* eslint-enable */ 43 | 44 | render () { 45 | const { id, atts, editor } = this.props 46 | const { background, color, hoverColor, hoverBackground, buttonUrl, buttonText, shape, alignment, customClass, toggleCustomHover, metaCustomId, size, toggleStretchButton } = atts 47 | 48 | let containerClasses = 'vce-css-var-btn-container' 49 | let wrapperClasses = 'vce-css-var-btn-wrapper vce' 50 | let classes = 'vce-css-var-btn' 51 | let customProps = {} 52 | let CustomTag = 'button' 53 | // Object that will hold CSS variables for current button element 54 | const stylesVariables = {} 55 | 56 | if (buttonUrl && buttonUrl.url) { 57 | CustomTag = 'a' 58 | const { url, title, targetBlank, relNofollow } = buttonUrl 59 | customProps = { 60 | href: url, 61 | title: title, 62 | target: targetBlank ? '_blank' : undefined, 63 | rel: relNofollow ? 'nofollow' : undefined 64 | } 65 | } 66 | 67 | if (typeof customClass === 'string' && customClass) { 68 | containerClasses += ' ' + customClass 69 | } 70 | 71 | // Set property values to an object (CSS variables) 72 | if (shape) { 73 | stylesVariables['--border-radius'] = shape 74 | } 75 | 76 | if (color) { 77 | stylesVariables['--color'] = color 78 | // By default make color darken by 10% 79 | stylesVariables['--hover-color'] = this.pSBC(-0.1, color) 80 | } 81 | 82 | if (background) { 83 | stylesVariables['--background-color'] = background 84 | // By default make background color darken by 10% 85 | stylesVariables['--hover-background-color'] = this.pSBC(-0.1, background) 86 | } 87 | 88 | if (toggleCustomHover && hoverColor) { 89 | stylesVariables['--hover-color'] = hoverColor 90 | } 91 | 92 | if (toggleCustomHover && hoverBackground) { 93 | stylesVariables['--hover-background-color'] = hoverBackground 94 | } 95 | 96 | if (alignment) { 97 | stylesVariables['--text-align'] = alignment 98 | } 99 | 100 | if (size) { 101 | classes += ` vce-css-var-btn--size-${size}` 102 | } 103 | 104 | if (toggleStretchButton) { 105 | wrapperClasses += ' vce-css-var-btn-wrapper--stretched' 106 | } 107 | 108 | if (metaCustomId) { 109 | customProps.id = metaCustomId 110 | } 111 | 112 | const doMargin = this.applyDO('margin') 113 | const doRest = this.applyDO('padding border background animation') 114 | 115 | // Use style attribute to set the scope of the CSS variables to an element 116 | return ( 117 |
118 | 119 | 120 | {buttonText} 121 | 122 | 123 |
124 | ) 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /elements/cssVariablesButton/cssVariablesButton/editor.css: -------------------------------------------------------------------------------- 1 | .vce-button--style-basic-container { 2 | min-height: 1em; 3 | } 4 | -------------------------------------------------------------------------------- /elements/cssVariablesButton/cssVariablesButton/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-webpack-loader-syntax */ 2 | import vcCake from 'vc-cake' 3 | import CssVariablesButton from './component' 4 | 5 | const vcvAddElement = vcCake.getService('cook').add 6 | 7 | vcvAddElement( 8 | require('./settings.json'), 9 | // Component callback 10 | function (component) { 11 | component.add(CssVariablesButton) 12 | }, 13 | // css for editor and element 14 | // no PCSS mixins included 15 | // styles.css is compiled from LESS source files 16 | // to compile styles.css run: 17 | // lessc cssVariablesButton/public/src/init.less cssVariablesButton/styles.css 18 | { 19 | css: require('raw-loader!./styles.css'), 20 | editorCss: require('raw-loader!./editor.css') 21 | } 22 | ) 23 | -------------------------------------------------------------------------------- /elements/cssVariablesButton/cssVariablesButton/public/css-variables-button-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/cssVariablesButton/cssVariablesButton/public/css-variables-button-preview.png -------------------------------------------------------------------------------- /elements/cssVariablesButton/cssVariablesButton/public/css-variables-button-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/cssVariablesButton/cssVariablesButton/public/css-variables-button-thumbnail.png -------------------------------------------------------------------------------- /elements/cssVariablesButton/cssVariablesButton/public/src/init.less: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------- 2 | * Basic Button 3 | * ---------------------------------------------- */ 4 | 5 | //== import styles 6 | @import "styles"; 7 | 8 | 9 | //== import mixins 10 | @import "mixins"; 11 | 12 | 13 | //== import variable 14 | @import "variables"; 15 | -------------------------------------------------------------------------------- /elements/cssVariablesButton/cssVariablesButton/public/src/mixins.less: -------------------------------------------------------------------------------- 1 | // Mixins for Basic Button 2 | //----------------------------------------- 3 | 4 | .vce-button-size(@padding-vertical; @padding-horizontal; @font-size;) { 5 | font-size: @font-size; 6 | padding: @padding-vertical @padding-horizontal; 7 | } 8 | 9 | 10 | -------------------------------------------------------------------------------- /elements/cssVariablesButton/cssVariablesButton/public/src/styles.less: -------------------------------------------------------------------------------- 1 | // Styles for Buttons 2 | //----------------------------------------- 3 | 4 | .vce-css-var-btn-container { 5 | --background-color: #557cbf; 6 | --text-align: left; 7 | --border-radius: 0px; 8 | --color: #fff; 9 | --hover-color: #fff; 10 | --hover-background-color: #4d70ac; 11 | text-align: var(--text-align); 12 | } 13 | 14 | .vce-css-var-btn-wrapper { 15 | display: inline-block; 16 | vertical-align: top; 17 | max-width: 100%; 18 | 19 | .vce-css-var-btn { 20 | box-shadow: none; 21 | &:hover, &:focus, &:link { 22 | box-shadow: none; 23 | } 24 | } 25 | } 26 | 27 | .vce-css-var-btn-wrapper--stretched { 28 | width: 100%; 29 | 30 | .vce-css-var-btn { 31 | width: 100%; 32 | } 33 | } 34 | 35 | // By default .vce-button does not look like much. It will be a basic text with hover cursor 36 | .vce-css-var-btn { 37 | a&, 38 | button& { 39 | background-color: var(--background-color); 40 | background-image: none; 41 | border: none; // For input.btn 42 | border-radius: var(--border-radius); 43 | box-sizing: border-box; 44 | color: var(--color); 45 | cursor: pointer; 46 | display: inline-block; 47 | margin: 0; 48 | max-width: 100%; 49 | // If the contnet of the button is more than the containers, the text will break normally 50 | position: relative; 51 | text-align: center; 52 | text-decoration: none; 53 | vertical-align: middle; 54 | white-space: normal; 55 | touch-action: manipulation; 56 | user-select: none; 57 | line-height: normal; 58 | transition: all @vce-button-transition-duration @vce-button-transition-timing-function; 59 | 60 | &:hover, 61 | &:focus { 62 | text-decoration: none; 63 | outline: none; 64 | color: var(--hover-color); 65 | } 66 | 67 | &:hover { 68 | background-color: var(--hover-background-color); 69 | } 70 | } 71 | 72 | button& { 73 | -webkit-appearance: none; 74 | } 75 | 76 | // Basic solid button 77 | &.vce-css-var-btn--size-small { 78 | .vce-button-size(@vce-button-padding-vertical-small; @vce-button-padding-horizontal-small; @vce-button-font-size-small;); 79 | } 80 | &.vce-css-var-btn--size-medium { 81 | .vce-button-size(@vce-button-padding-vertical-medium; @vce-button-padding-horizontal-medium; @vce-button-font-size-medium;); 82 | } 83 | &.vce-css-var-btn--size-large { 84 | .vce-button-size(@vce-button-padding-vertical-large; @vce-button-padding-horizontal-large; @vce-button-font-size-large;); 85 | } 86 | } 87 | 88 | // RTL support 89 | .rtl, 90 | [dir="rlt"] { 91 | &.vce-css-var-btn, 92 | .vce-css-var-btn { 93 | direction: rtl; 94 | unicode-bidi: embed; 95 | } 96 | } 97 | 98 | // LTR 99 | .ltr, 100 | [dir="ltr"] { 101 | &.vce-css-var-btn, 102 | .vce-css-var-btn { 103 | direction: ltr; 104 | unicode-bidi: normal; 105 | } 106 | } 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /elements/cssVariablesButton/cssVariablesButton/public/src/variables.less: -------------------------------------------------------------------------------- 1 | // Variables for Button 2 | //----------------------------------------- 3 | 4 | @vce-button-color: inherit; 5 | 6 | @vce-button-font-size-small: 11px; 7 | @vce-button-font-size-medium: 16px; 8 | @vce-button-font-size-large: 21px; 9 | // Sizing of the button 10 | @vce-button-padding-vertical-small: 10px; 11 | @vce-button-padding-vertical-medium: 15px; 12 | @vce-button-padding-vertical-large: 20px; 13 | @vce-button-padding-horizontal-small: 30px; 14 | @vce-button-padding-horizontal-medium: 43px; 15 | @vce-button-padding-horizontal-large: 56px; 16 | @vce-button-border-radius: 0; 17 | 18 | @vce-button-rounded: 5px; 19 | @vce-button-round: 4em; 20 | 21 | @vce-button-transition-duration: 0.2s; 22 | @vce-button-transition-timing-function: ease-in-out; 23 | 24 | @vce-button-basic-border-radius: 0; 25 | 26 | -------------------------------------------------------------------------------- /elements/cssVariablesButton/cssVariablesButton/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "tag": { 3 | "access": "protected", 4 | "type": "string", 5 | "value": "cssVariablesButton" 6 | }, 7 | "groups": { 8 | "type": "string", 9 | "access": "protected", 10 | "value": "Buttons" 11 | }, 12 | "relatedTo": { 13 | "type": "group", 14 | "access": "protected", 15 | "value": [ 16 | "General", 17 | "Buttons" 18 | ] 19 | }, 20 | "buttonUrl": { 21 | "type": "url", 22 | "access": "public", 23 | "value": { 24 | "url": "", 25 | "title": "", 26 | "targetBlank": false, 27 | "relNofollow": false 28 | }, 29 | "options": { 30 | "label": "Link selection", 31 | "dynamicField": true 32 | } 33 | }, 34 | "toggleCustomHover": { 35 | "type": "toggle", 36 | "access": "public", 37 | "value": false, 38 | "options": { 39 | "label": "Custom hover colors" 40 | } 41 | }, 42 | "hoverColor": { 43 | "type": "color", 44 | "access": "public", 45 | "value": "#fff", 46 | "options": { 47 | "label": "Title hover color", 48 | "onChange": { 49 | "rules": { 50 | "toggleCustomHover": { 51 | "rule": "toggle" 52 | } 53 | }, 54 | "actions": [ 55 | { 56 | "action": "toggleVisibility" 57 | } 58 | ] 59 | } 60 | } 61 | }, 62 | "hoverBackground": { 63 | "type": "color", 64 | "access": "public", 65 | "value": "#4d70ac", 66 | "options": { 67 | "label": "Background hover color", 68 | "onChange": { 69 | "rules": { 70 | "toggleCustomHover": { 71 | "rule": "toggle" 72 | } 73 | }, 74 | "actions": [ 75 | { 76 | "action": "toggleVisibility" 77 | } 78 | ] 79 | } 80 | } 81 | }, 82 | "buttonText": { 83 | "type": "string", 84 | "access": "public", 85 | "value": "Apply Now", 86 | "options": { 87 | "label": "Button text", 88 | "dynamicField": true 89 | } 90 | }, 91 | "color": { 92 | "type": "color", 93 | "access": "public", 94 | "value": "#fff", 95 | "options": { 96 | "label": "Title color" 97 | } 98 | }, 99 | "background": { 100 | "type": "color", 101 | "access": "public", 102 | "value": "#557cbf", 103 | "options": { 104 | "label": "Background color" 105 | } 106 | }, 107 | "shape": { 108 | "type": "buttonGroup", 109 | "access": "public", 110 | "value": "square", 111 | "options": { 112 | "label": "Shape", 113 | "values": [ 114 | { 115 | "label": "Square", 116 | "value": "0px", 117 | "icon": "vcv-ui-icon-attribute-shape-square" 118 | }, 119 | { 120 | "label": "Rounded", 121 | "value": "5px", 122 | "icon": "vcv-ui-icon-attribute-shape-rounded" 123 | }, 124 | { 125 | "label": "Round", 126 | "value": "4em", 127 | "icon": "vcv-ui-icon-attribute-shape-round" 128 | } 129 | ] 130 | } 131 | }, 132 | "designOptions": { 133 | "type": "designOptions", 134 | "access": "public", 135 | "value": {}, 136 | "options": { 137 | "label": "Design Options" 138 | } 139 | }, 140 | "alignment": { 141 | "type": "buttonGroup", 142 | "access": "public", 143 | "value": "left", 144 | "options": { 145 | "label": "Alignment", 146 | "values": [ 147 | { 148 | "label": "Left", 149 | "value": "left", 150 | "icon": "vcv-ui-icon-attribute-alignment-left" 151 | }, 152 | { 153 | "label": "Center", 154 | "value": "center", 155 | "icon": "vcv-ui-icon-attribute-alignment-center" 156 | }, 157 | { 158 | "label": "Right", 159 | "value": "right", 160 | "icon": "vcv-ui-icon-attribute-alignment-right" 161 | } 162 | ] 163 | } 164 | }, 165 | "size": { 166 | "type": "buttonGroup", 167 | "access": "public", 168 | "value": "medium", 169 | "options": { 170 | "label": "Size", 171 | "values": [ 172 | { 173 | "label": "Small", 174 | "value": "small", 175 | "text": "S" 176 | }, 177 | { 178 | "label": "Medium", 179 | "value": "medium", 180 | "text": "M" 181 | }, 182 | { 183 | "label": "Large", 184 | "value": "large", 185 | "text": "L" 186 | } 187 | ] 188 | } 189 | }, 190 | "toggleStretchButton": { 191 | "type": "toggle", 192 | "access": "public", 193 | "value": false, 194 | "options": { 195 | "label": "Stretch button" 196 | } 197 | }, 198 | "customClass": { 199 | "type": "string", 200 | "access": "public", 201 | "value": "", 202 | "options": { 203 | "label": "Extra class name", 204 | "description": "Add an extra class name to the element and refer to it from Custom CSS option." 205 | } 206 | }, 207 | "metaCustomId": { 208 | "type": "customId", 209 | "access": "public", 210 | "value": "", 211 | "options": { 212 | "label": "Element ID", 213 | "description": "Apply unique ID to element to link directly to it by using #your_id (for element ID use lowercase input only)." 214 | } 215 | }, 216 | "editFormTab1": { 217 | "type": "group", 218 | "access": "protected", 219 | "value": [ 220 | "buttonText", 221 | "buttonUrl", 222 | "alignment", 223 | "shape", 224 | "size", 225 | "toggleStretchButton", 226 | "color", 227 | "background", 228 | "toggleCustomHover", 229 | "hoverColor", 230 | "hoverBackground", 231 | "metaCustomId", 232 | "customClass" 233 | ], 234 | "options": { 235 | "label": "General" 236 | } 237 | }, 238 | "metaEditFormTabs": { 239 | "type": "group", 240 | "access": "protected", 241 | "value": [ 242 | "editFormTab1", 243 | "designOptions" 244 | ] 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /elements/cssVariablesButton/cssVariablesButton/styles.css: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------- 2 | * Basic Button 3 | * ---------------------------------------------- */ 4 | .vce-css-var-btn-container { 5 | --background-color: #557cbf; 6 | --text-align: left; 7 | --border-radius: 0px; 8 | --color: #fff; 9 | --hover-color: #fff; 10 | --hover-background-color: #4d70ac; 11 | text-align: var(--text-align); 12 | } 13 | .vce-css-var-btn-wrapper { 14 | display: inline-block; 15 | vertical-align: top; 16 | max-width: 100%; 17 | } 18 | .vce-css-var-btn-wrapper .vce-css-var-btn { 19 | box-shadow: none; 20 | } 21 | .vce-css-var-btn-wrapper .vce-css-var-btn:hover, 22 | .vce-css-var-btn-wrapper .vce-css-var-btn:focus, 23 | .vce-css-var-btn-wrapper .vce-css-var-btn:link { 24 | box-shadow: none; 25 | } 26 | .vce-css-var-btn-wrapper--stretched { 27 | width: 100%; 28 | } 29 | .vce-css-var-btn-wrapper--stretched .vce-css-var-btn { 30 | width: 100%; 31 | } 32 | a.vce-css-var-btn, 33 | button.vce-css-var-btn { 34 | background-color: var(--background-color); 35 | background-image: none; 36 | border: none; 37 | border-radius: var(--border-radius); 38 | box-sizing: border-box; 39 | color: var(--color); 40 | cursor: pointer; 41 | display: inline-block; 42 | margin: 0; 43 | max-width: 100%; 44 | position: relative; 45 | text-align: center; 46 | text-decoration: none; 47 | vertical-align: middle; 48 | white-space: normal; 49 | touch-action: manipulation; 50 | user-select: none; 51 | line-height: normal; 52 | transition: all 0.2s ease-in-out; 53 | } 54 | a.vce-css-var-btn:hover, 55 | button.vce-css-var-btn:hover, 56 | a.vce-css-var-btn:focus, 57 | button.vce-css-var-btn:focus { 58 | text-decoration: none; 59 | outline: none; 60 | color: var(--hover-color); 61 | } 62 | a.vce-css-var-btn:hover, 63 | button.vce-css-var-btn:hover { 64 | background-color: var(--hover-background-color); 65 | } 66 | button.vce-css-var-btn { 67 | -webkit-appearance: none; 68 | } 69 | .vce-css-var-btn.vce-css-var-btn--size-small { 70 | font-size: 11px; 71 | padding: 10px 30px; 72 | } 73 | .vce-css-var-btn.vce-css-var-btn--size-medium { 74 | font-size: 16px; 75 | padding: 15px 43px; 76 | } 77 | .vce-css-var-btn.vce-css-var-btn--size-large { 78 | font-size: 21px; 79 | padding: 20px 56px; 80 | } 81 | .rtl.vce-css-var-btn, 82 | [dir="rlt"].vce-css-var-btn, 83 | .rtl .vce-css-var-btn, 84 | [dir="rlt"] .vce-css-var-btn { 85 | direction: rtl; 86 | unicode-bidi: embed; 87 | } 88 | .ltr.vce-css-var-btn, 89 | [dir="ltr"].vce-css-var-btn, 90 | .ltr .vce-css-var-btn, 91 | [dir="ltr"] .vce-css-var-btn { 92 | direction: ltr; 93 | unicode-bidi: normal; 94 | } 95 | -------------------------------------------------------------------------------- /elements/cssVariablesButton/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "elements": { 3 | "cssVariablesButton": { 4 | "settings": { 5 | "name": "[Demo] CSS Variables Button", 6 | "metaThumbnailUrl": "[publicPath]/css-variables-button-thumbnail.png", 7 | "metaPreviewUrl": "[publicPath]/css-variables-button-preview.png", 8 | "metaDescription": "Basic button made with the help of CSS Variables (Properties)" 9 | } 10 | } 11 | }, 12 | "categories": { 13 | "Button": { 14 | "elements": [ 15 | "cssVariablesButton" 16 | ] 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /elements/cssVariablesButton/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vcwb", 3 | "version": "dev", 4 | "license": "SEE LICENSE IN ", 5 | "description": "Visual Composer Website Builder", 6 | "main": "index.php", 7 | "repository": { 8 | "type": "git", 9 | "url": "git@github.com:Visualcomposer/builder.git" 10 | }, 11 | "scripts": { 12 | "standard": "standard --version && standard", 13 | "build": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.js", 14 | "build-production": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.production.js", 15 | "watch": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.js --watch" 16 | }, 17 | "devDependencies": { 18 | "vc-webpack-vendors": "3.3.3" 19 | }, 20 | "babel": { 21 | "presets": [ 22 | "@babel/preset-env", 23 | "@babel/preset-react" 24 | ], 25 | "plugins": [ 26 | "@babel/plugin-transform-runtime", 27 | "@babel/plugin-proposal-class-properties" 28 | ] 29 | }, 30 | "standard": { 31 | "parser": "babel-eslint", 32 | "ignore": [ 33 | "public/dist/", 34 | "tests/", 35 | "**/public/js" 36 | ], 37 | "rules": { 38 | "jsx-quotes": [ 39 | 2, 40 | "prefer-single" 41 | ], 42 | "import/no-webpack-loader-syntax": "off" 43 | } 44 | }, 45 | "resolutions": { 46 | "core-js": "3.25.5", 47 | "postcss": "8.4.18", 48 | "css-loader": "6.7.1", 49 | "color-name": "1.1.4", 50 | "eslint": "8.25.0", 51 | "less": "4.1.3", 52 | "raw-loader": "1.0.0", 53 | "@babel/runtime": "7.19.4" 54 | }, 55 | "browserslist": [ 56 | "ie >= 11", 57 | "last 2 version" 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /elements/demoGrid/demoGrid/component.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import lodash from 'lodash' 3 | import { getService } from 'vc-cake' 4 | import { setCssVariables } from 'vc-helpers' 5 | 6 | const vcvAPI = getService('api') 7 | 8 | export default class DemoGrid extends vcvAPI.elementComponent { 9 | constructor (props) { 10 | super(props) 11 | this.ref = React.createRef() 12 | this.state = { 13 | shortcode: '', 14 | shortcodeContent: this.spinnerHTML() 15 | } 16 | this.debounceRequest = lodash.debounce(this.requestToServer, 750) 17 | } 18 | 19 | componentDidMount () { 20 | this.requestToServer() 21 | } 22 | 23 | componentDidUpdate (prevProps) { 24 | const isEqual = lodash.isEqual 25 | if (!isEqual(this.props.atts, prevProps.atts)) { 26 | this.debounceRequest() 27 | } 28 | } 29 | 30 | componentwillUnmount () { 31 | if (this.serverRequest) { 32 | this.serverRequest.cancelled = true 33 | } 34 | } 35 | 36 | requestToServer () { 37 | if (!this.props.atts.gridItem || !this.props.atts.sourceItem) { 38 | return 39 | } 40 | const dataProcessService = getService('dataProcessor') 41 | const Cook = getService('cook') 42 | const GridItemComponent = Cook.get(this.props.atts.gridItem) 43 | const SourceItemComponent = Cook.get(this.props.atts.sourceItem) 44 | const gridItemOutput = GridItemComponent.render(null, false) 45 | const sourceItemOutput = SourceItemComponent.render(null, false) 46 | const ReactDOMServer = require('react-dom/server') 47 | const striptags = require('striptags') 48 | if (this.ref.current) { 49 | this.ref.current.innerHTML = this.spinnerHTML() 50 | } 51 | this.serverRequest = dataProcessService.appServerRequest({ 52 | 'vcv-action': 'elements:posts_grid:adminNonce', 53 | 'vcv-nonce': window.vcvNonce, 54 | 'vcv-content': ReactDOMServer.renderToStaticMarkup(gridItemOutput), 55 | 'vcv-source-id': window.vcvSourceID, 56 | 'vcv-atts': { 57 | source: encodeURIComponent(JSON.stringify({ 58 | tag: this.props.atts.sourceItem.tag, 59 | value: striptags(ReactDOMServer.renderToStaticMarkup(sourceItemOutput)) 60 | })), 61 | unique_id: this.props.id, 62 | excerpt: this.props.atts.atts_excerpt ? '1' : '0', 63 | excerpt_length: this.props.atts.atts_excerpt_length, 64 | pagination: this.props.atts.atts_pagination ? '1' : '0', 65 | pagination_color: this.props.atts.atts_pagination_color, 66 | pagination_per_page: this.props.atts.atts_pagination_per_page, 67 | filter: this.props.atts.filtersToggle, 68 | filter_atts: encodeURIComponent(JSON.stringify(this.props.atts.filterItem)) 69 | } 70 | }).then((result) => { 71 | if (this.serverRequest && this.serverRequest.cancelled) { 72 | this.serverRequest = null 73 | return 74 | } 75 | const response = this.getResponse(result) 76 | if (response && response.status) { 77 | if (this.ref.current) { 78 | this.ref.current.setAttribute('data-vcvs-html', response.shortcode) 79 | this.ref.current.innerHTML = response.shortcodeContent || 'Failed to render the post grid' 80 | } 81 | } else { 82 | if (this.ref.current) { 83 | this.ref.current.setAttribute('data-vcvs-html', response.shortcode) 84 | this.ref.current.innerHTML = response.shortcodeContent || 'Failed to render the post grid' 85 | } 86 | } 87 | }) 88 | } 89 | 90 | render () { 91 | const { id, atts, editor } = this.props 92 | const { customClass, metaCustomId, gap, columns, atts_pagination_color: paginationColor, atts_pagination_active_color: paginationActiveColor, atts_pagination_text_color: paginationTextColor, atts_pagination_active_text_color: paginationActiveTextColor } = atts 93 | const gapPx = `${gap}px` 94 | const paginationHoverColor = this.getColorShade(-0.1, paginationColor) 95 | const paginationActiveHoverColor = this.getColorShade(-0.1, paginationActiveColor) 96 | const cssVars = { gapPx, columns, paginationColor, paginationActiveColor, paginationTextColor, paginationActiveTextColor, paginationHoverColor, paginationActiveHoverColor } 97 | const styleObj = setCssVariables(cssVars) 98 | const wrapperClasses = 'vce vce-demo-grid-wrapper' 99 | let containerClasses = 'vce-demo-grid-container' 100 | 101 | const customProps = {} 102 | 103 | if (customClass) { 104 | containerClasses += ` ${customClass}` 105 | } 106 | if (metaCustomId) { 107 | customProps.id = metaCustomId 108 | } 109 | 110 | const doAll = this.applyDO('all') 111 | 112 | return ( 113 |
114 |
115 |
116 |
117 |
118 | ) 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /elements/demoGrid/demoGrid/editor.css: -------------------------------------------------------------------------------- 1 | .vce-demo-grid-container { 2 | min-height: 1em; 3 | } 4 | -------------------------------------------------------------------------------- /elements/demoGrid/demoGrid/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-webpack-loader-syntax */ 2 | import vcCake from 'vc-cake' 3 | import DemoGrid from './component' 4 | 5 | const vcvAddElement = vcCake.getService('cook').add 6 | 7 | vcvAddElement( 8 | require('./settings.json'), 9 | // Component callback 10 | (component) => { 11 | component.add(DemoGrid) 12 | }, 13 | // css settings // css for element 14 | { 15 | css: require('raw-loader!./styles.css'), 16 | editorCss: require('raw-loader!./editor.css') 17 | } 18 | ) 19 | -------------------------------------------------------------------------------- /elements/demoGrid/demoGrid/public/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/demoGrid/demoGrid/public/preview.png -------------------------------------------------------------------------------- /elements/demoGrid/demoGrid/public/thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/demoGrid/demoGrid/public/thumbnail.png -------------------------------------------------------------------------------- /elements/demoGrid/demoGrid/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "gap": { 3 | "type": "number", 4 | "access": "public", 5 | "value": "10", 6 | "options": { 7 | "label": "Gap", 8 | "description": "Enter the gap in pixels (example: 5)." 9 | } 10 | }, 11 | "atts_excerpt": { 12 | "type": "toggle", 13 | "access": "public", 14 | "value": false, 15 | "options": { 16 | "label": "Custom excerpt length" 17 | } 18 | }, 19 | "atts_excerpt_length": { 20 | "type": "string", 21 | "access": "public", 22 | "value": "", 23 | "options": { 24 | "label": "Excerpt length", 25 | "description": "Limit the post grid excerpt length.", 26 | "placeholder": "55", 27 | "onChange": { 28 | "rules": { 29 | "atts_excerpt": { 30 | "rule": "toggle" 31 | } 32 | }, 33 | "actions": [ 34 | { 35 | "action": "toggleVisibility" 36 | } 37 | ] 38 | } 39 | } 40 | }, 41 | "columns": { 42 | "type": "number", 43 | "access": "public", 44 | "value": "3", 45 | "options": { 46 | "label": "Number of columns" 47 | } 48 | }, 49 | "atts_pagination": { 50 | "type": "toggle", 51 | "access": "public", 52 | "value": false, 53 | "options": { 54 | "label": "Enable paging", 55 | "description": "Divide your post grid into pages and control the maximum number of posts per page." 56 | } 57 | }, 58 | "atts_pagination_per_page": { 59 | "type": "string", 60 | "access": "public", 61 | "value": "10", 62 | "options": { 63 | "label": "Items per page" 64 | } 65 | }, 66 | "atts_pagination_color": { 67 | "type": "color", 68 | "access": "public", 69 | "value": "#EEE", 70 | "options": { 71 | "label": "Inactive page color" 72 | } 73 | }, 74 | "atts_pagination_active_color": { 75 | "type": "color", 76 | "access": "public", 77 | "value": "#557CBF", 78 | "options": { 79 | "label": "Active page color" 80 | } 81 | }, 82 | "atts_pagination_text_color": { 83 | "type": "color", 84 | "access": "public", 85 | "value": "#3d3d3d", 86 | "options": { 87 | "label": "Inactive text color" 88 | } 89 | }, 90 | "atts_pagination_active_text_color": { 91 | "type": "color", 92 | "access": "public", 93 | "value": "#FFF", 94 | "options": { 95 | "label": "Active text color" 96 | } 97 | }, 98 | "editFormTab1": { 99 | "type": "group", 100 | "access": "protected", 101 | "value": [ 102 | "columns", 103 | "gap", 104 | "atts_excerpt", 105 | "atts_excerpt_length", 106 | "atts_pagination", 107 | "filtersToggle", 108 | "metaCustomId", 109 | "customClass" 110 | ], 111 | "options": { 112 | "label": "General" 113 | } 114 | }, 115 | "filtersToggle": { 116 | "type": "toggle", 117 | "access": "public", 118 | "value": false, 119 | "options": { 120 | "label": "Enable filters", 121 | "description": "Display content by categories, tags, and other taxonomies." 122 | } 123 | }, 124 | "pagination": { 125 | "type": "group", 126 | "access": "protected", 127 | "value": [ 128 | "atts_pagination_per_page", 129 | "atts_pagination_color", 130 | "atts_pagination_active_color", 131 | "atts_pagination_text_color", 132 | "atts_pagination_active_text_color" 133 | ], 134 | "options": { 135 | "label": "Pagination", 136 | "tooltip": "Specify how many items will be displayed within the page.", 137 | "onChange": { 138 | "rules": { 139 | "atts_pagination": { 140 | "rule": "toggle" 141 | } 142 | }, 143 | "actions": [ 144 | { 145 | "action": "toggleSectionVisibility" 146 | } 147 | ] 148 | } 149 | } 150 | }, 151 | "filterItem": { 152 | "type": "element", 153 | "access": "public", 154 | "value": { 155 | "tag": "postGridFilter" 156 | }, 157 | "options": { 158 | "category": "_postsGridFilters", 159 | "label": "Filters", 160 | "tooltip": "Specify what filters will be displayed within the grid.", 161 | "onChange": { 162 | "rules": { 163 | "filtersToggle": { 164 | "rule": "toggle" 165 | } 166 | }, 167 | "actions": [ 168 | { 169 | "action": "toggleSectionVisibility" 170 | } 171 | ] 172 | } 173 | } 174 | }, 175 | "sourceItem": { 176 | "type": "element", 177 | "access": "public", 178 | "value": { 179 | "tag": "postsGridDataSourcePost" 180 | }, 181 | "options": { 182 | "category": "_postsGridSources", 183 | "_fixElementDownload": [ 184 | { 185 | "tag": "postsGridDataSourcePost" 186 | }, 187 | { 188 | "tag": "postsGridDataSourcePage" 189 | }, 190 | { 191 | "tag": "postsGridDataSourceCustomPostType" 192 | }, 193 | { 194 | "tag": "postsGridDataSourceListOfIds" 195 | } 196 | ], 197 | "label": "Data Source", 198 | "tooltip": "Specify the type of content to display in the Post grid element.", 199 | "replaceView": "dropdown", 200 | "merge": { 201 | "attributes": [ 202 | { 203 | "key": "attsOffset", 204 | "type": "string" 205 | }, 206 | { 207 | "key": "attsLimit", 208 | "type": "string" 209 | } 210 | ] 211 | } 212 | } 213 | }, 214 | "gridItem": { 215 | "type": "element", 216 | "access": "public", 217 | "value": { 218 | "tag": "demoGridItem" 219 | }, 220 | "options": { 221 | "_category": "postsGridItems", 222 | "tabLabel": "Grid Item", 223 | "tooltip": "Modify existing parameters of a single grid item of the chosen grid element." 224 | } 225 | }, 226 | "designOptions": { 227 | "type": "designOptions", 228 | "access": "public", 229 | "value": [], 230 | "options": { 231 | "label": "Design Options" 232 | } 233 | }, 234 | "metaEditFormTabs": { 235 | "type": "group", 236 | "access": "protected", 237 | "value": [ 238 | "editFormTab1", 239 | "filterItem", 240 | "sourceItem", 241 | "pagination", 242 | "gridItem", 243 | "designOptions" 244 | ] 245 | }, 246 | "relatedTo": { 247 | "type": "group", 248 | "access": "protected", 249 | "value": [ 250 | "General" 251 | ] 252 | }, 253 | "metaCustomId": { 254 | "type": "customId", 255 | "access": "public", 256 | "value": "", 257 | "options": { 258 | "label": "Element ID", 259 | "description": "Apply a unique ID to the element to link it directly by using #your_id (for element ID use lowercase input only)." 260 | } 261 | }, 262 | "customClass": { 263 | "type": "string", 264 | "access": "public", 265 | "value": "", 266 | "options": { 267 | "label": "Extra class name", 268 | "description": "Add an extra class name to the element and refer to it from the custom CSS option." 269 | } 270 | }, 271 | "tag": { 272 | "access": "protected", 273 | "type": "string", 274 | "value": "demoGrid" 275 | } 276 | } -------------------------------------------------------------------------------- /elements/demoGrid/demoGrid/styles.css: -------------------------------------------------------------------------------- 1 | .vce-demo-grid-wrapper { 2 | overflow: hidden; 3 | } 4 | 5 | .vce-demo-grid-container .vce-posts-grid-list { 6 | display: flex; 7 | flex-direction: row; 8 | justify-content: flex-start; 9 | align-items: stretch; 10 | align-content: flex-start; 11 | flex-wrap: wrap; 12 | } 13 | 14 | .vce-demo-grid-container .vce-demo-grid-item { 15 | flex: 0 0 100%; 16 | max-width: 100%; 17 | box-sizing: border-box; 18 | display: flex; 19 | flex-direction: column; 20 | overflow: hidden; 21 | position: relative; 22 | border: none; 23 | } 24 | 25 | .vce-demo-grid-container .vce-posts-grid-pagination { 26 | text-align: center; 27 | margin: 30px 0 12px; 28 | font-style: italic; 29 | } 30 | 31 | .vce-demo-grid-container .vce-posts-grid-pagination .vce-posts-grid-pagination-item { 32 | display: inline-block; 33 | border-radius: 50%; 34 | margin: 3px 7px; 35 | height: 30px; 36 | width: 30px; 37 | text-decoration: none; 38 | line-height: 30px; 39 | box-shadow: none; 40 | border: 0; 41 | outline: none; 42 | transition: background .2s ease-in-out; 43 | } 44 | 45 | .vce-demo-grid-container .vce-posts-grid-pagination .vce-posts-grid-pagination-item:hover { 46 | text-decoration: none; 47 | box-shadow: none; 48 | border: 0; 49 | outline: none; 50 | } 51 | 52 | .vce-demo-grid-container .vce-posts-grid-pagination .vce-posts-grid-pagination-item:focus { 53 | text-decoration: none; 54 | box-shadow: none; 55 | border: 0; 56 | outline: none; 57 | } 58 | 59 | .vce-demo-grid-container .vce-posts-grid-pagination-rest-items { 60 | padding: 0 18px; 61 | } 62 | 63 | .vce.vce-demo-grid-wrapper .vce-posts-grid-list { 64 | margin-left: calc(calc(var(--gapPx) * -1) / 2); 65 | margin-right: calc(calc(var(--gapPx) * -1) / 2); 66 | margin-bottom: calc(var(--gapPx) * -1); 67 | } 68 | 69 | .vce.vce-demo-grid-wrapper .vce-demo-grid-item { 70 | padding-left: calc(var(--gapPx) / 2); 71 | padding-right: calc(var(--gapPx) / 2); 72 | margin-bottom: var(--gapPx); 73 | } 74 | 75 | @media (min-width: 544px) { 76 | .vce.vce-demo-grid-wrapper .vce-demo-grid-item { 77 | -webkit-flex: 0 0 calc(100% / var(--columns)); 78 | -ms-flex: 0 0 calc(100% / var(--columns)); 79 | flex: 0 0 calc(100% / var(--columns)); 80 | max-width: calc(100% / var(--columns)); 81 | } 82 | } 83 | 84 | .vce.vce-demo-grid-wrapper .vce-posts-grid-pagination .vce-posts-grid-pagination-item { 85 | background-color: var(--paginationColor); 86 | color: var(--paginationTextColor); 87 | } 88 | 89 | .vce.vce-demo-grid-wrapper .vce-posts-grid-pagination .vce-posts-grid-pagination-item:hover { 90 | background-color: var(--paginationHoverColor); 91 | color: var(--paginationTextColor); 92 | } 93 | 94 | .vce.vce-demo-grid-wrapper .vce-posts-grid-pagination-item.vce-state--active { 95 | background-color: var(--paginationActiveColor); 96 | color: var(--paginationActiveTextColor); 97 | } 98 | 99 | .vce.vce-demo-grid-wrapper .vce-posts-grid-pagination-item.vce-state--active:hover { 100 | background-color: var(--paginationActiveHoverColor); 101 | } 102 | 103 | .vce.vce-demo-grid-wrapper .vce-posts-grid-pagination-item.vce-state--active:hover, 104 | .vce.vce-demo-grid-wrapper .vce-posts-grid-pagination-item.vce-state--active:focus { 105 | color: var(--paginationActiveTextColor); 106 | } -------------------------------------------------------------------------------- /elements/demoGrid/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "elements": { 3 | "demoGrid": { 4 | "settings": { 5 | "name": "[Demo] Demo Grid", 6 | "metaThumbnailUrl": "[publicPath]/thumbnail.png", 7 | "metaPreviewUrl": "[publicPath]/preview.png", 8 | "metaDescription": "Add page, post or custom post type grid teasers in grid layout." 9 | } 10 | } 11 | }, 12 | "categories": { 13 | "Grids": { 14 | "elements": [ 15 | "demoGrid" 16 | ] 17 | } 18 | }, 19 | "dependencies": [ 20 | "element/postsGrid", 21 | "element/postGridFilter", 22 | "element/postsGridDataSourcePage", 23 | "element/postsGridDataSourceListOfIds", 24 | "element/postsGridDataSourceCustomPostType", 25 | "element/postsGridDataSourcePost", 26 | "element/postsGridDataSourceArchive", 27 | "element/demoGridItem" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /elements/demoGrid/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vcwb", 3 | "version": "dev", 4 | "license": "SEE LICENSE IN ", 5 | "description": "Visual Composer Website Builder", 6 | "main": "index.php", 7 | "repository": { 8 | "type": "git", 9 | "url": "git@github.com:Visualcomposer/builder.git" 10 | }, 11 | "scripts": { 12 | "standard": "standard --version && standard", 13 | "build": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.js", 14 | "build-production": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.production.js", 15 | "watch": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.js --watch" 16 | }, 17 | "devDependencies": { 18 | "vc-webpack-vendors": "3.3.3" 19 | }, 20 | "babel": { 21 | "presets": [ 22 | "@babel/preset-env", 23 | "@babel/preset-react" 24 | ], 25 | "plugins": [ 26 | "@babel/plugin-transform-runtime", 27 | "@babel/plugin-proposal-class-properties" 28 | ] 29 | }, 30 | "standard": { 31 | "parser": "babel-eslint", 32 | "ignore": [ 33 | "public/dist/", 34 | "tests/", 35 | "**/public/js" 36 | ], 37 | "rules": { 38 | "jsx-quotes": [ 39 | 2, 40 | "prefer-single" 41 | ], 42 | "import/no-webpack-loader-syntax": "off" 43 | } 44 | }, 45 | "resolutions": { 46 | "core-js": "3.25.5", 47 | "postcss": "8.4.18", 48 | "css-loader": "6.7.1", 49 | "color-name": "1.1.4", 50 | "eslint": "8.25.0", 51 | "less": "4.1.3", 52 | "raw-loader": "1.0.0", 53 | "@babel/runtime": "7.19.4" 54 | }, 55 | "browserslist": [ 56 | "ie >= 11", 57 | "last 2 version" 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /elements/demoGridItem/demoGridItem/component.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import classNames from 'classnames' 3 | import { getService } from 'vc-cake' 4 | 5 | const vcvAPI = getService('api') 6 | 7 | export default class DemoGridItem extends vcvAPI.elementComponent { 8 | render () { 9 | const { padding, background, animation, aspectRatio } = this.props.atts 10 | const postDescriptionClasses = classNames({ 11 | 'vce-post-description': true, 12 | 'vce-post-description--full': !padding, 13 | 'vce-post-description--animation': animation, 14 | 'vce-post-description--has-background': padding && background 15 | }) 16 | const backgroundStyle = {} 17 | backgroundStyle['--aspect-ratio'] = aspectRatio 18 | if (padding && background) { 19 | backgroundStyle.backgroundColor = background 20 | } 21 | 22 | return ( 23 | 34 | ) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /elements/demoGridItem/demoGridItem/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-webpack-loader-syntax */ 2 | import vcCake from 'vc-cake' 3 | import DemoGridItem from './component' 4 | 5 | const vcvAddElement = vcCake.getService('cook').add 6 | 7 | vcvAddElement( 8 | require('./settings.json'), 9 | // Component callback 10 | (component) => { 11 | component.add(DemoGridItem) 12 | }, 13 | // css settings // css for element 14 | { 15 | css: require('raw-loader!./styles.css'), 16 | editorCss: false 17 | } 18 | ) 19 | -------------------------------------------------------------------------------- /elements/demoGridItem/demoGridItem/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "groups": { 3 | "type": "string", 4 | "access": "protected", 5 | "value": "Buttons" 6 | }, 7 | "padding": { 8 | "type": "toggle", 9 | "access": "public", 10 | "value": false, 11 | "options": { 12 | "label": "Content spacing", 13 | "description": "Set automatic right and left spacing for title and excerpt grid items." 14 | } 15 | }, 16 | "background": { 17 | "type": "color", 18 | "access": "public", 19 | "value": "", 20 | "options": { 21 | "label": "Background color", 22 | "onChange": { 23 | "rules": { 24 | "padding": { 25 | "rule": "toggle" 26 | } 27 | }, 28 | "actions": [ 29 | { 30 | "action": "toggleVisibility" 31 | } 32 | ] 33 | } 34 | } 35 | }, 36 | "animation": { 37 | "type": "toggle", 38 | "access": "public", 39 | "value": true, 40 | "options": { 41 | "label": "Zoom on hover", 42 | "description": "Apply zoom effect to featured images." 43 | } 44 | }, 45 | "aspectRatio": { 46 | "type": "dropdown", 47 | "access": "public", 48 | "value": "16/9", 49 | "options": { 50 | "label": "Aspect ratio", 51 | "values": [ 52 | { 53 | "label": "1:1", 54 | "value": "1/1" 55 | }, 56 | { 57 | "label": "16:9", 58 | "value": "16/9" 59 | }, 60 | { 61 | "label": "9:16", 62 | "value": "9/16" 63 | }, 64 | { 65 | "label": "4:3", 66 | "value": "4/3" 67 | }, 68 | { 69 | "label": "3:4", 70 | "value": "3/4" 71 | } 72 | ] 73 | } 74 | }, 75 | "editFormTab1": { 76 | "type": "group", 77 | "access": "public", 78 | "value": [ 79 | "padding", 80 | "background", 81 | "animation", 82 | "aspectRatio" 83 | ], 84 | "options": { 85 | "label": "Post Description" 86 | } 87 | }, 88 | "metaEditFormTabs": { 89 | "type": "group", 90 | "access": "protected", 91 | "value": [ 92 | "editFormTab1" 93 | ] 94 | }, 95 | "tag": { 96 | "access": "protected", 97 | "type": "string", 98 | "value": "demoGridItem" 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /elements/demoGridItem/demoGridItem/styles.css: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------- 2 | * Post Description 3 | * ---------------------------------------------- */ 4 | .vce-demo-grid-wrapper .vce-post-description { 5 | --aspect-ratio: 16/9; 6 | } 7 | 8 | .vce-post-description { 9 | box-sizing: border-box; 10 | border: none; 11 | display: flex; 12 | flex-direction: column; 13 | overflow: hidden; 14 | position: relative; 15 | width: 100%; 16 | } 17 | 18 | .vce-post-description * { 19 | box-sizing: border-box; 20 | } 21 | 22 | /* 23 | aspect-ratio: var(--aspect-ratio); 24 | */ 25 | 26 | .featured-image { 27 | background-color: orange; 28 | background-position: center; 29 | background-size: cover; 30 | display: flex; 31 | flex-direction: column; 32 | justify-content: flex-end; 33 | padding: 10px; 34 | 35 | aspect-ratio: var(--aspect-ratio); 36 | 37 | } 38 | 39 | /* Overlay */ 40 | .featured-image::before { 41 | content: ''; 42 | position: absolute; 43 | top: 0; 44 | left: 0; 45 | width: 100%; 46 | height: 100%; 47 | background-color: rgba(0, 0, 0, 0.4); 48 | z-index: 0; 49 | opacity: 0; 50 | transition: opacity 0.2s ease-in-out; 51 | } 52 | 53 | .vce-post-description:hover .post-category, 54 | .vce-post-description:hover .post-title, 55 | .vce-post-description:hover .featured-image::before { 56 | opacity: 1; 57 | } 58 | 59 | .post-category, 60 | .post-title { 61 | color: #fff; 62 | opacity: 0; 63 | z-index: 1; 64 | pointer-events: none; 65 | transition: opacity 0.2s ease-in-out; 66 | } 67 | 68 | .vce-post-description--background { 69 | box-sizing: border-box; 70 | position: relative; 71 | width: 100%; 72 | transition: transform 0.2s ease-in-out; 73 | } 74 | 75 | .vce-post-description--background-wrapper { 76 | position: relative; 77 | overflow: hidden; 78 | } 79 | 80 | .vce-post-description--background:after { 81 | content: ''; 82 | display: block; 83 | /* intrinsic aspect ratio */ 84 | height: 0; 85 | padding-bottom: 50%; 86 | } 87 | 88 | .vce-post-description--background { 89 | background-color: #fff; 90 | background-repeat: no-repeat; 91 | background-size: cover; 92 | background-position: center; 93 | -webkit-transform: scale(1); 94 | transform: scale(1); 95 | } 96 | 97 | .vce-post-description-link { 98 | position: absolute; 99 | top: 0; 100 | left: 0; 101 | right: 0; 102 | bottom: 0; 103 | opacity: 0; 104 | z-index: 1; 105 | } 106 | 107 | .vce-post-description.vce-post-description--animation .vce-post-description-link:hover+.vce-post-description--background-wrapper-box .vce-post-description--background, 108 | .vce-post-description.vce-post-description--animation .vce-post-description-link:focus+.vce-post-description--background-wrapper-box .vce-post-description--background { 109 | -webkit-transform: scale(1.2); 110 | transform: scale(1.2); 111 | } 112 | 113 | .vce-post-description--content { 114 | padding: 0 20px 20px; 115 | position: relative; 116 | text-align: left; 117 | } 118 | 119 | .vce-post-description--content.vce-post-description-content--has-excerpt p:last-child, 120 | .vce-post-description--content.vce-post-description-content--has-title:not(.vce-post-description-content--has-excerpt) h3 { 121 | margin: 0; 122 | } 123 | 124 | .vce-post-description--content.vce-post-description-content--has-title.vce-post-description-content--has-excerpt h3 { 125 | margin-bottom: 10px; 126 | } 127 | 128 | .vce-post-description--has-background .vce-post-description--content { 129 | padding-top: 20px; 130 | } 131 | 132 | .vce-post-description--title { 133 | text-transform: uppercase; 134 | } 135 | 136 | .vce-post-description--title h3 { 137 | font-size: 18px; 138 | font-weight: 500; 139 | padding: 0; 140 | margin: 0; 141 | line-height: 1.1; 142 | text-transform: uppercase; 143 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 144 | } 145 | 146 | .vce-post-description--title a { 147 | text-decoration: none; 148 | box-shadow: none; 149 | border: none; 150 | color: #333; 151 | } 152 | 153 | .vce-post-description--title a:hover, 154 | .vce-post-description--title a:focus { 155 | color: #333; 156 | } 157 | 158 | .vce-post-description--excerpt { 159 | color: #646568; 160 | line-height: 1.6; 161 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 162 | } 163 | 164 | .vce-post-description--full .vce-post-description--background-wrapper-box { 165 | padding: 0; 166 | } 167 | 168 | .vce-post-description--full .vce-post-description--background:after { 169 | padding-bottom: 50%; 170 | } 171 | 172 | .vce-post-description--full .vce-post-description--content { 173 | padding: 0 0 20px; 174 | } 175 | 176 | .vce-post-description--background-wrapper-box+.vce-post-description--content { 177 | padding-top: 20px; 178 | } 179 | 180 | .vce-demo-grid-container .vce-demo-grid-wrapper .vce-demo-grid-item .vce-post-description { 181 | margin: 0; 182 | } 183 | 184 | /*RTL support. */ 185 | .rtl.vce-post-description, 186 | [dir="rtl"].vce-post-description, 187 | .rtl .vce-post-description, 188 | [dir="rtl"] .vce-post-description { 189 | direction: rtl; 190 | unicode-bidi: embed; 191 | } 192 | 193 | .rtl.vce-post-description--content, 194 | [dir="rtl"].vce-post-description--content, 195 | .rtl .vce-post-description--content, 196 | [dir="rtl"] .vce-post-description--content { 197 | text-align: right; 198 | } 199 | 200 | .ltr.vce-post-description, 201 | [dir="ltr"].vce-post-description, 202 | .ltr .vce-post-description, 203 | [dir="ltr"] .vce-post-description { 204 | direction: ltr; 205 | unicode-bidi: normal; 206 | } 207 | 208 | .ltr.vce-post-description--content, 209 | [dir="ltr"].vce-post-description--content, 210 | .ltr .vce-post-description--content, 211 | [dir="ltr"] .vce-post-description--content { 212 | text-align: left; 213 | } -------------------------------------------------------------------------------- /elements/demoGridItem/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "elements": { 3 | "demoGridItem": { 4 | "settings": { 5 | "name": "Post Description", 6 | "metaDescription": "" 7 | }, 8 | "phpFiles": [] 9 | } 10 | }, 11 | "categories": { 12 | "_postsGridItem": { 13 | "elements": [ 14 | "demoGridItem" 15 | ] 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /elements/demoGridItem/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vcwb", 3 | "version": "dev", 4 | "license": "SEE LICENSE IN ", 5 | "description": "Visual Composer Website Builder", 6 | "main": "index.php", 7 | "repository": { 8 | "type": "git", 9 | "url": "git@github.com:Visualcomposer/builder.git" 10 | }, 11 | "scripts": { 12 | "standard": "standard --version && standard", 13 | "build": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.js", 14 | "build-production": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.production.js", 15 | "watch": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.js --watch" 16 | }, 17 | "devDependencies": { 18 | "vc-webpack-vendors": "3.3.3" 19 | }, 20 | "babel": { 21 | "presets": [ 22 | "@babel/preset-env", 23 | "@babel/preset-react" 24 | ], 25 | "plugins": [ 26 | "@babel/plugin-transform-runtime", 27 | "@babel/plugin-proposal-class-properties" 28 | ] 29 | }, 30 | "standard": { 31 | "parser": "babel-eslint", 32 | "ignore": [ 33 | "public/dist/", 34 | "tests/", 35 | "**/public/js" 36 | ], 37 | "rules": { 38 | "jsx-quotes": [ 39 | 2, 40 | "prefer-single" 41 | ], 42 | "import/no-webpack-loader-syntax": "off" 43 | } 44 | }, 45 | "resolutions": { 46 | "core-js": "3.25.5", 47 | "postcss": "8.4.18", 48 | "css-loader": "6.7.1", 49 | "color-name": "1.1.4", 50 | "eslint": "8.25.0", 51 | "less": "4.1.3", 52 | "raw-loader": "1.0.0", 53 | "@babel/runtime": "7.19.4" 54 | }, 55 | "browserslist": [ 56 | "ie >= 11", 57 | "last 2 version" 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/ci/phpcs.phar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/imageGalleryWithTestZoom/ci/phpcs.phar -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/ci/ruleset.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | A custom coding standard 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | ./visualcomposer/Requirements.php 63 | 64 | 65 | ./visualcomposer/Requirements.php 66 | 67 | 68 | ./visualcomposer/resources/* 69 | 70 | 71 | ./visualcomposer/resources/* 72 | 73 | 74 | ./visualcomposer/resources/* 75 | 76 | 77 | ./visualcomposer 78 | ./bootstrap 79 | ./plugin-wordpress.php 80 | 81 | ./plugin-wordpress.php 82 | 83 | 84 | 85 | tests/* 86 | vendor/* 87 | 88 | 89 | -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/component.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { getService } from 'vc-cake' 3 | import classNames from 'classnames' 4 | 5 | const vcvAPI = getService('api') 6 | 7 | export default class ImageGalleryWithTestZoom extends vcvAPI.elementComponent { 8 | imageSources = [] 9 | imageOrder = {} 10 | 11 | constructor (props) { 12 | super(props) 13 | this.createCustomSizeImage = this.createCustomSizeImage.bind(this) 14 | } 15 | 16 | componentDidMount () { 17 | this.imageSources = [] 18 | this.imageOrder = {} 19 | this.prepareImage(this.props.atts.image) 20 | } 21 | 22 | componentWillReceiveProps (nextProps) { 23 | this.imageSources = [] 24 | this.imageOrder = {} 25 | this.prepareImage(nextProps.atts.image) 26 | } 27 | 28 | prepareImage (image) { 29 | if (image.length && typeof image[0] === 'object') { 30 | const newImages = [] 31 | image.forEach((item, index) => { 32 | const newItem = item 33 | newItem.full = newItem.id ? newItem.full : this.getImageUrl(newItem.full) 34 | newItem.id = newItem.id ? newItem.id : Math.random() 35 | newImages.push(item) 36 | }) 37 | image = newImages 38 | this.setImageOrder(image) 39 | this.resizeImage(image) 40 | } 41 | const imgArr = [] 42 | image.forEach((img) => { 43 | if (image && image.id) { 44 | imgArr.push({ imgSrc: this.getImageUrl(img) }) 45 | } else { 46 | imgArr.push({ imgSrc: this.getImageUrl(img) }) 47 | } 48 | }) 49 | this.setImgSrcState(imgArr) 50 | } 51 | 52 | setImageOrder (imageArray) { 53 | imageArray.forEach((image, index) => { 54 | this.imageOrder[index] = image.id 55 | }) 56 | } 57 | 58 | checkImageSize (image, callback, imgCount) { 59 | const img = new window.Image() 60 | img.onload = () => { 61 | const size = { 62 | width: img.width, 63 | height: img.height 64 | } 65 | callback(image, size, imgCount) 66 | } 67 | img.src = image.full 68 | } 69 | 70 | resizeImage (imageArray) { 71 | imageArray.forEach((image) => { 72 | this.checkImageSize(image, this.createCustomSizeImage, imageArray.length) 73 | }) 74 | } 75 | 76 | createCustomSizeImage (image, size, imgCount) { 77 | image.orientation = this.checkOrientation(size) 78 | const checkImg = this.imageSources.filter((obj) => { 79 | return obj.id === image.id 80 | }) 81 | if (!checkImg.length) { 82 | this.imageSources.push(image) 83 | } 84 | 85 | if (this.imageSources.length === imgCount) { 86 | this.orderImages() 87 | } 88 | } 89 | 90 | orderImages () { 91 | const imagesInOrder = [] 92 | this.imageSources.forEach((img, index) => { 93 | const imgObj = this.imageSources.filter((obj) => { 94 | return obj.id === this.imageOrder[index] 95 | }) 96 | if (imgObj[0]) { 97 | imagesInOrder.push({ 98 | imgSrc: this.getImageUrl(imgObj[0], 'large'), 99 | orientation: imgObj[0].orientation, 100 | originalSrc: this.getImageUrl(imgObj[0]), 101 | alt: imgObj[0].alt, 102 | title: imgObj[0].title 103 | }) 104 | } 105 | }) 106 | 107 | this.setImgSrcState(imagesInOrder) 108 | } 109 | 110 | checkOrientation (size) { 111 | return size.width >= size.height ? 'landscape' : 'portrait' 112 | } 113 | 114 | setImgSrcState (imgSrc) { 115 | this.setState({ imgSrc }) 116 | } 117 | 118 | render () { 119 | const { id, atts, editor } = this.props 120 | const { image, shape, clickableOptions, showCaption, zoomEffect, customClass, metaCustomId } = atts 121 | let containerClasses = ['vce-image-gallery-with-zoom'] 122 | let wrapperClasses = ['vce', 'vce-image-gallery-with-zoom-wrapper'] 123 | const containerProps = {} 124 | let CustomTag = 'div' 125 | const imgSrc = this.state && this.state.imgSrc 126 | 127 | if (typeof customClass === 'string' && customClass) { 128 | containerClasses.push(customClass) 129 | } 130 | 131 | let mixinData = this.getMixinData('imageGalleryGap') 132 | if (mixinData) { 133 | containerClasses.push(`vce-image-gallery-with-zoom--gap-${mixinData.selector}`) 134 | } 135 | 136 | mixinData = this.getMixinData('imageGalleryColumns') 137 | if (mixinData) { 138 | containerClasses.push(`vce-image-gallery-with-zoom--columns-${mixinData.selector}`) 139 | } 140 | 141 | if (shape === 'rounded') { 142 | containerClasses.push('vce-image-gallery-with-zoom--border-rounded') 143 | } 144 | 145 | if (shape === 'round') { 146 | containerClasses.push('vce-image-gallery-with-zoom--border-round') 147 | } 148 | 149 | if (zoomEffect) { 150 | containerClasses.push(`vce-image-gallery-with-zoom--effect-${zoomEffect}`) 151 | } 152 | 153 | if (metaCustomId) { 154 | containerProps.id = metaCustomId 155 | } 156 | 157 | const galleryItems = [] 158 | 159 | imgSrc && imgSrc.forEach((src, index) => { 160 | let customProps = {} 161 | let classes = ['vce-image-gallery-with-zoom-item-inner'] 162 | let imgClasses = ['vce-image-gallery-with-zoom-img'] 163 | const customImageProps = { 164 | alt: src && src.alt ? src.alt : '', 165 | title: src && src.title ? src.title : '' 166 | } 167 | const itemProps = {} 168 | 169 | if (src.orientation === 'portrait') { 170 | imgClasses.push('vce-image-gallery-with-zoom-img--orientation-portrait') 171 | } 172 | 173 | if (clickableOptions === 'url' && image[index].link && image[index].link.url) { 174 | CustomTag = 'a' 175 | const { url, title, targetBlank, relNofollow } = image[index].link 176 | customProps = { 177 | href: url, 178 | title: title, 179 | target: targetBlank ? '_blank' : undefined, 180 | rel: relNofollow ? 'nofollow' : undefined 181 | } 182 | } else if (clickableOptions === 'imageNewTab') { 183 | CustomTag = 'a' 184 | customProps = { 185 | href: src.originalSrc || src.imgSrc, 186 | target: '_blank' 187 | } 188 | } else if (clickableOptions === 'lightbox') { 189 | CustomTag = 'a' 190 | customProps = { 191 | href: src.originalSrc || src.imgSrc, 192 | 'data-lightbox': `lightbox-${id}` 193 | } 194 | } else if (clickableOptions === 'photoswipe') { 195 | CustomTag = 'a' 196 | customProps = { 197 | href: src.originalSrc || src.imgSrc, 198 | 'data-photoswipe-image': id, 199 | 'data-photoswipe-index': index 200 | } 201 | if (showCaption) { 202 | customProps['data-photoswipe-caption'] = image[index].caption 203 | } 204 | containerProps['data-photoswipe-gallery'] = id 205 | itemProps['data-photoswipe-item'] = `photoswipe-${id}` 206 | } 207 | 208 | if (image[index].filter && image[index].filter !== 'normal') { 209 | classes.push(`vce-image-filter--${image[index].filter}`) 210 | imgClasses.push(`vce-image-filter--${image[index].filter}`) 211 | } 212 | 213 | classes = classNames(classes) 214 | imgClasses = classNames(imgClasses) 215 | 216 | galleryItems.push( 217 |
218 |
219 | 220 | 221 | 222 |
223 |
224 | ) 225 | }) 226 | 227 | const doAll = this.applyDO('all') 228 | containerClasses = classNames(containerClasses) 229 | wrapperClasses = classNames(wrapperClasses) 230 | 231 | return ( 232 |
233 |
234 |
235 | {galleryItems} 236 |
237 |
238 |
239 | ) 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/cssMixins/imageGalleryColumns.pcss: -------------------------------------------------------------------------------- 1 | @media (min-width: 544px) { 2 | .vce-image-gallery-with-zoom { 3 | &--columns-$selector { 4 | .vce-image-gallery-with-zoom-item { 5 | @if $columns != false { 6 | flex: 0 0 calc(100% / $columns); 7 | max-width: calc(100% / $columns); 8 | } 9 | } 10 | } 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/cssMixins/imageGalleryGap.pcss: -------------------------------------------------------------------------------- 1 | .vce-image-gallery-with-zoom { 2 | &--gap-$selector { 3 | .vce-image-gallery-with-zoom-list { 4 | @if $gap != false { 5 | margin-left: calc(-$(gap)px / 2); 6 | margin-right: calc(-$(gap)px / 2); 7 | margin-bottom: -$(gap)px; 8 | } 9 | } 10 | .vce-image-gallery-with-zoom-item { 11 | @if $gap != false { 12 | padding-left: calc($(gap)px / 2); 13 | padding-right: calc($(gap)px / 2); 14 | margin-bottom: $(gap)px; 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/editor.css: -------------------------------------------------------------------------------- 1 | .vce-image-gallery-with-zoom { 2 | min-height: 1em; 3 | } 4 | -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-webpack-loader-syntax */ 2 | import { getService } from 'vc-cake' 3 | import ImageGalleryWithTestZoom from './component' 4 | 5 | const vcvAddElement = getService('cook').add 6 | 7 | vcvAddElement( 8 | require('./settings.json'), 9 | // Component callback 10 | (component) => { 11 | component.add(ImageGalleryWithTestZoom) 12 | }, 13 | // css settings // css for element 14 | { 15 | css: require('raw-loader!./styles.css'), 16 | editorCss: require('raw-loader!./editor.css'), 17 | mixins: { 18 | imageGalleryColumns: { 19 | mixin: require('raw-loader!./cssMixins/imageGalleryColumns.pcss') 20 | }, 21 | imageGalleryGap: { 22 | mixin: require('raw-loader!./cssMixins/imageGalleryGap.pcss') 23 | } 24 | } 25 | } 26 | ) 27 | -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/public/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/public/close.png -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/public/default-skin/default-skin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/public/default-skin/default-skin.png -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/public/default-skin/default-skin.svg: -------------------------------------------------------------------------------- 1 | default-skin 2 -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/public/default-skin/preloader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/public/default-skin/preloader.gif -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/public/dist/dist/photoswipe-init.min.js: -------------------------------------------------------------------------------- 1 | !function(t){var e={};function o(i){if(e[i])return e[i].exports;var n=e[i]={i:i,l:!1,exports:{}};return t[i].call(n.exports,n,n.exports,o),n.l=!0,n.exports}o.m=t,o.c=e,o.d=function(t,e,i){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.t=function(t,e){if(1&e&&(t=o(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(o.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var n in t)o.d(i,n,function(e){return t[e]}.bind(null,n));return i},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,"a",e),e},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},o.p="",o(o.s=0)}([function(t,e,o){t.exports=o(1)},function(t,e){var o;window.vcv.on("ready",(function(){var t=document.getElementById("pswp");t&&(o&&o.destroy&&o.destroy(),t.remove());var e=document.createElement("div");e.innerHTML='',t=e.children[0],document.body.appendChild(t);var i=function(e){var i=e.dataset.photoswipeGallery,n=t,r=function t(e,o){return e&&(o(e)?e:t(e.parentNode,o))},a=function(t){if((t=t||window.event).preventDefault?t.preventDefault():t.returnValue=!1,r(t.target,(function(t){return t.dataset&&t.dataset.photoswipeGallery}))){var e=r(t.target,(function(t){return!!t.dataset.photoswipeImage})),o=r(e,(function(t){return t.dataset.photoswipeGallery&&t.dataset.photoswipeGallery===e.dataset.photoswipeImage}));if(o){var i=e.dataset.photoswipeIndex;return i>=0&&s(i,o),!1}}},s=function(t,r,a,s){var p=function(){var t=[],o=e.querySelectorAll("[data-photoswipe-item]:not([data-cloned])[data-photoswipe-image]");return o.length||(o=e.querySelectorAll("[data-photoswipe-item]:not([data-cloned]) [data-photoswipe-image]")),o&&(o=Array.prototype.slice.call(o)).forEach((function(e){var o=e.querySelector("img");if(o){var i=Array.prototype.slice.call(o.classList).find((function(t){return t.match(/vce\-image\-filter\-\-/)}))||"",n={src:e.href,w:o.naturalWidth,h:o.naturalHeight,el:e,title:e.dataset.photoswipeCaption,filterClass:i};t.push(n)}})),t}(),l={galleryUID:i,getThumbBoundsFn:function(t){var e=window.pageYOffset||document.documentElement.scrollTop,o=p[t].el.getBoundingClientRect();return{x:o.left,y:o.top+e,w:o.width}}};if(s)if(l.galleryPIDs){for(var d=0;d
',t=e.children[0],document.body.appendChild(t);var i=function(e){var i=e.dataset.photoswipeGallery,n=t,r=function t(e,o){return e&&(o(e)?e:t(e.parentNode,o))},a=function(t){if((t=t||window.event).preventDefault?t.preventDefault():t.returnValue=!1,r(t.target,(function(t){return t.dataset&&t.dataset.photoswipeGallery}))){var e=r(t.target,(function(t){return!!t.dataset.photoswipeImage})),o=r(e,(function(t){return t.dataset.photoswipeGallery&&t.dataset.photoswipeGallery===e.dataset.photoswipeImage}));if(o){var i=e.dataset.photoswipeIndex;return i>=0&&s(i,o),!1}}},s=function(t,r,a,s){var p=function(){var t=[],o=e.querySelectorAll("[data-photoswipe-item]:not([data-cloned])[data-photoswipe-image]");return o.length||(o=e.querySelectorAll("[data-photoswipe-item]:not([data-cloned]) [data-photoswipe-image]")),o&&(o=Array.prototype.slice.call(o)).forEach((function(e){var o=e.querySelector("img");if(o){var i=Array.prototype.slice.call(o.classList).find((function(t){return t.match(/vce\-image\-filter\-\-/)}))||"",n={src:e.href,w:o.naturalWidth,h:o.naturalHeight,el:e,title:e.dataset.photoswipeCaption,filterClass:i};t.push(n)}})),t}(),l={galleryUID:i,getThumbBoundsFn:function(t){var e=window.pageYOffset||document.documentElement.scrollTop,o=p[t].el.getBoundingClientRect();return{x:o.left,y:o.top+e,w:o.width}}};if(s)if(l.galleryPIDs){for(var d=0;d
').appendTo(window.jQuery("body")),this.$lightbox=window.jQuery("#vce-lightbox"),this.$overlay=window.jQuery("#vce-lightboxOverlay"),this.$outerContainer=this.$lightbox.find(".vce-lb-outerContainer"),this.$container=this.$lightbox.find(".vce-lb-container"),this.containerTopPadding=parseInt(this.$container.css("padding-top"),10),this.containerRightPadding=parseInt(this.$container.css("padding-right"),10),this.containerBottomPadding=parseInt(this.$container.css("padding-bottom"),10),this.containerLeftPadding=parseInt(this.$container.css("padding-left"),10),this.$overlay.hide().on("click",function(){return t.end(),!1}),this.$lightbox.hide().on("click",function(i){return"vce-lightbox"===window.jQuery(i.target).attr("id")&&t.end(),!1}),this.$outerContainer.on("click",function(i){return"vce-lightbox"===window.jQuery(i.target).attr("id")&&t.end(),!1}),this.$lightbox.find(".vce-lb-prev").on("click",function(){return 0===t.currentImageIndex?t.changeImage(t.album.length-1):t.changeImage(t.currentImageIndex-1),!1}),this.$lightbox.find(".vce-lb-next").on("click",function(){return t.currentImageIndex===t.album.length-1?t.changeImage(0):t.changeImage(t.currentImageIndex+1),!1}),this.$lightbox.find(".vce-lb-loader, .vce-lb-close").on("click",function(){return t.end(),!1})},t.prototype.start=function(t){function i(t){var i=Array.prototype.slice.call(t.get(0).classList).find(function(t){return t.match(/vce\-image\-filter\-\-/)})||"";e.album.push({link:t.attr("href"),title:t.attr("data-title")||t.attr("title"),filterClass:i})}var e=this,n=window.jQuery(window);n.on("resize",window.jQuery.proxy(this.sizeOverlay,this)),window.jQuery("select, object, embed").css({visibility:"hidden"}),this.sizeOverlay(),this.album=[];var o,a=0,r=t.attr("data-lightbox");if(r){o=window.jQuery(t.prop("tagName")+'[data-lightbox="'+r+'"]');for(var s=0;ss||n.height>r)&&(n.width/s>n.height/r?(a=s,o=parseInt(n.height/(n.width/a),10),e.width(a),e.height(o)):(o=r,a=parseInt(n.width/(n.height/o),10),e.width(a),e.height(o)))),i.sizeContainer(e.width(),e.height())},n.src=this.album[t].link,this.album[t].filterClass&&n.classList.add(this.album[t].filterClass),this.currentImageIndex=t},t.prototype.sizeOverlay=function(){this.$overlay.width(window.jQuery(document).width()).height(window.jQuery(document).height())},t.prototype.sizeContainer=function(t,i){function e(){n.$lightbox.find(".vce-lb-dataContainer").width(r),n.$lightbox.find(".vce-lb-prevLink").height(s),n.$lightbox.find(".vce-lb-nextLink").height(s),n.showImage()}var n=this,o=this.$outerContainer.outerWidth(),a=this.$outerContainer.outerHeight(),r=t+this.containerLeftPadding+this.containerRightPadding,s=i+this.containerTopPadding+this.containerBottomPadding;o!==r||a!==s?this.$outerContainer.animate({width:r,height:s},this.options.resizeDuration,"swing",function(){e()}):e()},t.prototype.showImage=function(){this.$lightbox.find(".vce-lb-loader").stop(!0).hide(),this.$lightbox.find(".vce-lb-image").fadeIn("slow"),this.updateNav(),this.updateDetails(),this.preloadNeighboringImages(),this.enableKeyboardNav()},t.prototype.updateNav=function(){var t=!1;try{document.createEvent("TouchEvent"),t=!!this.options.alwaysShowNavOnTouchDevices}catch(t){}this.$lightbox.find(".vce-lb-nav").show(),this.album.length>1&&(this.options.wrapAround?(t&&this.$lightbox.find(".vce-lb-prev, .vce-lb-next").css("opacity","1"),this.$lightbox.find(".vce-lb-prev, .vce-lb-next").show()):(this.currentImageIndex>0&&(this.$lightbox.find(".vce-lb-prev").show(),t&&this.$lightbox.find(".vce-lb-prev").css("opacity","1")),this.currentImageIndex1&&this.options.showImageNumberLabel){var i=this.imageCountLabel(this.currentImageIndex+1,this.album.length);this.$lightbox.find(".vce-lb-number").text(i).fadeIn("fast")}else this.$lightbox.find(".vce-lb-number").hide();this.$outerContainer.removeClass("animating"),this.$lightbox.find(".vce-lb-dataContainer").fadeIn(this.options.resizeDuration,function(){return t.sizeOverlay()})},t.prototype.preloadNeighboringImages=function(){this.album.length>this.currentImageIndex+1&&((new Image).src=this.album[this.currentImageIndex+1].link),this.currentImageIndex>0&&((new Image).src=this.album[this.currentImageIndex-1].link)},t.prototype.enableKeyboardNav=function(){window.jQuery(document).on("keyup.keyboard",window.jQuery.proxy(this.keyboardAction,this))},t.prototype.disableKeyboardNav=function(){window.jQuery(document).off(".keyboard")},t.prototype.keyboardAction=function(t){var i=t.keyCode,e=String.fromCharCode(i).toLowerCase();27===i||e.match(/x|o|c/)?this.end():"p"===e||37===i?0!==this.currentImageIndex?this.changeImage(this.currentImageIndex-1):this.options.wrapAround&&this.album.length>1&&this.changeImage(this.album.length-1):"n"!==e&&39!==i||(this.currentImageIndex!==this.album.length-1?this.changeImage(this.currentImageIndex+1):this.options.wrapAround&&this.album.length>1&&this.changeImage(0))},t.prototype.end=function(){this.disableKeyboardNav(),window.jQuery(window).off("resize",this.sizeOverlay),this.$lightbox.fadeOut(this.options.fadeDuration),this.$overlay.fadeOut(this.options.fadeDuration),window.jQuery("select, object, embed").css({visibility:"visible"}),this.options.disableScrolling&&window.jQuery("body").removeClass("vce-lb-disable-scrolling")},new t)}); -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/public/dist/photoswipe-init.min.js: -------------------------------------------------------------------------------- 1 | !function(t){function e(o){if(i[o])return i[o].exports;var a=i[o]={exports:{},id:o,loaded:!1};return t[o].call(a.exports,a,a.exports,e),a.loaded=!0,a.exports}var i={};return e.m=t,e.c=i,e.p="",e(0)}([function(t,e,i){t.exports=i(1)},function(t,e){!function(){var t;window.vcv.on("ready",function(){var e=document.getElementById("pswp");e&&(t&&t.destroy&&t.destroy(),e.remove());var i='',o=document.createElement("div");o.innerHTML=i,e=o.children[0],document.body.appendChild(e);var a=function(i){var o=i.dataset.photoswipeGallery,a=e,s=function(){var t=[],e=i.querySelectorAll("[data-photoswipe-item]:not([data-cloned])[data-photoswipe-image]");return e.length||(e=i.querySelectorAll("[data-photoswipe-item]:not([data-cloned]) [data-photoswipe-image]")),e&&(e=Array.prototype.slice.call(e),e.forEach(function(e){var i=e.querySelector("img");if(i){var o=Array.prototype.slice.call(i.classList).find(function(t){return t.match(/vce\-image\-filter\-\-/)})||"",a={src:e.href,w:i.naturalWidth,h:i.naturalHeight,el:e,title:e.dataset.photoswipeCaption,filterClass:o};t.push(a)}})),t},n=function u(t,e){return t&&(e(t)?t:u(t.parentNode,e))},r=function(t){if(t=t||window.event,t.preventDefault?t.preventDefault():t.returnValue=!1,n(t.target,function(t){return t.dataset&&t.dataset.photoswipeGallery})){var e=n(t.target,function(t){return!!t.dataset.photoswipeImage}),i=n(e,function(t){return t.dataset.photoswipeGallery&&t.dataset.photoswipeGallery===e.dataset.photoswipeImage});if(i){var o=e.dataset.photoswipeIndex;return o>=0&&l(o,i),!1}}},p=function(){var t=window.location.hash.substring(1),e={};if(t.length<5)return e;for(var i=t.split("&"),o=0;o= 0) { 72 | openPhotoSwipe(index, clickedGallery); 73 | } 74 | return false; 75 | }; 76 | 77 | // parse picture index and gallery index from URL (#&pid=1&gid=2) 78 | var photoswipeParseHash = function () { 79 | var hash = window.location.hash.substring(1), 80 | params = {}; 81 | if (hash.length < 5) { 82 | return params; 83 | } 84 | var vars = hash.split('&'); 85 | for (var i = 0; i < vars.length; i++) { 86 | if (!vars[ i ]) { 87 | continue; 88 | } 89 | var pair = vars[ i ].split('='); 90 | if (pair.length < 2) { 91 | continue; 92 | } 93 | params[ pair[ 0 ] ] = pair[ 1 ]; 94 | } 95 | return params; 96 | }; 97 | 98 | var openPhotoSwipe = function (index, galleryElement, disableAnimation, fromURL) { 99 | var items = parseElements(galleryElement); 100 | var options = { 101 | galleryUID: galleryId, 102 | getThumbBoundsFn: function (index) { 103 | var pageYScroll = window.pageYOffset || document.documentElement.scrollTop; 104 | var rect = items[ index ].el.getBoundingClientRect(); 105 | return { x: rect.left, y: rect.top + pageYScroll, w: rect.width }; 106 | } 107 | }; 108 | 109 | if (fromURL) { 110 | if (options.galleryPIDs) { 111 | // parse real index when custom PIDs are used 112 | // http://photoswipe.com/documentation/faq.html#custom-pid-in-url 113 | for (var j = 0; j < items.length; j++) { 114 | if (items[ j ].pid == index) { 115 | options.index = j; 116 | break; 117 | } 118 | } 119 | } else { 120 | // in URL indexes start from 1 121 | options.index = parseInt(index, 10) - 1; 122 | } 123 | } else { 124 | options.index = parseInt(index, 10); 125 | } 126 | 127 | if (isNaN(options.index)) { 128 | return; 129 | } 130 | 131 | if (disableAnimation) { 132 | options.showAnimationDuration = 0; 133 | } 134 | 135 | options.hideAnimationDuration = 100; 136 | 137 | gallery = openedPhotoswipe = new PhotoSwipe(domPswp, PhotoSwipeUI_Default, items, options); 138 | gallery.init(); 139 | }; 140 | 141 | var galleryElements = domGallery.querySelectorAll('[data-photoswipe-image]'); 142 | if (galleryElements) { 143 | galleryElements = Array.prototype.slice.call(galleryElements); 144 | galleryElements.forEach(function (item, index) { 145 | item.setAttribute('data-pswp-uid', index + 1); 146 | item.onclick = onThumbnailsClick; 147 | }); 148 | } 149 | 150 | // Parse URL and open gallery if it contains #&pid=3&gid=1 151 | var hashData = photoswipeParseHash(); 152 | if (hashData.pid && hashData.gid) { 153 | openPhotoSwipe(hashData.pid, galleryElements[ hashData.gid - 1 ], true, true); 154 | } 155 | }; 156 | 157 | var galleries = document.querySelectorAll('[data-photoswipe-gallery]'); 158 | if (galleries) { 159 | galleries = Array.prototype.slice.call(galleries); 160 | galleries.forEach(function (gallery) { 161 | initPhotoSwipeFromDOM(gallery); 162 | }); 163 | } 164 | }) 165 | })() 166 | /* eslint-enable */ 167 | -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/public/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/public/loading.gif -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/public/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/public/next.png -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/public/prev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/public/prev.png -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/public/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: { 3 | photoswipeInit: ['./js/lib/photoswipe/photoswipeInit.js'] 4 | }, 5 | output: { 6 | filename: 'dist/[name].min.js' 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/imageGalleryWithTestZoom/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "image": { 3 | "type": "attachimage", 4 | "access": "public", 5 | "value": [ 6 | "image-1.png", 7 | "image-2.png", 8 | "image-3.png" 9 | ], 10 | "options": { 11 | "label": "Images", 12 | "multiple": true, 13 | "onChange": { 14 | "rules": { 15 | "clickableOptions": { 16 | "rule": "value", 17 | "options": { 18 | "value": "url" 19 | } 20 | } 21 | }, 22 | "actions": [ 23 | { 24 | "action": "attachImageUrls" 25 | } 26 | ] 27 | }, 28 | "url": false, 29 | "imageFilter": true 30 | } 31 | }, 32 | "shape": { 33 | "type": "buttonGroup", 34 | "access": "public", 35 | "value": "square", 36 | "options": { 37 | "label": "Shape", 38 | "values": [ 39 | { 40 | "label": "Square", 41 | "value": "square", 42 | "icon": "vcv-ui-icon-attribute-shape-square" 43 | }, 44 | { 45 | "label": "Rounded", 46 | "value": "rounded", 47 | "icon": "vcv-ui-icon-attribute-shape-rounded" 48 | }, 49 | { 50 | "label": "Round", 51 | "value": "round", 52 | "icon": "vcv-ui-icon-attribute-shape-round" 53 | } 54 | ] 55 | } 56 | }, 57 | "designOptions": { 58 | "type": "designOptions", 59 | "access": "public", 60 | "value": {}, 61 | "options": { 62 | "label": "Design Options" 63 | } 64 | }, 65 | "editFormTab1": { 66 | "type": "group", 67 | "access": "protected", 68 | "value": [ 69 | "clickableOptions", 70 | "showCaption", 71 | "image", 72 | "columns", 73 | "gap", 74 | "shape", 75 | "zoomEffect", 76 | "metaCustomId", 77 | "customClass" 78 | ], 79 | "options": { 80 | "label": "General" 81 | } 82 | }, 83 | "metaEditFormTabs": { 84 | "type": "group", 85 | "access": "protected", 86 | "value": [ 87 | "editFormTab1", 88 | "designOptions" 89 | ] 90 | }, 91 | "relatedTo": { 92 | "type": "group", 93 | "access": "protected", 94 | "value": [ 95 | "General" 96 | ] 97 | }, 98 | "customClass": { 99 | "type": "string", 100 | "access": "public", 101 | "value": "", 102 | "options": { 103 | "label": "Extra class name", 104 | "description": "Add an extra class name to the element and refer to it from Custom CSS option." 105 | } 106 | }, 107 | "clickableOptions": { 108 | "type": "dropdown", 109 | "access": "public", 110 | "value": "lightbox", 111 | "options": { 112 | "label": "OnClick action", 113 | "values": [ 114 | { 115 | "label": "None", 116 | "value": "" 117 | }, 118 | { 119 | "label": "Lightbox", 120 | "value": "lightbox" 121 | }, 122 | { 123 | "label": "PhotoSwipe", 124 | "value": "photoswipe" 125 | }, 126 | { 127 | "label": "Open Image in New Tab", 128 | "value": "imageNewTab" 129 | }, 130 | { 131 | "label": "Link selector", 132 | "value": "url" 133 | } 134 | ] 135 | } 136 | }, 137 | "showCaption": { 138 | "type": "toggle", 139 | "access": "public", 140 | "value": false, 141 | "options": { 142 | "label": "Show image caption in gallery view", 143 | "onChange": { 144 | "rules": { 145 | "clickableOptions": { 146 | "rule": "value", 147 | "options": { 148 | "value": "photoswipe" 149 | } 150 | } 151 | }, 152 | "actions": [ 153 | { 154 | "action": "toggleVisibility" 155 | } 156 | ] 157 | } 158 | } 159 | }, 160 | "gap": { 161 | "type": "number", 162 | "access": "public", 163 | "value": "10", 164 | "options": { 165 | "label": "Gap", 166 | "description": "Enter gap in pixels (Example: 5).", 167 | "min": 0, 168 | "cssMixin": { 169 | "mixin": "imageGalleryGap", 170 | "property": "gap", 171 | "namePattern": "[\\da-f]+" 172 | } 173 | } 174 | }, 175 | "columns": { 176 | "type": "number", 177 | "access": "public", 178 | "value": "3", 179 | "options": { 180 | "label": "Number of Columns", 181 | "min": 1, 182 | "cssMixin": { 183 | "mixin": "imageGalleryColumns", 184 | "property": "columns", 185 | "namePattern": "[\\da-f]+" 186 | } 187 | } 188 | }, 189 | "zoomEffect": { 190 | "type": "dropdown", 191 | "access": "public", 192 | "value": "zoom", 193 | "options": { 194 | "label": "Zoom effect", 195 | "values": [ 196 | { 197 | "label": "Zoom", 198 | "value": "zoom" 199 | }, 200 | { 201 | "label": "Zoom with rotation", 202 | "value": "rotate" 203 | } 204 | ] 205 | } 206 | }, 207 | "metaCustomId": { 208 | "type": "customId", 209 | "access": "public", 210 | "value": "", 211 | "options": { 212 | "label": "Element ID", 213 | "description": "Apply unique ID to element to link directly to it by using #your_id (for element ID use lowercase input only)." 214 | } 215 | }, 216 | "tag": { 217 | "access": "protected", 218 | "type": "string", 219 | "value": "imageGalleryWithTestZoom" 220 | }, 221 | "metaPublicJs": { 222 | "access": "protected", 223 | "type": "string", 224 | "value": { 225 | "libraries": [ 226 | { 227 | "rules": { 228 | "clickableOptions": { 229 | "rule": "value", 230 | "options": { 231 | "value": "lightbox" 232 | } 233 | } 234 | }, 235 | "libPaths": "public/dist/lightbox.min.js" 236 | }, 237 | { 238 | "rules": { 239 | "clickableOptions": { 240 | "rule": "value", 241 | "options": { 242 | "value": "photoswipe" 243 | } 244 | } 245 | }, 246 | "libPaths": [ 247 | "public/dist/photoswipe.min.js", 248 | "public/dist/photoswipe-ui-default.min.js", 249 | "public/dist/photoswipe-init.min.js" 250 | ] 251 | } 252 | ] 253 | } 254 | } 255 | } -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "elements": { 3 | "imageGalleryWithTestZoom": { 4 | "settings": { 5 | "name": "[Demo] Gallery", 6 | "metaThumbnailUrl": "[publicPath]/image-gallery-thumbnail.png", 7 | "metaPreviewUrl": "[publicPath]/image-gallery-preview.png", 8 | "metaDescription": "A grid type image gallery with a test zoom effect upon hover to catch visitors' attention." 9 | } 10 | } 11 | }, 12 | "categories": { 13 | "Image gallery": { 14 | "elements": [ 15 | "imageGalleryWithTestZoom" 16 | ] 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /elements/imageGalleryWithTestZoom/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vcwb", 3 | "version": "1.0.0-dev", 4 | "description": "Image Gallery with Test Zoom", 5 | "main": "index.php", 6 | "repository": { 7 | "type": "git", 8 | "url": "git@github.com:Visualcomposer/vcwb-demo-element-example-plugin.git" 9 | }, 10 | "author": "@visualcomposer", 11 | "license": "GPL-2.0+", 12 | "engines": { 13 | "node": ">=8", 14 | "npm": ">=5.8" 15 | }, 16 | "scripts": { 17 | "standard": "standard --version && standard", 18 | "build": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.js", 19 | "build-production": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.production.js", 20 | "watch": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.js --watch" 21 | }, 22 | "devDependencies": { 23 | "vc-webpack-vendors": "3.3.3" 24 | }, 25 | "babel": { 26 | "presets": [ 27 | "@babel/preset-env", 28 | "@babel/preset-react" 29 | ], 30 | "plugins": [ 31 | "@babel/plugin-transform-runtime", 32 | "@babel/plugin-proposal-class-properties" 33 | ] 34 | }, 35 | "standard": { 36 | "parser": "babel-eslint", 37 | "ignore": [ 38 | "public/dist/", 39 | "tests/", 40 | "**/public/js" 41 | ], 42 | "rules": { 43 | "jsx-quotes": [ 44 | 2, 45 | "prefer-single" 46 | ], 47 | "import/no-webpack-loader-syntax": "off" 48 | } 49 | }, 50 | "resolutions": { 51 | "core-js": "3.25.5", 52 | "postcss": "8.4.18", 53 | "css-loader": "6.7.1", 54 | "color-name": "1.1.4", 55 | "eslint": "8.25.0", 56 | "less": "4.1.3", 57 | "raw-loader": "1.0.0", 58 | "@babel/runtime": "7.19.4" 59 | }, 60 | "browserslist": [ 61 | "ie >= 11", 62 | "last 2 version" 63 | ] 64 | } 65 | -------------------------------------------------------------------------------- /elements/imageSlider/imageSlider/component.js: -------------------------------------------------------------------------------- 1 | // Example of a simple image slider element 2 | // It uses Visual Composer shared asset library - slickSlider 3 | // Component generates the markup of the slider, 4 | // it stores the markup as a string inside a data attribute of a helper element .vcvhelper 5 | 6 | import React from 'react' 7 | import { renderToStaticMarkup } from 'react-dom/server' 8 | import { getService } from 'vc-cake' 9 | 10 | const vcvAPI = getService('api') 11 | 12 | export default class ImageSlider extends vcvAPI.elementComponent { 13 | render () { 14 | const { id, atts, editor } = this.props 15 | let { images, autoplay, autoplayDelay, effect, pointers, arrows, metaCustomId, customClass } = atts 16 | 17 | let containerClasses = 'vce-image-slider' 18 | const wrapperClasses = 'vce-image-slider-wrapper vce' 19 | const dotsClasses = 'vce-image-slider-dots' 20 | const containerProps = {} 21 | 22 | if (typeof customClass === 'string' && customClass) { 23 | containerClasses += ` ${customClass}` 24 | } 25 | 26 | if (metaCustomId) { 27 | containerProps.id = metaCustomId 28 | } 29 | 30 | // Generate array of JSX of images 31 | const Slides = images.map((image, index) => { 32 | const customProps = {} 33 | const CustomTag = 'div' 34 | let imgClasses = 'vce-image-slider-img' 35 | const imgTagClasses = '' 36 | const imgSrc = this.getImageUrl(image) // This is the common method available for all elements 37 | const itemProps = {} 38 | 39 | customProps.style = { backgroundImage: `url(${imgSrc})` } 40 | 41 | if (image.filter && image.filter !== 'normal') { 42 | imgClasses += ` vce-image-filter--${image.filter}` 43 | } 44 | 45 | return ( 46 |
47 | 48 | {(image 49 | 50 |
51 | ) 52 | }) 53 | 54 | const doAll = this.applyDO('all') 55 | 56 | autoplayDelay *= 1000 57 | 58 | let prevArrow = '' 59 | let nextArrow = '' 60 | 61 | // Generate markup for Slick slider arrows 62 | if (arrows) { 63 | const arrowClasses = 'vce-image-slider-arrow' 64 | 65 | prevArrow = ( 66 |
67 | 68 | 69 | 70 |
71 | ) 72 | nextArrow = ( 73 |
74 | 75 | 76 | 77 |
78 | ) 79 | } 80 | 81 | // Compose the markup of the slider 82 | // Store slick settings in the data attributes 83 | const listHTML = ( 84 |
92 |
93 | {prevArrow} 94 |
95 | {Slides} 96 |
97 | {nextArrow} 98 |
99 |
100 | ) 101 | 102 | // Generate raw HTML string to initiate on View Page 103 | let htmlString = renderToStaticMarkup(listHTML) 104 | htmlString += renderToStaticMarkup(
) 105 | 106 | // Use .vcvhelper element to render slick slider in editor 107 | // Store raw HTML string inside data attribute to initiate it on View Page 108 | return ( 109 |
110 |
111 |
112 |
121 |
122 | {prevArrow} 123 |
124 | {Slides} 125 |
126 | {nextArrow} 127 |
128 |
129 |
130 |
131 |
132 |
133 | ) 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /elements/imageSlider/imageSlider/editor.css: -------------------------------------------------------------------------------- 1 | .vce-image-slider { 2 | min-height: 1em; 3 | } 4 | -------------------------------------------------------------------------------- /elements/imageSlider/imageSlider/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-webpack-loader-syntax */ 2 | import { getService } from 'vc-cake' 3 | import ImageSlider from './component' 4 | 5 | const vcvAddElement = getService('cook').add 6 | 7 | vcvAddElement( 8 | require('./settings.json'), 9 | // Component callback 10 | (component) => { 11 | component.add(ImageSlider) 12 | }, 13 | // css settings // css for element 14 | { 15 | css: require('raw-loader!./styles.css'), 16 | editorCss: require('raw-loader!./editor.css') 17 | } 18 | ) 19 | -------------------------------------------------------------------------------- /elements/imageSlider/imageSlider/public/dist/imageSlider.min.js: -------------------------------------------------------------------------------- 1 | !function(e){var t={};function n(i){if(t[i])return t[i].exports;var o=t[i]={i:i,l:!1,exports:{}};return e[i].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(i,o,function(t){return e[t]}.bind(null,o));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){e.exports=n(1)},function(e,t){!function(e){function t(e){const t=e.parent().find(".vce-image-slider-dots"),n=e.find(".vce-image-slider-prev-arrow")||"",i=e.find(".vce-image-slider-next-arrow")||"",o={autoplay:"on"===e[0].dataset.slickAutoplay,autoplaySpeed:e[0].dataset.slickAutoplayDelay,fade:"fade"===e[0].dataset.slickEffect,arrows:"on"===e[0].dataset.slickArrows,prevArrow:n,nextArrow:i,appendDots:t,dots:"on"===e[0].dataset.slickDots,initialSlide:0,respondTo:"slider",swipe:"on"!==e[0].dataset.slickDisableSwipe,swipeToSlide:"on"!==e[0].dataset.slickDisableSwipe,touchMove:"on"!==e[0].dataset.slickDisableSwipe};e.hasClass("slick-initialized")&&e.vcSlick&&e.vcSlick("unslick"),e.vcSlick&&e.vcSlick(o)}window.vcv.on("ready",()=>{!function(){const n=e(".vce-image-slider-list");n.length&&n.each((function(){t(e(this))}))}()}),window.vcv.on("reInit",(n,i="")=>{const o=setTimeout(()=>{const n=e(`#el-${i} .vce-image-slider-list`);n&&t(n),clearTimeout(o)},0)})}(window.jQuery)}]); -------------------------------------------------------------------------------- /elements/imageSlider/imageSlider/public/image-slide-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/imageSlider/imageSlider/public/image-slide-1.png -------------------------------------------------------------------------------- /elements/imageSlider/imageSlider/public/image-slide-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/imageSlider/imageSlider/public/image-slide-2.png -------------------------------------------------------------------------------- /elements/imageSlider/imageSlider/public/image-slide-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/imageSlider/imageSlider/public/image-slide-3.png -------------------------------------------------------------------------------- /elements/imageSlider/imageSlider/public/image-slider-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/imageSlider/imageSlider/public/image-slider-preview.png -------------------------------------------------------------------------------- /elements/imageSlider/imageSlider/public/image-slider-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/imageSlider/imageSlider/public/image-slider-thumbnail.png -------------------------------------------------------------------------------- /elements/imageSlider/imageSlider/public/js/imageSlider.js: -------------------------------------------------------------------------------- 1 | // Script to initialize Slick Slider in Visual Composer editor 2 | // and on View Page, this file is minified and located in the dist folder. 3 | // Minified version of this file is included in settings.json under metaPublicJs property. 4 | 5 | // To minify this file inside imageSlider/public folder a webpack.config.js file should be created 6 | // next inside terminal enter imageSlider/public folder and run: 7 | // ../../node_modules/.bin/webpack --config=webpack.config.js -p 8 | 9 | (function ($) { 10 | // Get all settings from data attributes 11 | // Check if this element is already initialized, then destroy Slick slider 12 | // Initialize slider 13 | // vcSlick is a custom Visual Composer property on an element to control Slick 14 | function initSlider (slider) { 15 | const dots = slider.parent().find('.vce-image-slider-dots') 16 | const prevArrow = slider.find('.vce-image-slider-prev-arrow') || '' 17 | const nextArrow = slider.find('.vce-image-slider-next-arrow') || '' 18 | const settings = { 19 | autoplay: slider[0].dataset.slickAutoplay === 'on', 20 | autoplaySpeed: slider[0].dataset.slickAutoplayDelay, 21 | fade: slider[0].dataset.slickEffect === 'fade', 22 | arrows: slider[0].dataset.slickArrows === 'on', 23 | prevArrow: prevArrow, 24 | nextArrow: nextArrow, 25 | appendDots: dots, 26 | dots: slider[0].dataset.slickDots === 'on', 27 | initialSlide: 0, 28 | respondTo: 'slider', 29 | swipe: slider[0].dataset.slickDisableSwipe !== 'on', 30 | swipeToSlide: slider[0].dataset.slickDisableSwipe !== 'on', 31 | touchMove: slider[0].dataset.slickDisableSwipe !== 'on' 32 | } 33 | if (slider.hasClass('slick-initialized')) { 34 | slider.vcSlick && slider.vcSlick('unslick') 35 | } 36 | slider.vcSlick && slider.vcSlick(settings) 37 | } 38 | 39 | // Selects all possible imageSlider element on the page 40 | // Iterates over each one and initialize it 41 | function initialize () { 42 | const sliders = $('.vce-image-slider-list') 43 | if (sliders.length) { 44 | // Use `function` keyword instead of arrow function for correct `this` keyword scope 45 | sliders.each(function () { 46 | const slider = $(this) 47 | initSlider(slider) 48 | }) 49 | } 50 | } 51 | 52 | // window.vcv.on('ready', function () {}) is a global event listener 53 | // it is triggered each time element is added to the page or gets edited (in VC editor) 54 | window.vcv.on('ready', () => { 55 | initialize() 56 | }) 57 | 58 | // window.vcv.on('reInit', function () {}) is a global event listener 59 | // it is triggered each time element is added to the page or gets edited (in VC editor) 60 | // Selects particular imageSlider elemnt (based on ID) and re-initialize it with timeout 61 | window.vcv.on('reInit', (action, id = '') => { 62 | const timeout = setTimeout(() => { 63 | const slider = $(`#el-${id} .vce-image-slider-list`) 64 | if (slider) { 65 | initSlider(slider) 66 | } 67 | clearTimeout(timeout) 68 | }, 0) 69 | }) 70 | })(window.jQuery) 71 | -------------------------------------------------------------------------------- /elements/imageSlider/imageSlider/public/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: { 3 | imageSlider: ['./js/imageSlider.js'] 4 | }, 5 | output: { 6 | filename: '[name].min.js' 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /elements/imageSlider/imageSlider/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "tag": { 3 | "access": "protected", 4 | "type": "string", 5 | "value": "imageSlider" 6 | }, 7 | "relatedTo": { 8 | "type": "group", 9 | "access": "protected", 10 | "value": [ 11 | "General" 12 | ] 13 | }, 14 | "images": { 15 | "type": "attachimage", 16 | "access": "public", 17 | "value": [ 18 | "image-slide-1.png", 19 | "image-slide-2.png", 20 | "image-slide-3.png" 21 | ], 22 | "options": { 23 | "label": "Images", 24 | "multiple": true, 25 | "onChange": { 26 | "rules": { 27 | "clickableOptions": { 28 | "rule": "value", 29 | "options": { 30 | "value": "url" 31 | } 32 | } 33 | }, 34 | "actions": [ 35 | { 36 | "action": "attachImageUrls" 37 | } 38 | ] 39 | }, 40 | "url": false, 41 | "imageFilter": true 42 | } 43 | }, 44 | "autoplay": { 45 | "type": "toggle", 46 | "access": "public", 47 | "value": true, 48 | "options": { 49 | "label": "Autoplay" 50 | } 51 | }, 52 | "autoplayDelay": { 53 | "type": "number", 54 | "access": "public", 55 | "value": "3", 56 | "options": { 57 | "label": "Autoplay Delay in seconds", 58 | "onChange": { 59 | "rules": { 60 | "autoplay": { 61 | "rule": "toggle" 62 | } 63 | }, 64 | "actions": [ 65 | { 66 | "action": "toggleVisibility" 67 | } 68 | ] 69 | } 70 | } 71 | }, 72 | "effect": { 73 | "type": "dropdown", 74 | "access": "public", 75 | "value": "slideIn", 76 | "options": { 77 | "label": "Slide effect", 78 | "values": [ 79 | { 80 | "label": "Slide In", 81 | "value": "slideIn" 82 | }, 83 | { 84 | "label": "Fade", 85 | "value": "fade" 86 | } 87 | ] 88 | } 89 | }, 90 | "pointers": { 91 | "type": "toggle", 92 | "access": "public", 93 | "value": true, 94 | "options": { 95 | "label": "Show pointers" 96 | } 97 | }, 98 | "arrows": { 99 | "type": "toggle", 100 | "access": "public", 101 | "value": false, 102 | "options": { 103 | "label": "Show arrows" 104 | } 105 | }, 106 | "designOptions": { 107 | "type": "designOptions", 108 | "access": "public", 109 | "value": {}, 110 | "options": { 111 | "label": "Design Options" 112 | } 113 | }, 114 | "editFormTab1": { 115 | "type": "group", 116 | "access": "protected", 117 | "value": [ 118 | "images", 119 | "autoplay", 120 | "autoplayDelay", 121 | "effect", 122 | "pointers", 123 | "arrows", 124 | "metaCustomId", 125 | "customClass" 126 | ], 127 | "options": { 128 | "label": "General" 129 | } 130 | }, 131 | "metaEditFormTabs": { 132 | "type": "group", 133 | "access": "protected", 134 | "value": [ 135 | "editFormTab1", 136 | "designOptions" 137 | ] 138 | }, 139 | "customClass": { 140 | "type": "string", 141 | "access": "public", 142 | "value": "", 143 | "options": { 144 | "label": "Extra class name", 145 | "description": "Add an extra class name to the element and refer to it from Custom CSS option." 146 | } 147 | }, 148 | "metaCustomId": { 149 | "type": "customId", 150 | "access": "public", 151 | "value": "", 152 | "options": { 153 | "label": "Element ID", 154 | "description": "Apply unique ID to element to link directly to it by using #your_id (for element ID use lowercase input only)." 155 | } 156 | }, 157 | "sharedAssetsLibrary": { 158 | "access": "protected", 159 | "type": "string", 160 | "value": { 161 | "libraries": [ 162 | { 163 | "libsNames": [ 164 | "slickSlider" 165 | ] 166 | } 167 | ] 168 | } 169 | }, 170 | "metaPublicJs": { 171 | "access": "protected", 172 | "type": "string", 173 | "value": { 174 | "libraries": [ 175 | { 176 | "libPaths": [ 177 | "public/dist/imageSlider.min.js" 178 | ] 179 | } 180 | ] 181 | } 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /elements/imageSlider/imageSlider/styles.css: -------------------------------------------------------------------------------- 1 | .vce-image-slider { 2 | width: 100%; 3 | max-width: 100%; 4 | box-sizing: border-box; 5 | direction: ltr; 6 | } 7 | 8 | .vce-image-slider-wrapper { 9 | position: relative; 10 | overflow: hidden; 11 | color: transparent; 12 | padding-top: 56.25%; 13 | z-index: 0; 14 | } 15 | 16 | .vce-image-slider .vce-image-slider-list { 17 | position: absolute; 18 | top: 0; 19 | right: 0; 20 | bottom: 0; 21 | left: 0; 22 | z-index: 1; 23 | height: 100%; 24 | } 25 | 26 | .vce-image-slider .vce-image-slider-list *:focus { 27 | outline: none; 28 | } 29 | 30 | .vce-image-slider-list .slick-list { 31 | overflow: hidden; 32 | height: 100%; 33 | } 34 | 35 | .vce-image-slider-list .slick-track, 36 | .vce-image-slider-list .slick-slide, 37 | .vce-image-slider-list .vce-image-slider-img { 38 | /* position: absolute; 39 | width: 100%; */ 40 | height: 100%; 41 | } 42 | 43 | .vce-image-slider-list .vce-image-slider-img { 44 | display: block; 45 | background-repeat: no-repeat; 46 | background-position: center; 47 | background-size: cover; 48 | } 49 | 50 | .vce-image-slider-arrow { 51 | display: block; 52 | position: absolute; 53 | z-index: 9; 54 | top: 0; 55 | bottom: 0; 56 | width: 35px; 57 | cursor: pointer; 58 | opacity: 0; 59 | visibility: hidden; 60 | transition: opacity .3s ease, visibility .3s ease; 61 | } 62 | 63 | .vce-image-slider-list:hover .vce-image-slider-arrow { 64 | opacity: 1; 65 | visibility: visible; 66 | } 67 | 68 | .vce-image-slider-arrow.vce-image-slider-prev-arrow { 69 | left: 0; 70 | } 71 | 72 | .vce-image-slider-arrow.vce-image-slider-next-arrow { 73 | right: 0; 74 | } 75 | 76 | .vce-image-slider-arrow svg { 77 | display: block; 78 | position: absolute; 79 | top: 50%; 80 | transform: translateY(-50%); 81 | left: 0; 82 | right: 0; 83 | margin: 0 auto; 84 | } 85 | 86 | .vce-image-slider-arrow svg polygon { 87 | fill: rgba(255, 255, 255, .5); 88 | transition: fill .3s ease; 89 | } 90 | 91 | .vce-image-slider-arrow svg:hover polygon { 92 | fill: #fff; 93 | } 94 | 95 | .vce-image-slider-dots { 96 | position: absolute; 97 | bottom: 20px; 98 | left: 0; 99 | right: 0; 100 | text-align: center; 101 | z-index: 2; 102 | } 103 | 104 | .vce-image-slider-dots .slick-dots { 105 | list-style: none; 106 | margin: 0 auto; 107 | padding: 0; 108 | } 109 | 110 | .vce-image-slider-dots .slick-dots li { 111 | list-style: none; 112 | display: inline-block; 113 | padding: 7px; 114 | } 115 | 116 | .vce-image-slider-dots .slick-dots li:before, 117 | .vce-image-slider-dots .slick-dots li:after { 118 | content: none; 119 | } 120 | 121 | .vce-image-slider-dots .slick-dots button { 122 | background: #fff; 123 | font-size: 0px; 124 | display: block; 125 | width: 10px; 126 | height: 10px; 127 | border-radius: 50%; 128 | cursor: pointer; 129 | border: 0; 130 | outline: none; 131 | margin: 0; 132 | padding: 0; 133 | } 134 | 135 | .vce-image-slider-dots .slick-dots button:hover, 136 | .vce-image-slider-dots .slick-dots .slick-active button { 137 | background: #fd9a00; 138 | } 139 | 140 | a.vce-image-slider-img { 141 | border-bottom: 0; 142 | text-decoration: none; 143 | box-shadow: none; 144 | } 145 | 146 | a.vce-image-slider-img:hover, 147 | a.vce-image-slider-img:focus { 148 | text-decoration: none; 149 | box-shadow: none; 150 | border-bottom: 0; 151 | } 152 | 153 | .vce-image-slider .vce-image-slider-img img { 154 | box-shadow: none; 155 | } 156 | 157 | /* slick css */ 158 | .vce-image-slider .slick-slider { 159 | display: block; 160 | box-sizing: border-box; 161 | -webkit-user-select: none; 162 | -moz-user-select: none; 163 | -ms-user-select: none; 164 | user-select: none; 165 | -webkit-touch-callout: none; 166 | -khtml-user-select: none; 167 | -ms-touch-action: pan-y; 168 | touch-action: pan-y; 169 | -webkit-tap-highlight-color: transparent; 170 | } 171 | 172 | .vce-image-slider .slick-list { 173 | position: relative; 174 | display: block; 175 | overflow: hidden; 176 | margin: 0; 177 | padding: 0; 178 | } 179 | 180 | .vce-image-slider .slick-list:focus { 181 | outline: none; 182 | } 183 | 184 | .vce-image-slider .slick-list.dragging { 185 | cursor: pointer; 186 | cursor: hand; 187 | } 188 | 189 | .vce-image-slider .slick-slider .slick-track, 190 | .vce-image-slider .slick-slider .slick-list { 191 | -webkit-transform: translate3d(0, 0, 0); 192 | -moz-transform: translate3d(0, 0, 0); 193 | -ms-transform: translate3d(0, 0, 0); 194 | -o-transform: translate3d(0, 0, 0); 195 | transform: translate3d(0, 0, 0); 196 | } 197 | 198 | .vce-image-slider .slick-track { 199 | position: relative; 200 | top: 0; 201 | left: 0; 202 | display: block; 203 | } 204 | 205 | .vce-image-slider .slick-track:before, 206 | .vce-image-slider .slick-track:after { 207 | display: table; 208 | content: ''; 209 | } 210 | 211 | .vce-image-slider .slick-track:after { 212 | clear: both; 213 | } 214 | 215 | .vce-image-slider .slick-loading .slick-track { 216 | visibility: hidden; 217 | } 218 | 219 | .vce-image-slider .slick-slide { 220 | display: none; 221 | float: left; 222 | height: 100%; 223 | min-height: 1px; 224 | } 225 | 226 | .vce-image-slider .slick-slide img { 227 | display: block; 228 | } 229 | 230 | .vce-image-slider .slick-slide.slick-loading img { 231 | display: none; 232 | } 233 | 234 | .vce-image-slider .slick-slide.dragging img { 235 | pointer-events: none; 236 | } 237 | 238 | .vce-image-slider .slick-initialized .slick-slide { 239 | display: block; 240 | } 241 | 242 | .vce-image-slider .slick-loading .slick-slide { 243 | visibility: hidden; 244 | } 245 | 246 | .vce-image-slider .slick-arrow.slick-hidden { 247 | display: none; 248 | } 249 | -------------------------------------------------------------------------------- /elements/imageSlider/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "elements": { 3 | "imageSlider": { 4 | "settings": { 5 | "name": "[Demo] Image Slider", 6 | "metaThumbnailUrl": "[publicPath]/image-slider-thumbnail.png", 7 | "metaPreviewUrl": "[publicPath]/image-slider-preview.png", 8 | "metaDescription": "Media Library Image slider with dot controls and swipe option for better mobile experience." 9 | } 10 | } 11 | }, 12 | "categories": { 13 | "Image Slider": { 14 | "elements": [ 15 | "imageSlider" 16 | ] 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /elements/imageSlider/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vcwb", 3 | "version": "dev", 4 | "license": "SEE LICENSE IN ", 5 | "description": "Visual Composer Website Builder", 6 | "main": "index.php", 7 | "repository": { 8 | "type": "git", 9 | "url": "git@github.com:Visualcomposer/builder.git" 10 | }, 11 | "scripts": { 12 | "standard": "standard --version && standard", 13 | "build": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.js", 14 | "build-production": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.production.js", 15 | "watch": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.js --watch" 16 | }, 17 | "devDependencies": { 18 | "vc-webpack-vendors": "3.3.3" 19 | }, 20 | "babel": { 21 | "presets": [ 22 | "@babel/preset-env", 23 | "@babel/preset-react" 24 | ], 25 | "plugins": [ 26 | "@babel/plugin-transform-runtime", 27 | "@babel/plugin-proposal-class-properties" 28 | ] 29 | }, 30 | "standard": { 31 | "parser": "babel-eslint", 32 | "ignore": [ 33 | "public/dist/", 34 | "tests/", 35 | "**/public/js" 36 | ], 37 | "rules": { 38 | "jsx-quotes": [ 39 | 2, 40 | "prefer-single" 41 | ], 42 | "import/no-webpack-loader-syntax": "off" 43 | } 44 | }, 45 | "resolutions": { 46 | "core-js": "3.25.5", 47 | "postcss": "8.4.18", 48 | "css-loader": "6.7.1", 49 | "color-name": "1.1.4", 50 | "eslint": "8.25.0", 51 | "less": "4.1.3", 52 | "raw-loader": "1.0.0", 53 | "@babel/runtime": "7.19.4" 54 | }, 55 | "browserslist": [ 56 | "ie >= 11", 57 | "last 2 version" 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /elements/logoSuperTest/ci/phpcs.phar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/logoSuperTest/ci/phpcs.phar -------------------------------------------------------------------------------- /elements/logoSuperTest/ci/ruleset.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | A custom coding standard 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | ./visualcomposer/Requirements.php 63 | 64 | 65 | ./visualcomposer/Requirements.php 66 | 67 | 68 | ./visualcomposer/resources/* 69 | 70 | 71 | ./visualcomposer/resources/* 72 | 73 | 74 | ./visualcomposer/resources/* 75 | 76 | 77 | ./visualcomposer 78 | ./bootstrap 79 | ./plugin-wordpress.php 80 | 81 | ./plugin-wordpress.php 82 | 83 | 84 | 85 | tests/* 86 | vendor/* 87 | 88 | 89 | -------------------------------------------------------------------------------- /elements/logoSuperTest/logoSuperTest/LogoSuperTestShortcodes.php: -------------------------------------------------------------------------------- 1 | addEvent('vcv:inited', 'registerShortcode'); 27 | $this->addFilter('vcv:editor:variables vcv:editor:variables/logoSuperTest', 'getVariables'); 28 | define('VCV_LOGO_SUPER_TEST_WIDGET_SHORTCODE', true); 29 | } 30 | } 31 | 32 | /** 33 | * Register Shortcode 34 | */ 35 | protected function registerShortcode() 36 | { 37 | $this->addShortcode('vcv_logo', 'renderLogo'); 38 | } 39 | 40 | protected function getVariables($variables) 41 | { 42 | if (has_custom_logo()) { 43 | $value = get_custom_logo(); 44 | $variables[] = [ 45 | 'key' => 'vcvLogo', 46 | 'value' => $value, 47 | 'type' => 'variable', 48 | ]; 49 | } 50 | 51 | return $variables; 52 | } 53 | 54 | /** 55 | * @param $atts 56 | * @param $content 57 | * @param $tag 58 | * 59 | * @return string 60 | */ 61 | protected function renderLogo($atts, $content, $tag) 62 | { 63 | if (has_custom_logo()) { 64 | if (isset($atts) && isset($atts['size'])) { 65 | $this->sizes = explode('x', $atts['size']); 66 | $this->customLogoId = get_theme_mod('custom_logo'); 67 | if (intval($this->sizes[0]) && intval($this->sizes[1])) { 68 | $this->wpAddFilter( 69 | 'wp_get_attachment_image_src', 70 | function ($image, $attachmentId, $size, $icon) { 71 | if ($attachmentId === $this->customLogoId) { 72 | $image[1] = intval($this->sizes[0]); 73 | $image[2] = intval($this->sizes[1]); 74 | } 75 | 76 | return $image; 77 | } 78 | ); 79 | $this->wpAddFilter( 80 | 'wp_get_attachment_image_attributes', 81 | function ($attr, $attachment, $size) { 82 | if ($attachment->ID === $this->customLogoId) { 83 | $attr['width'] = $this->sizes[0]; 84 | $attr['height'] = $this->sizes[1]; 85 | $attr['sizes'] = '(max-width: ' . $this->sizes[0] . 'px) 100vw, ' . $this->sizes[0] 86 | . 'px'; 87 | } 88 | 89 | return $attr; 90 | } 91 | ); 92 | } 93 | } 94 | $html = get_custom_logo(); 95 | 96 | return $html; 97 | } else { 98 | return ''; 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /elements/logoSuperTest/logoSuperTest/component.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { getService } from 'vc-cake' 3 | import classNames from 'classnames' 4 | 5 | const vcvAPI = getService('api') 6 | 7 | export default class LogoSuperTest extends vcvAPI.elementComponent { 8 | constructor (props) { 9 | super(props) 10 | this.state = { 11 | logo: window.vcvLogo || '' 12 | } 13 | } 14 | 15 | getLogo () { 16 | return ( 17 |
18 | ) 19 | } 20 | 21 | render () { 22 | const { id, atts, editor } = this.props 23 | const { size, alignment, customClass, metaCustomId } = atts 24 | let containerClasses = [] 25 | let elementClasses = [ 'vce', 'vce-logo-widget' ] 26 | let containerStyle = {} 27 | let customProps = {} 28 | 29 | const Sizes = window.vcvImageSizes ? window.vcvImageSizes : { 30 | humbnail: { width: 150 }, 31 | medium: { width: 300 }, 32 | large: { width: 1024 } 33 | } 34 | 35 | if (Sizes[ size ] && Sizes[ size ].width) { 36 | containerStyle.width = `${Sizes[ size ].width}px` 37 | } else { 38 | let sizeMatch = size.match(/\d+x\d+$/g) 39 | if (sizeMatch && sizeMatch.length === 1) { 40 | let sizes = sizeMatch[0].split('x') 41 | containerStyle.width = `${sizes[0]}px` 42 | containerStyle.height = `${sizes[1]}px` 43 | } else { 44 | containerStyle.width = '' 45 | containerStyle.height = '' 46 | } 47 | } 48 | 49 | if (alignment) { 50 | containerClasses.push(`vce-logo-widget--align-${alignment}`) 51 | } 52 | 53 | if (typeof customClass === 'string' && customClass) { 54 | containerClasses.push(customClass) 55 | } 56 | 57 | containerClasses = classNames(containerClasses) 58 | elementClasses = classNames(elementClasses) 59 | 60 | if (metaCustomId) { 61 | customProps.id = metaCustomId 62 | } 63 | 64 | const doAll = this.applyDO('all') 65 | 66 | return ( 67 |
68 |
69 | This is test logo: {this.getLogo()} 70 |
71 |
72 | ) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /elements/logoSuperTest/logoSuperTest/editor.css: -------------------------------------------------------------------------------- 1 | .vce-logo-widget { 2 | min-height: 1em; 3 | } 4 | 5 | .vce-logo-widget vcvhelper, .vce-logo-widget .vcvhelper { 6 | height: 100%; 7 | border: 1px dotted #aaa; 8 | } -------------------------------------------------------------------------------- /elements/logoSuperTest/logoSuperTest/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-webpack-loader-syntax */ 2 | import { getService } from 'vc-cake' 3 | import LogoSuperTest from './component' 4 | 5 | const vcvAddElement = getService('cook').add 6 | 7 | vcvAddElement( 8 | require('./settings.json'), 9 | // Component callback 10 | (component) => { 11 | component.add(LogoSuperTest) 12 | }, 13 | // css settings // css for element 14 | { 15 | 'css': require('raw-loader!./styles.css'), 16 | 'editorCss': require('raw-loader!./editor.css'), 17 | 'mixins': {} 18 | } 19 | ) 20 | -------------------------------------------------------------------------------- /elements/logoSuperTest/logoSuperTest/public/logo-element-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/logoSuperTest/logoSuperTest/public/logo-element-preview.png -------------------------------------------------------------------------------- /elements/logoSuperTest/logoSuperTest/public/logo-element-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/logoSuperTest/logoSuperTest/public/logo-element-thumbnail.png -------------------------------------------------------------------------------- /elements/logoSuperTest/logoSuperTest/public/src/init.less: -------------------------------------------------------------------------------- 1 | @import "styles"; 2 | -------------------------------------------------------------------------------- /elements/logoSuperTest/logoSuperTest/public/src/styles.less: -------------------------------------------------------------------------------- 1 | .vce-logo-widget { 2 | display: inline-block; 3 | width: 100%; 4 | max-width: 100%; 5 | overflow: hidden; 6 | 7 | &--align-left { 8 | text-align: left; 9 | } 10 | 11 | &--align-center { 12 | text-align: center; 13 | } 14 | 15 | &--align-right { 16 | text-align: right; 17 | } 18 | 19 | .custom-logo-link { 20 | padding-right: 0; 21 | box-shadow: none; 22 | 23 | img { 24 | box-shadow: none; 25 | } 26 | } 27 | 28 | img { 29 | max-height: 100%; 30 | max-width: 100%; 31 | box-shadow: none; 32 | height: auto; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /elements/logoSuperTest/logoSuperTest/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "size": { 3 | "type": "string", 4 | "access": "public", 5 | "value": "full", 6 | "options": { 7 | "label": "Size", 8 | "description": "Enter image size (Example: 'thumbnail', 'medium', 'large', 'full' or other sizes defined by theme). Alternatively enter size in pixels (Example: 200x100 (Width x Height))." 9 | } 10 | }, 11 | "alignment": { 12 | "type": "buttonGroup", 13 | "access": "public", 14 | "value": "left", 15 | "options": { 16 | "label": "Alignment", 17 | "values": [ 18 | { 19 | "label": "Left", 20 | "value": "left", 21 | "icon": "vcv-ui-icon-attribute-alignment-left" 22 | }, 23 | { 24 | "label": "Center", 25 | "value": "center", 26 | "icon": "vcv-ui-icon-attribute-alignment-center" 27 | }, 28 | { 29 | "label": "Right", 30 | "value": "right", 31 | "icon": "vcv-ui-icon-attribute-alignment-right" 32 | } 33 | ] 34 | } 35 | }, 36 | "customClass": { 37 | "type": "string", 38 | "access": "public", 39 | "value": "", 40 | "options": { 41 | "label": "Extra class name", 42 | "description": "Add an extra class name to the element and refer to it from Custom CSS option." 43 | } 44 | }, 45 | "designOptions": { 46 | "type": "designOptions", 47 | "access": "public", 48 | "value": {}, 49 | "options": { 50 | "label": "Design Options" 51 | } 52 | }, 53 | "editFormTab1": { 54 | "type": "group", 55 | "access": "protected", 56 | "value": [ 57 | "size", 58 | "alignment", 59 | "metaCustomId", 60 | "customClass" 61 | ], 62 | "options": { 63 | "label": "General" 64 | } 65 | }, 66 | "metaEditFormTabs": { 67 | "type": "group", 68 | "access": "protected", 69 | "value": [ 70 | "editFormTab1", 71 | "designOptions" 72 | ] 73 | }, 74 | "relatedTo": { 75 | "type": "group", 76 | "access": "protected", 77 | "value": [ 78 | "General" 79 | ] 80 | }, 81 | "metaCustomId": { 82 | "type": "customId", 83 | "access": "public", 84 | "value": "", 85 | "options": { 86 | "label": "Element ID", 87 | "description": "Apply unique ID to element to link directly to it by using #your_id (for element ID use lowercase input only)." 88 | } 89 | }, 90 | "tag": { 91 | "access": "protected", 92 | "type": "string", 93 | "value": "logoSuperTest" 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /elements/logoSuperTest/logoSuperTest/styles.css: -------------------------------------------------------------------------------- 1 | .vce-logo-widget { 2 | display: inline-block; 3 | width: 100%; 4 | max-width: 100%; 5 | overflow: hidden; 6 | } 7 | .vce-logo-widget--align-left { 8 | text-align: left; 9 | } 10 | .vce-logo-widget--align-center { 11 | text-align: center; 12 | } 13 | .vce-logo-widget--align-right { 14 | text-align: right; 15 | } 16 | .vce-logo-widget .custom-logo-link { 17 | padding-right: 0; 18 | box-shadow: none; 19 | } 20 | .vce-logo-widget .custom-logo-link img { 21 | box-shadow: none; 22 | } 23 | .vce-logo-widget img { 24 | max-height: 100%; 25 | max-width: 100%; 26 | box-shadow: none; 27 | height: auto; 28 | } 29 | -------------------------------------------------------------------------------- /elements/logoSuperTest/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "elements": { 3 | "logoSuperTest": { 4 | "settings": { 5 | "name": "[Demo] Logo Element", 6 | "metaThumbnailUrl": "[publicPath]/logo-element-thumbnail.png", 7 | "metaPreviewUrl": "[publicPath]/logo-element-preview.png", 8 | "metaDescription": "Widget to display your site logo" 9 | }, 10 | "phpFiles": [ 11 | "LogoSuperTestShortcodes.php" 12 | ] 13 | } 14 | }, 15 | "categories": { 16 | "Misc": { 17 | "elements": [ 18 | "logoSuperTest" 19 | ] 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /elements/logoSuperTest/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vcwb", 3 | "version": "1.0.0-dev", 4 | "description": "Logo Super Test", 5 | "main": "index.php", 6 | "repository": { 7 | "type": "git", 8 | "url": "git@github.com:Visualcomposer/vcwb-demo-element-example-plugin.git" 9 | }, 10 | "author": "@visualcomposer", 11 | "license": "GPL-2.0+", 12 | "engines": { 13 | "node": ">=8", 14 | "npm": ">=5.8" 15 | }, 16 | "scripts": { 17 | "standard": "standard --version && standard", 18 | "build": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.js", 19 | "build-production": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.production.js", 20 | "watch": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.js --watch" 21 | }, 22 | "devDependencies": { 23 | "vc-webpack-vendors": "3.3.3" 24 | }, 25 | "babel": { 26 | "presets": [ 27 | "@babel/preset-env", 28 | "@babel/preset-react" 29 | ], 30 | "plugins": [ 31 | "@babel/plugin-transform-runtime", 32 | "@babel/plugin-proposal-class-properties" 33 | ] 34 | }, 35 | "standard": { 36 | "parser": "babel-eslint", 37 | "ignore": [ 38 | "public/dist/", 39 | "tests/", 40 | "**/public/js" 41 | ], 42 | "rules": { 43 | "jsx-quotes": [ 44 | 2, 45 | "prefer-single" 46 | ], 47 | "import/no-webpack-loader-syntax": "off" 48 | } 49 | }, 50 | "resolutions": { 51 | "core-js": "3.25.5", 52 | "postcss": "8.4.18", 53 | "css-loader": "6.7.1", 54 | "color-name": "1.1.4", 55 | "eslint": "8.25.0", 56 | "less": "4.1.3", 57 | "raw-loader": "1.0.0", 58 | "@babel/runtime": "7.19.4" 59 | }, 60 | "browserslist": [ 61 | "ie >= 11", 62 | "last 2 version" 63 | ] 64 | } 65 | -------------------------------------------------------------------------------- /elements/textTest/ci/phpcs.phar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/textTest/ci/phpcs.phar -------------------------------------------------------------------------------- /elements/textTest/ci/ruleset.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | A custom coding standard 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | ./visualcomposer/Requirements.php 63 | 64 | 65 | ./visualcomposer/Requirements.php 66 | 67 | 68 | ./visualcomposer/resources/* 69 | 70 | 71 | ./visualcomposer/resources/* 72 | 73 | 74 | ./visualcomposer/resources/* 75 | 76 | 77 | ./visualcomposer 78 | ./bootstrap 79 | ./plugin-wordpress.php 80 | 81 | ./plugin-wordpress.php 82 | 83 | 84 | 85 | tests/* 86 | vendor/* 87 | 88 | 89 | -------------------------------------------------------------------------------- /elements/textTest/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "elements": { 3 | "textTest": { 4 | "settings": { 5 | "name": "[Demo] Text Element", 6 | "metaThumbnailUrl": "[publicPath]/text-element-thumbnail.png", 7 | "metaPreviewUrl": "[publicPath]/text-element-preview.png", 8 | "metaDescription": "Simple text editor for working with static text, including paragraphs, titles, bullets and even media. Simple text block is a copy of default WordPress editor." 9 | } 10 | } 11 | }, 12 | "categories": { 13 | "Misc": { 14 | "elements": [ 15 | "textTest" 16 | ] 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /elements/textTest/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vcwb", 3 | "version": "1.0.0-dev", 4 | "description": "Test Text", 5 | "main": "index.php", 6 | "repository": { 7 | "type": "git", 8 | "url": "git@github.com:Visualcomposer/vcwb-demo-element-example-plugin.git" 9 | }, 10 | "author": "@visualcomposer", 11 | "license": "GPL-2.0+", 12 | "engines": { 13 | "node": ">=8", 14 | "npm": ">=5.8" 15 | }, 16 | "scripts": { 17 | "standard": "standard --version && standard", 18 | "build": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.js", 19 | "build-production": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.production.js", 20 | "watch": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.js --watch" 21 | }, 22 | "devDependencies": { 23 | "vc-webpack-vendors": "3.3.3" 24 | }, 25 | "babel": { 26 | "presets": [ 27 | "@babel/preset-env", 28 | "@babel/preset-react" 29 | ], 30 | "plugins": [ 31 | "@babel/plugin-transform-runtime", 32 | "@babel/plugin-proposal-class-properties" 33 | ] 34 | }, 35 | "standard": { 36 | "parser": "babel-eslint", 37 | "ignore": [ 38 | "public/dist/", 39 | "tests/", 40 | "**/public/js" 41 | ], 42 | "rules": { 43 | "jsx-quotes": [ 44 | 2, 45 | "prefer-single" 46 | ], 47 | "import/no-webpack-loader-syntax": "off" 48 | } 49 | }, 50 | "resolutions": { 51 | "core-js": "3.25.5", 52 | "postcss": "8.4.18", 53 | "css-loader": "6.7.1", 54 | "color-name": "1.1.4", 55 | "eslint": "8.25.0", 56 | "less": "4.1.3", 57 | "raw-loader": "1.0.0", 58 | "@babel/runtime": "7.19.4" 59 | }, 60 | "browserslist": [ 61 | "ie >= 11", 62 | "last 2 version" 63 | ] 64 | } 65 | -------------------------------------------------------------------------------- /elements/textTest/public/dist/element.bundle.js: -------------------------------------------------------------------------------- 1 | /* 2 | * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). 3 | * This devtool is neither made for production nor for readable output files. 4 | * It uses "eval()" calls to create a separate source file in the browser devtools. 5 | * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) 6 | * or disable the default devtool with "devtool: false". 7 | * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). 8 | */ 9 | (self["vcvWebpackJsonp4x"] = self["vcvWebpackJsonp4x"] || []).push([["element"],{ 10 | 11 | /***/ "./textTest/component.js": 12 | /*!*******************************!*\ 13 | !*** ./textTest/component.js ***! 14 | \*******************************/ 15 | /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { 16 | 17 | "use strict"; 18 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* binding */ TextTestElement; }\n/* harmony export */ });\n/* harmony import */ var _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/extends */ \"./node_modules/@babel/runtime/helpers/esm/extends.js\");\n/* harmony import */ var _babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @babel/runtime/helpers/classCallCheck */ \"./node_modules/@babel/runtime/helpers/esm/classCallCheck.js\");\n/* harmony import */ var _babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @babel/runtime/helpers/createClass */ \"./node_modules/@babel/runtime/helpers/esm/createClass.js\");\n/* harmony import */ var _babel_runtime_helpers_inherits__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @babel/runtime/helpers/inherits */ \"./node_modules/@babel/runtime/helpers/esm/inherits.js\");\n/* harmony import */ var _babel_runtime_helpers_possibleConstructorReturn__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @babel/runtime/helpers/possibleConstructorReturn */ \"./node_modules/@babel/runtime/helpers/esm/possibleConstructorReturn.js\");\n/* harmony import */ var _babel_runtime_helpers_getPrototypeOf__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @babel/runtime/helpers/getPrototypeOf */ \"./node_modules/@babel/runtime/helpers/esm/getPrototypeOf.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var vc_cake__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! vc-cake */ \"./node_modules/vc-cake/index.js\");\n/* harmony import */ var vc_cake__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(vc_cake__WEBPACK_IMPORTED_MODULE_7__);\n\n\n\n\n\n\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0,_babel_runtime_helpers_getPrototypeOf__WEBPACK_IMPORTED_MODULE_5__[\"default\"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0,_babel_runtime_helpers_getPrototypeOf__WEBPACK_IMPORTED_MODULE_5__[\"default\"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0,_babel_runtime_helpers_possibleConstructorReturn__WEBPACK_IMPORTED_MODULE_4__[\"default\"])(this, result); }; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\n\n\nvar vcvAPI = (0,vc_cake__WEBPACK_IMPORTED_MODULE_7__.getService)('api');\n\nvar TextTestElement = /*#__PURE__*/function (_vcvAPI$elementCompon) {\n (0,_babel_runtime_helpers_inherits__WEBPACK_IMPORTED_MODULE_3__[\"default\"])(TextTestElement, _vcvAPI$elementCompon);\n\n var _super = _createSuper(TextTestElement);\n\n function TextTestElement() {\n (0,_babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(this, TextTestElement);\n\n return _super.apply(this, arguments);\n }\n\n (0,_babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(TextTestElement, [{\n key: \"render\",\n value: function render() {\n var _this$props = this.props,\n id = _this$props.id,\n atts = _this$props.atts,\n editor = _this$props.editor;\n var output = atts.output,\n customClass = atts.customClass,\n metaCustomId = atts.metaCustomId; // destructuring assignment for attributes from settings.json with access public\n\n var textBlockClasses = 'vce-text-test-block';\n var wrapperClasses = 'vce-text-block-test-wrapper vce';\n var customProps = {};\n\n if (typeof customClass === 'string' && customClass) {\n textBlockClasses = textBlockClasses.concat(' ' + customClass);\n }\n\n if (metaCustomId) {\n customProps.id = metaCustomId;\n }\n\n var doAll = this.applyDO('all');\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_6__.createElement(\"div\", (0,_babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({\n className: textBlockClasses\n }, editor, customProps), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_6__.createElement(\"div\", (0,_babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({\n className: wrapperClasses,\n id: 'el-' + id\n }, doAll), output));\n }\n }]);\n\n return TextTestElement;\n}(vcvAPI.elementComponent);\n\n\n\n//# sourceURL=webpack://vcwb/./textTest/component.js?"); 19 | 20 | /***/ }), 21 | 22 | /***/ "./textTest/index.js": 23 | /*!***************************!*\ 24 | !*** ./textTest/index.js ***! 25 | \***************************/ 26 | /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { 27 | 28 | "use strict"; 29 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vc_cake__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vc-cake */ \"./node_modules/vc-cake/index.js\");\n/* harmony import */ var vc_cake__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(vc_cake__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./component */ \"./textTest/component.js\");\n/* eslint-disable import/no-webpack-loader-syntax */\n\n\nvar vcvAddElement = (0,vc_cake__WEBPACK_IMPORTED_MODULE_0__.getService)('cook').add;\nvcvAddElement(__webpack_require__(/*! ./settings.json */ \"./textTest/settings.json\"), // Component callback\nfunction (component) {\n component.add(_component__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n}, // css settings // css for element\n{\n css: false,\n editorCss: __webpack_require__(/*! raw-loader!./editor.css */ \"./node_modules/raw-loader/index.js!./textTest/editor.css\")\n});\n\n//# sourceURL=webpack://vcwb/./textTest/index.js?"); 30 | 31 | /***/ }), 32 | 33 | /***/ "./node_modules/raw-loader/index.js!./textTest/editor.css": 34 | /*!****************************************************************!*\ 35 | !*** ./node_modules/raw-loader/index.js!./textTest/editor.css ***! 36 | \****************************************************************/ 37 | /***/ (function(module) { 38 | 39 | eval("module.exports = \".vce-text-block {\\n min-height: 1em;\\n}\\n\"\n\n//# sourceURL=webpack://vcwb/./textTest/editor.css?./node_modules/raw-loader/index.js"); 40 | 41 | /***/ }), 42 | 43 | /***/ "./textTest/settings.json": 44 | /*!********************************!*\ 45 | !*** ./textTest/settings.json ***! 46 | \********************************/ 47 | /***/ (function(module) { 48 | 49 | "use strict"; 50 | eval("module.exports = JSON.parse('{\"output\":{\"type\":\"htmleditor\",\"access\":\"public\",\"value\":\"

Testing Elements API. HTML editor also the part of the editor

\",\"options\":{\"label\":\"Content\",\"description\":\"Content for text block\",\"inline\":true,\"skinToggle\":\"darkTextSkin\"}},\"darkTextSkin\":{\"type\":\"toggleSmall\",\"access\":\"public\",\"value\":false},\"designOptions\":{\"type\":\"designOptions\",\"access\":\"public\",\"value\":{},\"options\":{\"label\":\"Design Options\"}},\"editFormTab1\":{\"type\":\"group\",\"access\":\"protected\",\"value\":[\"output\",\"metaCustomId\",\"customClass\"],\"options\":{\"label\":\"General\"}},\"metaEditFormTabs\":{\"type\":\"group\",\"access\":\"protected\",\"value\":[\"editFormTab1\",\"designOptions\"]},\"relatedTo\":{\"type\":\"group\",\"access\":\"protected\",\"value\":[\"General\"]},\"customClass\":{\"type\":\"string\",\"access\":\"public\",\"value\":\"\",\"options\":{\"label\":\"Extra class name\",\"description\":\"Add an extra class name to the element and refer to it from Custom CSS option.\"}},\"metaCustomId\":{\"type\":\"customId\",\"access\":\"public\",\"value\":\"\",\"options\":{\"label\":\"Element ID\",\"description\":\"Apply unique ID to element to link directly to it by using #your_id (for element ID use lowercase input only).\"}},\"tag\":{\"access\":\"protected\",\"type\":\"string\",\"value\":\"textTest\"}}');\n\n//# sourceURL=webpack://vcwb/./textTest/settings.json?"); 51 | 52 | /***/ }) 53 | 54 | },[['./textTest/index.js']]]); -------------------------------------------------------------------------------- /elements/textTest/textTest/component.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { getService } from 'vc-cake' 3 | const vcvAPI = getService('api') 4 | 5 | export default class TextTestElement extends vcvAPI.elementComponent { 6 | render () { 7 | const { id, atts, editor } = this.props 8 | const { output, customClass, metaCustomId } = atts // destructuring assignment for attributes from settings.json with access public 9 | let textBlockClasses = 'vce-text-test-block' 10 | const wrapperClasses = 'vce-text-block-test-wrapper vce' 11 | const customProps = {} 12 | if (typeof customClass === 'string' && customClass) { 13 | textBlockClasses = textBlockClasses.concat(' ' + customClass) 14 | } 15 | 16 | if (metaCustomId) { 17 | customProps.id = metaCustomId 18 | } 19 | 20 | const doAll = this.applyDO('all') 21 | 22 | return ( 23 |
24 |
25 | {output} 26 |
27 |
28 | ) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /elements/textTest/textTest/editor.css: -------------------------------------------------------------------------------- 1 | .vce-text-block { 2 | min-height: 1em; 3 | } 4 | -------------------------------------------------------------------------------- /elements/textTest/textTest/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-webpack-loader-syntax */ 2 | import { getService } from 'vc-cake' 3 | import TextTestElement from './component' 4 | 5 | const vcvAddElement = getService('cook').add 6 | 7 | vcvAddElement( 8 | require('./settings.json'), 9 | // Component callback 10 | function (component) { 11 | component.add(TextTestElement) 12 | }, 13 | // css settings // css for element 14 | { 15 | css: false, 16 | editorCss: require('raw-loader!./editor.css') 17 | } 18 | ) 19 | -------------------------------------------------------------------------------- /elements/textTest/textTest/public/text-element-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/textTest/textTest/public/text-element-preview.png -------------------------------------------------------------------------------- /elements/textTest/textTest/public/text-element-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/textTest/textTest/public/text-element-thumbnail.png -------------------------------------------------------------------------------- /elements/textTest/textTest/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "output": { 3 | "type": "htmleditor", 4 | "access": "public", 5 | "value": "

Testing Elements API. HTML editor also the part of the editor

", 6 | "options": { 7 | "label": "Content", 8 | "description": "Content for text block", 9 | "inline": true, 10 | "skinToggle": "darkTextSkin" 11 | } 12 | }, 13 | "darkTextSkin": { 14 | "type": "toggleSmall", 15 | "access": "public", 16 | "value": false 17 | }, 18 | "designOptions": { 19 | "type": "designOptions", 20 | "access": "public", 21 | "value": {}, 22 | "options": { 23 | "label": "Design Options" 24 | } 25 | }, 26 | "editFormTab1": { 27 | "type": "group", 28 | "access": "protected", 29 | "value": [ 30 | "output", 31 | "metaCustomId", 32 | "customClass" 33 | ], 34 | "options": { 35 | "label": "General" 36 | } 37 | }, 38 | "metaEditFormTabs": { 39 | "type": "group", 40 | "access": "protected", 41 | "value": [ 42 | "editFormTab1", 43 | "designOptions" 44 | ] 45 | }, 46 | "relatedTo": { 47 | "type": "group", 48 | "access": "protected", 49 | "value": [ 50 | "General" 51 | ] 52 | }, 53 | "customClass": { 54 | "type": "string", 55 | "access": "public", 56 | "value": "", 57 | "options": { 58 | "label": "Extra class name", 59 | "description": "Add an extra class name to the element and refer to it from Custom CSS option." 60 | } 61 | }, 62 | "metaCustomId": { 63 | "type": "customId", 64 | "access": "public", 65 | "value": "", 66 | "options": { 67 | "label": "Element ID", 68 | "description": "Apply unique ID to element to link directly to it by using #your_id (for element ID use lowercase input only)." 69 | } 70 | }, 71 | "tag": { 72 | "access": "protected", 73 | "type": "string", 74 | "value": "textTest" 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /elements/verticalChart/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "elements": { 3 | "verticalChart": { 4 | "settings": { 5 | "name": "[Demo] Vertical Chart", 6 | "metaThumbnailUrl": "[publicPath]/vertical-chart-thumbnail.png", 7 | "metaPreviewUrl": "[publicPath]/vertical-chart-preview.png", 8 | "metaDescription": "A chart that shows vertical columns with percentage values." 9 | } 10 | } 11 | }, 12 | "categories": { 13 | "Charts": { 14 | "elements": [ 15 | "verticalChart" 16 | ] 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /elements/verticalChart/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vcwb", 3 | "version": "dev", 4 | "license": "SEE LICENSE IN ", 5 | "description": "Visual Composer Website Builder", 6 | "main": "index.php", 7 | "repository": { 8 | "type": "git", 9 | "url": "git@github.com:Visualcomposer/builder.git" 10 | }, 11 | "scripts": { 12 | "standard": "standard --version && standard", 13 | "build": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.js", 14 | "build-production": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.production.js", 15 | "watch": "webpack --version && webpack --config=./node_modules/vc-webpack-vendors/webpack.config.js --watch" 16 | }, 17 | "devDependencies": { 18 | "vc-webpack-vendors": "3.3.3" 19 | }, 20 | "babel": { 21 | "presets": [ 22 | "@babel/preset-env", 23 | "@babel/preset-react" 24 | ], 25 | "plugins": [ 26 | "@babel/plugin-transform-runtime", 27 | "@babel/plugin-proposal-class-properties" 28 | ] 29 | }, 30 | "standard": { 31 | "parser": "babel-eslint", 32 | "ignore": [ 33 | "public/dist/", 34 | "tests/", 35 | "**/public/js" 36 | ], 37 | "rules": { 38 | "jsx-quotes": [ 39 | 2, 40 | "prefer-single" 41 | ], 42 | "import/no-webpack-loader-syntax": "off" 43 | } 44 | }, 45 | "resolutions": { 46 | "core-js": "3.25.5", 47 | "postcss": "8.4.18", 48 | "css-loader": "6.7.1", 49 | "color-name": "1.1.4", 50 | "eslint": "8.25.0", 51 | "less": "4.1.3", 52 | "raw-loader": "1.0.0", 53 | "@babel/runtime": "7.19.4" 54 | }, 55 | "browserslist": [ 56 | "ie >= 11", 57 | "last 2 version" 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /elements/verticalChart/verticalChart/bar.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import classNames from 'classnames' 3 | 4 | export default class Bar extends React.Component { 5 | render () { 6 | const { colorType, getMixin, itemIndex } = this.props 7 | const { title, value } = this.props.atts 8 | let containerClasses = ['vce-bar-container'] 9 | const titleProps = {} 10 | titleProps.style = {} 11 | const valueProps = {} 12 | valueProps.style = {} 13 | const customProps = {} 14 | 15 | let mixin = getMixin('barValue', itemIndex) 16 | if (mixin) { 17 | containerClasses.push(`vce-bar--value-${mixin.selector}`) 18 | } 19 | 20 | mixin = getMixin('barColor', itemIndex) 21 | if (mixin) { 22 | const colorClass = `vce-bar--${colorType}-${mixin.selector}` 23 | containerClasses.push(colorClass) 24 | } 25 | 26 | mixin = getMixin('barBackgroundColor', itemIndex) 27 | if (mixin) { 28 | containerClasses.push(`vce-bar--background-color-${mixin.selector}`) 29 | } 30 | 31 | containerClasses = classNames(containerClasses) 32 | 33 | customProps['data-vce-count-up-end-value'] = value || 0 34 | customProps['data-vce-count-up-start-value'] = 0 35 | customProps['data-vce-count-up-grouping'] = false 36 | customProps['data-vce-count-up-duration'] = 1 37 | customProps['data-vce-count-up-easing'] = false 38 | 39 | return ( 40 |
41 | 42 | 0% 43 | 44 |
45 | {value} % 46 |
47 |
48 |

{title}

49 |
50 |
51 | ) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /elements/verticalChart/verticalChart/component.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { getService } from 'vc-cake' 3 | import classNames from 'classnames' 4 | import { renderToStaticMarkup } from 'react-dom/server' 5 | 6 | // Import Bar component for each chart bar (column) 7 | // Attributes for each bar are taken from paramsGroup attribute type in settings.json 8 | import Bar from './bar' 9 | 10 | const vcvAPI = getService('api') 11 | 12 | export default class VerticalChart extends vcvAPI.elementComponent { 13 | // Generate an array of JSX with chart vertical bars (columns) 14 | getContent () { 15 | const { bars } = this.props.atts 16 | 17 | const items = bars.value ? bars.value : bars 18 | return items.map((item, i) => { 19 | const key = `bar-${this.props.id}-${i}` 20 | const attributes = item 21 | attributes.atts = {} 22 | attributes.atts.tag = this.props.atts.tag 23 | attributes.atts.title = item.title 24 | attributes.atts.value = item.value 25 | attributes.itemIndex = i 26 | attributes.getMixin = this.getInnerMixinData.bind(this, 'bars') 27 | return 28 | }) 29 | } 30 | 31 | render () { 32 | const { id, atts, editor } = this.props 33 | const { toggleValue, customClass, metaCustomId } = atts 34 | let containerClasses = ['vce', 'vce-vertical-charts-container'] 35 | const customProps = {} 36 | 37 | if (typeof customClass === 'string' && customClass) { 38 | containerClasses.push(customClass) 39 | } 40 | 41 | if (metaCustomId) { 42 | customProps.id = metaCustomId 43 | } 44 | 45 | if (toggleValue) { 46 | containerClasses.push('vce-vertical-chart-display-value') 47 | } 48 | 49 | let mixinData = this.getMixinData('barThickness') 50 | if (mixinData) { 51 | containerClasses.push(`vce-vertical-chart-thickness--${mixinData.selector}`) 52 | } 53 | 54 | mixinData = this.getMixinData('titleColor') 55 | if (mixinData) { 56 | containerClasses.push(`vce-vertical-chart-title-color--${mixinData.selector}`) 57 | } 58 | 59 | containerClasses = classNames(containerClasses) 60 | 61 | const doAll = this.applyDO('all') 62 | const content = this.getContent() 63 | 64 | // Content is saved as a String with raw HTML 65 | const barsHTML = renderToStaticMarkup(content) 66 | 67 | // Need to use wrapper with .vcvhelper to save raw HTML string in data attribute for View Page 68 | return ( 69 |
70 |
71 |
72 | {content} 73 |
74 |
75 |
76 | ) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /elements/verticalChart/verticalChart/cssMixins/barBackgroundColor.pcss: -------------------------------------------------------------------------------- 1 | .vce-bar--background-color-$selector { 2 | .vce-bar-wrapper::before { 3 | background-color: $backgroundColor; 4 | } 5 | } -------------------------------------------------------------------------------- /elements/verticalChart/verticalChart/cssMixins/barThickness.pcss: -------------------------------------------------------------------------------- 1 | .vce-vertical-chart-thickness--$selector { 2 | .vce-bar-wrapper { 3 | width: $(thickness)px; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /elements/verticalChart/verticalChart/cssMixins/barValue.pcss: -------------------------------------------------------------------------------- 1 | .vce-bar--value-$selector { 2 | .vce-bar-play-animation.vce-bar-wrapper::before { 3 | height: $(value)%; 4 | animation: vcv-fill-animation-$selector 1s ease-in-out forwards; 5 | } 6 | } 7 | 8 | @keyframes vcv-fill-animation-$selector { 9 | $step: resolve(100 / $value); 10 | @for $count from 0 to $(value) by 1 { 11 | $percentages: resolve($step * $count); 12 | 13 | $(percentages)% { 14 | height: $(count)%; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /elements/verticalChart/verticalChart/editor.css: -------------------------------------------------------------------------------- 1 | .vce-vertical-chart { 2 | min-height: 1em; 3 | } -------------------------------------------------------------------------------- /elements/verticalChart/verticalChart/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-webpack-loader-syntax */ 2 | import vcCake from 'vc-cake' 3 | import VerticalChart from './component' 4 | 5 | const vcvAddElement = vcCake.getService('cook').add 6 | 7 | vcvAddElement( 8 | require('./settings.json'), 9 | // Component callback 10 | (component) => { 11 | component.add(VerticalChart) 12 | }, 13 | // css settings // css for element 14 | { 15 | css: require('raw-loader!./styles.css'), 16 | editorCss: require('raw-loader!./editor.css'), 17 | mixins: { 18 | barThickness: { 19 | mixin: require('raw-loader!./cssMixins/barThickness.pcss') 20 | }, 21 | barValue: { 22 | mixin: require('raw-loader!./cssMixins/barValue.pcss') 23 | }, 24 | barBackgroundColor: { 25 | mixin: require('raw-loader!./cssMixins/barBackgroundColor.pcss') 26 | } 27 | } 28 | } 29 | ) 30 | -------------------------------------------------------------------------------- /elements/verticalChart/verticalChart/public/dist/countUpStarter.min.js: -------------------------------------------------------------------------------- 1 | !function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=0)}([function(e,t,r){e.exports=r(1)},function(e,t){!function(e){var t;this.Element&&((t=Element.prototype).closest=t.closest||function(e){for(var t=this;t.matches&&!t.matches(e);)t=t.parentNode;return t.matches?t:null});var r=function(t,r,n){var o=r.vcvWaypoints;o&&o.destroy();var a=new e.Waypoint({element:r,handler:function(r,o,u,i,c){t.error?console.error(t.error):(t.start(),function(t){if(t.closest(".vcvhelper")){t.classList.contains("vce-bar-play-animation")&&t.classList.remove("vce-bar-play-animation");var r=setTimeout((function(){t.classList.add("vce-bar-play-animation"),e.clearTimeout(r)}),1)}else t.classList.add("vce-bar-play-animation")}(n)),a.destroy()},offset:"95%"});r.vcvWaypoints=a};e.vcv.on("ready",(function(t,n,o){if(!("merge"===t||o&&o.changedAttribute&&["designOptions","customClass","metaCustomId"].indexOf(o.changedAttribute)>-1)){var a=t?100:10;e.vcCountUp?setTimeout((function(){[].slice.call(document.querySelectorAll(".vce-bar-container")).forEach((function(t){var n=t.getAttribute("data-vce-count-up-start-value"),o=t.getAttribute("data-vce-count-up-end-value"),a="true"===t.getAttribute("data-vce-count-up-grouping"),u=t.getAttribute("data-vce-count-up-separator"),i=parseFloat(t.getAttribute("data-vce-count-up-duration")),c="true"===t.getAttribute("data-vce-count-up-easing"),s=o.split(".")[1]?o.split(".")[1].length:0,l=t.querySelector(".vce-bar-value-result"),p=t.querySelector(".vce-bar-wrapper"),f={useEasing:c,useGrouping:a,separator:u,decimal:".",prefix:"",suffix:""},v=new e.vcCountUp(l,parseFloat(n),parseFloat(o),s,i,f);r(v,l,p)}))}),a):console.error("countUp library is not enqueued")}}))}(window)}]); -------------------------------------------------------------------------------- /elements/verticalChart/verticalChart/public/js/countUpStarter.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // Script to animate Vertical Chart bars both in Visual Composer editor 4 | // and on View Page, this file is minified and located in the dist folder. 5 | // Minified version of this file is included in settings.json under metaPublicJs property. 6 | 7 | // To minify this file inside verticalChart/public folder a webpack.config.js file should be created 8 | // next inside terminal enter verticalChart/public folder and run: 9 | // ../../node_modules/.bin/webpack --config=webpack.config.js -p 10 | 11 | (function (window) { 12 | // Polyfill for Element.closest() method 13 | this.Element && function(ElementPrototype) { 14 | ElementPrototype.closest = ElementPrototype.closest || 15 | function(selector) { 16 | var el = this; 17 | while (el.matches && !el.matches(selector)) el = el.parentNode; 18 | return el.matches ? el : null; 19 | } 20 | }(Element.prototype); 21 | 22 | var startBarAnimation = function (element) { 23 | if (element.closest('.vcvhelper')) { 24 | if (element.classList.contains('vce-bar-play-animation')) { 25 | element.classList.remove('vce-bar-play-animation') 26 | } 27 | var timeout = setTimeout(function() { 28 | element.classList.add('vce-bar-play-animation') 29 | window.clearTimeout(timeout) 30 | }, 1) 31 | } else { 32 | element.classList.add('vce-bar-play-animation') 33 | } 34 | } 35 | var startCountUp = function (countUp, valueElement, barElement) { 36 | var previousElementWaypoints = valueElement.vcvWaypoints 37 | if (previousElementWaypoints) { 38 | previousElementWaypoints.destroy() 39 | } 40 | var waypointObj = new window.Waypoint({ 41 | element: valueElement, 42 | handler: function (a, b, c, d, e) { 43 | if (!countUp.error) { 44 | countUp.start(); 45 | startBarAnimation(barElement); 46 | } else { 47 | console.error(countUp.error); 48 | } 49 | waypointObj.destroy() 50 | }, 51 | offset: '95%' 52 | }) 53 | valueElement.vcvWaypoints = waypointObj 54 | } 55 | 56 | var enableCountUp = function () { 57 | var counters = []; 58 | 59 | counters = [].slice.call(document.querySelectorAll('.vce-bar-container')); 60 | 61 | counters.forEach(function(countUpElement) { 62 | var startValue = countUpElement.getAttribute('data-vce-count-up-start-value'); 63 | var endValue = countUpElement.getAttribute('data-vce-count-up-end-value'); 64 | var useGrouping = countUpElement.getAttribute('data-vce-count-up-grouping') === 'true'; 65 | var separator = countUpElement.getAttribute('data-vce-count-up-separator'); 66 | var duration = parseFloat(countUpElement.getAttribute('data-vce-count-up-duration')); 67 | var useEasing = countUpElement.getAttribute('data-vce-count-up-easing') === 'true'; 68 | var decimalCount = endValue.split('.')[ 1 ] ? endValue.split('.')[ 1 ].length : 0; 69 | var countUpResult = countUpElement.querySelector('.vce-bar-value-result'); 70 | var countUpBar = countUpElement.querySelector('.vce-bar-wrapper'); 71 | 72 | var options = { 73 | useEasing: useEasing, 74 | useGrouping: useGrouping, 75 | separator: separator, 76 | decimal: '.', 77 | prefix: '', 78 | suffix: '' 79 | }; 80 | var countUp = new window.vcCountUp(countUpResult, parseFloat(startValue), parseFloat(endValue), decimalCount, duration, options); 81 | startCountUp(countUp, countUpResult, countUpBar); 82 | }); 83 | } 84 | 85 | // window.vcv.on('ready', function () {}) is a global event listener 86 | // it is triggered each time element is added to the page or gets edited (in VC editor) 87 | window.vcv.on('ready', function (action, id, options) { 88 | var skipAttributes = ['designOptions', 'customClass', 'metaCustomId']; 89 | var skipCounter = action === 'merge' || (options && options.changedAttribute && (skipAttributes.indexOf(options.changedAttribute) > -1)); 90 | 91 | if (!skipCounter) { 92 | // Delay for editor 93 | var delay = action ? 100 : 10; 94 | 95 | // window.vcCountUp is a global variable available upon countUp library enqueue 96 | // it is included in settings.json under sharedAssetsLibrary property alond with waypoints library 97 | if (window.vcCountUp) { 98 | setTimeout(function () { 99 | enableCountUp(); 100 | }, delay); 101 | } else { 102 | console.error('countUp library is not enqueued'); 103 | } 104 | } 105 | }); 106 | }(window)); 107 | /* eslint-enable */ 108 | -------------------------------------------------------------------------------- /elements/verticalChart/verticalChart/public/vertical-chart-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/verticalChart/verticalChart/public/vertical-chart-preview.png -------------------------------------------------------------------------------- /elements/verticalChart/verticalChart/public/vertical-chart-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComposer/vcwb-demo-element-example-plugin/aa1bd6f392f4d26e620249c0c2f6edc3aa3ee452/elements/verticalChart/verticalChart/public/vertical-chart-thumbnail.png -------------------------------------------------------------------------------- /elements/verticalChart/verticalChart/public/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: { 3 | 'countUpStarter': [ './js/countUpStarter.js' ] 4 | }, 5 | output: { 6 | filename: '[name].min.js' 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /elements/verticalChart/verticalChart/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "tag": { 3 | "access": "protected", 4 | "type": "string", 5 | "value": "verticalChart" 6 | }, 7 | "relatedTo": { 8 | "type": "group", 9 | "access": "protected", 10 | "value": [ 11 | "General" 12 | ] 13 | }, 14 | "thickness": { 15 | "type": "number", 16 | "access": "public", 17 | "value": "20", 18 | "options": { 19 | "label": "Thickness", 20 | "description": "Enter chart bar thickness in pixels.", 21 | "cssMixin": { 22 | "mixin": "barThickness", 23 | "property": "thickness", 24 | "namePattern": "[\\da-f]+" 25 | }, 26 | "min": 1 27 | } 28 | }, 29 | "toggleValue": { 30 | "type": "toggle", 31 | "access": "public", 32 | "value": true, 33 | "options": { 34 | "label": "Show value", 35 | "description": "Option to disable percentage display" 36 | } 37 | }, 38 | "bars": { 39 | "type": "paramsGroup", 40 | "access": "public", 41 | "value": { 42 | "value": [ 43 | { 44 | "title": "HTML", 45 | "value": 90, 46 | "backgroundColor": "#C45959" 47 | }, 48 | { 49 | "title": "CSS", 50 | "value": 80, 51 | "backgroundColor": "#C45959" 52 | }, 53 | { 54 | "title": "JavaScript", 55 | "value": 75, 56 | "backgroundColor": "#C45959" 57 | } 58 | ] 59 | }, 60 | "options": { 61 | "label": "General", 62 | "title": "Chart bar", 63 | "groupDefaultTile": "Chart bar", 64 | "settings": { 65 | "title": { 66 | "type": "string", 67 | "access": "public", 68 | "value": "Chart bar", 69 | "options": { 70 | "label": "Title", 71 | "dynamicField": true 72 | } 73 | }, 74 | "value": { 75 | "type": "range", 76 | "access": "public", 77 | "value": "70", 78 | "options": { 79 | "label": "Value", 80 | "cssMixin": { 81 | "mixin": "barValue", 82 | "property": "value", 83 | "namePattern": "[\\da-f]+" 84 | } 85 | } 86 | }, 87 | "backgroundColor": { 88 | "type": "color", 89 | "access": "public", 90 | "value": "#C45959", 91 | "options": { 92 | "label": "Background color", 93 | "cssMixin": { 94 | "mixin": "barBackgroundColor", 95 | "property": "backgroundColor", 96 | "namePattern": "[\\da-f]+" 97 | } 98 | } 99 | }, 100 | "_paramGroupEditFormTab1": { 101 | "type": "group", 102 | "access": "protected", 103 | "value": [ 104 | "title", 105 | "value", 106 | "backgroundColor" 107 | ], 108 | "options": { 109 | "label": "General" 110 | } 111 | }, 112 | "metaEditFormTabs": { 113 | "type": "group", 114 | "access": "protected", 115 | "value": [ 116 | "_paramGroupEditFormTab1" 117 | ] 118 | } 119 | } 120 | } 121 | }, 122 | "customClass": { 123 | "type": "string", 124 | "access": "public", 125 | "value": "", 126 | "options": { 127 | "label": "Extra class name", 128 | "description": "Add an extra class name to the element and refer to it from Custom CSS option." 129 | } 130 | }, 131 | "metaCustomId": { 132 | "type": "customId", 133 | "access": "public", 134 | "value": "", 135 | "options": { 136 | "label": "Element ID", 137 | "description": "Apply unique ID to element to link directly to it by using #your_id (for element ID use lowercase input only)." 138 | } 139 | }, 140 | "designOptions": { 141 | "type": "designOptions", 142 | "access": "public", 143 | "value": {}, 144 | "options": { 145 | "label": "Design Options" 146 | } 147 | }, 148 | "editFormTab1": { 149 | "type": "group", 150 | "access": "protected", 151 | "value": [ 152 | "thickness", 153 | "toggleValue", 154 | "bars", 155 | "metaCustomId", 156 | "customClass" 157 | ], 158 | "options": { 159 | "label": "General" 160 | } 161 | }, 162 | "metaEditFormTabs": { 163 | "type": "group", 164 | "access": "protected", 165 | "value": [ 166 | "editFormTab1", 167 | "designOptions" 168 | ] 169 | }, 170 | "sharedAssetsLibrary": { 171 | "access": "protected", 172 | "type": "string", 173 | "value": { 174 | "libraries": [ 175 | { 176 | "libsNames": [ 177 | "waypoints", 178 | "countUp" 179 | ] 180 | } 181 | ] 182 | } 183 | }, 184 | "metaPublicJs": { 185 | "access": "protected", 186 | "type": "string", 187 | "value": { 188 | "libraries": [ 189 | { 190 | "libPaths": "public/dist/countUpStarter.min.js" 191 | } 192 | ] 193 | } 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /elements/verticalChart/verticalChart/styles.css: -------------------------------------------------------------------------------- 1 | .vce-bar-container { 2 | display: inline-flex; 3 | flex-direction: column; 4 | align-items: center; 5 | margin: 0 15px 35px 0; 6 | } 7 | 8 | .vce-bar-container:last-of-type { 9 | margin-right: 0; 10 | } 11 | 12 | .vce-bar-wrapper { 13 | position: relative; 14 | background-color: #eee; 15 | overflow: hidden; 16 | height: 150px; 17 | margin: 0 0 10px; 18 | } 19 | 20 | .vce-bar-wrapper::before { 21 | content: ""; 22 | position: absolute; 23 | bottom: 0; 24 | left: 0; 25 | height: 0; 26 | width: 100%; 27 | } 28 | 29 | .vce-bar { 30 | /* Reset the default appearance */ 31 | -webkit-appearance: none; 32 | -moz-appearance: none; 33 | appearance: none; 34 | /* Get rid of default border in Firefox. */ 35 | border: none; 36 | height: 20px; 37 | visibility: hidden; 38 | } 39 | 40 | .vce-bar-text { 41 | display: -ms-flexbox; 42 | display: flex; 43 | -ms-flex-pack: justify; 44 | justify-content: space-between; 45 | -webkit-box-align: center; 46 | -ms-flex-align: center; 47 | align-items: center; 48 | } 49 | 50 | .vce-bar-container .vce-bar-title, 51 | .vce-bar-container .vce-bar-value { 52 | line-height: 1; 53 | margin: 0 0 10px; 54 | } 55 | 56 | .vce-bar-container .vce-bar-title { 57 | overflow: hidden; 58 | text-overflow: ellipsis; 59 | } 60 | 61 | .vce-bar-value { 62 | display: none; 63 | flex-shrink: 0; 64 | } 65 | 66 | .vce-bar-container .vce-bar-value::before { 67 | display: none; 68 | } 69 | 70 | .vce-vertical-chart-display-value .vce-bar-value { 71 | display: inline-block; 72 | } 73 | 74 | @keyframes progress-animation { 75 | 100% { 76 | width: 100%; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | elements; 37 | foreach ($elementsToRegister as $tag) { 38 | $manifestPath = __DIR__ . '/elements/' . $tag . '/manifest.json'; 39 | $elementBaseUrl = $pluginBaseUrl . '/elements/' . $tag; 40 | $elementsApi->add($manifestPath, $elementBaseUrl); 41 | } 42 | } 43 | ); 44 | --------------------------------------------------------------------------------