Material ripple
Splash screen
RTL support
RTL mode
Theme settings panel
Light style
Material style
Dark style
PAGE LAYOUT
LAYOUT OPTIONS
{{option[1]}}
Fixed navbar
Fixed footer
Reversed
Collapsed sidenav
THEME
NAVBAR BG
{{option}}
SIDENAV BG
{{option}}
FOOTER BG
{{option}}
Laravel + Vue.js Starter
{% if settingsPanel -%}
{% endif %} {% if materialRipple %} {% endif %} {%- if materialRipple and not settingsPanel -%} {% endif %} {% if pageLayout != 'blank' or settingsPanel %} {% endif %} {% if settingsPanel %} {%- endif %} {% if splashScreen %}
CompanyName
{% endif %}
const { EnvironmentPlugin } = require('webpack') const mix = require('laravel-mix') const glob = require('glob') const path = require('path') /* |-------------------------------------------------------------------------- | Mix config |-------------------------------------------------------------------------- */ mix.options({ resourceRoot: !Mix.config.hmr ? process.env.ASSET_URL : undefined, postCss: [require('autoprefixer')], hmrOptions: { host: 'localhost', port: 8081 } }) /* |-------------------------------------------------------------------------- | Webpack config |-------------------------------------------------------------------------- */ mix.webpackConfig({ output: { publicPath: !Mix.config.hmr ? process.env.ASSET_URL : undefined, }, plugins: [ new EnvironmentPlugin({ // Application's public url BASE_URL: !Mix.config.hmr && process.env.ASSET_URL ? `${process.env.ASSET_URL}/` : '/' }) ], module: { rules: [{ test: /node_modules(?:\/|\\).+\.m?js$/, loader: 'babel-loader', include: [ path.join(__dirname, 'node_modules/bootstrap-vue'), path.join(__dirname, 'node_modules/vuejs-datepicker'), path.join(__dirname, 'node_modules/vue-echarts'), path.join(__dirname, 'node_modules/resize-detector'), path.join(__dirname, 'node_modules/vue-c3'), path.join(__dirname, 'node_modules/vue-masonry'), path.join(__dirname, 'node_modules/vue-cropper'), path.join(__dirname, 'node_modules/vuedraggable'), path.join(__dirname, 'node_modules/sweet-modal-vue'), path.join(__dirname, 'node_modules/vue-simplemde'), path.join(__dirname, 'node_modules/vue2-dropzone'), path.join(__dirname, 'node_modules/dropzone'), path.join(__dirname, 'node_modules/marked'), path.join(__dirname, 'node_modules/vue-plyr'), path.join(__dirname, 'node_modules/swiper'), path.join(__dirname, 'node_modules/dom7') ], options: Object.assign({}, require('./package.json').babel, { babelrc: false }) }] }, resolve: { alias: { '@': path.join(__dirname, 'resources/assets/src'), 'node_modules': path.join(__dirname, 'node_modules') } }, devServer: { host: '0.0.0.0', port: 8081 } }) mix.override(config => { // Inject node-sass compiler config.module.rules .filter(rule => rule.test && ( (typeof rule.test == 'string' && (rule.test.endsWith('.sass') || rule.test.endsWith('.scss'))) || (typeof rule.test.test === 'function' && (rule.test.test('.sass') || rule.test.test('.scss'))) )) .forEach(rule => { let loaders = [] if (Array.isArray(rule.loaders)) { loaders = rule.loaders.find(loader => loader.loader === 'sass-loader') } else if (Array.isArray(rule.oneOf)) { rule.oneOf.forEach(item => { loaders = loaders.concat(item.use.find(loader => loader.loader === 'sass-loader')) }) } loaders.forEach(loader => { Object.assign(loader.options, { implementation: require('node-sass') }) }) }) return config }) /* |-------------------------------------------------------------------------- | Vendor assets |-------------------------------------------------------------------------- */ function mixAssetsDir(query, cb) { (glob.sync('resources/assets/' + query) || []).forEach(f => { f = f.replace(/[\\\/]+/g, '/') cb(f, f.replace('resources/assets', 'public')) }) } const sassOptions = { implementation: require('node-sass') } {% if settingsPanel -%} // Core stylesheets {%- for fileName in ['appwork', 'bootstrap', 'colors'] -%}{% set isFirstLoop = loop.first %}{% for styleName in styles %} {% if isFirstLoop and loop.first %}mix{% else %} {% endif -%} .sass('resources/assets/src/vendor/styles{% if rtlSupport %}/rtl{% endif %}/{{fileName}}{% if styleName == 'material' %}-material{% elif styleName == 'dark' %}-dark{% endif %}.scss', 'public/vendor/css', sassOptions) {%- endfor %}{% endfor %} .sass('resources/assets/src/vendor/styles{% if rtlSupport %}/rtl{% endif %}/uikit.scss', 'public/vendor/css', sassOptions) // Themes {%- for themeName in ['air', 'corporate', 'cotton', 'gradient', 'paper', 'shadow', 'soft', 'sunrise', 'twitlight', 'vibrant'] -%}{% set isFirstLoop = loop.first %}{% for styleName in styles %} {% if isFirstLoop and loop.first %}mix{% else %} {% endif -%} .sass('resources/assets/src/vendor/styles{% if rtlSupport %}/rtl{% endif %}/theme-{{themeName}}{% if styleName == 'material' %}-material{% elif styleName == 'dark' %}-dark{% endif %}.scss', 'public/vendor/css', sassOptions) {%- endfor %}{% endfor %} {%- endif %} // Core javascripts mixAssetsDir('vendor/js/**/*.js', (src, dest) => mix.scripts(src, dest)) // Fonts mixAssetsDir('vendor/fonts/*.css', (src, dest) => mix.copy(src, dest)) mixAssetsDir('vendor/fonts/*/*', (src, dest) => mix.copy(src, dest)) /* |-------------------------------------------------------------------------- | Entry point |-------------------------------------------------------------------------- */ mix.js('resources/assets/src/entry-point.js', 'public').vue({ version: 2 }) if (Mix.isUsing('hmr')) { mix.disableNotifications() } else { mix.version() }
import layoutHelpers from '@/layout/helpers.js' {% if settingsPanel -%} import themeSettings from '@/vendor/libs/theme-settings/theme-settings.js' {%- endif %} export default function () { return { // Public url publicUrl: process.env.BASE_URL, // Layout helpers layoutHelpers, {% if settingsPanel -%} // Theme settings themeSettings, {%- endif %} // Check for RTL layout get isRtlMode () { return document.documentElement.getAttribute('dir') === 'rtl' || document.body.getAttribute('dir') === 'rtl' }, // Check if IE get isIEMode () { return typeof document.documentMode === 'number' }, // Check if IE10 get isIE10Mode () { return this.isIEMode && document.documentMode === 10 }, // Layout navbar color get layoutNavbarBg () { {% if settingsPanel -%} return this.themeSettings.getOption('navbarBg') || '{{navbarBg}}' {%- else -%} return '{{navbarBg}}' {%- endif %} }, // Layout sidenav color get layoutSidenavBg () { {% if settingsPanel -%} return this.themeSettings.getOption('sidenavBg') || '{{sidenavBg}}' {%- else -%} return '{{sidenavBg}}' {%- endif %} }, // Layout footer color get layoutFooterBg () { {% if settingsPanel -%} return this.themeSettings.getOption('footerBg') || '{{footerBg}}' {%- else -%} return '{{footerBg}}' {%- endif %} }, // Animate scrollTop scrollTop (to, duration, element = document.scrollingElement || document.documentElement) { if (element.scrollTop === to) return const start = element.scrollTop const change = to - start const startDate = +new Date() // t = current time; b = start value; c = change in value; d = duration const easeInOutQuad = (t, b, c, d) => { t /= d / 2 if (t < 1) return c / 2 * t * t + b t-- return -c / 2 * (t * (t - 2) - 1) + b } const animateScroll = () => { const currentDate = +new Date() const currentTime = currentDate - startDate element.scrollTop = parseInt(easeInOutQuad(currentTime, start, change, duration)) if (currentTime < duration) { requestAnimationFrame(animateScroll) } else { element.scrollTop = to } } animateScroll() } } }
import Vue from 'vue' import Router from 'vue-router' import Meta from 'vue-meta' import NotFound from '@/components/NotFound' import globals from '@/globals' // Layouts import {{layoutClass(pageLayout)}} from '@/layout/{{layoutClass(pageLayout)}}' Vue.use(Router) Vue.use(Meta) const router = new Router({ base: '/', mode: 'history', routes: [{ path: '/', component: {{layoutClass(pageLayout)}}, children: [{ path: '', component: () => import('@/components/Home') }, { path: 'page-2', component: () => import('@/components/Page2') }] }, { // 404 Not Found page path: '*', component: NotFound }] }) router.afterEach(() => { {% if splashScreen -%} // Remove initial splash screen const splashScreen = document.querySelector('.app-splash-screen') if (splashScreen) { splashScreen.style.opacity = 0 setTimeout(() => splashScreen && splashScreen.parentNode && splashScreen.parentNode.removeChild(splashScreen) , 300) } {% endif -%} // On small screens collapse sidenav if (window.layoutHelpers && window.layoutHelpers.isSmallScreen() && !window.layoutHelpers.isCollapsed()) { setTimeout(() => window.layoutHelpers.setCollapsed(true, true), 10) } // Scroll to top of the page globals().scrollTop(0, 0) }) router.beforeEach((to, from, next) => { // Set loading state document.body.classList.add('app-loading') // Add tiny timeout to finish page transition setTimeout(() => next(), 10) }) export default router
{% if not settingsPanel -%} {%- endif %}
$enable-rtl-support: {% if rtlSupport %}true{% else %}false{% endif %}; $enable-light-style: {% if (not settingsPanel and style == 'light') or (settingsPanel and styles.indexOf('light') !== -1) %}true{% else %}false{% endif %}; $enable-material-style: {% if (not settingsPanel and style == 'material') or (settingsPanel and styles.indexOf('material') !== -1) %}true{% else %}false{% endif %}; $enable-dark-style: {% if (not settingsPanel and style == 'dark') or (settingsPanel and styles.indexOf('dark') !== -1) %}true{% else %}false{% endif %}; @mixin feature-ltr($as-child: true) { @if $enable-rtl-support { @if $as-child { html:not([dir=rtl]) & { @content; } } @else { html:not([dir=rtl]) { @content; } } } @else { @content; } } @mixin feature-ltr-style() { @if $enable-rtl-support { &:not([dir=rtl]) { @content; } } @else { @content; } } @mixin feature-rtl($as-child: true) { @if $enable-rtl-support { @if $as-child { [dir=rtl] & { @content; } } @else { [dir=rtl] { @content; } } } } @mixin feature-rtl-style() { @if $enable-rtl-support { &[dir=rtl] { @content; } } }