Showing preview only (201K chars total). Download the full file or copy to clipboard to get everything.
Repository: baianat/vuse
Branch: master
Commit: e6678f2f6ba8
Files: 64
Total size: 185.6 KB
Directory structure:
gitextract_7xlm9eti/
├── .babelrc
├── .eslintrc.json
├── .gitignore
├── .npmignore
├── LICENSE
├── README.md
├── demo/
│ ├── App.vue
│ ├── Uploader.vue
│ ├── app.js
│ ├── index.html
│ ├── render.html
│ ├── sections/
│ │ ├── forms/
│ │ │ └── newsletter.vue
│ │ ├── hero/
│ │ │ ├── hero1.vue
│ │ │ └── hero2.vue
│ │ ├── section/
│ │ │ ├── section1.vue
│ │ │ └── section2.vue
│ │ └── social/
│ │ ├── social1.vue
│ │ ├── social2.vue
│ │ ├── social3.vue
│ │ └── social4.vue
│ ├── style/
│ │ ├── _demo.styl
│ │ ├── colors.styl
│ │ ├── header.styl
│ │ ├── helper.styl
│ │ ├── main.styl
│ │ ├── scrolling.styl
│ │ ├── section.styl
│ │ ├── social.styl
│ │ ├── transition.styl
│ │ ├── user.styl
│ │ └── variables.styl
│ └── webpack.config.js
├── docs/
│ ├── .vuepress/
│ │ ├── config.js
│ │ ├── enhanceApp.js
│ │ └── public/
│ │ └── style.css
│ ├── API.md
│ ├── README.md
│ ├── example.md
│ ├── exporting.md
│ ├── getting-started.md
│ ├── section.md
│ └── styler.md
├── package.json
├── scripts/
│ ├── build.js
│ ├── config.js
│ └── deploy.sh
└── src/
├── components/
│ ├── VuseBuilder.vue
│ ├── VuseIcon.js
│ ├── VuseRenderer.vue
│ └── VuseStyler.vue
├── index.esm.js
├── index.js
├── mixin.js
├── plugins/
│ ├── pwa.js
│ └── scrolling.js
├── section.js
├── seeder.js
├── styler.js
├── stylus/
│ ├── _app.styl
│ ├── colors.styl
│ └── variables.styl
├── types.js
├── util.js
└── vuse.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .babelrc
================================================
{
"presets": [
["@babel/preset-env", { "modules": false }]
],
"env": {
"test": {
"presets": [
["@babel/preset-env", { "targets": { "node": "current" }}]
]
}
}
}
================================================
FILE: .eslintrc.json
================================================
{
"extends": [
"standard",
"plugin:vue/recommended"
],
"rules": {
"semi": "off",
"no-new": "off",
"vue/valid-template-root": "off"
}
}
================================================
FILE: .gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Dependency directories
node_modules/
jspm_packages/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# visual studio code
.vscode
# macOS custom Icon
Icon/
# vuepress output
docs/.vuepress/dist
# dist folders
dist
================================================
FILE: .npmignore
================================================
/docs
/dev
/src
/static
/scripts
.*
yarn.lock
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2017 Baianat
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# Vuse
<p align="center">
<a href="https://github.com/baianat/vuse" target="_blank">
<img width="450" src="https://github.com/baianat/vuse/blob/master/Logo/Vuse_Logo_Horizontal_Gradient.png">
</a>
</p>
> Logo by [chimzycash](https://github.com/chimzycash)
**WIP: Vuse active development is now halted.**
Advanced page/email builder based on [Vue.js](https://vuejs.org/).
[documentation](https://baianat.github.io/vuse/)
## Credits
- Logo by [chimzycash](https://github.com/chimzycash).
## License
MIT
================================================
FILE: demo/App.vue
================================================
<template>
<VuseBuilder @saved="onSave" />
</template>
<script>
export default {
name: 'App',
methods: {
onSave (vuse) {
vuse.export('preview');
vuse.export('pwa');
}
}
}
</script>
================================================
FILE: demo/Uploader.vue
================================================
<template lang="pug">
div.uploader
img(:src="src")
input.uploader-input(
type="file"
ref="uploader"
@change="updateImage"
v-if="$builder.isEditing && mode === 'input'"
)
</template>
<script>
export default {
name: 'Uploader',
inject: ['$builder', '$section'],
props: {
path: {
type: String,
required: true
},
mode: {
default: 'input',
type: String
}
},
data: () => ({
src: ''
}),
created () {
this.src = this.$section.get(this.path);
},
methods: {
updateImage () {
const file = this.$refs.uploader.files[0];
if (!file) return;
const imageURL = URL.createObjectURL(file);
this.src = imageURL;
this.$section.set(this.path, imageURL);
}
}
}
</script>
<style lang="stylus">
@import '../src/stylus/_app.styl'
.uploader
position: relative
cursor: pointer
outline: none
&-input
position: absolute
top: 0
right: 0
bottom: 0
left: 0
width: 100%
opacity: 0
z-index: 100
cursor: pointer
>img
width: 100%
display: block
&:hover
box-shadow: 0 0 0 2px $gray
</style>
================================================
FILE: demo/app.js
================================================
// Vuse scripts
import Vue from 'vue';
import pwa from '../src/plugins/pwa';
import Vuse from '../src';
// demo scripts
import './style/_demo.styl';
import App from './App.vue';
import Uploader from './Uploader'
import hero1 from './sections/hero/hero1';
import hero2 from './sections/hero/hero2';
import section1 from './sections/section/section1';
import section2 from './sections/section/section2';
import social1 from './sections/social/social1';
import social2 from './sections/social/social2';
import social3 from './sections/social/social3';
import social4 from './sections/social/social4';
import newsletter from './sections/forms/newsletter';
// add the uploader to the list of sub-components.
Vuse.mix({
components: {
Uploader
}
});
// register components.
Vuse.component(hero1);
Vuse.component(hero2);
Vuse.component(section1);
Vuse.component(section2);
Vuse.component(social1);
Vuse.component(social2);
Vuse.component(social3);
Vuse.component(social4);
Vuse.component(newsletter);
// install pwa plugin.
Vuse.use(pwa);
// install the builder
Vue.use(Vuse, {
// main css file
assets: {
css: 'css/style.css'
},
// builder default themes
themes: [{
name: 'Theme 1',
sections: [hero1, section1, social1, social3, newsletter]
}, {
name: 'Theme 2',
sections: [hero2, section2, social3, social4, newsletter]
}]
});
new Vue({
el: '#app',
render: h => h(App)
});
================================================
FILE: demo/index.html
================================================
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
<title>Vuse</title>
</head>
<body>
<div id="app">
</div>
</body>
</html>
================================================
FILE: demo/render.html
================================================
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Vuse</title>
</head>
<body>
<div id="app">
<VuseRenderer :data="{ title: 'My title', sections: [{ name: 'social2', data: { classes: ['is-dark'], content: 'This is my content yo!', images: ['static/img/avatar.png'] } },{ name: 'social2', data: { classes: ['is-red'], content: 'This is my content yo boi!', images: ['static/img/avatar.png'] } }] }"></VuseRenderer>
</div>
</body>
</html>
================================================
FILE: demo/sections/forms/newsletter.vue
================================================
<template lang="pug">
section.header(
v-styler:section="$sectionData.classes"
:class="$sectionData.classes"
)
.container
.grid.is-center
.row
h3.header-title Sign up for our newsletter
form.row(@submit.prevent="onSubmit")
.column.is-desktop-4
.input-group.has-itemAfter
input.input(type="text" name="email" placeholder="Email address" v-model="$sectionData.form.email")
a.button(
@click.prevent="onSubmit"
:class="$sectionData.action.classes"
:href="$sectionData.action.href"
v-html="$sectionData.action.text"
v-styler="$sectionData.action"
)
</template>
<script>
import * as types from '../../../src/types';
export default {
name: 'Newsletter',
cover: 'img/covers/newsletter.png',
group: 'forms',
$schema: {
classes: types.ClassList,
action: types.Button,
form: {
email: ''
}
},
props: {
id: {
type: Number,
required: true
}
},
methods: {
onSubmit () {
if (this.$builder.isEditing) return;
const endpoint = this.$sectionData.action.href;
console.log(`Pinging ${endpoint} with ${this.$sectionData.form.email}`);
// SEND DATA TO ENDPOINT
}
}
};
</script>
================================================
FILE: demo/sections/hero/hero1.vue
================================================
<template lang="pug">
section.header(
v-styler="$sectionData.classes"
:class="$sectionData.classes"
)
.container
.grid
.column.is-desktop-6.add-center-vertical
h3.header-title(
v-html="$sectionData.title"
v-styler="$sectionData.title"
)
p.header-content(
v-html="$sectionData.content"
v-styler="$sectionData.content"
)
a.button(
:class="$sectionData.button.classes"
:href="$sectionData.button.href"
v-html="$sectionData.button.text"
v-styler="$sectionData.button"
)
.column.is-desktop-6
uploader(
class="header-image"
path="$sectionData.images[0]"
)
</template>
<script>
import * as types from '../../../src/types';
export default {
name: 'Hero1',
cover: 'img/covers/hero1.png',
group: 'hero',
$schema: {
title: types.Title,
content: types.Text,
images: [types.Image],
button: types.Button,
classes: types.ClassList
},
props: {
id: {
type: Number,
required: true
}
}
};
</script>
================================================
FILE: demo/sections/hero/hero2.vue
================================================
<template lang="pug">
section.header(
v-styler="$sectionData.classes"
:class="$sectionData.classes"
)
.container
.grid
.column.is-desktop-6.is-offset-screen-3.add-center-horizontal.add-padding.add-text-center
h3.header-title(
v-html="$sectionData.title"
v-styler="$sectionData.title"
)
p.header-content(
v-html="$sectionData.content"
v-styler="$sectionData.content"
)
a.button(
:class="$sectionData.button.classes"
:href="$sectionData.button.href"
v-html="$sectionData.button.text"
v-styler="$sectionData.button"
)
.column.is-desktop-8.is-offset-screen-2
uploader(
class="header-image"
path="$sectionData.images[0]"
)
</template>
<script>
import * as types from '../../../src/types';
export default {
name: 'Hero2',
cover: 'img/covers/hero2.png',
group: 'hero',
$schema: {
title: types.Title,
content: types.Text,
images: [types.Image],
button: types.Button,
classes: types.ClassList
},
props: {
id: {
type: Number,
required: true
}
}
};
</script>
================================================
FILE: demo/sections/section/section1.vue
================================================
<template lang="pug">
section.section(
v-styler="$sectionData.classes"
:class="$sectionData.classes"
)
.container
.grid.is-center
.column(
:class="gridClasses[0]"
v-styler:grid="$sectionData.columns[0].grid"
)
h2.section-title(
v-html="$sectionData.columns[0].title"
v-styler="$sectionData.columns[0].title"
)
p.section-paragraph(
v-html="$sectionData.columns[0].content"
v-styler="$sectionData.columns[0].content"
)
.column.is-offset-screen-1(
:class="gridClasses[1]"
v-styler:grid="$sectionData.columns[1].grid"
)
h2.section-title(
v-html="$sectionData.columns[1].title"
v-styler="$sectionData.columns[1].title"
)
p.section-paragraph(
v-html="$sectionData.columns[1].content"
v-styler="$sectionData.columns[1].content"
)
</template>
<script>
import * as types from '../../../src/types';
export default {
name: 'Section1',
cover: 'img/covers/section1.png',
group: 'section',
$schema: {
classes: types.ClassList,
columns: [
{
title: types.Title,
content: types.Text,
grid: {
mobile: 0,
desktop: 5
}
},
{
title: types.Title,
content: types.Text,
grid: {
mobile: 0,
desktop: 5
}
}
]
},
props: {
id: {
type: Number, required: true
}
}
};
</script>
================================================
FILE: demo/sections/section/section2.vue
================================================
<template lang="pug">
section.section(
v-styler:section="$sectionData.classes"
:class="$sectionData.classes"
)
.container
.grid.is-center
.column(
:class="gridClasses[0]"
v-styler="$sectionData.columns[0].grid"
)
h2.section-title(
v-html="$sectionData.columns[0].title"
v-styler="$sectionData.columns[0].title"
)
p.section-paragraph(
v-html="$sectionData.columns[0].content"
v-styler="$sectionData.columns[0].content"
)
.column(
:class="gridClasses[1]"
v-styler="$sectionData.columns[1].grid"
)
h2.section-title(
v-html="$sectionData.columns[1].title"
v-styler="$sectionData.columns[1].title"
)
p.section-paragraph(
v-html="$sectionData.columns[1].content"
v-styler="$sectionData.columns[1].content"
)
.column(
:class="gridClasses[2]"
v-styler="$sectionData.columns[2].grid"
)
h2.section-title(
v-html="$sectionData.columns[2].title"
v-styler="$sectionData.columns[2].title"
)
p.section-paragraph(
v-html="$sectionData.columns[2].content"
v-styler="$sectionData.columns[2].content"
)
</template>
<script>
import * as types from '../../../src/types';
export default {
name: 'Section2',
cover: 'img/covers/section2.png',
group: 'section',
$schema: {
classes: types.ClassList,
columns: [
{
title: types.Title,
content: types.Text,
grid: types.Grid
}, {
title: types.Title,
content: types.Text,
grid: types.Grid
}, {
title: types.Title,
content: types.Text,
grid: types.Grid
}
]
},
props: {
id: {
type: Number, required: true
}
}
};
</script>
================================================
FILE: demo/sections/social/social1.vue
================================================
<template lang="pug">
section.social(
v-styler:section="$sectionData.classes"
:class="$sectionData.classes"
)
.container
.grid.is-center
.column.is-desktop-2.social-item
h6.social-number(
v-html="$sectionData.columns[0].content"
v-styler="$sectionData.columns[0].content"
)
b.social-keyword(
v-html="$sectionData.columns[0].title"
v-styler="$sectionData.columns[0].title"
)
.column.is-desktop-2.social-item
h6.social-number(
v-html="$sectionData.columns[1].content"
v-styler="$sectionData.columns[1].content"
)
b.social-keyword(
v-html="$sectionData.columns[1].title"
v-styler="$sectionData.columns[1].title"
)
.column.is-desktop-2.social-item
h6.social-number(
v-html="$sectionData.columns[2].content"
v-styler="$sectionData.columns[2].content"
)
b.social-keyword(
v-html="$sectionData.columns[2].title"
v-styler="$sectionData.columns[2].title"
)
</template>
<script>
import * as types from '../../../src/types';
export default {
name: 'Social1',
cover: 'img/covers/social1.png',
group: 'social',
$schema: {
classes: types.ClassList,
columns: [
{
title: types.Title,
content: Number
}, {
title: types.Title,
content: Number
}, {
title: types.Title,
content: Number
}
]
},
props: {
id: {
type: Number, required: true
}
}
};
</script>
================================================
FILE: demo/sections/social/social2.vue
================================================
<template lang="pug">
section.social(
v-styler:section="$sectionData.classes"
:class="$sectionData.classes"
)
.container
.grid
.row.is-center
.column.is-desktop-6
p.social-quote(
v-html="$sectionData.content"
v-styler="$sectionData.content"
)
.row.is-center
.column.is-desktop-2
.user.is-alt
uploader(
class="user-avatar"
path="$sectionData.images[0]"
)
.user-data
h4.user-name Ahmed
span.user-caption SEO at Baianat
</template>
<script>
import * as types from '../../../src/types';
export default {
name: 'Social2',
cover: 'img/covers/social2.png',
group: 'social',
$schema: {
classes: types.ClassList,
content: types.Text,
images: [types.Avatar]
},
props: {
id: {
type: Number,
required: true
}
}
};
</script>
================================================
FILE: demo/sections/social/social3.vue
================================================
<template lang="pug">
section.social(
v-styler:section="$sectionData.classes"
:class="$sectionData.classes"
)
.container
.grid
.row.is-center
.column.is-12.is-desktop-7
h3.social-title(
v-html="$sectionData.title"
v-styler="$sectionData.title"
)
.column.is-12.is-desktop-7
p.social-content(
v-html="$sectionData.content"
v-styler="$sectionData.content"
)
.row.is-center
.column.is-desktop-2(v-for="(logo, index) in $sectionData.images")
uploader(
class="social-logo"
:path="`$sectionData.images[${index}]`"
)
</template>
<script>
import * as types from '../../../src/types';
export default {
name: 'Social3',
cover: 'img/covers/social3.png',
group: 'social',
$schema: {
classes: types.ClassList,
title: types.Title,
content: types.Text,
images: [
types.Logo,
types.Logo,
types.Logo
]
},
props: {
id: {
type: Number, required: true
}
}
};
</script>
================================================
FILE: demo/sections/social/social4.vue
================================================
<template lang="pug">
section.social(
v-styler:section="$sectionData.classes"
:class="$sectionData.classes"
)
.container
.grid
.row.is-center
.column.is-12
h3.social-title(
v-html="$sectionData.title"
v-styler="$sectionData.title"
)
.row.is-center
.column.is-12.is-desktop-4
p(
v-html="$sectionData.columns[0].content"
v-styler="$sectionData.columns[0].content"
)
.user
uploader(
class="user-avatar"
path="$sectionData.images[0]"
)
.user-data
h4.user-name Ahmed
span.user-caption SEO at Baianat
.column.is-12.is-desktop-4
p(
v-html="$sectionData.columns[1].content"
v-styler:text="$sectionData.columns[1].content"
)
.user
uploader(
class="user-avatar"
path="$sectionData.images[1]"
)
.user-data
h4.user-name Ahmed
span.user-caption SEO at Baianat
.column.is-12.is-desktop-4
p(
v-html="$sectionData.columns[2].content"
v-styler:text="$sectionData.columns[2].content"
)
.user
uploader(
class="user-avatar"
path="$sectionData.images[2]"
)
.user-data
h4.user-name Ahmed
span.user-caption SEO at Baianat
</template>
<script>
import * as types from '../../../src/types';
export default {
name: 'Social4',
cover: 'img/covers/social4.png',
group: 'social',
$schema: {
classes: [types.ClassList],
title: types.Title,
columns: [
{ content: types.Text },
{ content: types.Text },
{ content: types.Text }
],
images: [
types.Avatar,
types.Avatar,
types.Avatar
]
},
props: {
id: {
type: Number, required: true
}
}
};
</script>
================================================
FILE: demo/style/_demo.styl
================================================
@import variables
@import '~@baianat/base.framework/base'
@import main
@import header
@import section
@import social
@import user
@import helper
@import scrolling
.column
transition: 0.2s
================================================
FILE: demo/style/colors.styl
================================================
/*
* Color theme
*/
$magenta ?= #eb008b
$blue ?= #0072FF
$cyan ?= #00d4f0
$green ?= #18d88b
$yellow ?= #ffdd57
$orange ?= #ffa557
$red ?= #ff3d3d
$purple ?= #a324ea
/*
* Graysacle
*/
$black ?= #000
$dark ?= #323c47
$gray ?= #c1c1c1
$gray-dark ?= darken($gray, 10%)
$gray-light ?= lighten($gray, 10%)
$light ?= #f5f5f5
$white ?= #fff
================================================
FILE: demo/style/header.styl
================================================
.header
width: 100%
padding: 50px
color: $white
&-title
font-size: 50px
line-height: 1em
margin: 20px 0
font-weight: lighter
&-content
font-size: 16px
margin-bottom: 50px
font-weight: lighter
&-image
>img
width 100%
&,
&.is-red
background-image: linear-gradient(30deg, $red, $yellow)
&.is-black
background-image: linear-gradient(30deg, $black, lighten($black, 30%))
&.is-green
background-image: linear-gradient(30deg, $green, $yellow)
&.is-blue
background-image: linear-gradient(30deg, $blue, lighten($blue, 30%))
&.is-white
background-image: linear-gradient(45deg, darken($white, 10%), $white)
================================================
FILE: demo/style/helper.styl
================================================
+prefix-classes('add-')
.center-horizontal
display: flex
flex-direction: column
justify-content: center
align-items: center
.center-vertical
display: flex
flex-direction: column
justify-content: center
align-items: flex-start
.padding
padding: 20px
.text-center
text-align: center
.full-width
width: 100%
================================================
FILE: demo/style/main.styl
================================================
::selection
color: inherit
.button
white-space: nowrap
================================================
FILE: demo/style/scrolling.styl
================================================
.is-active
img
opacity: 1
transition: 0.4s
p
h1
h2
h3
h6
b
opacity: 1
transform: translate3d(0, 0, 0)
transition: 0.4s
.is-inactive
img
opacity: 0
transition: 0.4s
p
h1
h2
h3
h6
b
opacity: 0
transform: translate3d(0, -200px, 0)
transition: 0.4s
================================================
FILE: demo/style/section.styl
================================================
.section
padding: 20px 30px
&-title
font-size: 30px
color: $dark
&-paragraph
font-size: 16px
color: lighten($dark, 20%)
&.is-red
background: $red
&.is-black
background: $black
&.is-green
background: $green
&.is-blue
background: $blue
&.is-white
background: $white
================================================
FILE: demo/style/social.styl
================================================
.social
padding: 100px 0
&-number
font-size: 50px
margin: 20px 0 50px
&-item
display: flex
flex-direction: column
justify-content: center
align-items: center
&-title
font-size: 30px
margin: 30px 0
text-align: center
&-content
font-size: 20px
margin: 0 0 40px
text-align: center
&-logo
width: 100%
margin: 20px 0
@extend $flexCenter
&-quote
font-size: 30px
color: $black
quotes: "“" "”" "‘" "’"
&:before
content: open-quote
margin-right: 20px
font-size: 40px
&:after
content: close-quote
margin-left: 20px
font-size: 40px
&.is-red
background: $red
&.is-black
background: $black
&.is-green
background: $green
&.is-blue
background: $blue
================================================
FILE: demo/style/transition.styl
================================================
.fade-enter-active
.fade-leave-active
transition: all .3s ease
transform: scaleX(1)
.fade-enter
.fade-leave-to
transform: scaleX(0)
================================================
FILE: demo/style/user.styl
================================================
.user
display: flex
align-items: center
margin: 10px 0
&.is-alt
justify-content: center
flex-direction: column
&-avatar
border-radius: 50%
width: 60px
height: 60px
margin-right: 20px
flex-shrink: 0
overflow: hidden
.is-alt &
margin: 0 0 20px
&-data
text-align: left
white-space: nowrap
.is-alt &
text-align: center
&-name
font-size: 16px
color: $black
margin: 5px 0
&-caption
font-size: 16px
color: $gray
margin: 0 0 5px
================================================
FILE: demo/style/variables.styl
================================================
$flexCenter
display: flex
justify-content: center
align-items: center
================================================
FILE: demo/webpack.config.js
================================================
const path = require('path');
const webpack = require('webpack');
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const env = process.env.NODE_ENV;
const production = env === 'production';
// render page
const page = (name) => {
return new HtmlWebpackPlugin({
inject: true,
template: path.join(__dirname, `./${name}.html`),
filename: path.join(__dirname, `./dist/${name}.html`)
});
};
const config = {
mode: production ? 'production' : 'development',
devtool: production ? 'source-map' : 'cheap-source-map',
entry: {
app: path.join(__dirname, './app.js')
},
output: {
path: path.join(__dirname, 'dist'),
filename: 'js/[name].js'
},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/style.css'
}),
new CleanWebpackPlugin(['./dist']),
new VueLoaderPlugin(),
new webpack.LoaderOptionsPlugin({ options: {} }),
new FriendlyErrorsWebpackPlugin(),
new ProgressBarPlugin(),
new CopyWebpackPlugin([{ from: path.join(__dirname, 'img'), to: './img/' }]),
page('index'),
page('render')
],
watchOptions: {
aggregateTimeout: 300,
poll: 1000
},
devServer: {
historyApiFallback: true,
hot: true,
inline: true,
stats: 'errors-only',
host: '0.0.0.0',
port: 8080
},
module: {
rules: [
{
test: /.js$/,
exclude: /node_modules/,
loader: 'eslint-loader',
enforce: 'pre'
},
{
test: /.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: { babelrc: true }
}
},
{
test: /\.vue$/,
loader: 'eslint-loader',
enforce: 'pre'
},
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.css$/,
loader: ['style-loader', 'css-loader']
},
{
test: /\.styl(us)?$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'stylus-loader'
]
},
{
test: /\.(ttf|eot|svg)(\?.*)?$/,
loader: 'file-loader',
options: {
name: 'font/[name].[ext]'
}
},
{
test: /.pug$/,
exclude: /node_modules/,
loader: 'pug-plain-loader',
options: {
pretty: true
}
}
]
},
resolve: {
extensions: ['.js', '.vue', '.json']
}
};
module.exports = config;
================================================
FILE: docs/.vuepress/config.js
================================================
module.exports = {
title: 'Vuse',
description: 'Advanced page builder based on Vue.js',
base: '/vuse/',
themeConfig: {
lastUpdated: 'Last Updated',
repo: 'baianat/vuse',
docsRepo: 'baianat/vuse',
docsDir: 'docs',
docsBranch: 'master',
editLinks: true,
sidebar: [
'/',
'/getting-started',
'/section',
'/styler',
'/exporting',
'/API',
],
nav: [
{ text: 'API', link: '/API' },
{ text: 'Example', link: '/example' },
]
}
}
================================================
FILE: docs/.vuepress/enhanceApp.js
================================================
// Vuse scripts
import Vuse from '../../src';
// demo scripts
import '../../demo/style/_demo.styl';
import Uploader from '../../demo/Uploader.vue'
import hero1 from '../../demo/sections/hero/hero1';
import hero2 from '../../demo/sections/hero/hero2';
import section1 from '../../demo/sections/section/section1';
import section2 from '../../demo/sections/section/section2';
import social1 from '../../demo/sections/social/social1';
import social2 from '../../demo/sections/social/social2';
import social3 from '../../demo/sections/social/social3';
import social4 from '../../demo/sections/social/social4';
import newsletter from '../../demo/sections/forms/newsletter';
// add the uploader to the list of sub-components.
Vuse.mix({
components: {
Uploader
}
});
// register components.
Vuse.component(hero1);
Vuse.component(hero2);
Vuse.component(section1);
Vuse.component(section2);
Vuse.component(social1);
Vuse.component(social2);
Vuse.component(social3);
Vuse.component(social4);
Vuse.component(newsletter);
export default ({ Vue }) => {
// install the builder
Vue.use(Vuse, {
// main css file
assets: {
css: 'style.css'
},
// builder default themes
themes: [{
name: 'Theme 1',
sections: [hero1, section1, social1, social3, newsletter]
}, {
name: 'Theme 2',
sections: [hero2, section2, social3, social4, newsletter]
}]
});
}
function normalize (component) {
component.cover = component.cover.replace('static', '.');
}
================================================
FILE: docs/.vuepress/public/style.css
================================================
.vuse-icon {
display: block;
width: 20px;
height: 20px;
}
.controller-button:hover,
.menu-element:hover {
cursor: pointer;
box-shadow: 0 14px 28px rgba(0,0,0,0.125), 0 10px 10px rgba(0,0,0,0.1);
}
.artboard {
transform-origin: top center;
}
.artboard.is-editable .is-editable {
outline: none;
}
.artboard.is-editable .is-editable:hover {
box-shadow: inset 0 0 0 2px #c1c1c1;
}
.controller {
box-sizing: border-box;
}
.controller-panel {
position: fixed;
z-index: 200;
bottom: 30px;
right: 40px;
}
.controller-input {
outline: none;
border: 1px solid #c1c1c1;
padding: 0.5em 1em;
margin: 20px 0;
border-radius: 40px;
width: 100%;
font-size: 16px;
}
.controller-input:focus {
border-color: #0072ff;
box-shadow: 0 0 0 2px rgba(0,114,255,0.5);
}
.controller-button {
transition: 0.2s;
border: none;
outline: none;
border-radius: 20px;
padding: 5px;
color: #fff;
fill: #fff;
font-size: 16px;
}
.controller-button svg {
transition: 0.2s;
}
.controller-button:not(:last-child) {
margin-right: 20px;
}
.controller-button.is-rotated >svg {
transform: rotate(45deg);
}
.controller-button.is-blue {
background-color: #0072ff;
}
.controller-button.is-blue:hover {
background-color: #005bcc;
}
.controller-button.is-red {
background-color: #ff3d3d;
}
.controller-button.is-red:hover {
background-color: #fd0000;
}
.controller-button.is-green {
background-color: #18d88b;
}
.controller-button.is-green:hover {
background-color: #13ad6f;
}
.controller-button.is-dark {
background-color: #323c47;
}
.controller-button.is-dark:hover {
background-color: #283039;
}
.controller-button.is-gray {
background-color: $gary;
}
.controller-button.is-gray:hover {
background-color: #9a9a9a;
}
.controller-intro {
width: 100%;
max-width: 500px;
margin: auto;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
padding: 70px 50px;
text-align: center;
font-size: 30px;
color: #323c47;
}
.controller-themes {
display: flex;
flex-direction: column;
width: 100%;
}
.controller-theme {
background-color: #fff;
color: #323c47;
border: 1px solid #c1c1c1;
margin: 5px;
padding: 20px;
border-radius: 4px;
width: 100%;
cursor: pointer;
font-size: 16px;
}
.controller-theme:hover {
border-color: #0072ff;
}
.menu {
user-select: none;
-moz-user-select: none;
position: fixed;
z-index: 300;
top: 0;
left: 0;
bottom: 0;
margin: 0;
width: 250px;
background: #fff;
padding: 20px 10px;
display: flex;
flex-direction: column;
overflow-y: auto;
list-style: none;
transition: 0.4s;
box-shadow: 1px 0 10px rgba(50,60,71,0.2);
transform: translate3d(-100%, 0, 0);
}
.menu.is-visiable {
transform: translate3d(0, 0, 0);
}
.menu-body {
display: none;
padding: 0;
margin: 0;
list-style: none;
}
.menu-group .menu-body {
width: 90%;
margin: 10px auto;
}
.menu-group.is-visiable .menu-body {
display: block;
}
.menu-icon {
width: 24px;
height: 24px;
fill: #c1c1c1;
transition: 0.2s;
}
.menu-group.is-visiable .menu-icon {
transform: rotate(180deg);
}
.menu-element {
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
min-height: 50px;
border-radius: 5px;
background: #aeaeae;
transition: 0.3s;
cursor: pointer;
color: #fff;
overflow: hidden;
user-select: none;
-moz-user-select: none;
}
.menu-element:not(:last-child) {
margin-bottom: 10px;
}
.menu-elementImage {
max-width: 100%;
pointer-events: none;
}
.menu-elementTitle {
position: absolute;
right: 0;
bottom: 0;
left: 0;
text-shadow: 1px 1px 2px rgba(0,0,0,0.8);
text-align: center;
padding: 5px;
}
.menu-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 5px;
border-bottom: 1px solid rgba(0,0,0,0.05);
}
.sortable-ghost {
opacity: 0.3;
box-shadow: 0 0 2px 1px #0072ff;
}
.is-editable:hover {
box-shadow: inset 0 0 0 2px #c1c1c1;
}
.styler {
position: absolute;
top: 0;
z-index: 200;
visibility: hidden;
opacity: 0;
margin: 10px 0;
padding: 5px;
background: #323c47;
border-radius: 26px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.styler-list,
.align,
.colorer {
display: flex;
justify-content: center;
align-items: center;
list-style: none;
margin: 0;
padding: 0;
}
.styler-input {
background: #fff;
color: #323c47;
border: 0;
outline: 0;
width: 40px;
height: 40px;
border-radius: 42px;
margin: 0 5px 0 0;
text-align: center;
-webkit-appearance: none;
-moz-appearance: textfield;
appearance: none;
}
.styler-button {
display: flex;
justify-content: center;
align-items: center;
outline: 0;
background: #323c47;
border: 0;
fill: #fff;
color: #fff;
width: 42px;
height: 42px;
border-radius: 42px;
margin: 0 5px 0 0;
}
.styler-button:hover {
background: #283039;
}
.styler-button:first-child {
margin-left: 5px;
}
.styler-selector {
margin: 0 5px;
}
.styler.is-visible {
visibility: visible;
opacity: 1;
}
.styler .input-group {
margin: 5px;
}
.align {
height: 42px;
}
.colorer {
height: 42px;
}
.colorer li >input {
-webkit-appearance: none;
-moz-appearance: textfield;
appearance: none;
width: 30px;
height: 30px;
border-radius: 40px;
border: 4px solid #283039;
margin: 0 5px;
outline: none;
}
.colorer li >input:checked {
border-color: #526375;
}
.colorer li >input:hover {
border-color: #526375;
}
.colorer li >input#colorRed {
background: #ff3d3d;
}
.colorer li >input#colorBlue {
background: #0072ff;
}
.colorer li >input#colorGreen {
background: #18d88b;
}
.colorer li >input#colorBlack {
background: #000;
}
.colorer li >input#colorWhite {
background: #fff;
}
.is-hidden {
display: none;
}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
.social-logo {
display: flex;
justify-content: center;
align-items: center;
}
.button.is-tiny,
.buttons.is-tiny >.button,
.label.is-tiny,
.input.is-tiny,
.input-tag.is-tiny,
.input-group.is-tiny >.button,
.input-group.is-tiny >.input,
.input-group.is-tiny >.input-tag,
.checkbox.is-tiny,
.radio.is-tiny,
.switcher.is-tiny,
.textarea.is-tiny,
.select.is-tiny,
.pagination.is-tiny,
.content.is-tiny {
font-size: calc( 0.253378378378378vw + 8.554054054054054px );
}
@media screen and (max-width: 767px) {
.button.is-tiny,
.buttons.is-tiny >.button,
.label.is-tiny,
.input.is-tiny,
.input-tag.is-tiny,
.input-group.is-tiny >.button,
.input-group.is-tiny >.input,
.input-group.is-tiny >.input-tag,
.checkbox.is-tiny,
.radio.is-tiny,
.switcher.is-tiny,
.textarea.is-tiny,
.select.is-tiny,
.pagination.is-tiny,
.content.is-tiny {
font-size: 10.5px;
}
}
@media screen and (min-width: 1360px) {
.button.is-tiny,
.buttons.is-tiny >.button,
.label.is-tiny,
.input.is-tiny,
.input-tag.is-tiny,
.input-group.is-tiny >.button,
.input-group.is-tiny >.input,
.input-group.is-tiny >.input-tag,
.checkbox.is-tiny,
.radio.is-tiny,
.switcher.is-tiny,
.textarea.is-tiny,
.select.is-tiny,
.pagination.is-tiny,
.content.is-tiny {
font-size: 12px;
}
}
.button.is-small,
.buttons.is-small >.button,
.label,
.label.is-small,
.input.is-small,
.input-tag.is-small,
.input-group.is-small >.button,
.input-group.is-small >.input,
.input-group.is-small >.input-tag,
.checkbox.is-small,
.radio.is-small,
.switcher.is-small,
.textarea.is-small,
[tooltip]:after,
.select.is-small,
.pagination.is-small,
.content.is-small {
font-size: calc( 0.295608108108108vw + 9.97972972972973px );
}
@media screen and (max-width: 767px) {
.button.is-small,
.buttons.is-small >.button,
.label,
.label.is-small,
.input.is-small,
.input-tag.is-small,
.input-group.is-small >.button,
.input-group.is-small >.input,
.input-group.is-small >.input-tag,
.checkbox.is-small,
.radio.is-small,
.switcher.is-small,
.textarea.is-small,
[tooltip]:after,
.select.is-small,
.pagination.is-small,
.content.is-small {
font-size: 12.25px;
}
}
@media screen and (min-width: 1360px) {
.button.is-small,
.buttons.is-small >.button,
.label,
.label.is-small,
.input.is-small,
.input-tag.is-small,
.input-group.is-small >.button,
.input-group.is-small >.input,
.input-group.is-small >.input-tag,
.checkbox.is-small,
.radio.is-small,
.switcher.is-small,
.textarea.is-small,
[tooltip]:after,
.select.is-small,
.pagination.is-small,
.content.is-small {
font-size: 14px;
}
}
p,
body,
.button,
.button.is-normal,
.buttons.is-normal >.button,
.label,
.label.is-normal,
.input,
.input.is-normal,
.input-tag,
.input-tag.is-normal,
.input-group.is-normal >.button,
.input-group.is-normal >.input,
.input-group.is-normal >.input-tag,
.checkbox,
.checkbox.is-normal,
.radio,
.radio.is-normal,
.switcher,
.switcher.is-normal,
.table,
.textarea,
.textarea.is-normal,
.select,
.select.is-normal,
.modal,
.navbar-item,
.pagination-item,
.pagination-next,
.pagination-prev,
.pagination-first,
.pagination-last,
.pagination,
.pagination.is-normal,
.content,
.content.is-normal {
font-size: calc( 0.337837837837838vw + 11.405405405405405px );
}
@media screen and (max-width: 767px) {
p,
body,
.button,
.button.is-normal,
.buttons.is-normal >.button,
.label,
.label.is-normal,
.input,
.input.is-normal,
.input-tag,
.input-tag.is-normal,
.input-group.is-normal >.button,
.input-group.is-normal >.input,
.input-group.is-normal >.input-tag,
.checkbox,
.checkbox.is-normal,
.radio,
.radio.is-normal,
.switcher,
.switcher.is-normal,
.table,
.textarea,
.textarea.is-normal,
.select,
.select.is-normal,
.modal,
.navbar-item,
.pagination-item,
.pagination-next,
.pagination-prev,
.pagination-first,
.pagination-last,
.pagination,
.pagination.is-normal,
.content,
.content.is-normal {
font-size: 14px;
}
}
@media screen and (min-width: 1360px) {
p,
body,
.button,
.button.is-normal,
.buttons.is-normal >.button,
.label,
.label.is-normal,
.input,
.input.is-normal,
.input-tag,
.input-tag.is-normal,
.input-group.is-normal >.button,
.input-group.is-normal >.input,
.input-group.is-normal >.input-tag,
.checkbox,
.checkbox.is-normal,
.radio,
.radio.is-normal,
.switcher,
.switcher.is-normal,
.table,
.textarea,
.textarea.is-normal,
.select,
.select.is-normal,
.modal,
.navbar-item,
.pagination-item,
.pagination-next,
.pagination-prev,
.pagination-first,
.pagination-last,
.pagination,
.pagination.is-normal,
.content,
.content.is-normal {
font-size: 16px;
}
}
.button.is-large,
.buttons.is-large >.button,
.label.is-large,
.input.is-large,
.input-tag.is-large,
.input-group.is-large >.button,
.input-group.is-large >.input,
.input-group.is-large >.input-tag,
.checkbox.is-large,
.radio.is-large,
.switcher.is-large,
.textarea.is-large,
.select.is-large,
.pagination.is-large,
.content.is-large {
font-size: calc( 0.422297297297297vw + 14.256756756756756px );
}
@media screen and (max-width: 767px) {
.button.is-large,
.buttons.is-large >.button,
.label.is-large,
.input.is-large,
.input-tag.is-large,
.input-group.is-large >.button,
.input-group.is-large >.input,
.input-group.is-large >.input-tag,
.checkbox.is-large,
.radio.is-large,
.switcher.is-large,
.textarea.is-large,
.select.is-large,
.pagination.is-large,
.content.is-large {
font-size: 17.5px;
}
}
@media screen and (min-width: 1360px) {
.button.is-large,
.buttons.is-large >.button,
.label.is-large,
.input.is-large,
.input-tag.is-large,
.input-group.is-large >.button,
.input-group.is-large >.input,
.input-group.is-large >.input-tag,
.checkbox.is-large,
.radio.is-large,
.switcher.is-large,
.textarea.is-large,
.select.is-large,
.pagination.is-large,
.content.is-large {
font-size: 20px;
}
}
.button.is-massive,
.buttons.is-massive >.button,
.label.is-massive,
.input.is-massive,
.input-tag.is-massive,
.input-group.is-massive >.button,
.input-group.is-massive >.input,
.input-group.is-massive >.input-tag,
.checkbox.is-massive,
.radio.is-massive,
.switcher.is-massive,
.textarea.is-massive,
.select.is-massive,
.pagination.is-massive,
.content.is-massive {
font-size: calc( 0.506756756756757vw + 17.10810810810811px );
}
@media screen and (max-width: 767px) {
.button.is-massive,
.buttons.is-massive >.button,
.label.is-massive,
.input.is-massive,
.input-tag.is-massive,
.input-group.is-massive >.button,
.input-group.is-massive >.input,
.input-group.is-massive >.input-tag,
.checkbox.is-massive,
.radio.is-massive,
.switcher.is-massive,
.textarea.is-massive,
.select.is-massive,
.pagination.is-massive,
.content.is-massive {
font-size: 21px;
}
}
@media screen and (min-width: 1360px) {
.button.is-massive,
.buttons.is-massive >.button,
.label.is-massive,
.input.is-massive,
.input-tag.is-massive,
.input-group.is-massive >.button,
.input-group.is-massive >.input,
.input-group.is-massive >.input-tag,
.checkbox.is-massive,
.radio.is-massive,
.switcher.is-massive,
.textarea.is-massive,
.select.is-massive,
.pagination.is-massive,
.content.is-massive {
font-size: 24px;
}
}
html {
line-height: 1.1875 /* 1 */;
-ms-text-size-adjust: 100% /* 2 */;
-webkit-text-size-adjust: 100% /* 2 */;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
}
article,
aside,
footer,
header,
nav,
section {
display: block;
}
figcaption,
figure,
main {
/* 1 */
display: block;
}
figure {
margin: 1em 40px;
}
hr {
overflow: visible /* 2 */;
box-sizing: content-box /* 1 */;
height: 0 /* 1 */;
}
pre {
font-size: 1em /* 2 */;
font-family: monospace, monospace /* 1 */;
}
a {
background-color: transparent /* 1 */;
-webkit-text-decoration-skip: objects /* 2 */;
}
abbr[title] {
border-bottom: none /* 1 */;
text-decoration: underline /* 2 */;
text-decoration: underline dotted /* 2 */;
}
b,
strong {
font-weight: inherit;
}
b,
strong {
font-weight: bolder;
}
code,
kbd,
samp {
font-size: 1em /* 2 */;
font-family: monospace, monospace /* 1 */;
}
dfn {
font-style: italic;
}
mark {
background-color: #ff0;
color: #000;
}
small {
font-size: 80%;
}
sub,
sup {
position: relative;
vertical-align: baseline;
font-size: 75%;
line-height: 0;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
audio,
video {
display: inline-block;
}
audio:not([controls]) {
display: none;
height: 0;
}
img {
border-style: none;
}
svg:not(:root) {
overflow: hidden;
}
button,
input,
optgroup,
select,
textarea {
margin: 0 /* 2 */;
font-size: 100% /* 1 */;
font-family: sans-serif /* 1 */;
line-height: 1.15 /* 1 */;
}
button,
input {
/* 1 */
overflow: visible;
}
button,
select {
/* 1 */
text-transform: none;
}
button,
html [type='button'],
[type='reset'],
[type='submit'] {
-webkit-appearance: button /* 2 */;
}
button::-moz-focus-inner,
[type='button']::-moz-focus-inner,
[type='reset']::-moz-focus-inner,
[type='submit']::-moz-focus-inner {
padding: 0;
border-style: none;
}
button:-moz-focusring,
[type='button']:-moz-focusring,
[type='reset']:-moz-focusring,
[type='submit']:-moz-focusring {
outline: 1px dotted ButtonText;
}
fieldset {
padding: 0.35em 0.75em 0.625em;
}
legend {
display: table /* 1 */;
box-sizing: border-box /* 1 */;
padding: 0 /* 3 */;
max-width: 100% /* 1 */;
color: inherit /* 2 */;
white-space: normal /* 1 */;
}
progress {
display: inline-block /* 1 */;
vertical-align: baseline /* 2 */;
}
textarea {
overflow: auto;
}
[type='checkbox'],
[type='radio'] {
box-sizing: border-box /* 1 */;
padding: 0 /* 2 */;
}
[type='number']::-webkit-inner-spin-button,
[type='number']::-webkit-outer-spin-button {
margin: 0;
-webkit-appearance: none;
}
[type=number] {
-moz-appearance: textfield;
}
[type='search'] {
outline-offset: -2px /* 2 */;
-webkit-appearance: textfield /* 1 */;
}
[type='search']::-webkit-search-cancel-button,
[type='search']::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-file-upload-button {
font: inherit /* 2 */;
-webkit-appearance: button /* 1 */;
}
details,
menu {
display: block;
}
summary {
display: list-item;
}
canvas {
display: inline-block;
}
template {
display: none;
}
[hidden] {
display: none;
}
h1,
.h1,
h2,
.h2,
h3,
.h3,
h4,
.h4,
h5,
.h5,
h6,
.h6 {
margin-top: 0;
margin-bottom: 0.5em;
line-height: 1.1875;
font-weight: 900;
}
h1,
.h1 {
font-size: calc( 0.844594594594595vw + 28.513513513513512px );
}
@media screen and (max-width: 767px) {
h1,
.h1 {
font-size: 35px;
}
}
@media screen and (min-width: 1360px) {
h1,
.h1 {
font-size: 40px;
}
}
h2,
.h2 {
font-size: calc( 0.675675675675676vw + 22.81081081081081px );
}
@media screen and (max-width: 767px) {
h2,
.h2 {
font-size: 28px;
}
}
@media screen and (min-width: 1360px) {
h2,
.h2 {
font-size: 32px;
}
}
h3,
.h3 {
font-size: calc( 0.591216216216216vw + 19.95945945945946px );
}
@media screen and (max-width: 767px) {
h3,
.h3 {
font-size: 24.5px;
}
}
@media screen and (min-width: 1360px) {
h3,
.h3 {
font-size: 28px;
}
}
h4,
.h4 {
font-size: calc( 0.506756756756757vw + 17.10810810810811px );
}
@media screen and (max-width: 767px) {
h4,
.h4 {
font-size: 21px;
}
}
@media screen and (min-width: 1360px) {
h4,
.h4 {
font-size: 24px;
}
}
h5,
.h5 {
font-size: calc( 0.422297297297297vw + 14.256756756756756px );
}
@media screen and (max-width: 767px) {
h5,
.h5 {
font-size: 17.5px;
}
}
@media screen and (min-width: 1360px) {
h5,
.h5 {
font-size: 20px;
}
}
h6,
.h6 {
font-size: calc( 0.337837837837838vw + 11.405405405405405px );
}
@media screen and (max-width: 767px) {
h6,
.h6 {
font-size: 14px;
}
}
@media screen and (min-width: 1360px) {
h6,
.h6 {
font-size: 16px;
}
}
p,
body {
margin: 0;
}
::selection {
background: #0072ff;
color: #fff;
}
*::placeholder {
color: #aeaeae;
opacity: 1;
}
*::placeholder:focus {
outline: 0;
}
html,
input,
button {
direction: ltr;
font-family: 'Graphik', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
font-weight: 400;
}
a {
color: #0072ff;
cursor: pointer;
text-decoration: none;
}
a:hover {
color: #eb008b;
}
img {
max-width: 100%;
height: auto;
}
strong,
b {
font-weight: 900;
}
pre {
direction: ltr;
}
.container {
width: calc(100% - 22px);
margin: auto;
padding-left: 1.5625vw;
padding-right: 1.5625vw;
}
@media screen and (min-width: 768px) {
.container {
width: 724px;
}
}
@media screen and (min-width: 991px) {
.container {
width: 925px;
}
}
@media screen and (min-width: 1360px) {
.container {
width: 1272px;
}
}
@media screen and (min-width: 1920px) {
.container {
width: 1810px;
}
}
.container-full {
width: 100%;
padding-left: 8vw;
padding-right: 8vw;
}
.column {
flex: 1 0;
padding-right: 1.5625vw;
padding-left: 1.5625vw;
}
.column[class*='is-tablet-'],
.column[class*='is-desktop-'],
.column[class*='is-widescreen-'],
.column[class*='is-ultrawide-'],
.grid[class*='is-tablet-'] >.column:not([class*='is-']),
.grid[class*='is-desktop-'] >.column:not([class*='is-']),
.grid[class*='is-widescreen-'] >.column:not([class*='is-']),
.grid[class*='is-ultrawide-'] >.column:not([class*='is-']),
.row[class*='is-tablet-'] >.column:not([class*='is-']),
.row[class*='is-desktop-'] >.column:not([class*='is-']),
.row[class*='is-widescreen-'] >.column:not([class*='is-']),
.row[class*='is-ultrawide-'] >.column:not([class*='is-']) {
flex: 1 0 100%;
min-width: 100%;
}
.column.is-0,
.column.is-mobile-0 {
flex: 0 0 0%;
min-width: 0%;
}
.column.is-offset-0,
.column.is-offset-mobile-0 {
margin-left: 0%;
}
.column.is-1,
.column.is-mobile-1,
.grid.is-1 >.column:not([class*='is-']),
.grid.is-mobile-1 >.column:not([class*='is-']),
.row.is-1 >.column:not([class*='is-']),
.row.is-mobile-1 >.column:not([class*='is-']) {
flex: 0 0 8.333333333333332%;
min-width: 8.333333333333332%;
}
.column.is-offset-1,
.column.is-offset-mobile-1 {
margin-left: 8.333333333333332%;
}
.column.is-2,
.column.is-mobile-2,
.grid.is-2 >.column:not([class*='is-']),
.grid.is-mobile-2 >.column:not([class*='is-']),
.row.is-2 >.column:not([class*='is-']),
.row.is-mobile-2 >.column:not([class*='is-']) {
flex: 0 0 16.666666666666664%;
min-width: 16.666666666666664%;
}
.column.is-offset-2,
.column.is-offset-mobile-2 {
margin-left: 16.666666666666664%;
}
.column.is-3,
.column.is-mobile-3,
.grid.is-3 >.column:not([class*='is-']),
.grid.is-mobile-3 >.column:not([class*='is-']),
.row.is-3 >.column:not([class*='is-']),
.row.is-mobile-3 >.column:not([class*='is-']) {
flex: 0 0 25%;
min-width: 25%;
}
.column.is-offset-3,
.column.is-offset-mobile-3 {
margin-left: 25%;
}
.column.is-4,
.column.is-mobile-4,
.grid.is-4 >.column:not([class*='is-']),
.grid.is-mobile-4 >.column:not([class*='is-']),
.row.is-4 >.column:not([class*='is-']),
.row.is-mobile-4 >.column:not([class*='is-']) {
flex: 0 0 33.33333333333333%;
min-width: 33.33333333333333%;
}
.column.is-offset-4,
.column.is-offset-mobile-4 {
margin-left: 33.33333333333333%;
}
.column.is-5,
.column.is-mobile-5,
.grid.is-5 >.column:not([class*='is-']),
.grid.is-mobile-5 >.column:not([class*='is-']),
.row.is-5 >.column:not([class*='is-']),
.row.is-mobile-5 >.column:not([class*='is-']) {
flex: 0 0 41.66666666666667%;
min-width: 41.66666666666667%;
}
.column.is-offset-5,
.column.is-offset-mobile-5 {
margin-left: 41.66666666666667%;
}
.column.is-6,
.column.is-mobile-6,
.grid.is-6 >.column:not([class*='is-']),
.grid.is-mobile-6 >.column:not([class*='is-']),
.row.is-6 >.column:not([class*='is-']),
.row.is-mobile-6 >.column:not([class*='is-']) {
flex: 0 0 50%;
min-width: 50%;
}
.column.is-offset-6,
.column.is-offset-mobile-6 {
margin-left: 50%;
}
.column.is-7,
.column.is-mobile-7,
.grid.is-7 >.column:not([class*='is-']),
.grid.is-mobile-7 >.column:not([class*='is-']),
.row.is-7 >.column:not([class*='is-']),
.row.is-mobile-7 >.column:not([class*='is-']) {
flex: 0 0 58.333333333333336%;
min-width: 58.333333333333336%;
}
.column.is-offset-7,
.column.is-offset-mobile-7 {
margin-left: 58.333333333333336%;
}
.column.is-8,
.column.is-mobile-8,
.grid.is-8 >.column:not([class*='is-']),
.grid.is-mobile-8 >.column:not([class*='is-']),
.row.is-8 >.column:not([class*='is-']),
.row.is-mobile-8 >.column:not([class*='is-']) {
flex: 0 0 66.66666666666666%;
min-width: 66.66666666666666%;
}
.column.is-offset-8,
.column.is-offset-mobile-8 {
margin-left: 66.66666666666666%;
}
.column.is-9,
.column.is-mobile-9,
.grid.is-9 >.column:not([class*='is-']),
.grid.is-mobile-9 >.column:not([class*='is-']),
.row.is-9 >.column:not([class*='is-']),
.row.is-mobile-9 >.column:not([class*='is-']) {
flex: 0 0 75%;
min-width: 75%;
}
.column.is-offset-9,
.column.is-offset-mobile-9 {
margin-left: 75%;
}
.column.is-10,
.column.is-mobile-10,
.grid.is-10 >.column:not([class*='is-']),
.grid.is-mobile-10 >.column:not([class*='is-']),
.row.is-10 >.column:not([class*='is-']),
.row.is-mobile-10 >.column:not([class*='is-']) {
flex: 0 0 83.33333333333334%;
min-width: 83.33333333333334%;
}
.column.is-offset-10,
.column.is-offset-mobile-10 {
margin-left: 83.33333333333334%;
}
.column.is-11,
.column.is-mobile-11,
.grid.is-11 >.column:not([class*='is-']),
.grid.is-mobile-11 >.column:not([class*='is-']),
.row.is-11 >.column:not([class*='is-']),
.row.is-mobile-11 >.column:not([class*='is-']) {
flex: 0 0 91.66666666666666%;
min-width: 91.66666666666666%;
}
.column.is-offset-11,
.column.is-offset-mobile-11 {
margin-left: 91.66666666666666%;
}
.column.is-12,
.column.is-mobile-12,
.grid.is-12 >.column:not([class*='is-']),
.grid.is-mobile-12 >.column:not([class*='is-']),
.row.is-12 >.column:not([class*='is-']),
.row.is-mobile-12 >.column:not([class*='is-']) {
flex: 0 0 100%;
min-width: 100%;
}
.column.is-offset-12,
.column.is-offset-mobile-12 {
margin-left: 100%;
}
@media screen and (min-width: 768px) {
.column.is-tablet-0 {
flex: 0 0 0%;
min-width: 0%;
}
.column.is-offset-tablet-0 {
margin-left: 0%;
}
.column.is-tablet-1,
.grid.is-tablet-1 >.column:not([class*='is-']),
.row.is-tablet-1 >.column:not([class*='is-']) {
flex: 0 0 8.333333333333332%;
min-width: 8.333333333333332%;
}
.column.is-offset-tablet-1 {
margin-left: 8.333333333333332%;
}
.column.is-tablet-2,
.grid.is-tablet-2 >.column:not([class*='is-']),
.row.is-tablet-2 >.column:not([class*='is-']) {
flex: 0 0 16.666666666666664%;
min-width: 16.666666666666664%;
}
.column.is-offset-tablet-2 {
margin-left: 16.666666666666664%;
}
.column.is-tablet-3,
.grid.is-tablet-3 >.column:not([class*='is-']),
.row.is-tablet-3 >.column:not([class*='is-']) {
flex: 0 0 25%;
min-width: 25%;
}
.column.is-offset-tablet-3 {
margin-left: 25%;
}
.column.is-tablet-4,
.grid.is-tablet-4 >.column:not([class*='is-']),
.row.is-tablet-4 >.column:not([class*='is-']) {
flex: 0 0 33.33333333333333%;
min-width: 33.33333333333333%;
}
.column.is-offset-tablet-4 {
margin-left: 33.33333333333333%;
}
.column.is-tablet-5,
.grid.is-tablet-5 >.column:not([class*='is-']),
.row.is-tablet-5 >.column:not([class*='is-']) {
flex: 0 0 41.66666666666667%;
min-width: 41.66666666666667%;
}
.column.is-offset-tablet-5 {
margin-left: 41.66666666666667%;
}
.column.is-tablet-6,
.grid.is-tablet-6 >.column:not([class*='is-']),
.row.is-tablet-6 >.column:not([class*='is-']) {
flex: 0 0 50%;
min-width: 50%;
}
.column.is-offset-tablet-6 {
margin-left: 50%;
}
.column.is-tablet-7,
.grid.is-tablet-7 >.column:not([class*='is-']),
.row.is-tablet-7 >.column:not([class*='is-']) {
flex: 0 0 58.333333333333336%;
min-width: 58.333333333333336%;
}
.column.is-offset-tablet-7 {
margin-left: 58.333333333333336%;
}
.column.is-tablet-8,
.grid.is-tablet-8 >.column:not([class*='is-']),
.row.is-tablet-8 >.column:not([class*='is-']) {
flex: 0 0 66.66666666666666%;
min-width: 66.66666666666666%;
}
.column.is-offset-tablet-8 {
margin-left: 66.66666666666666%;
}
.column.is-tablet-9,
.grid.is-tablet-9 >.column:not([class*='is-']),
.row.is-tablet-9 >.column:not([class*='is-']) {
flex: 0 0 75%;
min-width: 75%;
}
.column.is-offset-tablet-9 {
margin-left: 75%;
}
.column.is-tablet-10,
.grid.is-tablet-10 >.column:not([class*='is-']),
.row.is-tablet-10 >.column:not([class*='is-']) {
flex: 0 0 83.33333333333334%;
min-width: 83.33333333333334%;
}
.column.is-offset-tablet-10 {
margin-left: 83.33333333333334%;
}
.column.is-tablet-11,
.grid.is-tablet-11 >.column:not([class*='is-']),
.row.is-tablet-11 >.column:not([class*='is-']) {
flex: 0 0 91.66666666666666%;
min-width: 91.66666666666666%;
}
.column.is-offset-tablet-11 {
margin-left: 91.66666666666666%;
}
.column.is-tablet-12,
.grid.is-tablet-12 >.column:not([class*='is-']),
.row.is-tablet-12 >.column:not([class*='is-']) {
flex: 0 0 100%;
min-width: 100%;
}
.column.is-offset-tablet-12 {
margin-left: 100%;
}
}
@media screen and (min-width: 991px) {
.column.is-desktop-0 {
flex: 0 0 0%;
min-width: 0%;
}
.column.is-offset-desktop-0 {
margin-left: 0%;
}
.column.is-desktop-1,
.grid.is-desktop-1 >.column:not([class*='is-']),
.row.is-desktop-1 >.column:not([class*='is-']) {
flex: 0 0 8.333333333333332%;
min-width: 8.333333333333332%;
}
.column.is-offset-desktop-1 {
margin-left: 8.333333333333332%;
}
.column.is-desktop-2,
.grid.is-desktop-2 >.column:not([class*='is-']),
.row.is-desktop-2 >.column:not([class*='is-']) {
flex: 0 0 16.666666666666664%;
min-width: 16.666666666666664%;
}
.column.is-offset-desktop-2 {
margin-left: 16.666666666666664%;
}
.column.is-desktop-3,
.grid.is-desktop-3 >.column:not([class*='is-']),
.row.is-desktop-3 >.column:not([class*='is-']) {
flex: 0 0 25%;
min-width: 25%;
}
.column.is-offset-desktop-3 {
margin-left: 25%;
}
.column.is-desktop-4,
.grid.is-desktop-4 >.column:not([class*='is-']),
.row.is-desktop-4 >.column:not([class*='is-']) {
flex: 0 0 33.33333333333333%;
min-width: 33.33333333333333%;
}
.column.is-offset-desktop-4 {
margin-left: 33.33333333333333%;
}
.column.is-desktop-5,
.grid.is-desktop-5 >.column:not([class*='is-']),
.row.is-desktop-5 >.column:not([class*='is-']) {
flex: 0 0 41.66666666666667%;
min-width: 41.66666666666667%;
}
.column.is-offset-desktop-5 {
margin-left: 41.66666666666667%;
}
.column.is-desktop-6,
.grid.is-desktop-6 >.column:not([class*='is-']),
.row.is-desktop-6 >.column:not([class*='is-']) {
flex: 0 0 50%;
min-width: 50%;
}
.column.is-offset-desktop-6 {
margin-left: 50%;
}
.column.is-desktop-7,
.grid.is-desktop-7 >.column:not([class*='is-']),
.row.is-desktop-7 >.column:not([class*='is-']) {
flex: 0 0 58.333333333333336%;
min-width: 58.333333333333336%;
}
.column.is-offset-desktop-7 {
margin-left: 58.333333333333336%;
}
.column.is-desktop-8,
.grid.is-desktop-8 >.column:not([class*='is-']),
.row.is-desktop-8 >.column:not([class*='is-']) {
flex: 0 0 66.66666666666666%;
min-width: 66.66666666666666%;
}
.column.is-offset-desktop-8 {
margin-left: 66.66666666666666%;
}
.column.is-desktop-9,
.grid.is-desktop-9 >.column:not([class*='is-']),
.row.is-desktop-9 >.column:not([class*='is-']) {
flex: 0 0 75%;
min-width: 75%;
}
.column.is-offset-desktop-9 {
margin-left: 75%;
}
.column.is-desktop-10,
.grid.is-desktop-10 >.column:not([class*='is-']),
.row.is-desktop-10 >.column:not([class*='is-']) {
flex: 0 0 83.33333333333334%;
min-width: 83.33333333333334%;
}
.column.is-offset-desktop-10 {
margin-left: 83.33333333333334%;
}
.column.is-desktop-11,
.grid.is-desktop-11 >.column:not([class*='is-']),
.row.is-desktop-11 >.column:not([class*='is-']) {
flex: 0 0 91.66666666666666%;
min-width: 91.66666666666666%;
}
.column.is-offset-desktop-11 {
margin-left: 91.66666666666666%;
}
.column.is-desktop-12,
.grid.is-desktop-12 >.column:not([class*='is-']),
.row.is-desktop-12 >.column:not([class*='is-']) {
flex: 0 0 100%;
min-width: 100%;
}
.column.is-offset-desktop-12 {
margin-left: 100%;
}
}
@media screen and (min-width: 1360px) {
.column.is-widescreen-0 {
flex: 0 0 0%;
min-width: 0%;
}
.column.is-offset-widescreen-0 {
margin-left: 0%;
}
.column.is-widescreen-1,
.grid.is-widescreen-1 >.column:not([class*='is-']),
.row.is-widescreen-1 >.column:not([class*='is-']) {
flex: 0 0 8.333333333333332%;
min-width: 8.333333333333332%;
}
.column.is-offset-widescreen-1 {
margin-left: 8.333333333333332%;
}
.column.is-widescreen-2,
.grid.is-widescreen-2 >.column:not([class*='is-']),
.row.is-widescreen-2 >.column:not([class*='is-']) {
flex: 0 0 16.666666666666664%;
min-width: 16.666666666666664%;
}
.column.is-offset-widescreen-2 {
margin-left: 16.666666666666664%;
}
.column.is-widescreen-3,
.grid.is-widescreen-3 >.column:not([class*='is-']),
.row.is-widescreen-3 >.column:not([class*='is-']) {
flex: 0 0 25%;
min-width: 25%;
}
.column.is-offset-widescreen-3 {
margin-left: 25%;
}
.column.is-widescreen-4,
.grid.is-widescreen-4 >.column:not([class*='is-']),
.row.is-widescreen-4 >.column:not([class*='is-']) {
flex: 0 0 33.33333333333333%;
min-width: 33.33333333333333%;
}
.column.is-offset-widescreen-4 {
margin-left: 33.33333333333333%;
}
.column.is-widescreen-5,
.grid.is-widescreen-5 >.column:not([class*='is-']),
.row.is-widescreen-5 >.column:not([class*='is-']) {
flex: 0 0 41.66666666666667%;
min-width: 41.66666666666667%;
}
.column.is-offset-widescreen-5 {
margin-left: 41.66666666666667%;
}
.column.is-widescreen-6,
.grid.is-widescreen-6 >.column:not([class*='is-']),
.row.is-widescreen-6 >.column:not([class*='is-']) {
flex: 0 0 50%;
min-width: 50%;
}
.column.is-offset-widescreen-6 {
margin-left: 50%;
}
.column.is-widescreen-7,
.grid.is-widescreen-7 >.column:not([class*='is-']),
.row.is-widescreen-7 >.column:not([class*='is-']) {
flex: 0 0 58.333333333333336%;
min-width: 58.333333333333336%;
}
.column.is-offset-widescreen-7 {
margin-left: 58.333333333333336%;
}
.column.is-widescreen-8,
.grid.is-widescreen-8 >.column:not([class*='is-']),
.row.is-widescreen-8 >.column:not([class*='is-']) {
flex: 0 0 66.66666666666666%;
min-width: 66.66666666666666%;
}
.column.is-offset-widescreen-8 {
margin-left: 66.66666666666666%;
}
.column.is-widescreen-9,
.grid.is-widescreen-9 >.column:not([class*='is-']),
.row.is-widescreen-9 >.column:not([class*='is-']) {
flex: 0 0 75%;
min-width: 75%;
}
.column.is-offset-widescreen-9 {
margin-left: 75%;
}
.column.is-widescreen-10,
.grid.is-widescreen-10 >.column:not([class*='is-']),
.row.is-widescreen-10 >.column:not([class*='is-']) {
flex: 0 0 83.33333333333334%;
min-width: 83.33333333333334%;
}
.column.is-offset-widescreen-10 {
margin-left: 83.33333333333334%;
}
.column.is-widescreen-11,
.grid.is-widescreen-11 >.column:not([class*='is-']),
.row.is-widescreen-11 >.column:not([class*='is-']) {
flex: 0 0 91.66666666666666%;
min-width: 91.66666666666666%;
}
.column.is-offset-widescreen-11 {
margin-left: 91.66666666666666%;
}
.column.is-widescreen-12,
.grid.is-widescreen-12 >.column:not([class*='is-']),
.row.is-widescreen-12 >.column:not([class*='is-']) {
flex: 0 0 100%;
min-width: 100%;
}
.column.is-offset-widescreen-12 {
margin-left: 100%;
}
}
@media screen and (min-width: 1920px) {
.column.is-ultrawide-0 {
flex: 0 0 0%;
min-width: 0%;
}
.column.is-offset-ultrawide-0 {
margin-left: 0%;
}
.column.is-ultrawide-1,
.grid.is-ultrawide-1 >.column:not([class*='is-']),
.row.is-ultrawide-1 >.column:not([class*='is-']) {
flex: 0 0 8.333333333333332%;
min-width: 8.333333333333332%;
}
.column.is-offset-ultrawide-1 {
margin-left: 8.333333333333332%;
}
.column.is-ultrawide-2,
.grid.is-ultrawide-2 >.column:not([class*='is-']),
.row.is-ultrawide-2 >.column:not([class*='is-']) {
flex: 0 0 16.666666666666664%;
min-width: 16.666666666666664%;
}
.column.is-offset-ultrawide-2 {
margin-left: 16.666666666666664%;
}
.column.is-ultrawide-3,
.grid.is-ultrawide-3 >.column:not([class*='is-']),
.row.is-ultrawide-3 >.column:not([class*='is-']) {
flex: 0 0 25%;
min-width: 25%;
}
.column.is-offset-ultrawide-3 {
margin-left: 25%;
}
.column.is-ultrawide-4,
.grid.is-ultrawide-4 >.column:not([class*='is-']),
.row.is-ultrawide-4 >.column:not([class*='is-']) {
flex: 0 0 33.33333333333333%;
min-width: 33.33333333333333%;
}
.column.is-offset-ultrawide-4 {
margin-left: 33.33333333333333%;
}
.column.is-ultrawide-5,
.grid.is-ultrawide-5 >.column:not([class*='is-']),
.row.is-ultrawide-5 >.column:not([class*='is-']) {
flex: 0 0 41.66666666666667%;
min-width: 41.66666666666667%;
}
.column.is-offset-ultrawide-5 {
margin-left: 41.66666666666667%;
}
.column.is-ultrawide-6,
.grid.is-ultrawide-6 >.column:not([class*='is-']),
.row.is-ultrawide-6 >.column:not([class*='is-']) {
flex: 0 0 50%;
min-width: 50%;
}
.column.is-offset-ultrawide-6 {
margin-left: 50%;
}
.column.is-ultrawide-7,
.grid.is-ultrawide-7 >.column:not([class*='is-']),
.row.is-ultrawide-7 >.column:not([class*='is-']) {
flex: 0 0 58.333333333333336%;
min-width: 58.333333333333336%;
}
.column.is-offset-ultrawide-7 {
margin-left: 58.333333333333336%;
}
.column.is-ultrawide-8,
.grid.is-ultrawide-8 >.column:not([class*='is-']),
.row.is-ultrawide-8 >.column:not([class*='is-']) {
flex: 0 0 66.66666666666666%;
min-width: 66.66666666666666%;
}
.column.is-offset-ultrawide-8 {
margin-left: 66.66666666666666%;
}
.column.is-ultrawide-9,
.grid.is-ultrawide-9 >.column:not([class*='is-']),
.row.is-ultrawide-9 >.column:not([class*='is-']) {
flex: 0 0 75%;
min-width: 75%;
}
.column.is-offset-ultrawide-9 {
margin-left: 75%;
}
.column.is-ultrawide-10,
.grid.is-ultrawide-10 >.column:not([class*='is-']),
.row.is-ultrawide-10 >.column:not([class*='is-']) {
flex: 0 0 83.33333333333334%;
min-width: 83.33333333333334%;
}
.column.is-offset-ultrawide-10 {
margin-left: 83.33333333333334%;
}
.column.is-ultrawide-11,
.grid.is-ultrawide-11 >.column:not([class*='is-']),
.row.is-ultrawide-11 >.column:not([class*='is-']) {
flex: 0 0 91.66666666666666%;
min-width: 91.66666666666666%;
}
.column.is-offset-ultrawide-11 {
margin-left: 91.66666666666666%;
}
.column.is-ultrawide-12,
.grid.is-ultrawide-12 >.column:not([class*='is-']),
.row.is-ultrawide-12 >.column:not([class*='is-']) {
flex: 0 0 100%;
min-width: 100%;
}
.column.is-offset-ultrawide-12 {
margin-left: 100%;
}
}
.column.is-middle {
align-self: center;
}
.column.is-top {
align-self: flex-start;
}
.column.is-bottom {
align-self: flex-end;
}
.column >.row {
margin: 0 -1.5625vw;
min-width: calc(100% + 3.125vw);
}
.grid,
.row {
position: relative;
display: flex;
flex-wrap: wrap;
margin-right: -1.5625vw;
margin-left: -1.5625vw;
width: auto;
}
.grid.is-center,
.row.is-center {
justify-content: center;
}
.grid.is-end,
.row.is-end {
justify-content: flex-end;
}
.grid.is-start,
.row.is-start {
justify-content: flex-start;
}
.grid.is-middle,
.row.is-middle {
align-items: center;
}
.grid.is-top,
.row.is-top {
align-items: flex-start;
}
.grid.is-bottom,
.row.is-bottom {
align-items: flex-end;
}
.grid.is-vertical,
.row.is-vertical {
flex-direction: column;
align-items: flex-start;
}
.grid.is-shrink >.column:not([class*='is-']),
.row.is-shrink >.column:not([class*='is-']) {
flex: 0 0 auto;
}
.grid.is-relaxed,
.row.is-relaxed {
margin-right: 0;
margin-left: 0;
}
.grid.is-relaxed >.column,
.row.is-relaxed >.column {
padding: 0;
}
.row {
width: 100%;
justify-content: inherit;
margin: 0;
}
.button {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
margin-bottom: 10px;
padding: 0.5em 0.75em;
outline: none;
border-width: 1px;
border-style: solid;
border-radius: 4px;
background-clip: border-box;
vertical-align: top;
text-align: center;
text-decoration: none;
cursor: pointer;
transition: 0.4s ease-in-out;
border-color: #0072ff;
background-color: #0072ff;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-inverse {
background-color: transparent;
color: #0072ff;
fill: #0072ff;
stroke-width: 0;
}
.button:hover,
.button:active,
.button.is-active {
border-color: #0061d9;
background-color: #0061d9;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button:focus {
box-shadow: 0 0 0 3px rgba(0,114,255,0.25);
}
.button[disabled] {
border-color: #0072ff;
background-color: #0072ff;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-primary,
.buttons.is-primary >.button,
.input-group.is-primary >.button {
border-color: #0072ff;
background-color: #0072ff;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-primary.is-inverse,
.buttons.is-primary >.button.is-inverse,
.input-group.is-primary >.button.is-inverse,
.buttons.is-primary.is-inverse >.button {
background-color: transparent;
color: #0072ff;
fill: #0072ff;
stroke-width: 0;
}
.button.is-primary:hover,
.buttons.is-primary >.button:hover,
.input-group.is-primary >.button:hover,
.button.is-primary:active,
.buttons.is-primary >.button:active,
.input-group.is-primary >.button:active,
.button.is-primary.is-active,
.buttons.is-primary >.button.is-active,
.input-group.is-primary >.button.is-active {
border-color: #0061d9;
background-color: #0061d9;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-primary:focus,
.buttons.is-primary >.button:focus,
.input-group.is-primary >.button:focus {
box-shadow: 0 0 0 3px rgba(0,114,255,0.25);
}
.button.is-primary[disabled],
.buttons.is-primary >.button[disabled],
.input-group.is-primary >.button[disabled] {
border-color: #0072ff;
background-color: #0072ff;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-secondary,
.buttons.is-secondary >.button,
.input-group.is-secondary >.button {
border-color: #c7c7c7;
background-color: #c7c7c7;
color: #000;
fill: #000;
stroke-width: 0;
}
.button.is-secondary.is-inverse,
.buttons.is-secondary >.button.is-inverse,
.input-group.is-secondary >.button.is-inverse,
.buttons.is-secondary.is-inverse >.button {
background-color: transparent;
color: #c7c7c7;
fill: #c7c7c7;
stroke-width: 0;
}
.button.is-secondary:hover,
.buttons.is-secondary >.button:hover,
.input-group.is-secondary >.button:hover,
.button.is-secondary:active,
.buttons.is-secondary >.button:active,
.input-group.is-secondary >.button:active,
.button.is-secondary.is-active,
.buttons.is-secondary >.button.is-active,
.input-group.is-secondary >.button.is-active {
border-color: #a9a9a9;
background-color: #a9a9a9;
color: #000;
fill: #000;
stroke-width: 0;
}
.button.is-secondary:focus,
.buttons.is-secondary >.button:focus,
.input-group.is-secondary >.button:focus {
box-shadow: 0 0 0 3px rgba(199,199,199,0.25);
}
.button.is-secondary[disabled],
.buttons.is-secondary >.button[disabled],
.input-group.is-secondary >.button[disabled] {
border-color: #c7c7c7;
background-color: #c7c7c7;
color: #000;
fill: #000;
stroke-width: 0;
}
.button.is-info,
.buttons.is-info >.button,
.input-group.is-info >.button {
border-color: #00d4f0;
background-color: #00d4f0;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-info.is-inverse,
.buttons.is-info >.button.is-inverse,
.input-group.is-info >.button.is-inverse,
.buttons.is-info.is-inverse >.button {
background-color: transparent;
color: #00d4f0;
fill: #00d4f0;
stroke-width: 0;
}
.button.is-info:hover,
.buttons.is-info >.button:hover,
.input-group.is-info >.button:hover,
.button.is-info:active,
.buttons.is-info >.button:active,
.input-group.is-info >.button:active,
.button.is-info.is-active,
.buttons.is-info >.button.is-active,
.input-group.is-info >.button.is-active {
border-color: #00b4cc;
background-color: #00b4cc;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-info:focus,
.buttons.is-info >.button:focus,
.input-group.is-info >.button:focus {
box-shadow: 0 0 0 3px rgba(0,212,240,0.25);
}
.button.is-info[disabled],
.buttons.is-info >.button[disabled],
.input-group.is-info >.button[disabled] {
border-color: #00d4f0;
background-color: #00d4f0;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-success,
.buttons.is-success >.button,
.input-group.is-success >.button {
border-color: #18d88b;
background-color: #18d88b;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-success.is-inverse,
.buttons.is-success >.button.is-inverse,
.input-group.is-success >.button.is-inverse,
.buttons.is-success.is-inverse >.button {
background-color: transparent;
color: #18d88b;
fill: #18d88b;
stroke-width: 0;
}
.button.is-success:hover,
.buttons.is-success >.button:hover,
.input-group.is-success >.button:hover,
.button.is-success:active,
.buttons.is-success >.button:active,
.input-group.is-success >.button:active,
.button.is-success.is-active,
.buttons.is-success >.button.is-active,
.input-group.is-success >.button.is-active {
border-color: #14b876;
background-color: #14b876;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-success:focus,
.buttons.is-success >.button:focus,
.input-group.is-success >.button:focus {
box-shadow: 0 0 0 3px rgba(24,216,139,0.25);
}
.button.is-success[disabled],
.buttons.is-success >.button[disabled],
.input-group.is-success >.button[disabled] {
border-color: #18d88b;
background-color: #18d88b;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-warning,
.buttons.is-warning >.button,
.input-group.is-warning >.button {
border-color: #ffa557;
background-color: #ffa557;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-warning.is-inverse,
.buttons.is-warning >.button.is-inverse,
.input-group.is-warning >.button.is-inverse,
.buttons.is-warning.is-inverse >.button {
background-color: transparent;
color: #ffa557;
fill: #ffa557;
stroke-width: 0;
}
.button.is-warning:hover,
.buttons.is-warning >.button:hover,
.input-group.is-warning >.button:hover,
.button.is-warning:active,
.buttons.is-warning >.button:active,
.input-group.is-warning >.button:active,
.button.is-warning.is-active,
.buttons.is-warning >.button.is-active,
.input-group.is-warning >.button.is-active {
border-color: #ff8a24;
background-color: #ff8a24;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-warning:focus,
.buttons.is-warning >.button:focus,
.input-group.is-warning >.button:focus {
box-shadow: 0 0 0 3px rgba(255,165,87,0.25);
}
.button.is-warning[disabled],
.buttons.is-warning >.button[disabled],
.input-group.is-warning >.button[disabled] {
border-color: #ffa557;
background-color: #ffa557;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-danger,
.buttons.is-danger >.button,
.input-group.is-danger >.button {
border-color: #ff3d3d;
background-color: #ff3d3d;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-danger.is-inverse,
.buttons.is-danger >.button.is-inverse,
.input-group.is-danger >.button.is-inverse,
.buttons.is-danger.is-inverse >.button {
background-color: transparent;
color: #ff3d3d;
fill: #ff3d3d;
stroke-width: 0;
}
.button.is-danger:hover,
.buttons.is-danger >.button:hover,
.input-group.is-danger >.button:hover,
.button.is-danger:active,
.buttons.is-danger >.button:active,
.input-group.is-danger >.button:active,
.button.is-danger.is-active,
.buttons.is-danger >.button.is-active,
.input-group.is-danger >.button.is-active {
border-color: #ff0e0e;
background-color: #ff0e0e;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-danger:focus,
.buttons.is-danger >.button:focus,
.input-group.is-danger >.button:focus {
box-shadow: 0 0 0 3px rgba(255,61,61,0.25);
}
.button.is-danger[disabled],
.buttons.is-danger >.button[disabled],
.input-group.is-danger >.button[disabled] {
border-color: #ff3d3d;
background-color: #ff3d3d;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-black,
.buttons.is-black >.button,
.input-group.is-black >.button {
border-color: #000;
background-color: #000;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-black.is-inverse,
.buttons.is-black >.button.is-inverse,
.input-group.is-black >.button.is-inverse,
.buttons.is-black.is-inverse >.button {
background-color: transparent;
color: #000;
fill: #000;
stroke-width: 0;
}
.button.is-black:hover,
.buttons.is-black >.button:hover,
.input-group.is-black >.button:hover,
.button.is-black:active,
.buttons.is-black >.button:active,
.input-group.is-black >.button:active,
.button.is-black.is-active,
.buttons.is-black >.button.is-active,
.input-group.is-black >.button.is-active {
border-color: #000;
background-color: #000;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-black:focus,
.buttons.is-black >.button:focus,
.input-group.is-black >.button:focus {
box-shadow: 0 0 0 3px rgba(0,0,0,0.25);
}
.button.is-black[disabled],
.buttons.is-black >.button[disabled],
.input-group.is-black >.button[disabled] {
border-color: #000;
background-color: #000;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-white,
.buttons.is-white >.button,
.input-group.is-white >.button {
border-color: #fff;
background-color: #fff;
color: #000;
fill: #000;
stroke-width: 0;
}
.button.is-white.is-inverse,
.buttons.is-white >.button.is-inverse,
.input-group.is-white >.button.is-inverse,
.buttons.is-white.is-inverse >.button {
background-color: transparent;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-white:hover,
.buttons.is-white >.button:hover,
.input-group.is-white >.button:hover,
.button.is-white:active,
.buttons.is-white >.button:active,
.input-group.is-white >.button:active,
.button.is-white.is-active,
.buttons.is-white >.button.is-active,
.input-group.is-white >.button.is-active {
border-color: #d9d9d9;
background-color: #d9d9d9;
color: #000;
fill: #000;
stroke-width: 0;
}
.button.is-white:focus,
.buttons.is-white >.button:focus,
.input-group.is-white >.button:focus {
box-shadow: 0 0 0 3px rgba(255,255,255,0.25);
}
.button.is-white[disabled],
.buttons.is-white >.button[disabled],
.input-group.is-white >.button[disabled] {
border-color: #fff;
background-color: #fff;
color: #000;
fill: #000;
stroke-width: 0;
}
.button.is-dark,
.buttons.is-dark >.button,
.input-group.is-dark >.button {
border-color: #323c47;
background-color: #323c47;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-dark.is-inverse,
.buttons.is-dark >.button.is-inverse,
.input-group.is-dark >.button.is-inverse,
.buttons.is-dark.is-inverse >.button {
background-color: transparent;
color: #323c47;
fill: #323c47;
stroke-width: 0;
}
.button.is-dark:hover,
.buttons.is-dark >.button:hover,
.input-group.is-dark >.button:hover,
.button.is-dark:active,
.buttons.is-dark >.button:active,
.input-group.is-dark >.button:active,
.button.is-dark.is-active,
.buttons.is-dark >.button.is-active,
.input-group.is-dark >.button.is-active {
border-color: #2a333c;
background-color: #2a333c;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-dark:focus,
.buttons.is-dark >.button:focus,
.input-group.is-dark >.button:focus {
box-shadow: 0 0 0 3px rgba(50,60,71,0.25);
}
.button.is-dark[disabled],
.buttons.is-dark >.button[disabled],
.input-group.is-dark >.button[disabled] {
border-color: #323c47;
background-color: #323c47;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.button.is-light,
.buttons.is-light >.button,
.input-group.is-light >.button {
border-color: #f5f5f5;
background-color: #f5f5f5;
color: #000;
fill: #000;
stroke-width: 0;
}
.button.is-light.is-inverse,
.buttons.is-light >.button.is-inverse,
.input-group.is-light >.button.is-inverse,
.buttons.is-light.is-inverse >.button {
background-color: transparent;
color: #f5f5f5;
fill: #f5f5f5;
stroke-width: 0;
}
.button.is-light:hover,
.buttons.is-light >.button:hover,
.input-group.is-light >.button:hover,
.button.is-light:active,
.buttons.is-light >.button:active,
.input-group.is-light >.button:active,
.button.is-light.is-active,
.buttons.is-light >.button.is-active,
.input-group.is-light >.button.is-active {
border-color: #d0d0d0;
background-color: #d0d0d0;
color: #000;
fill: #000;
stroke-width: 0;
}
.button.is-light:focus,
.buttons.is-light >.button:focus,
.input-group.is-light >.button:focus {
box-shadow: 0 0 0 3px rgba(245,245,245,0.25);
}
.button.is-light[disabled],
.buttons.is-light >.button[disabled],
.input-group.is-light >.button[disabled] {
border-color: #f5f5f5;
background-color: #f5f5f5;
color: #000;
fill: #000;
stroke-width: 0;
}
.button .icon:first-child:not(:last-child) {
margin-right: 0.25em;
}
.button .icon:last-child:not(:first-child) {
margin-left: 0.25em;
}
.button .icon:only-child {
margin: 0 -0.25em;
}
.button .label {
margin: -0.5em 0;
}
.button.is-block,
.buttons.is-block >.button,
.input-group.is-block >.button {
width: 100%;
}
.button.is-rounded,
.buttons.is-rounded >.button,
.input-group.is-rounded >.button {
border-width: 1px;
border-radius: 10em;
}
.button.is-clean {
margin: 0;
border: 0;
background-color: transparent;
color: #000;
fill: #000;
stroke-width: 0;
}
.button.is-link {
padding-top: 0.3em;
padding-bottom: 0.3em;
padding-left: 0;
padding-right: 0.7em;
border: 0;
background-color: transparent;
color: #0072ff;
fill: #0072ff;
stroke-width: 0;
}
.button.is-link:after {
position: absolute;
display: block;
content: '';
width: 100%;
height: 0.15em;
background-color: #0072ff;
bottom: 0;
left: 0;
right: 0;
}
.button.is-link:hover,
.button.is-link:active,
.button.is-link.is-active {
color: #eb008b;
}
.button.is-link:hover:after,
.button.is-link:active:after,
.button.is-link.is-active:after {
background-color: #eb008b;
height: 0.25em;
}
.button:hover {
text-decoration: none;
}
.button.is-disabled,
.button[disabled],
.buttons.is-disabled >.button,
.buttons[disabled] >.button,
.input-group.is-disabled >.button {
opacity: 0.8;
cursor: not-allowed;
}
.buttons {
display: flex;
flex-wrap: wrap;
align-items: center;
margin-bottom: 10px;
}
.buttons >.label {
z-index: 2;
margin: 0 -18.5px;
}
.buttons >.button {
margin-bottom: 0;
}
.buttons >.button:not(:first-child):not(:last-child) {
border-radius: 0;
}
.buttons >.button:first-child {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.buttons >.button:last-child {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.buttons.is-inverse .button:not(:first-child):not(:last-child) {
border-left-width: 0;
}
.buttons.is-inverse .button:last-child {
border-left-width: 0;
}
.label {
display: inline-flex;
justify-content: center;
align-items: center;
overflow: hidden;
margin: 0 2px;
margin-bottom: 10px;
padding: 0.5em;
min-width: 37px;
border-radius: 4px;
color: #000;
vertical-align: top;
font-weight: 200;
line-height: 1;
background-color: #c1c1c1;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.label img {
margin: -0.75em;
height: 2.5em;
vertical-align: top;
}
.label .icon {
height: 1em;
width: 1em;
}
.label .icon:first-child:not(:last-child),
.label img:first-child:not(:last-child) {
margin-right: 0.25em;
}
.label .icon:last-child:not(:first-child),
.label img:last-child:not(:first-child) {
margin-left: 0.25em;
}
.label.is-primary {
background-color: #0072ff;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.label.is-secondary {
background-color: #c7c7c7;
color: #000;
fill: #000;
stroke-width: 0;
}
.label.is-info {
background-color: #00d4f0;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.label.is-success {
background-color: #18d88b;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.label.is-warning {
background-color: #ffa557;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.label.is-danger {
background-color: #ff3d3d;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.label.is-black {
background-color: #000;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.label.is-white {
background-color: #fff;
color: #000;
fill: #000;
stroke-width: 0;
}
.label.is-dark {
background-color: #323c47;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.label.is-light {
background-color: #f5f5f5;
color: #000;
fill: #000;
stroke-width: 0;
}
.label.is-rounded {
border-radius: 10em;
}
.label.is-block {
display: flex;
}
.label.is-float {
position: absolute;
top: 0;
margin: 0;
margin-top: -1em;
right: 0;
margin-right: -1em;
}
.input {
margin-bottom: 10px;
padding: 0.5em 0.75em;
width: 100%;
outline: none;
border-width: 1px;
border-style: solid;
border-radius: 4px;
-webkit-appearance: none;
-moz-appearance: none;
border-color: #c1c1c1;
}
.input:focus {
border-color: #0061d9;
box-shadow: 0 0 0 3px rgba(0,114,255,0.25);
}
.input.is-primary,
.input-group.is-primary >.input {
border-color: #0072ff;
}
.input.is-primary:focus,
.input-group.is-primary >.input:focus {
border-color: #0061d9;
box-shadow: 0 0 0 3px rgba(0,114,255,0.25);
}
.input.is-secondary,
.input-group.is-secondary >.input {
border-color: #c7c7c7;
}
.input.is-secondary:focus,
.input-group.is-secondary >.input:focus {
border-color: #a9a9a9;
box-shadow: 0 0 0 3px rgba(199,199,199,0.25);
}
.input.is-info,
.input-group.is-info >.input {
border-color: #00d4f0;
}
.input.is-info:focus,
.input-group.is-info >.input:focus {
border-color: #00b4cc;
box-shadow: 0 0 0 3px rgba(0,212,240,0.25);
}
.input.is-success,
.input-group.is-success >.input {
border-color: #18d88b;
}
.input.is-success:focus,
.input-group.is-success >.input:focus {
border-color: #14b876;
box-shadow: 0 0 0 3px rgba(24,216,139,0.25);
}
.input.is-warning,
.input-group.is-warning >.input {
border-color: #ffa557;
}
.input.is-warning:focus,
.input-group.is-warning >.input:focus {
border-color: #ff8a24;
box-shadow: 0 0 0 3px rgba(255,165,87,0.25);
}
.input.is-danger,
.input-group.is-danger >.input {
border-color: #ff3d3d;
}
.input.is-danger:focus,
.input-group.is-danger >.input:focus {
border-color: #ff0e0e;
box-shadow: 0 0 0 3px rgba(255,61,61,0.25);
}
.input.is-black,
.input-group.is-black >.input {
border-color: #000;
}
.input.is-black:focus,
.input-group.is-black >.input:focus {
border-color: #000;
box-shadow: 0 0 0 3px rgba(0,0,0,0.25);
}
.input.is-white,
.input-group.is-white >.input {
border-color: #fff;
}
.input.is-white:focus,
.input-group.is-white >.input:focus {
border-color: #d9d9d9;
box-shadow: 0 0 0 3px rgba(255,255,255,0.25);
}
.input.is-dark,
.input-group.is-dark >.input {
border-color: #323c47;
}
.input.is-dark:focus,
.input-group.is-dark >.input:focus {
border-color: #2a333c;
box-shadow: 0 0 0 3px rgba(50,60,71,0.25);
}
.input.is-light,
.input-group.is-light >.input {
border-color: #f5f5f5;
}
.input.is-light:focus,
.input-group.is-light >.input:focus {
border-color: #d0d0d0;
box-shadow: 0 0 0 3px rgba(245,245,245,0.25);
}
.input.is-block,
.input-group.is-block >.input {
width: 100%;
}
.input.is-rounded,
.input-group.is-rounded >.input {
border-radius: 10em;
}
.input:disabled,
.input.is-disabled,
.input-group.is-disabled >.input {
cursor: not-allowed;
background: #c1c1c1;
}
.input.is-disabled,
.input-group.is-disabled >.input {
pointer-events: none;
}
.input-tag {
display: inline-flex;
padding: 0.5em 0.75em;
border-width: 1px;
border-style: solid;
border-radius: 4px;
vertical-align: top;
text-align: center;
border-color: #c1c1c1;
background-color: #c1c1c1;
color: #323c47;
fill: #323c47;
stroke-width: 0;
}
.input-tag .icon:first-child:not(:last-child) {
margin-right: 0.25em;
}
.input-tag .icon:last-child:not(:first-child) {
margin-left: 0.25em;
}
.input-tag .icon:only-child {
margin: 0 -0.25em;
}
.input-tag.is-primary,
.input-group.is-primary >.input-tag {
border-color: #0072ff;
background-color: #0072ff;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.input-tag.is-secondary,
.input-group.is-secondary >.input-tag {
border-color: #c7c7c7;
background-color: #c7c7c7;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.input-tag.is-info,
.input-group.is-info >.input-tag {
border-color: #00d4f0;
background-color: #00d4f0;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.input-tag.is-success,
.input-group.is-success >.input-tag {
border-color: #18d88b;
background-color: #18d88b;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.input-tag.is-warning,
.input-group.is-warning >.input-tag {
border-color: #ffa557;
background-color: #ffa557;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.input-tag.is-danger,
.input-group.is-danger >.input-tag {
border-color: #ff3d3d;
background-color: #ff3d3d;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.input-tag.is-black,
.input-group.is-black >.input-tag {
border-color: #000;
background-color: #000;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.input-tag.is-white,
.input-group.is-white >.input-tag {
border-color: #fff;
background-color: #fff;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.input-tag.is-dark,
.input-group.is-dark >.input-tag {
border-color: #323c47;
background-color: #323c47;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.input-tag.is-light,
.input-group.is-light >.input-tag {
border-color: #f5f5f5;
background-color: #f5f5f5;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.input-tag.is-rounded,
.input-group.is-rounded >.input-tag {
border-radius: 10em;
}
.input-tag.is-inverse {
background-color: transparent;
}
.input-tag.is-clean {
position: relative;
background-color: #fff;
fill: #c1c1c1;
stroke-width: 0;
border-right: 0;
margin-right: -2px;
}
.input-tag.is-disabled,
.input-group.is-disabled >.input-tag {
opacity: 0.9;
cursor: not-allowed;
}
.input-group {
display: flex;
margin-bottom: 10px;
}
.input-group >*:not(.inputGroup-label) {
margin-bottom: 0;
}
.input-group-label {
flex: 1;
margin-bottom: 0.5em;
margin-right: 10px;
white-space: nowrap;
}
.input-group.has-label {
flex-wrap: wrap;
}
.input-group.has-labelInline {
align-items: center;
}
.input-group.has-itemAfter .button {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.input-group.has-itemAfter .input {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
border-right: 0;
}
.input-group.has-itemBefore .input-tag {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.input-group.has-itemBefore .input {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
border-left: 0;
}
.file {
margin-bottom: 10px;
padding: 0.5em 0.75em;
width: 100%;
border: 2px dashed #0072ff;
border-radius: 4px;
font-size: 16px;
-webkit-appearance: none;
-moz-appearance: none;
}
.checkbox,
.radio {
margin: 10px 0;
display: flex;
align-items: center;
cursor: pointer;
}
.checkbox-label,
.radio-label {
vertical-align: middle;
}
.checkbox-input,
.radio-input {
display: inline-flex;
justify-content: center;
align-items: center;
padding: 0;
width: 1.3em;
height: 1.3em;
border: 1px solid #c1c1c1;
border-radius: 4px;
cursor: pointer;
margin-right: 0.4em;
outline: none;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
}
.checkbox-input:focus,
.radio-input:focus {
border-color: #0072ff;
box-shadow: 0 0 0 3px rgba(0,114,255,0.25);
}
.checkbox-input:checked,
.radio-input:checked {
background-color: #f5f5f5;
}
.checkbox-input:checked:after,
.radio-input:checked:after {
opacity: 1;
}
.checkbox-input:after,
.radio-input:after {
display: block;
opacity: 0;
width: 0.2em;
height: 0.5em;
border: solid #0072ff;
border-width: 0 0.13em 0.13em 0;
content: '';
transform: translate3d(0, -0.1em, 0) rotate(45deg);
}
.checkbox.is-disabled .checkbox-input,
.radio.is-disabled .radio-input,
.checkbox[disabled] .checkbox-input,
.radio[disabled] .radio-input {
opacity: 0.6;
cursor: not-allowed;
pointer-events: none;
}
.checkbox.is-inline,
.radio.is-inline {
display: inline-flex;
margin-right: 0.8em;
}
.checkbox.is-disabled,
.radio.is-disabled,
.checkbox[disabled],
.radio[disabled] {
pointer-events: none;
cursor: not-allowed;
}
.icon {
display: inline;
vertical-align: middle;
line-height: inherit;
font-size: 1em;
width: 1em;
height: 1em;
}
.icon.is-primary {
fill: #0072ff;
stroke-width: 0;
}
.icon.is-secondary {
fill: #c7c7c7;
stroke-width: 0;
}
.icon.is-info {
fill: #00d4f0;
stroke-width: 0;
}
.icon.is-success {
fill: #18d88b;
stroke-width: 0;
}
.icon.is-warning {
fill: #ffa557;
stroke-width: 0;
}
.icon.is-danger {
fill: #ff3d3d;
stroke-width: 0;
}
.icon.is-black {
fill: #000;
stroke-width: 0;
}
.icon.is-white {
fill: #fff;
stroke-width: 0;
}
.icon.is-dark {
fill: #323c47;
stroke-width: 0;
}
.icon.is-light {
fill: #f5f5f5;
stroke-width: 0;
}
.icon.is-tiny {
width: calc( 0.253378378378378vw + 8.554054054054054px );
}
@media screen and (max-width: 767px) {
.icon.is-tiny {
width: 10.5px;
}
}
@media screen and (min-width: 1360px) {
.icon.is-tiny {
width: 12px;
}
}
.icon.is-tiny {
height: calc( 0.253378378378378vw + 8.554054054054054px );
}
@media screen and (max-width: 767px) {
.icon.is-tiny {
height: 10.5px;
}
}
@media screen and (min-width: 1360px) {
.icon.is-tiny {
height: 12px;
}
}
.icon.is-small {
width: calc( 0.295608108108108vw + 9.97972972972973px );
}
@media screen and (max-width: 767px) {
.icon.is-small {
width: 12.25px;
}
}
@media screen and (min-width: 1360px) {
.icon.is-small {
width: 14px;
}
}
.icon.is-small {
height: calc( 0.295608108108108vw + 9.97972972972973px );
}
@media screen and (max-width: 767px) {
.icon.is-small {
height: 12.25px;
}
}
@media screen and (min-width: 1360px) {
.icon.is-small {
height: 14px;
}
}
.icon.is-normal {
width: calc( 0.337837837837838vw + 11.405405405405405px );
}
@media screen and (max-width: 767px) {
.icon.is-normal {
width: 14px;
}
}
@media screen and (min-width: 1360px) {
.icon.is-normal {
width: 16px;
}
}
.icon.is-normal {
height: calc( 0.337837837837838vw + 11.405405405405405px );
}
@media screen and (max-width: 767px) {
.icon.is-normal {
height: 14px;
}
}
@media screen and (min-width: 1360px) {
.icon.is-normal {
height: 16px;
}
}
.icon.is-large {
width: calc( 0.422297297297297vw + 14.256756756756756px );
}
@media screen and (max-width: 767px) {
.icon.is-large {
width: 17.5px;
}
}
@media screen and (min-width: 1360px) {
.icon.is-large {
width: 20px;
}
}
.icon.is-large {
height: calc( 0.422297297297297vw + 14.256756756756756px );
}
@media screen and (max-width: 767px) {
.icon.is-large {
height: 17.5px;
}
}
@media screen and (min-width: 1360px) {
.icon.is-large {
height: 20px;
}
}
.icon.is-massive {
width: calc( 0.506756756756757vw + 17.10810810810811px );
}
@media screen and (max-width: 767px) {
.icon.is-massive {
width: 21px;
}
}
@media screen and (min-width: 1360px) {
.icon.is-massive {
width: 24px;
}
}
.icon.is-massive {
height: calc( 0.506756756756757vw + 17.10810810810811px );
}
@media screen and (max-width: 767px) {
.icon.is-massive {
height: 21px;
}
}
@media screen and (min-width: 1360px) {
.icon.is-massive {
height: 24px;
}
}
.radio-input {
border-radius: 10em;
}
.radio-input:after {
width: 70%;
height: 70%;
border: none;
border-radius: 10em;
background: #0072ff;
transform: none;
}
.switcher {
display: inline-flex;
margin: 5px;
vertical-align: middle;
}
.switcher-input {
display: none;
}
.switcher-input:checked + .switcher-body {
background-color: #0072ff;
padding-left: 0.5em;
padding-right: 1.3em;
}
.switcher-input:checked + .switcher-body .switcher-handle {
left: calc(100% - 1.3em);
}
.switcher-input:checked + .switcher-body .switcher-true {
max-width: 40em;
opacity: 1;
}
.switcher-input:checked + .switcher-body .switcher-false {
max-width: 0em;
opacity: 0;
}
.switcher-input[disabled] {
opacity: 0.6;
cursor: not-allowed;
}
.switcher-input[disabled] + .switcher-body {
opacity: 0.6;
cursor: not-allowed;
}
.switcher-body {
position: relative;
display: inline-flex;
padding: 0;
padding-left: 1.3em;
padding-right: 0.5em;
min-width: 2.6em;
height: 1.3em;
background-color: #000;
cursor: pointer;
transition: 0.3s;
justify-content: center;
align-items: center;
color: #fff;
user-select: none;
}
.switcher-body p {
font-size: 0.8em;
}
.switcher-true {
max-width: 0em;
opacity: 0;
}
.switcher-false {
max-width: 40em;
opacity: 1;
}
.switcher-handle {
position: absolute;
left: 0;
margin: 0.25em;
top: 0;
display: block;
width: 0.8em;
height: 0.8em;
background-color: #fff;
content: '';
transition: 0.3s;
}
.switcher-handle.is-dragging {
transition: 0;
}
.switcher.is-rounded .switcher-handle,
.switcher.is-rounded .switcher-body {
border-radius: 100em;
}
.switcher.is-disabled,
.switcher[disabled] {
cursor: not-allowed;
pointer-events: none;
opacity: 0.6;
}
.switcher.is-disabled .switcher-input,
.switcher[disabled] .switcher-input {
cursor: not-allowed;
}
.table {
overflow: hidden;
width: 100%;
border: 1px solid #000;
border-spacing: 0;
border-collapse: separate;
border-radius: 4px;
color: #000;
text-align: left;
}
.table:not(:last-child) {
margin-bottom: 10px;
}
.table th:not(:last-child),
.table td:not(:last-child) {
border-right: 1px solid #000;
}
@media screen and (max-width: 767px) {
.table th:not(:last-child),
.table td:not(:last-child) {
border-right: 0;
}
}
@media screen and (max-width: 767px) {
.table th,
.table td {
display: block;
width: 100%;
}
}
.table thead {
background-color: #fff;
}
.table thead th {
border-bottom: 1px solid #000;
padding: 1em 0.5em;
font-weight: bold;
}
@media screen and (max-width: 767px) {
.table thead th {
border-bottom: 0;
}
}
.table tfoot {
background-color: #fff;
}
.table tfoot th {
border-top: 1px solid #000;
padding: 0.5em;
}
@media screen and (max-width: 767px) {
.table tr {
display: block;
border-top: 1px solid #000;
}
}
.table td {
padding: 0.5em;
border-top: 1px solid #000;
background-color: #fff;
}
@media screen and (max-width: 767px) {
.table td {
border: 0;
}
}
.table-wrapper {
position: relative;
display: table;
overflow-x: auto;
margin: 10px auto;
padding: 0.5em;
border: 1px solid #fff;
border-radius: 4px;
background-color: #fff;
width: 100%;
}
.table-sort {
float: right;
padding: 0;
outline: 0;
background: none;
border: none;
}
.table-sort.is-active {
fill: #0072ff;
stroke: #0072ff;
}
.table-sort.is-desc {
transform: scaleY(-1);
}
.table.is-striped tr:nth-child(2n) td {
background-color: $alight;
}
.table.is-relaxed {
border: 0;
}
.table.is-relaxed th,
.table.is-relaxed td {
border-right: 0;
}
.table.is-center {
text-align: center;
}
.table.is-top tbody {
vertical-align: top;
}
.table.is-bottom tbody {
vertical-align: bottom;
}
.table.is-middle tbody {
vertical-align: middle;
}
.table.is-small td {
padding: 0.25em 0.5em;
}
.table.is-large td {
padding: 1em 0.5em;
}
.textarea {
display: block;
margin-bottom: 10px;
padding: 0.5em;
min-width: 100%;
max-width: 100%;
outline: none;
border-width: 1px;
border-style: solid;
border-radius: 4px;
text-align: left;
line-height: 1.2;
border-color: #c1c1c1;
}
.textarea:focus {
border-color: #0061d9;
box-shadow: 0 0 0 3px rgba(0,114,255,0.25);
}
.textarea.is-primary {
border-color: #0072ff;
}
.textarea.is-primary:focus {
border-color: #0061d9;
box-shadow: 0 0 0 3px rgba(0,114,255,0.25);
}
.textarea.is-secondary {
border-color: #c7c7c7;
}
.textarea.is-secondary:focus {
border-color: #a9a9a9;
box-shadow: 0 0 0 3px rgba(199,199,199,0.25);
}
.textarea.is-info {
border-color: #00d4f0;
}
.textarea.is-info:focus {
border-color: #00b4cc;
box-shadow: 0 0 0 3px rgba(0,212,240,0.25);
}
.textarea.is-success {
border-color: #18d88b;
}
.textarea.is-success:focus {
border-color: #14b876;
box-shadow: 0 0 0 3px rgba(24,216,139,0.25);
}
.textarea.is-warning {
border-color: #ffa557;
}
.textarea.is-warning:focus {
border-color: #ff8a24;
box-shadow: 0 0 0 3px rgba(255,165,87,0.25);
}
.textarea.is-danger {
border-color: #ff3d3d;
}
.textarea.is-danger:focus {
border-color: #ff0e0e;
box-shadow: 0 0 0 3px rgba(255,61,61,0.25);
}
.textarea.is-black {
border-color: #000;
}
.textarea.is-black:focus {
border-color: #000;
box-shadow: 0 0 0 3px rgba(0,0,0,0.25);
}
.textarea.is-white {
border-color: #fff;
}
.textarea.is-white:focus {
border-color: #d9d9d9;
box-shadow: 0 0 0 3px rgba(255,255,255,0.25);
}
.textarea.is-dark {
border-color: #323c47;
}
.textarea.is-dark:focus {
border-color: #2a333c;
box-shadow: 0 0 0 3px rgba(50,60,71,0.25);
}
.textarea.is-light {
border-color: #f5f5f5;
}
.textarea.is-light:focus {
border-color: #d0d0d0;
box-shadow: 0 0 0 3px rgba(245,245,245,0.25);
}
.textarea:disabled,
.textarea.is-disabled {
cursor: not-allowed;
background: #c1c1c1;
color: #fff;
pointer-events: none;
}
[tooltip] {
position: relative;
}
[tooltip]:focus {
outline: none;
}
[tooltip]:hover:before,
[tooltip]:hover:after {
visibility: visible;
opacity: 1;
}
[tooltip]:before {
position: absolute;
top: 0;
left: 50%;
z-index: 99999;
display: block;
visibility: hidden;
width: 0;
height: 0;
border-width: 7px 7px 0 7px;
border-style: solid;
border-color: #000 transparent transparent transparent;
content: '';
opacity: 0;
transition: 0.4s;
transform: translateX(-50%) translateY(-100%);
user-select: none;
}
[tooltip]:after {
position: absolute;
top: 0;
left: 50%;
z-index: 99999;
display: block;
visibility: hidden;
padding: 0.5em;
border-radius: 4px;
background-color: #000;
color: #fff;
content: attr(tooltip);
white-space: nowrap;
opacity: 0;
transition: 0.4s;
transform: translateX(-50%) translateY(-100%) translateY(-7px);
user-select: none;
}
[tooltip-position='bottom']:before {
top: auto;
top: initial;
bottom: 0;
border-width: 0 7px 7px 7px;
border-color: transparent transparent #000 transparent;
transform: translateX(-50%) translateY(100%);
}
[tooltip-position='bottom']:after {
top: auto;
top: initial;
bottom: 0;
transform: translateX(-50%) translateY(100%) translateY(7px);
}
[tooltip-position='left']:before {
top: 50%;
left: 0;
border-width: 7px 0 7px 7px;
border-color: transparent transparent transparent #000;
transform: translateX(-100%) translateY(-50%);
}
[tooltip-position='left']:after {
top: 50%;
left: 0;
transform: translateX(-100%) translateX(-7px) translateY(-50%);
}
[tooltip-position='right']:before {
top: 50%;
right: 0;
left: auto;
left: initial;
border-width: 7px 7px 7px 0;
border-color: transparent #000 transparent transparent;
transform: translateX(100%) translateY(-50%);
}
[tooltip-position='right']:after {
top: 50%;
right: 0;
left: auto;
left: initial;
transform: translateX(100%) translateX(7px) translateY(-50%);
}
[tooltip-rounded]:after {
border-radius: 10em;
}
.select {
position: relative;
margin-bottom: 10px;
margin-bottom: 0;
padding: 0.5em 0.75em;
max-width: 100%;
width: 100%;
outline: none;
border-width: 1px;
border-style: solid;
border-radius: 4px;
background-color: #fff;
background-image: linear-gradient(45deg, transparent 50%, #000 50%), linear-gradient(135deg, #000 50%, transparent 50%);
background-position: calc(100% - 0.8em) calc(50% + 0.1em), calc(100% - 0.4em) calc(50% + 0.1em);
background-size: 0.4em 0.4em, 0.4em 0.4em;
background-repeat: no-repeat;
text-align: left;
-webkit-appearance: none;
-moz-appearance: none;
border-color: #c1c1c1;
background-image: linear-gradient(45deg, transparent 50%, #c1c1c1 50%), linear-gradient(135deg, #c1c1c1 50%, transparent 50%);
color: #0072ff;
/*
* select elments
*/
}
.select .select-label,
.select .select-item.is-selected,
.select .select-childItem.is-selected {
background-color: #0072ff;
color: #fff;
}
.select .select-item:not(.is-group):hover,
.select .select-childItem:hover {
background-color: #0061d9;
color: #fff;
}
.select:focus {
border-color: #a4a4a4;
box-shadow: 0 0 0 3px rgba(193,193,193,0.25);
}
.select-input {
display: flex;
padding: 0;
border: 0;
outline: none;
background-color: transparent;
color: inherit;
text-align: left;
font-size: inherit;
-webkit-appearance: textfield;
-moz-appearance: none;
}
.select select {
display: none;
}
.select-labels {
position: absolute;
top: 0;
left: 0;
display: inline-flex;
flex-wrap: wrap;
margin-right: 2em;
padding: 0;
}
.select-label {
display: inline-flex;
justify-content: center;
align-items: center;
overflow: hidden;
margin: 0.2em;
padding: 0.4em;
border-radius: 4px;
background-color: #000;
color: #fff;
font-size: 1em;
line-height: 1;
fill: currentColor;
stroke-width: 0;
}
.select-labelDismiss {
width: 1em;
height: 1em;
color: currentColor;
}
.select-labelDismiss:hover {
fill: #c1c1c1;
}
.select-menu {
position: absolute;
top: 100%;
right: 0;
left: 0;
z-index: 999;
margin: 0 -1px;
border-width: 0 1px 1px 1px;
border-style: solid;
border-color: inherit;
border-radius: 0 0 4px 4px;
background: #fff;
font-size: inherit;
}
.select-list {
overflow: auto;
margin: 0;
padding: 0;
max-height: 40vh;
list-style: none;
}
.select-item {
padding: 0;
width: 100%;
}
.select-item:not(.is-group) {
padding: 0.5em;
cursor: pointer;
}
.select-childMenu {
margin: 0;
padding: 0;
list-style: none;
}
.select-childTitle {
display: block;
padding: 0.5em;
color: #c1c1c1;
}
.select-childItem {
padding: 0.5em 0.5em 0.5em 1em;
cursor: pointer;
}
.select.is-primary {
border-color: #0072ff;
background-image: linear-gradient(45deg, transparent 50%, #0072ff 50%), linear-gradient(135deg, #0072ff 50%, transparent 50%);
color: #0072ff;
}
.select.is-primary .select-label,
.select.is-primary .select-item.is-selected,
.select.is-primary .select-childItem.is-selected {
background-color: #0072ff;
color: #fff;
}
.select.is-primary .select-item:not(.is-group):hover,
.select.is-primary .select-childItem:hover {
background-color: #0061d9;
color: #fff;
}
.select.is-primary:focus {
border-color: #0061d9;
box-shadow: 0 0 0 3px rgba(0,114,255,0.25);
}
.select.is-secondary {
border-color: #000;
background-image: linear-gradient(45deg, transparent 50%, #000 50%), linear-gradient(135deg, #000 50%, transparent 50%);
color: #000;
}
.select.is-secondary .select-label,
.select.is-secondary .select-item.is-selected,
.select.is-secondary .select-childItem.is-selected {
background-color: #000;
color: #fff;
}
.select.is-secondary .select-item:not(.is-group):hover,
.select.is-secondary .select-childItem:hover {
background-color: #000;
color: #fff;
}
.select.is-secondary:focus {
border-color: #000;
box-shadow: 0 0 0 3px rgba(0,0,0,0.25);
}
.select.is-info {
border-color: #00d4f0;
background-image: linear-gradient(45deg, transparent 50%, #00d4f0 50%), linear-gradient(135deg, #00d4f0 50%, transparent 50%);
color: #00d4f0;
}
.select.is-info .select-label,
.select.is-info .select-item.is-selected,
.select.is-info .select-childItem.is-selected {
background-color: #00d4f0;
color: #fff;
}
.select.is-info .select-item:not(.is-group):hover,
.select.is-info .select-childItem:hover {
background-color: #00b4cc;
color: #fff;
}
.select.is-info:focus {
border-color: #00b4cc;
box-shadow: 0 0 0 3px rgba(0,212,240,0.25);
}
.select.is-success {
border-color: #18d88b;
background-image: linear-gradient(45deg, transparent 50%, #18d88b 50%), linear-gradient(135deg, #18d88b 50%, transparent 50%);
color: #18d88b;
}
.select.is-success .select-label,
.select.is-success .select-item.is-selected,
.select.is-success .select-childItem.is-selected {
background-color: #18d88b;
color: #fff;
}
.select.is-success .select-item:not(.is-group):hover,
.select.is-success .select-childItem:hover {
background-color: #14b876;
color: #fff;
}
.select.is-success:focus {
border-color: #14b876;
box-shadow: 0 0 0 3px rgba(24,216,139,0.25);
}
.select.is-warning {
border-color: #ffa557;
background-image: linear-gradient(45deg, transparent 50%, #ffa557 50%), linear-gradient(135deg, #ffa557 50%, transparent 50%);
color: #ffa557;
}
.select.is-warning .select-label,
.select.is-warning .select-item.is-selected,
.select.is-warning .select-childItem.is-selected {
background-color: #ffa557;
color: #fff;
}
.select.is-warning .select-item:not(.is-group):hover,
.select.is-warning .select-childItem:hover {
background-color: #ff8a24;
color: #fff;
}
.select.is-warning:focus {
border-color: #ff8a24;
box-shadow: 0 0 0 3px rgba(255,165,87,0.25);
}
.select.is-danger {
border-color: #ff3d3d;
background-image: linear-gradient(45deg, transparent 50%, #ff3d3d 50%), linear-gradient(135deg, #ff3d3d 50%, transparent 50%);
color: #ff3d3d;
}
.select.is-danger .select-label,
.select.is-danger .select-item.is-selected,
.select.is-danger .select-childItem.is-selected {
background-color: #ff3d3d;
color: #fff;
}
.select.is-danger .select-item:not(.is-group):hover,
.select.is-danger .select-childItem:hover {
background-color: #ff0e0e;
color: #fff;
}
.select.is-danger:focus {
border-color: #ff0e0e;
box-shadow: 0 0 0 3px rgba(255,61,61,0.25);
}
.select.is-black {
border-color: #000;
background-image: linear-gradient(45deg, transparent 50%, #000 50%), linear-gradient(135deg, #000 50%, transparent 50%);
color: #000;
}
.select.is-black .select-label,
.select.is-black .select-item.is-selected,
.select.is-black .select-childItem.is-selected {
background-color: #000;
color: #fff;
}
.select.is-black .select-item:not(.is-group):hover,
.select.is-black .select-childItem:hover {
background-color: #000;
color: #fff;
}
.select.is-black:focus {
border-color: #000;
box-shadow: 0 0 0 3px rgba(0,0,0,0.25);
}
.select.is-white {
border-color: #000;
background-image: linear-gradient(45deg, transparent 50%, #000 50%), linear-gradient(135deg, #000 50%, transparent 50%);
color: #000;
}
.select.is-white .select-label,
.select.is-white .select-item.is-selected,
.select.is-white .select-childItem.is-selected {
background-color: #000;
color: #fff;
}
.select.is-white .select-item:not(.is-group):hover,
.select.is-white .select-childItem:hover {
background-color: #000;
color: #fff;
}
.select.is-white:focus {
border-color: #000;
box-shadow: 0 0 0 3px rgba(0,0,0,0.25);
}
.select.is-dark {
border-color: #323c47;
background-image: linear-gradient(45deg, transparent 50%, #323c47 50%), linear-gradient(135deg, #323c47 50%, transparent 50%);
color: #323c47;
}
.select.is-dark .select-label,
.select.is-dark .select-item.is-selected,
.select.is-dark .select-childItem.is-selected {
background-color: #323c47;
color: #fff;
}
.select.is-dark .select-item:not(.is-group):hover,
.select.is-dark .select-childItem:hover {
background-color: #2a333c;
color: #fff;
}
.select.is-dark:focus {
border-color: #2a333c;
box-shadow: 0 0 0 3px rgba(50,60,71,0.25);
}
.select.is-light {
border-color: #000;
background-image: linear-gradient(45deg, transparent 50%, #000 50%), linear-gradient(135deg, #000 50%, transparent 50%);
color: #000;
}
.select.is-light .select-label,
.select.is-light .select-item.is-selected,
.select.is-light .select-childItem.is-selected {
background-color: #000;
color: #fff;
}
.select.is-light .select-item:not(.is-group):hover,
.select.is-light .select-childItem:hover {
background-color: #000;
color: #fff;
}
.select.is-light:focus {
border-color: #000;
box-shadow: 0 0 0 3px rgba(0,0,0,0.25);
}
.select .is-visible {
display: block;
}
.select .is-hidden {
display: none;
}
.select.is-rounded {
border-radius: 10em;
}
.select:disabled,
.select.is-disabled {
opacity: 0.7;
cursor: not-allowed;
}
.select.is-active {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.select.is-disabled {
opacity: 0.7;
pointer-events: none;
}
.dropdown {
position: relative;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
}
.dropdown.is-right {
justify-content: flex-end;
}
.dropdown.is-center {
justify-content: center;
}
.dropdown-menu {
position: absolute;
top: 70px;
left: 0;
padding: 0.5em;
width: 300px;
border: 1px solid #000;
border-radius: 4px;
background-color: #fff;
color: #000;
list-style: none;
transform-origin: top left;
user-select: none;
}
.dropdown-menu li {
padding: 0;
font-size: 16px;
}
.dropdown-menu .dropdown-menu {
position: relative;
top: 0;
}
.dropdown-menu:empty {
display: none;
}
.dropdown-menu.is-hidden {
margin: 0;
padding: 0;
height: 0;
transform: scale(0);
}
.dropdown-menu.is-visible {
transform: scale(1);
}
.dropdown-menu:before {
position: absolute;
top: -0.5em;
left: 0.5em;
display: block;
width: 0;
height: 0;
border-width: 0 0.5em 0.5em 0.5em;
border-style: solid;
border-color: transparent transparent #000 transparent;
content: '';
}
.dropdown-menu:after {
position: absolute;
top: calc( 0.675675675675676vw + -11.18918918918919px );
left: 0.5em;
display: block;
width: 0;
height: 0;
border-width: 0 0.5em 0.5em 0.5em;
border-style: solid;
border-color: transparent transparent #fff transparent;
content: '';
}
.is-right .dropdown-menu {
right: 0;
left: auto;
left: initial;
transform-origin: top right;
}
.is-right .dropdown-menu:before,
.is-right .dropdown-menu:after {
right: 0.5em;
left: auto;
left: initial;
}
.is-center .dropdown-menu {
left: calc(50% - 150px);
transform-origin: top center;
}
.is-center .dropdown-menu:before,
.is-center .dropdown-menu:after {
left: calc(50% - 7px);
}
.modal {
position: relative;
z-index: 999;
display: flex;
flex-direction: column;
justify-content: center;
align-items: stretch;
margin: 10px 8vw;
padding: 2.5em;
width: 100%;
border: 0;
border-radius: 4px;
background-color: #fff;
max-width: 800px;
max-height: calc(100vh - 40px);
box-shadow: 0 15px 20px -10px rgba(0,0,0,0.2);
}
.modal-header {
position: relative;
margin-bottom: 2.5em;
}
.modal-title {
margin: 0;
}
.modal-body {
position: relative;
overflow: auto;
padding: 0;
max-height: 50vh;
}
.modal-icon {
margin-right: 2.5em;
}
.modal-footer {
margin-top: 2.5em;
}
.modal-footer .button {
margin-right: 1.25em;
}
.modal-footer >* {
margin-bottom: 0;
}
.modal-dismiss {
position: absolute;
top: 0;
z-index: 9999;
padding: 1.25em;
border: 0;
background-color: transparent;
right: 0;
cursor: pointer;
fill: inherit;
stroke-width: 0;
}
.modal-dismiss:hover {
fill: #0072ff;
stroke-width: 0;
}
.modal-container {
position: fixed;
top: 0;
right: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100vh;
background-color: rgba(0,0,0,0.1);
z-index: 999;
}
.modal-container.is-hidden {
display: none;
}
.modal-container.is-visable {
display: flex;
}
.modal.is-primary {
background-color: #e5f1ff;
color: #0072ff;
fill: #0072ff;
stroke-width: 0;
}
.modal.is-primary.is-outline {
border-color: #0072ff;
color: #0072ff;
fill: #0072ff;
stroke-width: 0;
}
.modal.is-primary:focus {
border-color: #0061d9;
box-shadow: 0 0 0 3px rgba(0,114,255,0.25);
}
.modal.is-secondary {
background-color: #f9f9f9;
color: #323c47;
fill: #323c47;
stroke-width: 0;
}
.modal.is-secondary.is-outline {
border-color: #c7c7c7;
color: #c7c7c7;
fill: #c7c7c7;
stroke-width: 0;
}
.modal.is-secondary:focus {
border-color: #a9a9a9;
box-shadow: 0 0 0 3px rgba(199,199,199,0.25);
}
.modal.is-info {
background-color: #e4fcff;
color: #00d4f0;
fill: #00d4f0;
stroke-width: 0;
}
.modal.is-info.is-outline {
border-color: #00d4f0;
color: #00d4f0;
fill: #00d4f0;
stroke-width: 0;
}
.modal.is-info:focus {
border-color: #00b4cc;
box-shadow: 0 0 0 3px rgba(0,212,240,0.25);
}
.modal.is-success {
background-color: #e7fcf4;
color: #18d88b;
fill: #18d88b;
stroke-width: 0;
}
.modal.is-success.is-outline {
border-color: #18d88b;
color: #18d88b;
fill: #18d88b;
stroke-width: 0;
}
.modal.is-success:focus {
border-color: #14b876;
box-shadow: 0 0 0 3px rgba(24,216,139,0.25);
}
.modal.is-warning {
background-color: #fff6ee;
color: #ffa557;
fill: #ffa557;
stroke-width: 0;
}
.modal.is-warning.is-outline {
border-color: #ffa557;
color: #ffa557;
fill: #ffa557;
stroke-width: 0;
}
.modal.is-warning:focus {
border-color: #ff8a24;
box-shadow: 0 0 0 3px rgba(255,165,87,0.25);
}
.modal.is-danger {
background-color: #ffecec;
color: #ff3d3d;
fill: #ff3d3d;
stroke-width: 0;
}
.modal.is-danger.is-outline {
border-color: #ff3d3d;
color: #ff3d3d;
fill: #ff3d3d;
stroke-width: 0;
}
.modal.is-danger:focus {
border-color: #ff0e0e;
box-shadow: 0 0 0 3px rgba(255,61,61,0.25);
}
.modal.is-black {
background-color: #e6e6e6;
color: #000;
fill: #000;
stroke-width: 0;
}
.modal.is-black.is-outline {
border-color: #000;
color: #000;
fill: #000;
stroke-width: 0;
}
.modal.is-black:focus {
border-color: #000;
box-shadow: 0 0 0 3px rgba(0,0,0,0.25);
}
.modal.is-white {
background-color: #fff;
color: #323c47;
fill: #323c47;
stroke-width: 0;
}
.modal.is-white.is-outline {
border-color: #fff;
color: #fff;
fill: #fff;
stroke-width: 0;
}
.modal.is-white:focus {
border-color: #d9d9d9;
box-shadow: 0 0 0 3px rgba(255,255,255,0.25);
}
.modal.is-dark {
background-color: #e8ebef;
color: #323c47;
fill: #323c47;
stroke-width: 0;
}
.modal.is-dark.is-outline {
border-color: #323c47;
color: #323c47;
fill: #323c47;
stroke-width: 0;
}
.modal.is-dark:focus {
border-color: #2a333c;
box-shadow: 0 0 0 3px rgba(50,60,71,0.25);
}
.modal.is-light {
background-color: #fefefe;
color: #323c47;
fill: #323c47;
stroke-width: 0;
}
.modal.is-light.is-outline {
border-color: #f5f5f5;
color: #f5f5f5;
fill: #f5f5f5;
stroke-width: 0;
}
.modal.is-light:focus {
border-color: #d0d0d0;
box-shadow: 0 0 0 3px rgba(245,245,245,0.25);
}
.modal.is-outline {
border-width: 1px;
border-style: solid;
background-color: transparent;
}
.navbar {
display: flex;
margin: 0;
padding: 5px 10px;
width: 100%;
background-color: #fff;
}
.navbar.is-fixed {
position: fixed;
top: 0;
left: 0;
right: 0;
transition: 0.4s;
}
.navbar.is-inverse {
background-color: #000;
}
.navbar.is-hidden {
transform: translate3d(0, -100%, 0);
}
.navbar-brand,
.navbar-start,
.navbar-end {
display: flex;
flex-wrap: wrap;
align-items: center;
}
.navbar-brand img {
max-height: 100%;
}
.navbar-brand.is-white {
filter: brightness(0) invert(1);
}
.navbar-start {
flex: 1;
}
.navbar-item {
display: block;
padding: 0.5em 1em;
color: #000;
text-decoration: none;
white-space: nowrap;
cursor: pointer;
fill: #000;
stroke-width: 0;
}
.navbar-item.dropdown {
height: auto;
}
.navbar-item:hover,
.navbar-item:focus {
color: #c7c7c7;
fill: #c7c7c7;
stroke-width: 0;
}
.navbar.is-inverse .navbar-item {
color: #fff;
fill: #fff;
stroke-width: 0;
}
.navbar.is-inverse .navbar-item:hover,
.navbar.is-inverse .navbar-item:focus {
color: #c7c7c7;
fill: #c7c7c7;
stroke-width: 0;
}
.navbar-item.is-active {
border-bottom: 4px solid #c7c7c7;
margin-bottom: -4px;
color: #c7c7c7;
}
.pagination {
display: flex;
align-items: top;
margin: 10px 0;
flex-wrap: wrap;
}
.pagination-item,
.pagination-next,
.pagination-prev,
.pagination-first,
.pagination-last {
position: relative;
display: inline-flex;
justify-content: center;
align-items: center;
width: 2em;
height: 2em;
outline-width: 0;
outline-offset: 0;
border: none;
text-decoration: none;
cursor: pointer;
background: #fff;
font-size: inherit;
fill: #000;
stroke-width: 0;
}
.pagination-item.is-active,
.pagination-next.is-active,
.pagination-prev.is-active,
.pagination-first.is-active,
.pagination-last.is-active,
.pagination-item:active,
.pagination-next:active,
.pagination-prev:active,
.pagination-first:active,
.pagination-last:active,
.pagination-item:hover:not(.is-disabled),
.pagination-next:hover:not(.is-disabled),
.pagination-prev:hover:not(.is-disabled),
.pagination-first:hover:not(.is-disabled),
.pagination-last:hover:not(.is-disabled) {
color: #0072ff;
fill: #0072ff;
stroke-width: 0;
}
.pagination-item.is-disabled,
.pagination-next.is-disabled,
.pagination-prev.is-disabled,
.pagination-first.is-disabled,
.pagination-last.is-disabled {
border-color: #c1c1c1;
color: #c1c1c1;
fill: #c1c1c1;
stroke-width: 0;
}
.pagination-item:focus,
.pagination-next:focus,
.pagination-prev:focus,
.pagination-first:focus,
.pagination-last:focus {
outline-color: 0;
}
.pagination-item .icon,
.pagination-next .icon,
.pagination-prev .icon,
.pagination-first .icon,
.pagination-last .icon {
width: 1.4em;
height: 1.4em;
}
.content li + li {
margin-top: 0.25em;
}
.content p:not(:last-child),
.content dl:not(:last-child),
.content ol:not(:last-child),
.content ul:not(:last-child),
.content blockquote:not(:last-child),
.content pre:not(:last-child),
.content table:not(:last-child) {
margin-bottom: 1em;
font-size: 1em;
}
.content h1 {
font-size: 2.4em;
margin-bottom: 0.5em;
}
.content h1:not(:first-child) {
margin-top: 1em;
}
.content h2 {
font-size: 2.2em;
margin-bottom: 0.5714em;
}
.content h2:not(:first-child) {
margin-top: 1.1428em;
}
.content h3 {
font-size: 2em;
margin-bottom: 0.6666em;
}
.content h3:not(:first-child) {
margin-top: 1.8em;
}
.content h4 {
font-size: 1.6em;
margin-bottom: 0.8em;
}
.content h5 {
font-size: 1.4em;
margin-bottom: 0.8888em;
}
.content h6 {
font-size: 1.2em;
margin-bottom: 1em;
}
.content blockquote {
border-left: 0.5em solid #0072ff;
padding: 0.5em;
margin: 0;
}
.content ol {
list-style: decimal outside;
margin-left: 1em;
margin-top: 1em;
padding: 0;
}
.content ul {
list-style: disc outside;
margin-left: 1em;
margin-top: 1em;
padding: 0;
}
.content ul ul {
list-style-type: circle;
margin-top: 0.5em;
}
.content ul ul ul {
list-style-type: square;
}
.content dd {
margin-left: 2em;
}
.content figure {
margin-left: 2em;
margin-right: 2em;
text-align: center;
}
.content figure:not(:first-child) {
margin-top: 2em;
}
.content figure:not(:last-child) {
margin-bottom: 2em;
}
.content figure img {
display: inline-block;
}
.content figure figcaption {
font-style: italic;
}
.content pre {
overflow-x: auto;
padding: 0.5em;
white-space: pre;
word-wrap: normal;
}
.content sup,
.content sub {
font-size: 75%;
}
.add-sticky {
position: sticky;
top: 10px;
}
.add-floatRight {
float: right;
}
.add-floatLeft {
float: left;
}
.add-flex {
display: flex;
}
.add-justifyCenter {
justify-content: center;
}
.add-justifyEnd {
justify-content: flex-end;
}
.add-justifyStart {
justify-content: flex-start;
}
.add-justifyAround {
justify-content: space-around;
}
.add-justifyBetween {
justify-content: space-between;
}
.add-alignCenter {
align-items: center;
}
.add-alignEnd {
align-items: flex-end;
}
.add-alignStart {
align-items: flex-start;
}
.add-alignBaseline {
align-items: baseline;
}
.add-alignStretch {
align-items: stretch;
}
.add-padding {
padding: 0.5em !important;
}
.add-paddingTop {
padding-top: 0.5em !important;
}
.add-paddingBottom {
padding-bottom: 0.5em !important;
}
.add-paddingRight {
padding-right: 0.5em !important;
}
.add-paddingLeft {
padding-left: 0.5em !important;
}
.add-margin {
margin: 10px !important;
}
.add-marginTop {
margin-top: 10px !important;
}
.add-marginBottom {
margin-bottom: 10px !important;
}
.add-marginRight {
margin-right: 10px !important;
}
.add-marginLeft {
margin-left: 10px !important;
}
.no-padding {
padding: 0 !important;
}
.no-paddingTop {
padding-top: 0 !important;
}
.no-paddingBottom {
padding-bottom: 0 !important;
}
.no-paddingRight {
padding-right: 0 !important;
}
.no-paddingLeft {
padding-left: 0 !important;
}
.no-margin {
margin: 0 !important;
}
.no-marginTop {
margin-top: 0 !important;
}
.no-marginBottom {
margin-bottom: 0 !important;
}
.no-marginRight {
margin-right: 0 !important;
}
.no-marginLeft {
margin-left: 0 !important;
}
::selection {
color: inherit;
}
.button {
white-space: nowrap;
}
.header {
width: 100%;
padding: 50px;
color: #fff;
}
.header-title {
font-size: 50px;
line-height: 1em;
margin: 20px 0;
font-weight: lighter;
}
.header-content {
font-size: 16px;
margin-bottom: 50px;
font-weight: lighter;
}
.header-image >img {
width: 100%;
}
.header,
.header.is-red {
background-image: linear-gradient(30deg, #ff3d3d, #ffdd57);
}
.header.is-black {
background-image: linear-gradient(30deg, #000, #4d4d4d);
}
.header.is-green {
background-image: linear-gradient(30deg, #18d88b, #ffdd57);
}
.header.is-blue {
background-image: linear-gradient(30deg, #0072ff, #4d9cff);
}
.header.is-white {
background-image: linear-gradient(45deg, #e6e6e6, #fff);
}
.section {
padding: 20px 30px;
}
.section-title {
font-size: 30px;
color: #323c47;
}
.section-paragraph {
font-size: 16px;
color: #526375;
}
.section.is-red {
background: #ff3d3d;
}
.section.is-black {
background: #000;
}
.section.is-green {
background: #18d88b;
}
.section.is-blue {
background: #0072ff;
}
.section.is-white {
background: #fff;
}
.social {
padding: 100px 0;
}
.social-number {
font-size: 50px;
margin: 20px 0 50px;
}
.social-item {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.social-title {
font-size: 30px;
margin: 30px 0;
text-align: center;
}
.social-content {
font-size: 20px;
margin: 0 0 40px;
text-align: center;
}
.social-logo {
width: 100%;
margin: 20px 0;
}
.social-quote {
font-size: 30px;
color: #000;
quotes: "\201C" "\201D" "\2018" "\2019";
}
.social-quote:before {
content: open-quote;
margin-right: 20px;
font-size: 40px;
}
.social-quote:after {
content: close-quote;
margin-left: 20px;
font-size: 40px;
}
.social.is-red {
background: #ff3d3d;
}
.social.is-black {
background: #000;
}
.social.is-green {
background: #18d88b;
}
.social.is-blue {
background: #0072ff;
}
.user {
display: flex;
align-items: center;
margin: 10px 0;
}
.user.is-alt {
justify-content: center;
flex-direction: column;
}
.user-avatar {
border-radius: 50%;
width: 60px;
height: 60px;
margin-right: 20px;
flex-shrink: 0;
overflow: hidden;
}
.is-alt .user-avatar {
margin: 0 0 20px;
}
.user-data {
text-align: left;
white-space: nowrap;
}
.is-alt .user-data {
text-align: center;
}
.user-name {
font-size: 16px;
color: #000;
margin: 5px 0;
}
.user-caption {
font-size: 16px;
color: #c1c1c1;
margin: 0 0 5px;
}
.add-center-horizontal {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.add-center-vertical {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
}
.add-padding {
padding: 20px;
}
.add-text-center {
text-align: center;
}
.add-full-width {
width: 100%;
}
.is-active img {
opacity: 1;
transition: 0.4s;
}
.is-active p,
.is-active h1,
.is-active h2,
.is-active h3,
.is-active h6,
.is-active b {
opacity: 1;
transform: translate3d(0, 0, 0);
transition: 0.4s;
}
.is-inactive img {
opacity: 0;
transition: 0.4s;
}
.is-inactive p,
.is-inactive h1,
.is-inactive h2,
.is-inactive h3,
.is-inactive h6,
.is-inactive b {
opacity: 0;
transform: translate3d(0, -200px, 0);
transition: 0.4s;
}
.column {
transition: 0.2s;
}
.vuse-icon {
display: block;
width: 20px;
height: 20px;
}
.uploader {
position: relative;
cursor: pointer;
outline: none;
}
.uploader-input {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
opacity: 0;
z-index: 100;
cursor: pointer;
}
.uploader >img {
width: 100%;
display: block;
}
.uploader:hover {
box-shadow: 0 0 0 2px #c1c1c1;
}
/*# sourceMappingURL=style.css.map*/
================================================
FILE: docs/API.md
================================================
# API
Your section components will have some properties injected to help you customize their behavior in building phase and production/render phase.
## $section
An instance of the [section class](https://github.com/baianat/vuse/blob/master/src/js/section.js) that represents this component.
## $builder
An instance of the singleton [builder class](https://github.com/baianat/vuse/blob/master/src/js/builder.js)
## $sectionData
Is a computed property that mirrors `$section.data` which contains the current values (text, images, etc...) for the section.
================================================
FILE: docs/README.md
================================================
---
home: true
actionText: Getting Started →
actionLink: ./getting-started
heroImage: /img/logo.png
---
================================================
FILE: docs/example.md
================================================
---
navbar: true
sidebar: false
editLink: false
pageClass: example
---
<vuse-builder @saved="onSave"></vuse-builder>
<script>
export default {
methods: {
onSave (vuse) {
vuse.export('preview');
}
}
}
</script>
<style>
.example .content {
padding: 0 !important;
margin: 0 !important;
max-width: 100% !important;
}
.example .page {
padding: 0 !important;
}
.example .page-edit {
display: none !important;
}
.example .menu {
margin: 0;
}
</style>
================================================
FILE: docs/exporting.md
================================================
# Exporting
There are three ways to export the built page: preview, pwa or json. When clicking the save button the `b-builder` component emits a saved event with the builder instance as its payload, which exposes an `export` method.
```html
<div id="app">
<b-builder @saved="onSave"></b-builder>
</div>
<script>
new Vue({
el: '#app',
methods: {
onSave (builder) {
// you can use 'preview', 'pwa' or 'json' strings
// 'json' is the default exporting mode
builder.export('preview');
}
}
});
</script>
```
================================================
FILE: docs/getting-started.md
================================================
# getting-started
## What is this
This builder (sections builder) reuses your Vue components as **editable sections** to produce an interactive page builder to the end user, you can use it as a prototyping tool as well as it is sort-of a block builder.
The user/developer can then export the builder for usability in multiple formats, the following are the officially supported ones:
- `json` A json object which can be later used to re-render a page, particularly useful if you plan to have dynamic pages or want to store them in a Database.
- `preview` opens a new page without the editable logic in new tab to see the end result.
- `pwa` produces a zip file which contains all the page files and images neatly packed, this is probably the format you will use for page/prototype landing page builder, The project is augmented by default with service workers to support offline viewing.
The builder is just a Vue plugin, so you can integrate this into your own projects without needing to create separate bundles for it.
## Installation
### Package managers
First step is to install it using `yarn` or `npm`:
```bash
npm install vuse
# or use yarn
yarn add vuse
```
### CDNs
Or add it as a script tag in your projects.
- [unpkg](https://unpkg.com/vuse)
```html
<script src="https://unpkg.com/vue@2.4.2"></script>
<script src="https://unpkg.com/vuse"></script>
```
### Usage
::: tip
If you added it using a script tag, you can skip this section. as it will be auto-installed for you
:::
```js
import Builder from 'vuse';
Vue.use(Builder);
```
You can start using the `b-builder` component to build things now.
This package does not include any sections. The builder is just a system of helpers for managing customizable sections, seeding fake data, exporting views and re-rendering them. The logic for your components/sections is written by you eventually. **we will be adding a huge number of sections soon to be used with this one**. You can use the included examples after reading the API to build your own for now.
================================================
FILE: docs/section.md
================================================
# Section
A section is the building block of the page, below is an example of a header section.
::: tip
Examples use [pug](https://pugjs.org) template language to make it easier to work with templates.
:::
```pug
<template lang="pug">
section.header(
v-styler="$sectionData.classes"
:class="[{'is-editable': $builder.isEditing}, $sectionData.classes]"
)
.container
.grid
.column.is-desktop-6.add-center-vertical
h3.header-title(
:class="{'is-editable': $builder.isEditing}"
v-html="$sectionData.title"
v-styler="$sectionData.title"
)
p.header-content(
:class="{'is-editable': $builder.isEditing}"
v-html="$sectionData.content"
v-styler="$sectionData.content"
)
a.button(
:class="[{'is-editable': $builder.isEditing}, $sectionData.button.classes]"
:href="$sectionData.button.href"
v-html="$sectionData.button.text"
v-styler="$sectionData.button"
)
.column.is-desktop-6
uploader(
class="header-image"
path="$sectionData.images[0]"
)
</template>
<script>
import { types } from 'vuse';
export default {
name: 'hero1',
cover: '../covers/hero1.png',
$schema: {
title: types.Title,
content: types.Text,
images: [types.Image],
button: types.Button,
classes: types.ClassList
},
props: {
id: {
type: Number,
required: true
}
}
};
</script>
```
Each section has several elements that can be edited. Section data are stored in `$sectionData` object which is reactive.
## Adding the ability to edit elements in a section
1. Add `is-editable` class to it. Since editable state can be toggled off/on, it's always good to bind `is-editable` class to change when editing mode changes. e.g. `:class="{'is-editable': $builder.isEditing}"`
1. Add [`v-styler`](https://github.com/baianat/builder#v-styler) directive to the element
1. Bind the element’s innerHTML with its equivalent data e.g. `v-html="$sectionData.button.text"`
1. If you have any other data that `v-styler` changes, you have to bind it too. e.g. `:href="$sectionData.button.href"`
Putting it all together
```html
<a
:class="[{'button', 'is-editable': $builder.isEditing}, $sectionData.button.classes]"
:href="$sectionData.button.href"
v-html="$sectionData.button.text"
v-styler="$sectionData.button"
></a>
```
After creating the HTML structure, you should configure the section schema to use the built-in seeder to provide you with initial/fake values when the component is instantiated in build/edit mode. Or you can set the initial values yourself instead of seeding them.
```html
<script>
import { types } from 'vuse';
export default {
// section name
name: 'hero1',
// section cover image
cover: '../cover-hero1.png',
// group multiple sections
group: 'heros',
// section data schema
$schema: {
// main title
title: types.Text,
// main content
content: types.Text,
// section classes
classes: types.ClassList,
// array of section's images
images: [
types.Image,
types.Image
],
// object holds button data, href etc..
button: types.Button,
// if section has many columns you can use
// a columns array to separate each column's data
columns: [
{
title: types.Title,
content: types.Text,
group: types.group
},
{
title: types.Title,
group: types.group
}
]
},
props: {
id: { type: Number, required: true } // it is required to have an id prop.
}
};
</script>
```
## Using the section
Until now, we have only been creating our section component, we now need to introduce it to our builder so it can use it:
```js
import Builder from 'vuse';
import section from './components/sections/section';
// Builder has Vue-like API when registering components.
Builder.component(section);
Vue.use(Builder);
new Vue({
el: '#app'
});
```
```html
<div id="app">
<b-builder></b-builder>
</div>
```
You only have to register the component on the Builder plugin, which has a Vue-like API. This ensures your Vue global scope isn't polluted by the builder and keeps everything contained within the `b-builder` component.
================================================
FILE: docs/styler.md
================================================
# Styler
This directive is automatically injected in your section components, and can be used to facilitate editing elements greatly, since it has support for multiple element types like `div`, `a`, `button` and `p` tags as well.
To tell styler which variable to update, you pass it as directive expression e.g. `v-styler="$sectionData.button"`
The styler directive has four types `text`, `button`, `section` or `grid`. By default, the directive can know the type implicitly, from the element tag or from the provided schema.
If you want to explicitly specify the type, you can pass it as a directive modifier e.g. `v-styler.button="$sectionData.button"`.
## How to use
coming soon...
================================================
FILE: package.json
================================================
{
"name": "vuse",
"version": "0.1.1",
"description": "Vue.js Page Builder",
"author": "Abdelrahman Ismail <abdelrahman3d@gmail.com>",
"module": "dist/vuse.esm.js",
"unpkg": "dist/vuse.min.js",
"main": "dist/vuse.js",
"scripts": {
"dev": "webpack-dev-server --hot --inline --config ./demo/webpack.config.js",
"build": "cross-env NODE_ENV=production node scripts/build.js",
"build:demo": "cross-env NODE_ENV=production webpack --config ./demo/webpack.config.js",
"docs:dev": "vuepress dev docs",
"docs:build": "vuepress build docs",
"docs:deploy": "scripts/deploy.sh",
"lint": "eslint ./src --fix"
},
"devDependencies": {
"@babel/core": "^7.0.0-rc.1",
"@babel/plugin-proposal-class-properties": "^7.0.0-rc.1",
"@babel/plugin-proposal-object-rest-spread": "^7.0.0-rc.1",
"@babel/preset-env": "^7.0.0-rc.1",
"babel-loader": "^8.0.0-beta",
"chalk": "^2.4.1",
"clean-webpack-plugin": "^0.1.19",
"copy-webpack-plugin": "^4.5.1",
"cross-env": "^5.0.5",
"css-loader": "^1.0.0",
"eslint": "^5.3.0",
"eslint-config-standard": "^11.0.0",
"eslint-loader": "^2.1.0",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-node": "^7.0.1",
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-standard": "^3.0.1",
"eslint-plugin-vue": "^4.7.1",
"file-loader": "^1.1.11",
"filesize": "^3.6.1",
"friendly-errors-webpack-plugin": "^1.6.1",
"gzip-size": "^5.0.0",
"html-webpack-plugin": "^4.0.0-alpha",
"mini-css-extract-plugin": "^0.4.4",
"mkdirp": "^0.5.1",
"progress-bar-webpack-plugin": "^1.10.0",
"pug": "^2.0.0-rc.3",
"pug-plain-loader": "^1.0.0",
"rollup": "^0.64.1",
"rollup-plugin-buble": "^0.19.2",
"rollup-plugin-commonjs": "^9.1.5",
"rollup-plugin-css-only": "^0.4.0",
"rollup-plugin-node-resolve": "^3.0.0",
"rollup-plugin-replace": "^2.0.0",
"rollup-plugin-uglify": "^4.0.0",
"rollup-plugin-vue": "^4.3.2",
"style-loader": "^0.22.1",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.1",
"stylus-relative-loader": "^3.4.0",
"util": "^0.11.0",
"vue": "^2.5.17",
"vue-loader": "^15.3.0",
"vue-template-compiler": "^2.5.17",
"vuepress": "^0.14.8",
"webpack": "^4.16.5",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5"
},
"dependencies": {
"@baianat/base.framework": "^2.0.0-beta.0",
"intersection-observer": "^0.5.0",
"jszip": "^3.1.4",
"lodash-es": "^4.17.4",
"popper.js": "^1.14.4",
"save-as": "^0.1.8",
"sortablejs": "^1.6.1",
"vue-server-renderer": "2.5.17"
},
"license": "MIT",
"files": [
"dist/*.js",
"dist/*.css"
],
"keywords": [
"page-builder",
"vuejs",
"ES6"
],
"maintainers": [
{
"name": "Abdelrahman Awad",
"email": "logaretm1@gmail.com"
},
{
"name": "Abdelrahman Ismail",
"email": "abdelrahman3d@gmail.com"
}
]
}
================================================
FILE: scripts/build.js
================================================
const chalk = require('chalk');
const mkdirpNode = require('mkdirp');
const { promisify } = require('util');
const { rollup } = require('rollup');
const { paths, configs, utils } = require('./config');
const mkdirp = promisify(mkdirpNode);
async function buildConfig (build) {
await mkdirp(paths.dist);
const bundleName = build.output.file.replace(paths.dist, '');
console.log(chalk.cyan(`📦 Generating ${bundleName}...`));
const bundle = await rollup(build.input);
await bundle.write(build.output);
console.log(chalk.green(`👍 ${bundleName} ${utils.stats({ path: build.output.file })}`));
}
async function build () {
await Promise.all(Object.keys(configs).map(key => {
return buildConfig(configs[key]).catch(err => {
console.log(err);
});
}));
process.exit(0);
}
build();
================================================
FILE: scripts/config.js
================================================
const path = require('path');
const fs = require('fs');
const replace = require('rollup-plugin-replace');
const vue = require('rollup-plugin-vue').default;
const resolve = require('rollup-plugin-node-resolve');
const css = require('rollup-plugin-css-only');
const buble = require('rollup-plugin-buble');
const commonjs = require('rollup-plugin-commonjs');
const filesize = require('filesize');
const gzipSize = require('gzip-size');
const { uglify } = require('rollup-plugin-uglify');
const version = process.env.VERSION || require('../package.json').version;
const common = {
banner:
`/**
* Vuse v${version}
* (c) ${new Date().getFullYear()} Baianat
* @license MIT
*/`,
paths: {
input: path.join(__dirname, '../src/index.js'),
src: path.join(__dirname, '../src/'),
dist: path.join(__dirname, '../dist/')
},
builds: {
umd: {
file: 'vuse.js',
format: 'umd',
name: 'vuse',
env: 'development'
},
umdMin: {
file: 'vuse.min.js',
format: 'umd',
name: 'vuse',
env: 'production'
},
esm: {
input: path.join(__dirname, '../src/index.esm.js'),
file: 'vuse.esm.js',
format: 'es'
}
}
};
function genConfig (options) {
const config = {
description: '',
input: {
input: options.input || common.paths.input,
plugins: [
commonjs(),
replace({ __VERSION__: version }),
css(),
vue({ css: false }),
resolve(),
buble()
]
},
output: {
banner: common.banner,
name: options.name,
format: options.format,
file: path.join(common.paths.dist, options.file)
}
};
if (options.env) {
config.input.plugins.unshift(replace({
'process.env.NODE_ENV': JSON.stringify(options.env)
}));
}
if (options.env === 'production') {
config.input.plugins.push(uglify());
}
return config;
};
const configs = Object.keys(common.builds).reduce((prev, key) => {
prev[key] = genConfig(common.builds[key]);
return prev;
}, {});
module.exports = {
configs,
uglifyOptions: common.uglifyOptions,
paths: common.paths,
utils: {
stats ({ path }) {
const code = fs.readFileSync(path);
const { size } = fs.statSync(path);
const gzipped = gzipSize.sync(code);
return `| Size: ${filesize(size)} | Gzip: ${filesize(gzipped)}`;
}
}
};
================================================
FILE: scripts/deploy.sh
================================================
#!/usr/bin/env sh
set -e
npm run docs:build
cd docs/.vuepress/dist
git init
git add -A
git commit -m 'deploy'
git push -f git@github.com:baianat/vuse.git master:gh-pages
cd -
================================================
FILE: src/components/VuseBuilder.vue
================================================
<template lang="pug">
div
div#artboard.artboard(
ref="artboard"
:class="{ 'is-sorting': $builder.isSorting, 'is-editable': $builder.isEditing }"
)
component(v-for='section in $builder.sections'
:is='section.name'
:key='section.id'
:id='section.id'
)
.controller
.controller-intro(v-if="showIntro && !this.$builder.sections.length")
label(for="projectName") Hello, start your project
input.controller-input(
id="projectName"
placeholder="project name"
v-model="title"
)
template(v-if="themes")
.controller-themes
button.controller-theme(
v-for="theme in themes"
@click="addTheme(theme)"
)
| {{ theme.name }}
.controller-panel
button.controller-button.is-green(
tooltip-position="top"
tooltip="export"
@click="submit"
)
VuseIcon(name='download')
button.controller-button.is-red(
v-if="!tempSections"
tooltip-position="top"
tooltip="clear sections"
@click="clearSections"
)
VuseIcon(name='trash')
button.controller-button.is-gray(
v-if="tempSections"
tooltip-position="top"
tooltip="undo"
@click="undo"
)
VuseIcon(name='undo')
button.controller-button.is-blue(
tooltip-position="top"
tooltip="sorting"
:class="{ 'is-red': $builder.isSorting }"
@click="toggleSort"
)
VuseIcon(name='sort')
button.controller-button.is-blue(
tooltip-position="top"
tooltip="add section"
:class="{ 'is-red': listShown, 'is-rotated': listShown }"
:disabled="!$builder.isEditing"
@click="newSection"
)
VuseIcon(name='plus')
ul.menu(:class="{ 'is-visiable': listShown }" ref="menu")
li.menu-group(v-for="(group, name) in groups" v-if="group.length")
.menu-header(@click="toggleGroupVisibility")
span.menu-title {{ name }}
span.menu-icon
VuseIcon(name='arrowDown')
.menu-body
template(v-for="section in group")
a.menu-element(
@click="addSection(section)"
@drag="currentSection = section"
)
img.menu-elementImage(v-if="section.cover" :src="section.cover")
span.menu-elementTitle {{ section.name }}
</template>
<script>
import Sortable from 'sortablejs';
import VuseIcon from './VuseIcon';
export default {
name: 'VuseBuilder',
components: {
VuseIcon
},
props: {
showIntro: {
type: Boolean,
default: true
},
data: {
type: Object,
default: () => ({
title: '',
sections: []
})
}
},
data () {
return {
title: null,
listShown: false,
tempSections: null,
sections: this.getSections(),
currentSection: '',
groups: {}
}
},
watch: {
title (value) {
this.$builder.title = value;
document.title = value;
}
},
created () {
// sets the initial data.
this.$builder.set(this.data);
this.title = this.$builder.title;
this.themes = this.$builder.themes;
this.generateGroups();
},
mounted () {
this.$builder.rootEl = this.$refs.artboard;
const groups = this.$refs.menu.querySelectorAll('.menu-body');
const _self = this;
groups.forEach((group) => {
Sortable.create(group, {
group: {
name: 'sections-group',
put: false,
pull: 'clone'
},
sort: false
});
});
this.sortable = Sortable.create(this.$refs.artboard, {
group: {
name: 'artboard',
put: 'sections-group'
},
animation: 150,
scroll: true,
scrollSpeed: 10,
sort: false,
disabled: true,
preventOnFilter: false,
onAdd (evt) {
_self.addSection(_self.currentSection, evt.newIndex);
evt.item.remove();
},
onUpdate (evt) {
_self.$builder.sort(evt.oldIndex, evt.newIndex);
}
});
},
updated () {
if (this.$builder.scrolling) {
this.$builder.scrolling(this.$refs.artboard);
}
},
beforeDestroy () {
this.$builder.clear();
},
methods: {
newSection () {
// add the section immediatly if none are present.
if (this.sections.length === 1) {
this.addSection(this.sections[0]);
return;
}
this.toggleListVisibility();
},
addSection (section, position) {
this.$builder.add(section, position);
},
clearSections () {
this.tempSections = this.$builder.clear();
setTimeout(() => {
this.tempSections = null;
}, 5000);
},
undo () {
this.$builder.sections = this.tempSections;
this.tempSections = null;
},
addTheme (theme) {
this.$builder.set(theme);
},
toggleSort () {
this.$builder.isSorting = !this.$builder.isSorting;
this.$builder.isEditing = !this.$builder.isSorting;
if (!this.$builder.isSorting && this.sortable) {
this.sortable.option('sort', false);
this.sortable.option('disabled', true);
return;
}
this.sortable.option('disabled', false);
this.sortable.option('sort', true);
},
toggleListVisibility () {
this.listShown = !this.listShown;
this.sortable.option('disabled', !this.listShown);
},
showList () {
this.listShown = true;
this.sortable.option('disabled', false);
},
hideList () {
this.listShown = false;
this.sortable.option('disabled', true);
},
toggleGroupVisibility (e) {
const element = e.target;
const group = element.closest('.menu-group');
group.classList.toggle('is-visiable');
},
submit () {
this.$emit('saved', this.$builder);
},
generateGroups () {
let groups = { random: [] };
// group sections together
this.sections.forEach((section) => {
let sectionGroup = section.group;
if (!sectionGroup) {
groups.random.push(section);
return;
}
if (!groups[sectionGroup]) {
groups[sectionGroup] = [section];
return;
}
groups[sectionGroup].push(section);
})
this.groups = groups;
},
getSections () {
let sections = [];
// get sections data
sections = Object.keys(this.$builder.components).map((sec) => {
return {
name: sec,
group: this.$builder.components[sec].options.group,
cover: this.$builder.components[sec].options.cover,
schema: this.$builder.components[sec].options.$schema
}
});
return sections;
}
}
};
</script>
<style lang="stylus">
@import '../stylus/_app.styl'
.artboard
transform-origin: top center
&.is-editable .is-editable
outline: none
&:hover
box-shadow: inset 0 0 0 2px $gray
.controller
box-sizing: border-box
&-panel
position: fixed
z-index: 200
bottom: 30px
right: 40px
&-input
outline: none
border: 1px solid $gray
padding: 0.5em 1em
margin: 20px 0
border-radius: 40px
width: 100%
font-size: 16px
&:focus
border-color: $blue
box-shadow: 0 0 0 2px alpha($blue, 50%)
&-button
transition: 0.2s
border: none
outline: none
border-radius: 20px
padding: 5px
color: $white
fill: $white
font-size: 16px
svg
transition: 0.2s
&:not(:last-child)
margin-right: 20px
&.is-rotated >svg
transform: rotate(45deg)
&:hover
@extends $floatHover
&.is-blue
background-color: $blue
&:hover
background-color: darken($blue, 20%)
&.is-red
background-color: $red
&:hover
background-color: darken($red, 20%)
&.is-green
background-color: $green
&:hover
background-color: darken($green, 20%)
&.is-dark
background-color: $dark
&:hover
background-color: darken($dark, 20%)
&.is-gray
background-color: $gary
&:hover
background-color: darken($gray, 20%)
&-intro
width: 100%
max-width: 500px
margin: auto
display: flex
justify-content: center
align-items: center
flex-direction: column
padding: 70px 50px
text-align: center
font-size: 30px
color: $dark
&-themes
display: flex
flex-direction: column
width: 100%
&-theme
background-color: $white
color: $dark
border: 1px solid $gray
margin: 5px
padding: 20px
border-radius: 4px
width: 100%
cursor: pointer
font-size: 16px
&:hover
border-color: $blue
.menu
user-select: none
-moz-user-select: none
position: fixed
z-index 300
top: 0
left: 0
bottom: 0
margin: 0
width: 250px
background: $white
padding: 20px 10px
display: flex
flex-direction: column
overflow-y: auto
list-style: none
transition: 0.4s
box-shadow: 1px 0 10px alpha($dark, 20%)
transform: translate3d(-100%, 0, 0)
&.is-visiable
transform: translate3d(0, 0, 0)
&-body
display: none
padding: 0
margin: 0
list-style: none
~/-group &
width: 90%
margin: 10px auto
~/-group.is-visiable &
display: block
&-icon
width: 24px
height: 24px
fill: $gray
transition: 0.2s
~/-group.is-visiable &
transform: rotate(180deg)
&-element
position: relative
display: flex
justify-content: center
align-items: center
width: 100%
min-height: 50px
border-radius: 5px
background: darken($gray, 10%)
transition: 0.3s
cursor: pointer
color: $white
overflow: hidden
user-select: none
-moz-user-select: none
&:not(:last-child)
margin-bottom: 10px
&:hover
@extends $floatHover
&-elementImage
max-width: 100%
pointer-events: none
+
~/-elementTitle
position: absolute
right: 0
bottom: 0
left: 0
text-shadow: 1px 1px 2px alpha($black, 80%)
text-align: center
padding: 5px
&-header
display: flex
justify-content: space-between
align-items: center
padding: 10px 5px
border-bottom: 1px solid alpha($black, 5%)
.sortable-ghost
opacity: 0.3
box-shadow: 0 0 2px 1px $blue
.is-editable
&:hover
box-shadow: inset 0 0 0 2px $gray
</style>
================================================
FILE: src/components/VuseIcon.js
================================================
const icons = {
plus: 'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z',
tic: 'M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z',
sort: 'M14 5h8v2h-8zm0 5.5h8v2h-8zm0 5.5h8v2h-8zM2 11.5C2 15.08 4.92 18 8.5 18H9v2l3-3-3-3v2h-.5C6.02 16 4 13.98 4 11.5S6.02 7 8.5 7H12V5H8.5C4.92 5 2 7.92 2 11.5z',
link: 'M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z',
palettes: 'M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9c.83 0 1.5-.67 1.5-1.5 0-.39-.15-.74-.39-1.01-.23-.26-.38-.61-.38-.99 0-.83.67-1.5 1.5-1.5H16c2.76 0 5-2.24 5-5 0-4.42-4.03-8-9-8zm-5.5 9c-.83 0-1.5-.67-1.5-1.5S5.67 9 6.5 9 8 9.67 8 10.5 7.33 12 6.5 12zm3-4C8.67 8 8 7.33 8 6.5S8.67 5 9.5 5s1.5.67 1.5 1.5S10.33 8 9.5 8zm5 0c-.83 0-1.5-.67-1.5-1.5S13.67 5 14.5 5s1.5.67 1.5 1.5S15.33 8 14.5 8zm3 4c-.83 0-1.5-.67-1.5-1.5S16.67 9 17.5 9s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z',
close: 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',
bold: 'M15.6 10.79c.97-.67 1.65-1.77 1.65-2.79 0-2.26-1.75-4-4-4H7v14h7.04c2.09 0 3.71-1.7 3.71-3.79 0-1.52-.86-2.82-2.15-3.42zM10 6.5h3c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5h-3v-3zm3.5 9H10v-3h3.5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5z',
italic: 'M10 4v3h2.21l-3.42 8H6v3h8v-3h-2.21l3.42-8H18V4z',
underline: 'M12 17c3.31 0 6-2.69 6-6V3h-2.5v8c0 1.93-1.57 3.5-3.5 3.5S8.5 12.93 8.5 11V3H6v8c0 3.31 2.69 6 6 6zm-7 2v2h14v-2H5z',
center: 'M7 15v2h10v-2H7zm-4 6h18v-2H3v2zm0-8h18v-2H3v2zm4-6v2h10V7H7zM3 3v2h18V3H3z',
left: 'M15 15H3v2h12v-2zm0-8H3v2h12V7zM3 13h18v-2H3v2zm0 8h18v-2H3v2zM3 3v2h18V3H3z',
right: 'M3 21h18v-2H3v2zm6-4h12v-2H9v2zm-6-4h18v-2H3v2zm6-4h12V7H9v2zM3 3v2h18V3H3z',
trash: 'M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zm2.46-7.12l1.41-1.41L12 12.59l2.12-2.12 1.41 1.41L13.41 14l2.12 2.12-1.41 1.41L12 15.41l-2.12 2.12-1.41-1.41L10.59 14l-2.13-2.12zM15.5 4l-1-1h-5l-1 1H5v2h14V4z',
align: 'M3 21h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18V7H3v2zm0-6v2h18V3H3z',
textStyle: 'M23 7V1h-6v2H7V1H1v6h2v10H1v6h6v-2h10v2h6v-6h-2V7h2zM3 3h2v2H3V3zm2 18H3v-2h2v2zm12-2H7v-2H5V7h2V5h10v2h2v10h-2v2zm4 2h-2v-2h2v2zM19 5V3h2v2h-2zm-5.27 9h-3.49l-.73 2H7.89l3.4-9h1.4l3.41 9h-1.63l-.74-2zm-3.04-1.26h2.61L12 8.91l-1.31 3.83z',
section: 'M10 18h5v-6h-5v6zm-6 0h5V5H4v13zm12 0h5v-6h-5v6zM10 5v6h11V5H10z',
arrowDown: 'M7.41 7.84L12 12.42l4.59-4.58L18 9.25l-6 6-6-6z',
arrowRight: 'M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z',
arrowLeft: 'M15.41 16.09l-4.58-4.59 4.58-4.59L14 5.5l-6 6 6 6z',
mobile: 'M15.5 1h-8C6.12 1 5 2.12 5 3.5v17C5 21.88 6.12 23 7.5 23h8c1.38 0 2.5-1.12 2.5-2.5v-17C18 2.12 16.88 1 15.5 1zm-4 21c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm4.5-4H7V4h9v14z',
tablet: 'M21 4H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h18c1.1 0 1.99-.9 1.99-2L23 6c0-1.1-.9-2-2-2zm-2 14H5V6h14v12z',
laptop: 'M20 18c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 6h16v10H4V6z',
monitor: 'M21 2H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h7v2H8v2h8v-2h-2v-2h7c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H3V4h18v12z',
download: 'M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z',
eye: 'M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z',
undo: 'M12.5 8c-2.65 0-5.05.99-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.16 3.16-1.88 5.12-1.88 3.54 0 6.55 2.31 7.6 5.5l2.37-.78C21.08 11.03 17.15 8 12.5 8z'
};
export default {
functional: true,
props: {
name: {
type: String,
required: true,
validator: (val) => {
if (!(val in icons) && process.env.NODE_ENV !== 'production') {
console.warn(`Invalid icon name "${val}"`);
return false;
}
return true;
}
}
},
render (h, { props }) {
const path = h('path', {
attrs: {
d: icons[props.name]
}
});
return h(
'svg',
{
attrs: {
version: '1.1',
xmlns: 'http://www.w3.org/2000/svg',
class: 'vuse-icon',
viewBox: '0 0 24 24'
}
},
[path]
);
}
};
================================================
FILE: src/components/VuseRenderer.vue
================================================
<template lang="pug">
#artboard.artboard
component(v-for='section in $builder.sections'
:is='section.name'
:key='section.id'
:id='section.id'
)
</template>
<script>
export default {
name: 'VuseRenderer',
props: {
data: {
type: Object,
default: () => ({
title: '',
sections: []
})
}
},
created () {
this.$builder.set(this.data);
this.$builder.isEditing = false;
this.$builder.isRendered = true;
}
};
</script>
================================================
FILE: src/components/VuseStyler.vue
================================================
<template lang="pug">
.styler(
ref="styler"
id="styler"
v-if="$builder.isEditing"
:class="{ 'is-visible': isVisible }"
@click.stop=""
)
ul.styler-list
li(v-if="type === 'button' || type === 'section'")
button.styler-button(@click="updateOption('colorer')")
VuseIcon(name='palettes')
li(v-if="type === 'button'")
button.styler-button(@click="updateOption('link')")
VuseIcon(name='link')
li(v-if="type === 'header' || type === 'section'")
button.styler-button(@click="removeSection")
VuseIcon(name='trash')
template(v-if="type === 'text'")
li: button.styler-button(@click="updateOption('textColor')")
VuseIcon(name='palettes')
li: button.styler-button(@click="updateOption('align')")
VuseIcon(name='align')
li: button.styler-button(@click="updateOption('textStyle')")
VuseIcon(name='textStyle')
template(v-if="type === 'grid'")
li: button.styler-button(@click="selectDevice('mobile')")
VuseIcon(name='mobile')
//- li: button.styler-button(@click="selectDevice('tablet')")
//- VuseIcon(name='tablet')
li: button.styler-button(@click="selectDevice('desktop')")
VuseIcon(name='laptop')
//- li: button.styler-button(@click="selectDevice('widescreen')")
//- VuseIcon(name='monitor')
ul.styler-list
li(v-if="currentOption === 'colorer'")
ul.colorer
li(v-for="color in colors")
input(
type="radio"
:id="`color${color.charAt(0).toUpperCase() + color.slice(1)}`"
name="colorer"
:value="color"
v-model="colorerColor"
)
li(v-if="currentOption === 'textColor'")
ul.colorer
li(v-for="(color, index) in colors")
input(
type="radio"
:id="`color${color.charAt(0).toUpperCase() + color.slice(1)}`"
name="colorer"
:value="textColors[index]"
v-model="textColor"
)
li(v-if="currentOption === 'link'")
.input-group.is-rounded.has-itemAfter.is-primary
input.input(type="text" placeholder="type your link" v-model="url")
button.button(@click="addLink")
VuseIcon(name='link')
li(v-if="currentOption === 'align'")
ul.align
li: button.styler-button(@click="execute('justifyleft')")
VuseIcon(name='left')
li: button.styler-button(@click="execute('justifycenter')")
VuseIcon(name='center')
li: button.styler-button(@click="execute('justifyright')")
VuseIcon(name='right')
li(v-if="currentOption === 'textStyle'")
ul.align
li: button.styler-button(@click="execute('bold')")
VuseIcon(name='bold')
li: button.styler-button(@click="execute('italic')")
VuseIcon(name='italic')
li: button.styler-button(@click="execute('underline')")
VuseIcon(name='underline')
li(v-if="currentOption === 'columnWidth'")
ul.align
li: button.styler-button(@click="gridValue--")
VuseIcon(name='arrowLeft')
li: input(type="number" min="0" max="12" v-model="gridValue").styler-input
li: button.styler-button(@click="gridValue++")
VuseIcon(name='arrowRight')
</template>
<script>
import Popper from 'popper.js';
import VuseIcon from './VuseIcon';
import { isParentTo } from './../util';
export default {
name: 'Styler',
components: {
VuseIcon
},
props: {
el: {
type: Object,
required: true
},
type: {
type: String,
required: true
},
name: {
type: String,
required: true
},
section: {
type: Object,
required: true
}
},
data: () => ({
colors: ['blue', 'green', 'red', 'black', 'white'],
textColors: ['#4da1ff', '#38E4B7', '#EA4F52', '#000000', '#FFFFFF'],
textColor: '',
oldColorerColor: '',
colorerColor: '',
mouseTarget: '',
currentOption: '',
url: '',
gridValue: 0,
isVisible: false
}),
watch: {
colorerColor: function () {
this.changeColor();
},
textColor: function () {
this.execute('forecolor', this.textColor)
},
gridValue: function () {
this.gridValue = Math.min(Math.max(this.gridValue, 0), 12);
this.section.set(this.name, (grid) => {
grid[this.device] = this.gridValue;
});
}
},
created () {
if (this.type === 'button') {
this.url = this.section.get(`${this.name}.href`);
this.el.contentEditable = 'true';
}
if (this.type === 'text') {
this.el.contentEditable = 'true';
}
},
mounted () {
if (!this.$builder.isEditing) return;
// add listeners to show/hide styler
this.el.addEventListener('click', this.showStyler);
},
beforeDestroy () {
this.hideStyler();
this.$refs.styler.remove();
this.el.classList.remove('is-editable');
this.el.removeEventListener('click', this.showStyler);
document.removeEventListener('click', this.hideStyler, true);
},
methods: {
updateOption (option) {
this.currentOption = option;
this.$nextTick(() => {
this.popper.update();
})
},
addLink () {
this.section.set(`${this.name}.href`, this.url);
},
changeColor () {
this.removeClass(`is-${this.oldColorerColor}`);
this.oldColorerColor = this.colorerColor;
this.addClass(`is-${this.colorerColor}`);
},
addClass (className) {
this.section.set(this.name, (value) => {
if (value && value.classes && Array.isArray(value.classes)) {
value = value.classes;
}
value.push(className);
});
},
selectDevice (device) {
const gridValue = this.section.get(this.name)[device];
this.updateOption('columnWidth');
this.device = device;
this.gridValue = gridValue;
},
removeClass (className) {
if (Array.isArray(className)) {
return className.forEach(c => {
this.removeClass(c);
});
}
this.section.set(this.name, value => {
if (value && value.classes && Array.isArray(value.classes)) {
value = value.classes;
}
const idx = value.indexOf(className);
value.splice(idx, 1);
});
},
removeSection () {
this.$builder.remove(this.section);
},
execute (command, value = null) {
this.el.focus();
document.execCommand(command, false, value);
},
showStyler (event) {
event.stopPropagation();
if (this.isVisible) return;
this.isVisible = true;
// exute popper element
if (!this.popper) {
const position = this.$props.type === 'section' ? 'left-start' : 'top';
this.popper = new Popper(this.el, this.$refs.styler, {
placement: position
});
}
document.addEventListener('click', this.hideStyler, true);
this.currentOption = '';
},
hideStyler (event) {
if (
(event && isParentTo(event.target, this.$el)) ||
(event && isParentTo(event.target, this.el))
) {
return
}
this.isVisible = false;
if (this.popper) {
this.popper.destroy();
this.popper = null;
}
document.removeEventListener('click', this.hideStyler, true);
if (this.type === 'section' || this.type === 'grid') {
return;
}
if (this.type === 'button') {
this.section.set(`${this.name}.text`, this.el.innerHTML);
return;
}
this.section.set(this.name, this.el.innerHTML);
}
}
};
</script>
<style lang="stylus">
@import '~@baianat/base.framework/src/stylus/util/colors'
.styler
position: absolute
top: 0
z-index: 200
visibility: hidden
opacity: 0
margin: 10px 0
padding: 5px
background: $dark
border-radius: 26px
display: flex
flex-direction: column
justify-content: center
align-items: center
&-list
display: flex
justify-content: center
align-items: center
list-style: none
margin: 0
padding: 0
&-input
background: $white
color: $dark
border: 0
outline: 0
width: 40px
height: 40px
border-radius: 42px
margin: 0 5px 0 0
text-align: center
-webkit-appearance: none
-moz-appearance: textfield
appearance: none
&-button
display: flex
justify-content: center
align-items: center
outline: 0
background: $dark
border: 0
fill: $white
color: $white
width: 42px
height: 42px
border-radius: 42px
margin: 0 5px 0 0
&:hover
background: darken($dark, 20%)
&:first-child
margin-left: 5px
&-selector
margin: 0 5px
&.is-visible
visibility: visible
opacity: 1
.input-group
margin: 5px
.align
@extend .styler-list
height: 42px
.colorer
@extend .styler-list
height: 42px
li >input
-webkit-appearance: none
-moz-appearance: textfield
appearance: none
width: 30px
height: 30px
border-radius: 40px
border: 4px solid darken($dark, 20%)
margin: 0 5px
outline: none
&:checked
border-color: lighten($dark, 20%)
&:hover
border-color: lighten($dark, 20%)
&#colorRed
background $red
&#colorBlue
background $blue
&#colorGreen
background $green
&#colorBlack
background $black
&#colorWhite
background $white
.is-hidden
display: none
input[type=number]::-webkit-inner-spin-button
input[type=number]::-webkit-outer-spin-button
-webkit-appearance: none
margin: 0
</style>
================================================
FILE: src/index.esm.js
================================================
import Vuse from './vuse';
import * as types from './types';
const version = '__VERSION__';
// Auto install if Vue is defined globally.
if (typeof Vue !== 'undefined') {
// eslint-disable-next-line
Vue.use(Builder);
}
export {
Vuse,
types,
version
};
export default Vuse;
================================================
FILE: src/index.js
================================================
import Vuse from './vuse';
import * as types from './types';
// Auto install if Vue is defined globally.
if (typeof Vue !== 'undefined') {
// eslint-disable-next-line
Vue.use(Builder);
}
Vuse.version = '__VERSION__';
Vuse.types = types;
export default Vuse;
================================================
FILE: src/mixin.js
================================================
function installMixin ({ builder }) {
builder.mixin = {
provide: function providesBuilder () {
const provides = {};
if (this.$builder) {
provides.$builder = this.$builder;
}
if (this.$section) {
provides.$section = this.$section;
}
return provides;
},
beforeCreate () {
this.$builder = builder;
if (!this.$options.propsData || this.$options.propsData.id === undefined) {
return;
}
this.$section = this.$builder.find(this.$options.propsData.id);
this.$options.computed = {
$sectionData: function getSectionData () {
return this.$section.data;
},
gridClasses: function getGridClasses () {
return this.$sectionData.columns.map(column => {
return Object.keys(column.grid).map(device => {
if (!column.grid[device]) {
return '';
}
const prefix = this.$builder.columnsPrefix[device]
return `${prefix}${column.grid[device]}`;
});
})
}
}
},
updated () {
Array.from(this.$el.querySelectorAll('[contentEditable]')).forEach((el) => {
el.contentEditable = this.$builder.isEditing;
});
}
};
};
export default installMixin;
================================================
FILE: src/plugins/pwa.js
================================================
import JSZip from 'jszip';
import saveAs from 'save-as';
import { getImageBlob, cleanDOM } from '../../src/util';
/**
* Adds a service worker that caches the static assets.
*/
function createSW (output, { images = [] } = {}) {
output.file('sw.js', `
const staticCacheName = 'bbuilder-static-v1';
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open(staticCacheName).then(function(cache) {
return cache.addAll([
'/',
'/assets/js/main.js',
${images.map(i => "'/assets/img/" + i.name + "'").join(',').trim(',')}
]);
})
);
});
function serveAsset(request) {
return caches.open(staticCacheName).then(function(cache) {
return cache.match(request).then(function(response) {
if (response) return response;
return fetch(request).then(function(networkResponse) {
cache.put(request, networkResponse.clone());
return networkResponse;
});
});
});
}
self.addEventListener('fetch', function(event) {
const requestUrl = new URL(event.request.url);
if (requestUrl.origin === location.origin) {
if (requestUrl.pathname === '/') {
event.respondWith(caches.match('/'));
return;
}
if (requestUrl.pathname.startsWith('/assets/')) {
event.respondWith(serveAsset(event.request));
return;
}
}
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
});
`);
const scripts = output.folder('assets/js');
scripts.file('main.js', `
function registerSW () {
if (!navigator.serviceWorker) return;
navigator.serviceWorker.register('/sw.js').then(function (reg) {
console.log('SW registered!');
});
}
registerSW();
`);
}
/**
* Adds some PWA features.
*/
function createPWA (output, payload) {
createSW(output, payload);
}
function download (assets) {
const frag = this.outputFragment();
const images = Array.from(frag.querySelectorAll('img'));
const artboard = frag.querySelector('#artboard');
const title = document.title;
const zip = new JSZip();
const output = zip.folder('project');
const imgFolder = output.folder('assets/img');
const cssFolder = output.folder('assets/css');
Promise.all(images.map((image) => {
const imageLoader = getImageBlob(image.src);
return imageLoader.then((img) => {
imgFolder.file(img.name, img.blob, { base64: true });
image.setAttribute('src', `assets/img/${img.name}`);
return img;
});
})).then(images => {
createPWA(output, { images });
}).then(() => {
return new Promise((resolve, reject) => {
const assetsClient = new XMLHttpRequest();
assetsClient.open('GET', assets.css);
assetsClient.onload = function () {
resolve(this.response);
}
assetsClient.send(null);
}).then((content) => {
cssFolder.file('app.css', content);
return content;
});
}).then(() => {
cleanDOM(frag);
output.file('index.html',
`<html>
<head>
<title>${title}</title>
<link href="assets/css/app.css" rel="stylesheet">
</head>
<body>
${artboard.innerHTML}
<script src="/assets/js/main.js"></script>
</body>
</html>`);
zip.generateAsync({ type: 'blob' }).then((blob) => {
saveAs(blob, 'project.zip');
});
});
}
export default function install ({ builder }) {
builder.download = download;
};
================================================
FILE: src/plugins/scrolling.js
================================================
import 'intersection-observer';
const callback = (entries, observer) => {
entries.forEach(entry => {
if (entry.intersectionRatio > 0.5) {
entry.target.classList.add('is-active');
entry.target.classList.remove('is-inactive');
return;
}
entry.target.classList.add('is-inactive');
entry.target.classList.remove('is-active');
});
}
const observer = new IntersectionObserver(callback, {
root: null,
rootMargin: '0px',
threshold: [0.1, 0.5, 0.9, 1]
});
const scrolling = (rootEl) => {
if (!rootEl) return;
let sections = Array.from(rootEl.querySelectorAll('section'));
sections.forEach(section => {
section.classList.add('is-inactive');
observer.observe(section);
});
}
export default function install ({ builder }) {
builder.scrolling = scrolling;
};
================================================
FILE: src/section.js
================================================
import getPath from 'lodash-es/get';
import toPath from 'lodash-es/toPath';
import Seeder from './seeder';
const SECTION_OPTIONS = {
name: null,
schema: {}
};
let counter = 0;
export default class Section {
constructor (options) {
this.id = counter++;
options = Object.assign({}, SECTION_OPTIONS, options);
this.name = options.name;
this.schema = options.schema;
this.data = options.data || Seeder.seed(options.schema);
this.stylers = [];
}
set (name, value) {
const path = toPath(name);
const prop = path.pop();
path.shift();
const obj = path.length === 0 ? this.data : getPath(this.data, path);
if (typeof value === 'function') {
value(obj[prop]);
return;
}
obj[prop] = value;
}
get (name) {
const path = toPath(name);
const prop = path.pop();
path.shift();
const obj = path.length === 0 ? this.data : getPath(this.data, path);
return obj[prop];
}
destroy () {
this.stylers.forEach(styler => styler.$destroy())
}
};
================================================
FILE: src/seeder.js
================================================
import * as types from './types';
import { isObject } from './util';
const ASSETS_DIR = '.';
const data = new Map([
[types.Title, 'Awesome title'],
[types.Text, 'We\'re creating the best place to go when starting a new business or company.With Baianat you can instantly search domain names, social media handles, and see your logo in beautiful logotypes.'],
[types.Avatar, `${ASSETS_DIR}/img/avatar.png`],
[types.Logo, `${ASSETS_DIR}/img/google.svg`],
[types.Link, 'http://example.com'],
[types.Image, `${ASSETS_DIR}/img/baianat.png`],
[types.ClassList, () => []],
[types.Button, () => ({ text: 'Click Me!', classes: [], href: 'http://example.com' })],
[types.Quote, 'When you were made a leader, you weren\'t given a crown; you were given the responsibility to bring out the best in others.'],
[types.Grid, () => ({mobile: '', tablet: '', desktop: '', widescreen: ''})],
[Number, 100],
[String, 'This is pretty neat']
]);
export default class Seeder {
// Seeds values using a schema.
static seed (schema) {
if (isObject(schema)) {
return Object.keys(schema).reduce((values, key) => {
values[key] = Seeder.seed(schema[key]);
return values;
}, {});
} else if (Array.isArray(schema)) {
return schema.map(s => {
return Seeder.seed(s)
});
}
let value = data.get(schema);
if (value === undefined) {
value = schema;
}
return typeof value === 'function' ? value() : value;
}
};
================================================
FILE: src/styler.js
================================================
import Styler from './components/VuseStyler.vue';
import { getTypeFromTagName, getTypeFromSchema } from './util';
function installStyler ({ builder, Vue }) {
const StylerInstance = Vue.extend(Styler).extend({
beforeCreate () {
this.$builder = builder;
}
});
builder.styler = {
inserted (el, binding, vnode) {
const newNode = document.createElement('div');
const section = vnode.context.$section;
const rootApp = vnode.context.$root.$el;
rootApp.appendChild(newNode);
el.classList.add('is-editable');
section.stylers.push(new StylerInstance({
propsData: {
el,
section: section,
type: binding.arg || getTypeFromSchema(binding.expression, section.schema) || getTypeFromTagName(el.tagName),
name: binding.expression
}
}).$mount(newNode));
}
};
};
export default installStyler;
================================================
FILE: src/stylus/_app.styl
================================================
@import variables
@import colors
.vuse-icon
display: block
width: 20px
height: 20px
$floatHover
cursor: pointer
box-shadow: 0 14px 28px alpha($black, 0.125), 0 10px 10px alpha($black, 0.1)
================================================
FILE: src/stylus/colors.styl
================================================
/*
* Color theme
*/
$magenta ?= #eb008b
$blue ?= #0072FF
$cyan ?= #00d4f0
$green ?= #18d88b
$yellow ?= #ffdd57
$orange ?= #ffa557
$red ?= #ff3d3d
$purple ?= #a324ea
/*
* Graysacle
*/
$black ?= #000
$dark ?= #323c47
$gray ?= #c1c1c1
$gray-dark ?= darken($gray, 10%)
$gray-light ?= lighten($gray, 10%)
$light ?= #f5f5f5
$white ?= #fff
================================================
FILE: src/stylus/variables.styl
================================================
$flexCenter
display: flex
justify-content: center
align-items: center
================================================
FILE: src/types.js
================================================
export class Avatar {};
export class Title {};
export class Text {};
export class Logo {};
export class Image {};
export class Quote {};
export class Link {};
export class ClassList {};
export class Button {};
export class Grid { };
================================================
FILE: src/util.js
================================================
import getPath from 'lodash/get';
import * as types from './types';
export function isObject (obj) {
return obj && typeof obj === 'object' && obj !== null && !Array.isArray(obj);
};
export function isParentTo (target, parent) {
let currentNode = target;
while (currentNode !== null) {
if (currentNode === parent) return true;
currentNode = currentNode.parentNode;
}
return false;
}
/**
*
* @param {String} target
* @param {Object} schema
*/
export function getTypeFromSchema (target, schema) {
const tempTarget = target.split('.');
tempTarget.shift();
const value = getPath(schema, tempTarget.join('.'));
if (value === types.Grid) return 'grid';
if (value === types.Text) return 'text';
if (value === types.Title) return 'text';
if (value === types.Button) return 'button';
if (value === types.ClassList) return 'section';
if (value === String) return 'text';
if (value === Number) return 'text';
return null;
}
export function getImageBlob (URL) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', URL);
xhr.responseType = 'blob';
xhr.onload = function () {
const imageBlob = this.response;
const fileType = this.response.type.split('/')[1].split('+')[0];
const randomNumber = new Date().getUTCMilliseconds();
const filename = `image-${randomNumber}.${fileType}`;
resolve({ blob: imageBlob, name: filename });
}
xhr.send(null);
});
}
export function getTypeFromTagName (tagName) {
tagName = tagName.toUpperCase();
switch (tagName) {
case 'H1':
return 'text';
case 'H2':
return 'text';
case 'H3':
return 'text';
case 'H4':
return 'text';
case 'H5':
return 'text';
case 'H6':
return 'text';
case 'P':
return 'text';
case 'B':
return 'text';
case 'SPAN':
return 'text';
case 'BUTTON':
return 'button';
case 'A':
return 'button';
case 'SECTION':
return 'section';
case 'HEADER':
return 'section';
default:
break;
}
}
export function cleanDOM (artboard) {
const editables = Array.from(artboard.querySelectorAll('.is-editable'));
const uploaders = Array.from(artboard.querySelectorAll('.uploader'));
const stylers = Array.from(artboard.querySelectorAll('.styler'));
editables.forEach((el) => {
el.contentEditable = 'inherit';
el.classList.remove('is-editable');
});
uploaders.forEach((el) => {
const input = el.querySelector(':scope > input');
const image = el.querySelector(':scope > img');
image.classList.add('add-full-width');
el.classList.remove('uploader');
input.remove();
});
stylers.forEach((styler) => {
styler.remove();
});
}
================================================
FILE: src/vuse.js
================================================
import merge from 'lodash-es/merge';
import Section from './section';
import VuseBuilder from './components/VuseBuilder.vue';
import VuseRenderer from './components/VuseRenderer.vue';
import styler from './styler';
import mixin from './mixin';
import { cleanDOM } from './util';
let PLUGINS = [];
let mixier = {};
const BUILDER_OPTIONS = {
title: '',
intro: true,
sections: [],
plugins: [],
themes: [],
columnsPrefix: {
mobile: 'is-mobile-',
tablet: 'is-tablet-',
desktop: 'is-desktop-',
widescreen: 'is-widescreen-',
ultrawide: 'is-ultrawide-'
}
};
// To tell if it is installed or not
let _Vue = null;
class Vuse {
constructor (options) {
this.isEditing = true;
this.isSorting = false;
this.isRendered = false;
this.title = options.title;
this.intro = options.intro;
this.sections = options.sections;
this.columnsPrefix = options.columnsPrefix;
this.themes = options.themes;
this.components = {};
this.assets = {
css: options.assets.css || 'dist/css/app.css'
}
this.installPlugins();
}
/**
* Creates and adds a new section to the list of sections.
* @param {*} options
*/
add (options, position) {
if (position !== undefined) {
this.sections.splice(position, 0, new Section(options));
return;
}
this.sections.push(new Section(options));
}
/**
* Finds a section with the specified id.
*
* @param {String|Number} id
*/
find (id) {
return this.sections.find(s => s.id === id);
}
/**
* Removes a section with the specified id.
* @param {String|Number} id
*/
remove (section) {
const id = this.sections.findIndex(s => s.id === section.id);
this.sections.splice(id, 1);
section.destroy();
}
/**
* Removes a section with the specified id.
* @param {String|Number} oldIndex
* @param {String|Number} newIndex
*/
sort (oldIndex, newIndex) {
const section = this.sections[oldIndex];
this.sections.splice(oldIndex, 1);
this.sections.splice(newIndex, 0, section);
}
/**
* Constructs a document fragment.
*/
outputFragment () {
const frag = document.createDocumentFragment();
frag.appendChild(document.head.cloneNode(true));
frag.appendChild(this.rootEl.cloneNode(true));
return frag;
}
/**
* clears the builder sections.
*/
clear () {
const tempSections = this.sections;
this.sections.forEach(section => section.destroy());
this.sections = [];
return tempSections;
}
/**
* Static helper for components registration pre-installation.
*
* @param {String} name
* @param {Object} definition
*/
static component (name, definition) {
// Just make a plugin that installs a component.
Vuse.use((ctx) => {
ctx.builder.component(name, definition);
});
}
/**
* Acts as a mixin for subcomponents.
* @param {Object} mixinObj
*/
static mix (mixinObj) {
mixier = merge(mixier, mixinObj);
}
/**
* Adds a component section to the builder and augments it with the styler.
* @param {*} name
* @param {*} definition
*/
component (name, definition) {
// reoslve the component name automatically.
if (typeof name === 'object') {
definition = name;
name = definition.name;
}
// if passed a plain object
if (!definition.extend) {
definition = _Vue.extend(definition);
}
this.components[name] = definition.extend({
directives: { styler: this.styler },
mixins: [this.mixin],
components: mixier.components
});
}
/**
* Installs added plugins.
*/
installPlugins () {
PLUGINS.forEach((ctx) => {
ctx.plugin({ builder: this, Vue: _Vue }, ctx.options);
});
// reset to prevent duplications.
PLUGINS = [];
}
static install (Vue, options = {}) {
// already installed
if (_Vue) return;
_Vue = Vue;
const builder = new Vuse(Object.assign({}, BUILDER_OPTIONS, options));
// configer assets output location
Vue.util.defineReactive(builder, 'sections', builder.sections);
Vue.util.defineReactive(builder, 'isEditing', builder.isEditing);
Vue.util.defineReactive(builder, 'isSorting', builder.isSorting);
const extension = {
components: builder.components,
beforeCreate () {
this.$builder = builder;
}
};
// register the main components.
Vue.component('VuseBuilder', Vue.extend(VuseBuilder).extend(extension));
Vue.component('VuseRenderer', Vue.extend(VuseRenderer).extend(extension));
}
/**
* The plugin to be installed with the builder. The function receives the installation context which
* contains the builder instance and the Vue prototype.
*
* @param {Function} plugin
* @param {Object} options
*/
static use (plugin, options = {}) {
if (typeof plugin !== 'function') {
return console.warn('Plugins must be a function');
}
// append to the list of to-be installed plugins.
PLUGINS.push({ plugin, options });
}
set (data) {
this.title = data.title !== undefined ? data.title : this.title;
if (data.sections && Array.isArray(data.sections)) {
this.sections = data.sections.map(section => {
const sectionData = {
name: section.name,
schema: section.schema,
data: section.data
};
if (!sectionData.schema) {
sectionData.schema = this.components[sectionData.name].options.$schema
}
return new Section(sectionData);
});
}
}
/**
* Outputs a JSON representation of the builder that can be used for rendering with the renderer component.
*/
toJSON () {
return {
title: this.title,
sections: this.sections.map(s => ({
name: s.name,
data: s.data
}))
};
}
/**
* Previews the created page in a seperate tap/window.
*/
preview () {
const frag = this.outputFragment();
const artboard = frag.querySelector('#artboard');
const printPreview = window.open('about:blank', 'print_preview');
const printDocument = printPreview.document;
cleanDOM(frag);
printDocument.open();
printDocument.write(
`<!DOCTYPE html>
<html>
<head>
<title>${this.title}</title>
<link href="${this.assets.css}" rel="stylesheet">
</head>
<body>
${artboard.innerHTML}
<body>
</html>`
);
}
/**
* Exports the builder instance to a specified output. default is json.
*
* @param {String} method
*/
export (method = 'json') {
if (method === 'pwa' || method === 'zip') {
if (typeof this.download === 'function') {
return this.download(this.assets);
}
return console.warn('You do not have the zip plugin installed.');
}
if (method === 'preview') {
return this.preview();
}
return this.toJSON();
}
};
// use the plugin API to add the styler and mixin functionalities.
Vuse.use(styler);
Vuse.use(mixin);
export default Vuse;
gitextract_7xlm9eti/
├── .babelrc
├── .eslintrc.json
├── .gitignore
├── .npmignore
├── LICENSE
├── README.md
├── demo/
│ ├── App.vue
│ ├── Uploader.vue
│ ├── app.js
│ ├── index.html
│ ├── render.html
│ ├── sections/
│ │ ├── forms/
│ │ │ └── newsletter.vue
│ │ ├── hero/
│ │ │ ├── hero1.vue
│ │ │ └── hero2.vue
│ │ ├── section/
│ │ │ ├── section1.vue
│ │ │ └── section2.vue
│ │ └── social/
│ │ ├── social1.vue
│ │ ├── social2.vue
│ │ ├── social3.vue
│ │ └── social4.vue
│ ├── style/
│ │ ├── _demo.styl
│ │ ├── colors.styl
│ │ ├── header.styl
│ │ ├── helper.styl
│ │ ├── main.styl
│ │ ├── scrolling.styl
│ │ ├── section.styl
│ │ ├── social.styl
│ │ ├── transition.styl
│ │ ├── user.styl
│ │ └── variables.styl
│ └── webpack.config.js
├── docs/
│ ├── .vuepress/
│ │ ├── config.js
│ │ ├── enhanceApp.js
│ │ └── public/
│ │ └── style.css
│ ├── API.md
│ ├── README.md
│ ├── example.md
│ ├── exporting.md
│ ├── getting-started.md
│ ├── section.md
│ └── styler.md
├── package.json
├── scripts/
│ ├── build.js
│ ├── config.js
│ └── deploy.sh
└── src/
├── components/
│ ├── VuseBuilder.vue
│ ├── VuseIcon.js
│ ├── VuseRenderer.vue
│ └── VuseStyler.vue
├── index.esm.js
├── index.js
├── mixin.js
├── plugins/
│ ├── pwa.js
│ └── scrolling.js
├── section.js
├── seeder.js
├── styler.js
├── stylus/
│ ├── _app.styl
│ ├── colors.styl
│ └── variables.styl
├── types.js
├── util.js
└── vuse.js
SYMBOL INDEX (58 symbols across 13 files)
FILE: docs/.vuepress/enhanceApp.js
function normalize (line 54) | function normalize (component) {
FILE: scripts/build.js
function buildConfig (line 8) | async function buildConfig (build) {
function build (line 19) | async function build () {
FILE: scripts/config.js
function genConfig (line 48) | function genConfig (options) {
method stats (line 94) | stats ({ path }) {
FILE: src/components/VuseIcon.js
method render (line 46) | render (h, { props }) {
FILE: src/mixin.js
function installMixin (line 1) | function installMixin ({ builder }) {
FILE: src/plugins/pwa.js
function createSW (line 8) | function createSW (output, { images = [] } = {}) {
function createPWA (line 75) | function createPWA (output, payload) {
function download (line 79) | function download (assets) {
function install (line 131) | function install ({ builder }) {
FILE: src/plugins/scrolling.js
function install (line 30) | function install ({ builder }) {
FILE: src/section.js
constant SECTION_OPTIONS (line 5) | const SECTION_OPTIONS = {
class Section (line 12) | class Section {
method constructor (line 13) | constructor (options) {
method set (line 22) | set (name, value) {
method get (line 36) | get (name) {
method destroy (line 45) | destroy () {
FILE: src/seeder.js
constant ASSETS_DIR (line 4) | const ASSETS_DIR = '.';
class Seeder (line 20) | class Seeder {
method seed (line 22) | static seed (schema) {
FILE: src/styler.js
function installStyler (line 4) | function installStyler ({ builder, Vue }) {
FILE: src/types.js
class Avatar (line 1) | class Avatar {}
class Title (line 3) | class Title {}
class Text (line 5) | class Text {}
class Logo (line 7) | class Logo {}
class Image (line 9) | class Image {}
class Quote (line 11) | class Quote {}
class Link (line 13) | class Link {}
class ClassList (line 15) | class ClassList {}
class Button (line 17) | class Button {}
class Grid (line 19) | class Grid { }
FILE: src/util.js
function isObject (line 4) | function isObject (obj) {
function isParentTo (line 8) | function isParentTo (target, parent) {
function getTypeFromSchema (line 22) | function getTypeFromSchema (target, schema) {
function getImageBlob (line 37) | function getImageBlob (URL) {
function getTypeFromTagName (line 54) | function getTypeFromTagName (tagName) {
function cleanDOM (line 88) | function cleanDOM (artboard) {
FILE: src/vuse.js
constant PLUGINS (line 9) | let PLUGINS = [];
constant BUILDER_OPTIONS (line 11) | const BUILDER_OPTIONS = {
class Vuse (line 29) | class Vuse {
method constructor (line 30) | constructor (options) {
method add (line 50) | add (options, position) {
method find (line 63) | find (id) {
method remove (line 71) | remove (section) {
method sort (line 82) | sort (oldIndex, newIndex) {
method outputFragment (line 91) | outputFragment () {
method clear (line 102) | clear () {
method component (line 115) | static component (name, definition) {
method mix (line 126) | static mix (mixinObj) {
method component (line 135) | component (name, definition) {
method installPlugins (line 157) | installPlugins () {
method install (line 165) | static install (Vue, options = {}) {
method use (line 194) | static use (plugin, options = {}) {
method set (line 203) | set (data) {
method toJSON (line 224) | toJSON () {
method preview (line 237) | preview () {
method export (line 263) | export (method = 'json') {
Condensed preview — 64 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (204K chars).
[
{
"path": ".babelrc",
"chars": 211,
"preview": "{\r\n \"presets\": [\r\n [\"@babel/preset-env\", { \"modules\": false }]\r\n ],\r\n \"env\": {\r\n \"test\": {\r\n \"presets\": [\r"
},
{
"path": ".eslintrc.json",
"chars": 191,
"preview": "{\n \"extends\": [\n \"standard\",\n \"plugin:vue/recommended\"\n ],\n\n \"rules\": {\n \"semi\": \"off\",\n "
},
{
"path": ".gitignore",
"chars": 425,
"preview": "# Logs\r\nlogs\r\n*.log\r\nnpm-debug.log*\r\nyarn-debug.log*\r\nyarn-error.log*\r\n\r\n# Dependency directories\r\nnode_modules/\r\njspm_p"
},
{
"path": ".npmignore",
"chars": 51,
"preview": "/docs\r\n/dev\r\n/src\r\n/static\r\n/scripts\r\n.*\r\nyarn.lock"
},
{
"path": "LICENSE",
"chars": 1064,
"preview": "MIT License\n\nCopyright (c) 2017 Baianat\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof"
},
{
"path": "README.md",
"chars": 518,
"preview": "# Vuse\n\n<p align=\"center\">\n <a href=\"https://github.com/baianat/vuse\" target=\"_blank\">\n <img width=\"450\" src=\"https:"
},
{
"path": "demo/App.vue",
"chars": 210,
"preview": "<template>\n <VuseBuilder @saved=\"onSave\" />\n</template>\n\n<script>\nexport default {\n name: 'App',\n methods: {\n onSa"
},
{
"path": "demo/Uploader.vue",
"chars": 1161,
"preview": "<template lang=\"pug\">\n div.uploader\n img(:src=\"src\")\n input.uploader-input(\n type=\"file\"\n ref=\"uploader"
},
{
"path": "demo/app.js",
"chars": 1478,
"preview": "// Vuse scripts\r\nimport Vue from 'vue';\r\nimport pwa from '../src/plugins/pwa';\r\nimport Vuse from '../src';\r\n\r\n// demo sc"
},
{
"path": "demo/index.html",
"chars": 280,
"preview": "<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\"/>\n <meta name=\"viewport\" content=\"width=device-width, initial-sca"
},
{
"path": "demo/render.html",
"chars": 622,
"preview": "<html lang=\"en\">\r\n <head>\r\n <meta charset=\"UTF-8\" />\r\n <meta name=\"viewport\" content=\"width=device-width, initial"
},
{
"path": "demo/sections/forms/newsletter.vue",
"chars": 1344,
"preview": "<template lang=\"pug\">\n section.header(\n v-styler:section=\"$sectionData.classes\"\n :class=\"$sectionData.classes\"\n "
},
{
"path": "demo/sections/hero/hero1.vue",
"chars": 1176,
"preview": "<template lang=\"pug\">\n section.header(\n v-styler=\"$sectionData.classes\"\n :class=\"$sectionData.classes\"\n )\n "
},
{
"path": "demo/sections/hero/hero2.vue",
"chars": 1250,
"preview": "<template lang=\"pug\">\n section.header(\n v-styler=\"$sectionData.classes\"\n :class=\"$sectionData.classes\"\n )\n "
},
{
"path": "demo/sections/section/section1.vue",
"chars": 1585,
"preview": "<template lang=\"pug\">\n section.section(\n v-styler=\"$sectionData.classes\"\n :class=\"$sectionData.classes\"\n )\n ."
},
{
"path": "demo/sections/section/section2.vue",
"chars": 1971,
"preview": "<template lang=\"pug\">\n section.section(\n v-styler:section=\"$sectionData.classes\"\n :class=\"$sectionData.classes\"\n "
},
{
"path": "demo/sections/social/social1.vue",
"chars": 1658,
"preview": "<template lang=\"pug\">\n section.social(\n v-styler:section=\"$sectionData.classes\"\n :class=\"$sectionData.classes\"\n "
},
{
"path": "demo/sections/social/social2.vue",
"chars": 989,
"preview": "<template lang=\"pug\">\n section.social(\n v-styler:section=\"$sectionData.classes\"\n :class=\"$sectionData.classes\"\n "
},
{
"path": "demo/sections/social/social3.vue",
"chars": 1140,
"preview": "<template lang=\"pug\">\n section.social(\n v-styler:section=\"$sectionData.classes\"\n :class=\"$sectionData.classes\"\n "
},
{
"path": "demo/sections/social/social4.vue",
"chars": 2169,
"preview": "<template lang=\"pug\">\n section.social(\n v-styler:section=\"$sectionData.classes\"\n :class=\"$sectionData.classes\"\n "
},
{
"path": "demo/style/_demo.styl",
"chars": 192,
"preview": "@import variables\n@import '~@baianat/base.framework/base'\n\n@import main\n@import header\n@import section\n@import social\n@i"
},
{
"path": "demo/style/colors.styl",
"chars": 338,
"preview": "/*\n * Color theme\n */\n$magenta ?= #eb008b\n$blue ?= #0072FF\n$cyan ?= #00d4f0\n$green ?= #18d88b\n$yellow ?= #ffdd57\n$orange"
},
{
"path": "demo/style/header.styl",
"chars": 676,
"preview": ".header\n width: 100%\n padding: 50px\n color: $white\n &-title\n font-size: 50px\n line-height: 1em\n margin: 20p"
},
{
"path": "demo/style/helper.styl",
"chars": 362,
"preview": "+prefix-classes('add-')\n .center-horizontal\n display: flex\n flex-direction: column \n justify-content: cente"
},
{
"path": "demo/style/main.styl",
"chars": 60,
"preview": "::selection\n color: inherit\n\n\n.button\n white-space: nowrap"
},
{
"path": "demo/style/scrolling.styl",
"chars": 313,
"preview": ".is-active\n img\n opacity: 1\n transition: 0.4s\n p\n h1\n h2\n h3\n h6\n b\n opacity: 1\n transform: translate"
},
{
"path": "demo/style/section.styl",
"chars": 317,
"preview": ".section\n padding: 20px 30px\n &-title\n font-size: 30px\n color: $dark\n\n &-paragraph\n font-size: 16px\n colo"
},
{
"path": "demo/style/social.styl",
"chars": 792,
"preview": ".social\n padding: 100px 0\n &-number\n font-size: 50px\n margin: 20px 0 50px\n &-item\n display: flex\n flex-di"
},
{
"path": "demo/style/transition.styl",
"chars": 138,
"preview": ".fade-enter-active\n.fade-leave-active\n transition: all .3s ease\n transform: scaleX(1)\n\n.fade-enter\n.fade-leave-to\n tr"
},
{
"path": "demo/style/user.styl",
"chars": 521,
"preview": ".user\n display: flex\n align-items: center\n margin: 10px 0\n &.is-alt\n justify-content: center\n flex-direction: "
},
{
"path": "demo/style/variables.styl",
"chars": 76,
"preview": "\n$flexCenter\n display: flex\n justify-content: center\n align-items: center"
},
{
"path": "demo/webpack.config.js",
"chars": 2827,
"preview": "const path = require('path');\nconst webpack = require('webpack');\nconst VueLoaderPlugin = require('vue-loader/lib/plugin"
},
{
"path": "docs/.vuepress/config.js",
"chars": 540,
"preview": "module.exports = {\r\n title: 'Vuse',\r\n description: 'Advanced page builder based on Vue.js',\r\n base: '/vuse/',\r\n them"
},
{
"path": "docs/.vuepress/enhanceApp.js",
"chars": 1553,
"preview": "// Vuse scripts\r\nimport Vuse from '../../src';\r\n\r\n// demo scripts\r\nimport '../../demo/style/_demo.styl';\r\nimport Uploade"
},
{
"path": "docs/.vuepress/public/style.css",
"chars": 99510,
"preview": "\n.vuse-icon {\n display: block;\n width: 20px;\n height: 20px;\n}\n.controller-button:hover,\n.menu-element:hover {\n curso"
},
{
"path": "docs/API.md",
"chars": 575,
"preview": "# API\r\n\r\nYour section components will have some properties injected to help you customize their behavior in building pha"
},
{
"path": "docs/README.md",
"chars": 110,
"preview": "---\r\nhome: true\r\nactionText: Getting Started →\r\nactionLink: ./getting-started\r\nheroImage: /img/logo.png\r\n---\r\n"
},
{
"path": "docs/example.md",
"chars": 511,
"preview": "---\r\nnavbar: true\r\nsidebar: false\r\neditLink: false\r\npageClass: example\r\n---\r\n\r\n<vuse-builder @saved=\"onSave\"></vuse-buil"
},
{
"path": "docs/exporting.md",
"chars": 562,
"preview": "# Exporting\r\n\r\nThere are three ways to export the built page: preview, pwa or json. When clicking the save button the `b"
},
{
"path": "docs/getting-started.md",
"chars": 2092,
"preview": "# getting-started\r\n\r\n## What is this\r\n\r\nThis builder (sections builder) reuses your Vue components as **editable section"
},
{
"path": "docs/section.md",
"chars": 4640,
"preview": "# Section\r\n\r\nA section is the building block of the page, below is an example of a header section.\r\n::: tip\r\n Examples "
},
{
"path": "docs/styler.md",
"chars": 705,
"preview": "# Styler\r\n\r\nThis directive is automatically injected in your section components, and can be used to facilitate editing e"
},
{
"path": "package.json",
"chars": 2962,
"preview": "{\n \"name\": \"vuse\",\n \"version\": \"0.1.1\",\n \"description\": \"Vue.js Page Builder\",\n \"author\": \"Abdelrahman Ismail <abdel"
},
{
"path": "scripts/build.js",
"chars": 810,
"preview": "const chalk = require('chalk');\nconst mkdirpNode = require('mkdirp');\nconst { promisify } = require('util');\nconst { rol"
},
{
"path": "scripts/config.js",
"chars": 2399,
"preview": "const path = require('path');\nconst fs = require('fs');\nconst replace = require('rollup-plugin-replace');\nconst vue = re"
},
{
"path": "scripts/deploy.sh",
"chars": 180,
"preview": "#!/usr/bin/env sh\n\nset -e\n\nnpm run docs:build\n\ncd docs/.vuepress/dist\n\ngit init\ngit add -A\ngit commit -m 'deploy'\n\ngit p"
},
{
"path": "src/components/VuseBuilder.vue",
"chars": 11069,
"preview": "<template lang=\"pug\">\r\n div\r\n div#artboard.artboard(\r\n ref=\"artboard\"\r\n :class=\"{ 'is-sorting': $builder.i"
},
{
"path": "src/components/VuseIcon.js",
"chars": 4317,
"preview": "const icons = {\n plus: 'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z',\n tic: 'M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2"
},
{
"path": "src/components/VuseRenderer.vue",
"chars": 530,
"preview": "<template lang=\"pug\">\r\n #artboard.artboard\r\n component(v-for='section in $builder.sections'\r\n :is='section.name"
},
{
"path": "src/components/VuseStyler.vue",
"chars": 10176,
"preview": "<template lang=\"pug\">\r\n .styler(\r\n ref=\"styler\"\r\n id=\"styler\"\r\n v-if=\"$builder.isEditing\"\r\n :class=\"{ 'is-v"
},
{
"path": "src/index.esm.js",
"chars": 286,
"preview": "import Vuse from './vuse';\nimport * as types from './types';\n\nconst version = '__VERSION__';\n\n// Auto install if Vue is "
},
{
"path": "src/index.js",
"chars": 278,
"preview": "import Vuse from './vuse';\r\nimport * as types from './types';\r\n\r\n// Auto install if Vue is defined globally.\r\nif (typeof"
},
{
"path": "src/mixin.js",
"chars": 1360,
"preview": "function installMixin ({ builder }) {\r\n builder.mixin = {\r\n provide: function providesBuilder () {\r\n const prov"
},
{
"path": "src/plugins/pwa.js",
"chars": 3689,
"preview": "import JSZip from 'jszip';\nimport saveAs from 'save-as';\nimport { getImageBlob, cleanDOM } from '../../src/util';\n\n/**\n "
},
{
"path": "src/plugins/scrolling.js",
"chars": 812,
"preview": "import 'intersection-observer';\n\nconst callback = (entries, observer) => {\n entries.forEach(entry => {\n if (entry.in"
},
{
"path": "src/section.js",
"chars": 1083,
"preview": "import getPath from 'lodash-es/get';\r\nimport toPath from 'lodash-es/toPath';\r\nimport Seeder from './seeder';\r\n\r\nconst SE"
},
{
"path": "src/seeder.js",
"chars": 1526,
"preview": "import * as types from './types';\r\nimport { isObject } from './util';\r\n\r\nconst ASSETS_DIR = '.';\r\nconst data = new Map(["
},
{
"path": "src/styler.js",
"chars": 934,
"preview": "import Styler from './components/VuseStyler.vue';\r\nimport { getTypeFromTagName, getTypeFromSchema } from './util';\r\n\r\nfu"
},
{
"path": "src/stylus/_app.styl",
"chars": 199,
"preview": "@import variables\n@import colors\n\n.vuse-icon\n display: block\n width: 20px\n height: 20px\n$floatHover\n cursor: pointer"
},
{
"path": "src/stylus/colors.styl",
"chars": 338,
"preview": "/*\n * Color theme\n */\n$magenta ?= #eb008b\n$blue ?= #0072FF\n$cyan ?= #00d4f0\n$green ?= #18d88b\n$yellow ?= #ffdd57\n$orange"
},
{
"path": "src/stylus/variables.styl",
"chars": 76,
"preview": "\n$flexCenter\n display: flex\n justify-content: center\n align-items: center"
},
{
"path": "src/types.js",
"chars": 261,
"preview": "export class Avatar {};\r\n\r\nexport class Title {};\r\n\r\nexport class Text {};\r\n\r\nexport class Logo {};\r\n\r\nexport class Imag"
},
{
"path": "src/util.js",
"chars": 2782,
"preview": "import getPath from 'lodash/get';\nimport * as types from './types';\n\nexport function isObject (obj) {\n return obj && ty"
},
{
"path": "src/vuse.js",
"chars": 7096,
"preview": "import merge from 'lodash-es/merge';\nimport Section from './section';\nimport VuseBuilder from './components/VuseBuilder."
}
]
About this extraction
This page contains the full source code of the baianat/vuse GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 64 files (185.6 KB), approximately 60.1k tokens, and a symbol index with 58 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.