├── .babelrc ├── .env.dev ├── .env.docdev ├── .env.docpro ├── .env.iframe ├── .env.pro ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .npmrc ├── README.md ├── babel.config.js ├── config ├── config.build.iframe.js ├── config.build.js ├── config.dev.js └── config.doc.js ├── doc ├── App.vue ├── babel.config.js ├── components │ ├── CodeSnippet.vue │ └── Collapse.vue ├── config.js ├── main.js ├── router.js ├── style │ ├── imports.scss │ ├── md-colors.scss │ ├── mixins.scss │ └── vars.scss └── views │ ├── Home.vue │ └── Start.vue ├── docs ├── favicon.ico ├── file-viewer │ ├── favicon.ico │ ├── fileTest │ │ ├── mp3.mp3 │ │ ├── mp4.mp4 │ │ ├── pdf.pdf │ │ ├── pic.png │ │ ├── ppt.pptx │ │ └── word.docx │ ├── index.html │ └── static │ │ ├── css │ │ ├── chunk-vendors.053867c8.css │ │ └── index.30170716.css │ │ └── js │ │ ├── chunk-vendors.101c5e96.js │ │ ├── chunk-vendors.101c5e96.js.map │ │ ├── index.a286462a.js │ │ ├── index.a286462a.js.map │ │ ├── pdf.worker.d60c6c06.worker.js │ │ ├── pdf.worker.d60c6c06.worker.js.map │ │ ├── pptx.worker.3c5d3299.worker.js │ │ └── pptx.worker.3c5d3299.worker.js.map ├── fileTest │ ├── mp3.mp3 │ ├── mp4.mp4 │ ├── pdf.pdf │ ├── pic.png │ ├── ppt.pptx │ └── word.docx ├── index.html └── static │ ├── css │ ├── chunk-vendors.5e3ffc13.css │ └── index.28319711.css │ └── js │ ├── chunk-vendors.e1710af5.js │ ├── chunk-vendors.e1710af5.js.map │ ├── index.f0ffebef.js │ ├── index.f0ffebef.js.map │ ├── pdf.worker.d60c6c06.worker.js │ ├── pdf.worker.d60c6c06.worker.js.map │ ├── pptx.worker.3c5d3299.worker.js │ └── pptx.worker.3c5d3299.worker.js.map ├── examples ├── App.vue └── main.js ├── jsconfig.json ├── package.json ├── packages ├── index.js ├── index.scss ├── index.vue ├── pollify.js ├── renders.js ├── util.js ├── util │ └── EventBus.js └── vendors │ ├── audio │ └── index.js │ ├── error │ ├── error.vue │ └── index.js │ ├── image │ ├── ImageViewer.vue │ └── index.js │ ├── mp4 │ └── index.js │ ├── notFind │ ├── index.js │ └── notFind.vue │ ├── officeOnline │ └── index.js │ ├── pdf │ ├── PdfView.vue │ ├── images │ │ ├── loading-icon.gif │ │ └── shadow.png │ ├── index.js │ └── pdf.css │ ├── pptx │ ├── backup │ │ ├── index.js │ │ ├── pptx_css.js │ │ ├── process_pptx.js │ │ ├── t_xml.js │ │ └── worker.js │ ├── index.js │ ├── lib │ │ ├── dingbat.js │ │ ├── divs2slides.js │ │ └── tXml.js │ ├── options.js │ ├── pptx.vue │ ├── process.js │ ├── styles │ │ └── pptxjs.css │ ├── support │ │ └── vendor.js │ └── worker │ │ └── pptx.worker.js │ ├── text │ ├── CodeViewer.vue │ └── index.js │ └── xlsx │ ├── Table.vue │ ├── color.js │ ├── index.js │ └── util.js ├── prettier.config.js ├── public ├── favicon.ico ├── file-viewer │ ├── favicon.ico │ ├── fileTest │ │ ├── mp3.mp3 │ │ ├── mp4.mp4 │ │ ├── pdf.pdf │ │ ├── pic.png │ │ ├── ppt.pptx │ │ └── word.docx │ ├── index.html │ └── static │ │ ├── css │ │ ├── chunk-vendors.053867c8.css │ │ └── index.30170716.css │ │ └── js │ │ ├── chunk-vendors.101c5e96.js │ │ ├── chunk-vendors.101c5e96.js.map │ │ ├── index.a286462a.js │ │ ├── index.a286462a.js.map │ │ ├── pdf.worker.d60c6c06.worker.js │ │ ├── pdf.worker.d60c6c06.worker.js.map │ │ ├── pptx.worker.3c5d3299.worker.js │ │ └── pptx.worker.3c5d3299.worker.js.map ├── fileTest │ ├── mp3.mp3 │ ├── mp4.mp4 │ ├── pdf.pdf │ ├── pic.png │ ├── ppt.pptx │ └── word.docx └── index.html ├── vue.config.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@vue/cli-plugin-babel/preset" 4 | ] 5 | } -------------------------------------------------------------------------------- /.env.dev: -------------------------------------------------------------------------------- 1 | NODE_ENV = development 2 | 3 | VUE_APP_ENV = development -------------------------------------------------------------------------------- /.env.docdev: -------------------------------------------------------------------------------- 1 | NODE_ENV = development 2 | 3 | VUE_APP_ENV = doc -------------------------------------------------------------------------------- /.env.docpro: -------------------------------------------------------------------------------- 1 | NODE_ENV = production 2 | 3 | VUE_APP_ENV = doc -------------------------------------------------------------------------------- /.env.iframe: -------------------------------------------------------------------------------- 1 | NODE_ENV = production 2 | 3 | VUE_APP_ENV = iframe -------------------------------------------------------------------------------- /.env.pro: -------------------------------------------------------------------------------- 1 | NODE_ENV = production 2 | 3 | VUE_APP_ENV = production -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | lib 2 | dist 3 | docs 4 | file-viewer 5 | vendors -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: zhanghan 3 | * @Date: 2023-01-04 13:49:25 4 | * @LastEditors: zhanghan 5 | * @LastEditTime: 2023-01-10 00:16:51 6 | * @Descripttion: 7 | */ 8 | module.exports = { 9 | root: true, 10 | env: { 11 | node: true 12 | }, 13 | extends: ['plugin:vue/essential', 'eslint:recommended'], 14 | parserOptions: { 15 | parser: '@babel/eslint-parser' 16 | }, 17 | rules: { 18 | 'no-console': 'off', 19 | 'no-debugger': 'off', 20 | 'no-unused-vars': ['error', { args: 'none' }], // 允许函数参数未使用 21 | 'no-control-regex': 0, // 允许在正则表达式中使用控制字符 22 | //关闭组件命名规则 23 | 'vue/multi-word-component-names': 'off', 24 | // 强制使用单引号 25 | quotes: ['error', 'single'], 26 | // 强制不使用分号结尾 27 | semi: ['error', 'never'] 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | /lib 5 | .cache 6 | .temp 7 | doc/.vuepress/dist/ 8 | 9 | # local env files 10 | .env.local 11 | .env.*.local 12 | 13 | # Log files 14 | npm-debug.log* 15 | yarn-debug.log* 16 | yarn-error.log* 17 | pnpm-debug.log* 18 | 19 | # Editor directories and files 20 | .idea 21 | .vscode 22 | *.suo 23 | *.ntvs* 24 | *.njsproj 25 | *.sln 26 | *.sw? 27 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | engine-strict=false 3 | save-exact=true 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-file-viewer 2 | 3 | ❤️ ❤️ ❤️ 开源不易,请各位大佬给个 Start✨✨✨,同时欢迎提 PR 和 Issure!:smile: 4 | 5 | #### 介绍: 6 | 7 | 这是以一个跨框架的解决方案(通过iframe引入) 8 | 9 | 该组件集成了市面上纯前端渲染多种常用文档格式的主流方案,如 pptx,docx,xlsx,pdf,视频,音频,纯文本和图片。 10 | 11 | 后期计划增加更多文件格式的在线浏览支持。 12 | 13 | ##### [☞☞☞ 项目 api 文档和演示戳这里](https://file-viewer.me7.cn/index.html) 14 | 15 | ##### 这里 特别鸣谢 [小爬的老粉丝](https://blog.csdn.net/wybaby168) 分享的文章、源码内核和思路,在此基础上进行了封包和优化 16 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: zhanghan 3 | * @Date: 2022-11-27 19:21:21 4 | * @LastEditors: zhanghan 5 | * @LastEditTime: 2022-11-28 20:19:04 6 | * @Descripttion: babe配置 7 | */ 8 | module.exports = { 9 | presets: ['@vue/cli-plugin-babel/preset'] 10 | } 11 | -------------------------------------------------------------------------------- /config/config.build.iframe.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: zhanghan 3 | * @Date: 2022-11-28 09:13:53 4 | * @LastEditors: zhanghan 5 | * @LastEditTime: 2023-01-11 15:23:46 6 | * @Descripttion: iframe开发环境配置 7 | */ 8 | const path = require('path') 9 | const fs = require('fs-extra') 10 | // 获取基于当前路径的目标文件 11 | const resolve = (dir) => path.join(__dirname, '../', dir) 12 | 13 | // 添加日志查看路径 14 | console.log('Source path:', resolve('public/file-viewer')) 15 | console.log('Target path:', resolve('docs')) 16 | 17 | module.exports = { 18 | publicPath: './', 19 | // 放在public下供项目演示时作为iframe入口使用 20 | outputDir: resolve('public/file-viewer'), 21 | pages: { 22 | index: { 23 | entry: 'examples/main.js', 24 | template: 'public/index.html', 25 | filename: 'index.html' 26 | } 27 | }, 28 | assetsDir: 'static', 29 | // 扩展 webpack 配置 30 | chainWebpack: (config) => { 31 | // set worker-loader 32 | config.module 33 | .rule('worker') 34 | .test(/\.worker\.js$/) 35 | .use('worker-loader') 36 | .loader('worker-loader') 37 | .end() 38 | 39 | // 解决:worker 热更新问题 40 | config.module.rule('js').exclude.add(/\.worker\.js$/) 41 | 42 | // packages 加入编译 43 | config.module 44 | .rule('js') 45 | .include.add('/packages') 46 | .end() 47 | .use('babel') 48 | .loader('babel-loader') 49 | 50 | // 别名配置 51 | config.resolve.alias.set('@', '/examples').set('@packages', '/packages') 52 | 53 | // 使用 fs-extra 复制文件 54 | config.plugin('copy-file-viewer').use({ 55 | apply: (compiler) => { 56 | compiler.hooks.done.tap('CopyFileViewerPlugin', (stats) => { 57 | const sourceDir = resolve('public/file-viewer') 58 | const targetDir = resolve('docs/file-viewer') 59 | 60 | // 添加日志 61 | console.log('开始复制文件...') 62 | console.log('源目录:', sourceDir) 63 | console.log('目标目录:', targetDir) 64 | 65 | try { 66 | fs.copySync(sourceDir, targetDir, { overwrite: true }) 67 | console.log('文件复制成功!') 68 | } catch (err) { 69 | console.error('复制失败:', err) 70 | } 71 | }) 72 | } 73 | }) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /config/config.build.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: zhanghan 3 | * @Date: 2022-11-28 09:13:53 4 | * @LastEditors: zhanghan 5 | * @LastEditTime: 2023-01-09 21:49:06 6 | * @Descripttion: 生产环境配置 7 | */ 8 | 9 | const path = require('path') 10 | // 获取基于当前路径的目标文件 11 | const resolve = (dir) => path.join(__dirname, '../', dir) 12 | 13 | const buildConfig = { 14 | // 输出文件目录 15 | outputDir: resolve('lib'), 16 | productionSourceMap: false, 17 | // webpack配置 18 | configureWebpack: { 19 | // 入口文件(这里获取到的是每个独立包的入口文件地址数组) 20 | entry: { 21 | // 全量引入的文件入口 22 | index: resolve('packages') 23 | }, 24 | // 输出配置 25 | output: { 26 | // 主入口文件名称 27 | filename: '[name]/index.js', 28 | // 构建依赖类型 29 | libraryTarget: 'umd', 30 | // 库中被导出的项 31 | libraryExport: 'default', 32 | // 引用时的依赖名 33 | library: 'vue-file-viewer' 34 | } 35 | }, 36 | css: { 37 | sourceMap: false, 38 | // 是否将组件中的css提取至一个独立的css,库构建时可以设置为false,免得用户需要自己导入css 39 | extract: false 40 | // extract: { 41 | // filename: '[name]/index.css', 42 | // }, 43 | }, 44 | chainWebpack: (config) => { 45 | // set worker-loader 46 | config.module 47 | .rule('worker') 48 | .test(/\.worker\.js$/) 49 | .use('worker-loader') 50 | .loader('worker-loader') 51 | .end() 52 | 53 | // 解决:worker 热更新问题 54 | config.module.rule('js').exclude.add(/\.worker\.js$/) 55 | 56 | // 一些构建优化 57 | // 删除splitChunks,因为每个组件是独立打包,不需要抽离每个组件的公共js出来。 58 | config.optimization.delete('splitChunks') 59 | // 删除copy,不要复制public文件夹内容到lib文件夹中。 60 | config.plugins.delete('copy') 61 | // 删除preload以及prefetch,因为不生成html页面,所以这两个也没用。 62 | config.plugins.delete('preload') 63 | config.plugins.delete('prefetch') 64 | // 删除html,只打包组件,不生成html页面。 65 | config.plugins.delete('html') 66 | // 删除hmr,删除热更新。 67 | config.plugins.delete('hmr') 68 | // 删除自动加上的入口App。 69 | config.entryPoints.delete('app') 70 | } 71 | } 72 | 73 | module.exports = buildConfig 74 | -------------------------------------------------------------------------------- /config/config.dev.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: zhanghan 3 | * @Date: 2022-11-28 09:13:53 4 | * @LastEditors: zhanghan 5 | * @LastEditTime: 2023-01-09 23:53:58 6 | * @Descripttion: 开发环境配置 7 | */ 8 | 9 | module.exports = { 10 | pages: { 11 | index: { 12 | entry: 'examples/main.js', 13 | template: 'public/index.html', 14 | filename: 'index.html' 15 | } 16 | }, 17 | // 扩展 webpack 配置 18 | chainWebpack: (config) => { 19 | // set worker-loader 20 | config.module 21 | .rule('worker') 22 | .test(/\.worker\.js$/) 23 | .use('worker-loader') 24 | .loader('worker-loader') 25 | .end() 26 | 27 | // 解决:worker 热更新问题 28 | config.module.rule('js').exclude.add(/\.worker\.js$/) 29 | 30 | // packages 加入编译 31 | config.module 32 | .rule('js') 33 | .include.add('/packages') 34 | .end() 35 | .use('babel') 36 | .loader('babel-loader') 37 | 38 | // 别名配置 39 | config.resolve.alias.set('@', '/examples').set('@packages', '/packages') 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /config/config.doc.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: zhanghan 3 | * @Date: 2022-11-28 09:13:53 4 | * @LastEditors: zhanghan 5 | * @LastEditTime: 2023-01-11 13:33:12 6 | * @Descripttion: 文档环境配置 7 | */ 8 | 9 | const path = require('path') 10 | 11 | module.exports = { 12 | outputDir: './docs', 13 | publicPath: './', 14 | assetsDir: 'static', 15 | pages: { 16 | index: { 17 | entry: 'doc/main.js', 18 | template: 'public/index.html', 19 | filename: 'index.html' 20 | } 21 | }, 22 | // 扩展 webpack 配置 23 | chainWebpack: (config) => { 24 | // set worker-loader 25 | config.module 26 | .rule('worker') 27 | .test(/\.worker\.js$/) 28 | .use('worker-loader') 29 | .loader('worker-loader') 30 | .end() 31 | 32 | // 解决:worker 热更新问题 33 | config.module.rule('js').exclude.add(/\.worker\.js$/) 34 | 35 | // packages 加入编译 36 | config.module 37 | .rule('js') 38 | .include.add('/packages') 39 | .end() 40 | .use('babel') 41 | .loader('babel-loader') 42 | 43 | // 别名配置 44 | config.resolve.alias 45 | .set('@', path.resolve(__dirname, '../doc')) 46 | .set('@packages', path.resolve(__dirname, '../packages')) 47 | }, 48 | css: { 49 | loaderOptions: { 50 | sass: { 51 | sassOptions: { 52 | // 设置 Sass 的严格模式,这有助于减少一些警告 53 | charset: false, 54 | outputStyle: 'expanded' 55 | }, 56 | additionalData: ` 57 | @use "sass:color"; 58 | @use "@/style/mixins" as mix; 59 | @use "@/style/vars" as var; 60 | @use "@/style/md-colors" as colors; 61 | ` 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /doc/App.vue: -------------------------------------------------------------------------------- 1 | 73 | 74 | 98 | 99 | 295 | -------------------------------------------------------------------------------- /doc/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /doc/components/CodeSnippet.vue: -------------------------------------------------------------------------------- 1 | 8 | 17 | 18 | 46 | 47 | 89 | -------------------------------------------------------------------------------- /doc/components/Collapse.vue: -------------------------------------------------------------------------------- 1 | 8 | 17 | 18 | 32 | 33 | 61 | -------------------------------------------------------------------------------- /doc/config.js: -------------------------------------------------------------------------------- 1 | export const config = require('../package.json') 2 | 3 | export const upName = config.name.replace(/(^\w|-\w)/g, m => m.replace('-', '').toUpperCase()) 4 | -------------------------------------------------------------------------------- /doc/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: zhanghan 3 | * @Date: 2023-01-10 14:28:32 4 | * @LastEditors: zhanghan 5 | * @LastEditTime: 2023-01-10 15:37:42 6 | * @Descripttion: 7 | */ 8 | 9 | import Vue from 'vue' 10 | import App from './App.vue' 11 | import router from './router' 12 | import VueFileViewer from '../packages' 13 | Vue.use(VueFileViewer) 14 | 15 | new Vue({ 16 | el: '#app', 17 | router, 18 | render: (h) => h(App) 19 | }) 20 | -------------------------------------------------------------------------------- /doc/router.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: zhanghan 3 | * @Date: 2023-01-10 14:28:32 4 | * @LastEditors: zhanghan 5 | * @LastEditTime: 2023-01-11 11:00:38 6 | * @Descripttion: 7 | */ 8 | import Vue from 'vue' 9 | import VueRouter from 'vue-router' 10 | import Home from './views/Home.vue' 11 | import Start from './views/Start.vue' 12 | 13 | Vue.use(VueRouter) 14 | 15 | export const routes = [ 16 | { path: '/', name: '快速上手', component: Home }, 17 | { path: '/start', name: '使用文档', component: Start }, 18 | { path: '*', redirect: '/' } 19 | ] 20 | 21 | const router = new VueRouter({ routes }) 22 | 23 | export default router 24 | -------------------------------------------------------------------------------- /doc/style/imports.scss: -------------------------------------------------------------------------------- 1 | @use './mixins' as mix; 2 | @use './vars' as var; 3 | @use './md-colors' as colors; 4 | 5 | -------------------------------------------------------------------------------- /doc/style/md-colors.scss: -------------------------------------------------------------------------------- 1 | $md-red: #f44336; 2 | $md-red-50: #ffebee; 3 | $md-red-100: #ffcdd2; 4 | $md-red-200: #ef9a9a; 5 | $md-red-300: #e57373; 6 | $md-red-400: #ef5350; 7 | $md-red-500: #f44336; 8 | $md-red-600: #e53935; 9 | $md-red-700: #d32f2f; 10 | $md-red-800: #c62828; 11 | $md-red-900: #b71c1c; 12 | $md-red-a100: #ff8a80; 13 | $md-red-a200: #ff5252; 14 | $md-red-a400: #ff1744; 15 | $md-red-a700: #d50000; 16 | 17 | $md-pink: #e91e63; 18 | $md-pink-50: #fce4ec; 19 | $md-pink-100: #f8bbd0; 20 | $md-pink-200: #f48fb1; 21 | $md-pink-300: #f06292; 22 | $md-pink-400: #ec407a; 23 | $md-pink-500: #e91e63; 24 | $md-pink-600: #d81b60; 25 | $md-pink-700: #c2185b; 26 | $md-pink-800: #ad1457; 27 | $md-pink-900: #880e4f; 28 | $md-pink-a100: #ff80ab; 29 | $md-pink-a200: #ff4081; 30 | $md-pink-a400: #f50057; 31 | $md-pink-a700: #c51162; 32 | 33 | $md-purple: #9c27b0; 34 | $md-purple-50: #f3e5f5; 35 | $md-purple-100: #e1bee7; 36 | $md-purple-200: #ce93d8; 37 | $md-purple-300: #ba68c8; 38 | $md-purple-400: #ab47bc; 39 | $md-purple-500: #9c27b0; 40 | $md-purple-600: #8e24aa; 41 | $md-purple-700: #7b1fa2; 42 | $md-purple-800: #6a1b9a; 43 | $md-purple-900: #4a148c; 44 | $md-purple-a100: #ea80fc; 45 | $md-purple-a200: #e040fb; 46 | $md-purple-a400: #d500f9; 47 | $md-purple-a700: #aa00ff; 48 | 49 | $md-deep-purple: #673ab7; 50 | $md-deep-purple-50: #ede7f6; 51 | $md-deep-purple-100: #d1c4e9; 52 | $md-deep-purple-200: #b39ddb; 53 | $md-deep-purple-300: #9575cd; 54 | $md-deep-purple-400: #7e57c2; 55 | $md-deep-purple-500: #673ab7; 56 | $md-deep-purple-600: #5e35b1; 57 | $md-deep-purple-700: #512da8; 58 | $md-deep-purple-800: #4527a0; 59 | $md-deep-purple-900: #311b92; 60 | $md-deep-purple-a100: #b388ff; 61 | $md-deep-purple-a200: #7c4dff; 62 | $md-deep-purple-a400: #651fff; 63 | $md-deep-purple-a700: #6200ea; 64 | 65 | $md-indigo: #3f51b5; 66 | $md-indigo-50: #e8eaf6; 67 | $md-indigo-100: #c5cae9; 68 | $md-indigo-200: #9fa8da; 69 | $md-indigo-300: #7986cb; 70 | $md-indigo-400: #5c6bc0; 71 | $md-indigo-500: #3f51b5; 72 | $md-indigo-600: #3949ab; 73 | $md-indigo-700: #303f9f; 74 | $md-indigo-800: #283593; 75 | $md-indigo-900: #1a237e; 76 | $md-indigo-a100: #8c9eff; 77 | $md-indigo-a200: #536dfe; 78 | $md-indigo-a400: #3d5afe; 79 | $md-indigo-a700: #304ffe; 80 | 81 | $md-blue: #2196f3; 82 | $md-blue-50: #e3f2fd; 83 | $md-blue-100: #bbdefb; 84 | $md-blue-200: #90caf9; 85 | $md-blue-300: #64b5f6; 86 | $md-blue-400: #42a5f5; 87 | $md-blue-500: #2196f3; 88 | $md-blue-600: #1e88e5; 89 | $md-blue-700: #1976d2; 90 | $md-blue-800: #1565c0; 91 | $md-blue-900: #0d47a1; 92 | $md-blue-a100: #82b1ff; 93 | $md-blue-a200: #448aff; 94 | $md-blue-a400: #2979ff; 95 | $md-blue-a700: #2962ff; 96 | 97 | $md-light-blue: #03a9f4; 98 | $md-light-blue-50: #e1f5fe; 99 | $md-light-blue-100: #b3e5fc; 100 | $md-light-blue-200: #81d4fa; 101 | $md-light-blue-300: #4fc3f7; 102 | $md-light-blue-400: #29b6f6; 103 | $md-light-blue-500: #03a9f4; 104 | $md-light-blue-600: #039be5; 105 | $md-light-blue-700: #0288d1; 106 | $md-light-blue-800: #0277bd; 107 | $md-light-blue-900: #01579b; 108 | $md-light-blue-a100: #80d8ff; 109 | $md-light-blue-a200: #40c4ff; 110 | $md-light-blue-a400: #00b0ff; 111 | $md-light-blue-a700: #0091ea; 112 | 113 | $md-cyan: #00bcd4; 114 | $md-cyan-50: #e0f7fa; 115 | $md-cyan-100: #b2ebf2; 116 | $md-cyan-200: #80deea; 117 | $md-cyan-300: #4dd0e1; 118 | $md-cyan-400: #26c6da; 119 | $md-cyan-500: #00bcd4; 120 | $md-cyan-600: #00acc1; 121 | $md-cyan-700: #0097a7; 122 | $md-cyan-800: #00838f; 123 | $md-cyan-900: #006064; 124 | $md-cyan-a100: #84ffff; 125 | $md-cyan-a200: #18ffff; 126 | $md-cyan-a400: #00e5ff; 127 | $md-cyan-a700: #00b8d4; 128 | 129 | $md-teal: #009688; 130 | $md-teal-50: #e0f2f1; 131 | $md-teal-100: #b2dfdb; 132 | $md-teal-200: #80cbc4; 133 | $md-teal-300: #4db6ac; 134 | $md-teal-400: #26a69a; 135 | $md-teal-500: #009688; 136 | $md-teal-600: #00897b; 137 | $md-teal-700: #00796b; 138 | $md-teal-800: #00695c; 139 | $md-teal-900: #004d40; 140 | $md-teal-a100: #a7ffeb; 141 | $md-teal-a200: #64ffda; 142 | $md-teal-a400: #1de9b6; 143 | $md-teal-a700: #00bfa5; 144 | 145 | $md-green: #4caf50; 146 | $md-green-50: #e8f5e9; 147 | $md-green-100: #c8e6c9; 148 | $md-green-200: #a5d6a7; 149 | $md-green-300: #81c784; 150 | $md-green-400: #66bb6a; 151 | $md-green-500: #4caf50; 152 | $md-green-600: #43a047; 153 | $md-green-700: #388e3c; 154 | $md-green-800: #2e7d32; 155 | $md-green-900: #1b5e20; 156 | $md-green-a100: #b9f6ca; 157 | $md-green-a200: #69f0ae; 158 | $md-green-a400: #00e676; 159 | $md-green-a700: #00c853; 160 | 161 | $md-light-green: #8bc34a; 162 | $md-light-green-50: #f1f8e9; 163 | $md-light-green-100: #dcedc8; 164 | $md-light-green-200: #c5e1a5; 165 | $md-light-green-300: #aed581; 166 | $md-light-green-400: #9ccc65; 167 | $md-light-green-500: #8bc34a; 168 | $md-light-green-600: #7cb342; 169 | $md-light-green-700: #689f38; 170 | $md-light-green-800: #558b2f; 171 | $md-light-green-900: #33691e; 172 | $md-light-green-a100: #ccff90; 173 | $md-light-green-a200: #b2ff59; 174 | $md-light-green-a400: #76ff03; 175 | $md-light-green-a700: #64dd17; 176 | 177 | $md-lime: #cddc39; 178 | $md-lime-50: #f9fbe7; 179 | $md-lime-100: #f0f4c3; 180 | $md-lime-200: #e6ee9c; 181 | $md-lime-300: #dce775; 182 | $md-lime-400: #d4e157; 183 | $md-lime-500: #cddc39; 184 | $md-lime-600: #c0ca33; 185 | $md-lime-700: #afb42b; 186 | $md-lime-800: #9e9d24; 187 | $md-lime-900: #827717; 188 | $md-lime-a100: #f4ff81; 189 | $md-lime-a200: #eeff41; 190 | $md-lime-a400: #c6ff00; 191 | $md-lime-a700: #aeea00; 192 | 193 | $md-yellow: #ffeb3b; 194 | $md-yellow-50: #fffde7; 195 | $md-yellow-100: #fff9c4; 196 | $md-yellow-200: #fff59d; 197 | $md-yellow-300: #fff176; 198 | $md-yellow-400: #ffee58; 199 | $md-yellow-500: #ffeb3b; 200 | $md-yellow-600: #fdd835; 201 | $md-yellow-700: #fbc02d; 202 | $md-yellow-800: #f9a825; 203 | $md-yellow-900: #f57f17; 204 | $md-yellow-a100: #ffff8d; 205 | $md-yellow-a200: #ffff00; 206 | $md-yellow-a400: #ffea00; 207 | $md-yellow-a700: #ffd600; 208 | 209 | $md-amber: #ffc107; 210 | $md-amber-50: #fff8e1; 211 | $md-amber-100: #ffecb3; 212 | $md-amber-200: #ffe082; 213 | $md-amber-300: #ffd54f; 214 | $md-amber-400: #ffca28; 215 | $md-amber-500: #ffc107; 216 | $md-amber-600: #ffb300; 217 | $md-amber-700: #ffa000; 218 | $md-amber-800: #ff8f00; 219 | $md-amber-900: #ff6f00; 220 | $md-amber-a100: #ffe57f; 221 | $md-amber-a200: #ffd740; 222 | $md-amber-a400: #ffc400; 223 | $md-amber-a700: #ffab00; 224 | 225 | $md-orange: #ff9800; 226 | $md-orange-50: #fff3e0; 227 | $md-orange-100: #ffe0b2; 228 | $md-orange-200: #ffcc80; 229 | $md-orange-300: #ffb74d; 230 | $md-orange-400: #ffa726; 231 | $md-orange-500: #ff9800; 232 | $md-orange-600: #fb8c00; 233 | $md-orange-700: #f57c00; 234 | $md-orange-800: #ef6c00; 235 | $md-orange-900: #e65100; 236 | $md-orange-a100: #ffd180; 237 | $md-orange-a200: #ffab40; 238 | $md-orange-a400: #ff9100; 239 | $md-orange-a700: #ff6d00; 240 | 241 | $md-deep-orange: #ff5722; 242 | $md-deep-orange-50: #fbe9e7; 243 | $md-deep-orange-100: #ffccbc; 244 | $md-deep-orange-200: #ffab91; 245 | $md-deep-orange-300: #ff8a65; 246 | $md-deep-orange-400: #ff7043; 247 | $md-deep-orange-500: #ff5722; 248 | $md-deep-orange-600: #f4511e; 249 | $md-deep-orange-700: #e64a19; 250 | $md-deep-orange-800: #d84315; 251 | $md-deep-orange-900: #bf360c; 252 | $md-deep-orange-a100: #ff9e80; 253 | $md-deep-orange-a200: #ff6e40; 254 | $md-deep-orange-a400: #ff3d00; 255 | $md-deep-orange-a700: #dd2c00; 256 | 257 | $md-brown: #795548; 258 | $md-brown-50: #efebe9; 259 | $md-brown-100: #d7ccc8; 260 | $md-brown-200: #bcaaa4; 261 | $md-brown-300: #a1887f; 262 | $md-brown-400: #8d6e63; 263 | $md-brown-500: #795548; 264 | $md-brown-600: #6d4c41; 265 | $md-brown-700: #5d4037; 266 | $md-brown-800: #4e342e; 267 | $md-brown-900: #3e2723; 268 | 269 | $md-grey: #9e9e9e; 270 | $md-grey-50: #fafafa; 271 | $md-grey-100: #f5f5f5; 272 | $md-grey-200: #eeeeee; 273 | $md-grey-300: #e0e0e0; 274 | $md-grey-400: #bdbdbd; 275 | $md-grey-500: #9e9e9e; 276 | $md-grey-600: #757575; 277 | $md-grey-700: #616161; 278 | $md-grey-800: #424242; 279 | $md-grey-900: #212121; 280 | 281 | $md-blue-grey: #607d8b; 282 | $md-blue-grey-50: #eceff1; 283 | $md-blue-grey-100: #cfd8dc; 284 | $md-blue-grey-200: #b0bec5; 285 | $md-blue-grey-300: #90a4ae; 286 | $md-blue-grey-400: #78909c; 287 | $md-blue-grey-500: #607d8b; 288 | $md-blue-grey-600: #546e7a; 289 | $md-blue-grey-700: #455a64; 290 | $md-blue-grey-800: #37474f; 291 | $md-blue-grey-900: #263238; 292 | 293 | $md-black: #000000; 294 | $md-white: #ffffff; 295 | -------------------------------------------------------------------------------- /doc/style/mixins.scss: -------------------------------------------------------------------------------- 1 | @mixin ellipsis { 2 | overflow: hidden; 3 | -ms-text-overflow: ellipsis; 4 | text-overflow: ellipsis; 5 | white-space: nowrap; 6 | } 7 | 8 | @mixin bounds($distance) { 9 | top: $distance; 10 | bottom: $distance; 11 | right: $distance; 12 | left: $distance; 13 | } 14 | 15 | @mixin overlay { 16 | position: absolute; 17 | @include bounds(0); 18 | } 19 | 20 | @mixin flex-box { 21 | display: flex; 22 | 23 | & > * { 24 | flex: auto 0 0; 25 | } 26 | } 27 | 28 | @mixin h-box { 29 | display: flex; 30 | 31 | & > * { 32 | flex: auto 0 0; 33 | } 34 | 35 | flex-direction: row; 36 | } 37 | 38 | @mixin v-box { 39 | display: flex; 40 | 41 | & > * { 42 | flex: auto 0 0; 43 | } 44 | 45 | flex-direction: column; 46 | } 47 | 48 | @mixin flex-control { 49 | width: 0 !important; 50 | } 51 | 52 | @mixin box-center { 53 | align-items: center; 54 | justify-content: center; 55 | } 56 | 57 | @function fade($color, $amount) { 58 | @return color.adjust($color, $alpha: -$amount / 100%); 59 | } 60 | 61 | @mixin toolbar-btn ($bg) { 62 | background: fade($bg, 80%); 63 | color: black; 64 | transition: background 0.2s; 65 | 66 | &:hover { 67 | color: black; 68 | background: $bg; 69 | } 70 | } 71 | 72 | @mixin space-between-x($margin) { 73 | margin-right: $margin; 74 | 75 | &:last-child { 76 | margin-right: 0; 77 | } 78 | } 79 | 80 | @mixin space-between-y($margin) { 81 | margin-bottom: $margin; 82 | 83 | &:last-child { 84 | margin-bottom: 0; 85 | } 86 | } 87 | 88 | @mixin unselectable { 89 | -moz-user-select: none; 90 | -webkit-user-select: none; 91 | -ms-user-select: none; 92 | user-select: none; 93 | } 94 | -------------------------------------------------------------------------------- /doc/style/vars.scss: -------------------------------------------------------------------------------- 1 | $primary-color: #40b883; 2 | -------------------------------------------------------------------------------- /doc/views/Home.vue: -------------------------------------------------------------------------------- 1 | 8 |