diff --git a/.babelrc b/.babelrc old mode 100644 new mode 100755 index 8c642c5f0187f7181db4028ed2935acf8ff04968..2aa7f94c2589add195d359ce294dc3ad364468da --- a/.babelrc +++ b/.babelrc @@ -12,6 +12,7 @@ ] ], "plugins": [ - "@babel/plugin-syntax-dynamic-import" + "@babel/plugin-syntax-dynamic-import", + "transform-vue-jsx" ] } \ No newline at end of file diff --git a/3.0.md b/3.0.md new file mode 100644 index 0000000000000000000000000000000000000000..da63c4192de95155ccaf7867d44530ed478c34c4 --- /dev/null +++ b/3.0.md @@ -0,0 +1,36 @@ + +`Alert` + +- 优化 `cloasable` 关闭时动画卡顿 +- 优化内容文字文字换行 +- 增加 `message` `description` 属性来呈现标题和内容 + +`Badge` + +- 增加 `dot` 隐藏显示 + +`Card` + +- 优化 `extra` 显示更友好 +- 优化标题居中显示,超出部分隐藏,调节字体大小 + +`Checkbox` + +- 统一禁用光标状态 +- `Group` 增加 `options` 属性来呈现子组件 + +`Carousel` + +- 优化切换动画 抖动和 尺寸变化的组件内部的动画展现形式 +- 增加循环无缝播放 + +`Radio` + +- `RadioGroup` 增加 `mini`, `large` ,`circle` ,`options` 来控制组件呈现模式 +- `RadioButton`增加 `icon` 属性来展示图标 + +`Switch` + +- 增加 `icon` 属性可展示图标切换开关 +- 优化组件,可展示多个文字切换开关 + diff --git a/build/build.js b/build/build.js old mode 100644 new mode 100755 index 8dfe6760335c36fb3b993f3fc23c57018fe964f0..f499d264a8a68e2bcc5964e7b8a6fdf738ed012a --- a/build/build.js +++ b/build/build.js @@ -1,36 +1,26 @@ -const rm = require('rimraf') -const ora = require('ora') -const spinner = ora('开始构建...') const chalk = require('chalk') const webpack = require('webpack') -const path = require('path') -let isBuildDoc = process.argv.splice(2).length>0; +let isBuildDoc = process.argv.splice(2).length > 0; let config = isBuildDoc ? require('./webpack.prod.doc.conf') : require('./webpack.prod.conf'); -let rmPath = isBuildDoc ? './docs/dist' : './dist'; -// spinner.start() - -rm(rmPath, (err) => { +webpack(config, function (err, stats) { + // spinner.stop() if (err) throw err - webpack(config, function (err, stats) { - // spinner.stop() - if (err) throw err - process.stdout.write(stats.toString({ - colors: true, - modules: false, - children: false, - chunks: false, - chunkModules: false - }) + '\n\n') + process.stdout.write(stats.toString({ + colors: true, + modules: false, + children: false, + chunks: false, + chunkModules: false + }) + '\n\n') - if (stats.hasErrors()) { - console.log(chalk.red(' 编译出现错误.\n')) - process.exit(1) - } + if (stats.hasErrors()) { + console.log(chalk.red(' 编译出现错误.\n')) + process.exit(1) + } - console.log(chalk.cyan(' 编译完成.\n')) - process.exit() - }) + console.log(chalk.cyan(' 编译完成.\n')) + process.exit() }) \ No newline at end of file diff --git a/build/md-loader/index.js b/build/md-loader/index.js new file mode 100755 index 0000000000000000000000000000000000000000..e464f65f96e38a89a16093400f2a044754a701fb --- /dev/null +++ b/build/md-loader/index.js @@ -0,0 +1 @@ +module.exports = require('./loader'); \ No newline at end of file diff --git a/build/md-loader/loader.js b/build/md-loader/loader.js new file mode 100755 index 0000000000000000000000000000000000000000..fc32e655866e68cd0b04d9a3634cb5db6b849e43 --- /dev/null +++ b/build/md-loader/loader.js @@ -0,0 +1,174 @@ +var loaderUtils = require('loader-utils'); +var hljs = require('highlight.js'); +var cheerio = require('cheerio'); +var markdown = require('markdown-it'); +var Token = require('markdown-it/lib/token'); + +/** + * `
` => `` + * `
` => `
`
+ * @param {string} str
+ * @return {string}
+ */
+var addVuePreviewAttr = function (str) {
+ return str.replace(/(vue file template + * @param {[type]} html [description] + * @return {[type]} [description] + */ +var renderVueTemplate = function (html, wrapper) { + var $ = cheerio.load(html, { + decodeEntities: false, + lowerCaseAttributeNames: false, + lowerCaseTags: false, + xmlMode: true, + }); + + var output = { + style: $.html('style'), + // get only the first script child. Causes issues if multiple script files in page. + script: $.html($('script').first()) + }; + var result; + + $('style').remove(); + $('script').remove(); + + if (wrapper) { + result = + `<${wrapper}>` + + $.html() + + `${wrapper}>\n` + } else { + result = + `` + + $.html() + + `\n` + } + result += output.style + '\n' + output.script; + + return result; +}; + +module.exports = function (source) { + this.cacheable && this.cacheable(); + var parser, preprocess; + // var params = loaderUtils.getOptions(this) || {}; + // var vueMarkdownOptions = this._compilation.__vueMarkdownOptions__; + // var opts = vueMarkdownOptions ? Object.create(vueMarkdownOptions.__proto__) : {}; // inherit prototype + var opts = loaderUtils.getOptions(this); + + var preventExtract = false; + + // opts = Object.assign(opts, params, vueMarkdownOptions); // assign attributes + + if (opts.preventExtract) { + delete opts.preventExtract; + preventExtract = true; + } + + if (typeof opts.render === 'function') { + parser = opts; + } else { + opts = Object.assign( + { + preset: 'default', + html: true, + highlight: renderHighlight, + wrapper: 'section' + }, + opts + ); + + var plugins = opts.use; + preprocess = opts.preprocess; + + delete opts.use; + delete opts.preprocess; + + parser = markdown(opts.preset, opts); + + //add ruler:extract script and style tags from html token content + !preventExtract && + parser.core.ruler.push('extract_script_or_style', function replace( + state + ) { + let tag_reg = new RegExp('<(script|style)(?:[^<]|<)+\\1>', 'g'); + let newTokens = []; + state.tokens + .filter(token => token.type == 'fence' && token.info == 'html') + .forEach(token => { + let tokens = (token.content.match(tag_reg) || []).map(content => { + let t = new Token('html_block', '', 0); + t.content = content; + return t; + }); + if (tokens.length > 0) { + newTokens.push.apply(newTokens, tokens); + } + }); + state.tokens.push.apply(state.tokens, newTokens); + }); + + if (plugins) { + plugins.forEach(function (plugin) { + if (Array.isArray(plugin)) { + parser.use.apply(parser, plugin); + } else { + parser.use(plugin); + } + }); + } + } + + /** + * override default parser rules by adding v-pre attribute on 'code' and 'pre' tags + * @param {Arraydiff --git a/docs/src/components/demo/index.js b/docs/components/demo/index.js old mode 100644 new mode 100755 similarity index 100% rename from docs/src/components/demo/index.js rename to docs/components/demo/index.js diff --git a/docs/components/header.vue b/docs/components/header.vue new file mode 100755 index 0000000000000000000000000000000000000000..acc023ab0b9432a8181210302e831ff256efebb6 --- /dev/null +++ b/docs/components/header.vue @@ -0,0 +1,77 @@ + +} rules rules to override + */ + function overrideParserRules(rules) { + if (parser && parser.renderer && parser.renderer.rules) { + var parserRules = parser.renderer.rules; + rules.forEach(function (rule) { + if (parserRules && parserRules[rule]) { + var defaultRule = parserRules[rule]; + parserRules[rule] = function () { + return addVuePreviewAttr(defaultRule.apply(this, arguments)); + }; + } + }); + } + } + + overrideParserRules(['code_inline', 'code_block', 'fence']); + + if (preprocess) { + source = preprocess.call(this, parser, source); + } + + source = source.replace(/@/g, '__at__'); + + var content = parser.render(source).replace(/__at__/g, '@'); + var result = renderVueTemplate(content, opts.wrapper); + + if (opts.raw) { + return result; + } else { + return 'module.exports = ' + JSON.stringify(result); + } +}; diff --git a/build/md-loader/render.js b/build/md-loader/render.js new file mode 100755 index 0000000000000000000000000000000000000000..4eb0b99cf8ee28e00a0eebdbf2e7ff7f1fb4b03f --- /dev/null +++ b/build/md-loader/render.js @@ -0,0 +1,121 @@ +const cheerio = require('cheerio'); +const Token = require('markdown-it/lib/token'); +const hljs = require('highlight.js'); +const anchor = require('markdown-it-anchor') + + +const cnReg = new RegExp('<(cn)(?:[^<]|<)+\\1>', 'g'); + +const getDomHtml = (str, tag, scoped) => { + const $ = cheerio.load(str, { decodeEntities: false, xmlMode: true, }); //xmlMode 为false 闭合标签 编译错误 + if (!tag) { + return str; + } + if (tag === 'style') { + return scoped + ? $(`${tag}[scoped]`).html() + : $(`${tag}`).not(`${tag}[scoped]`).html(); + } + return $(tag).html() || ''; +}; + +const render = (md, options) => { + + md.core.ruler.push('render', ({ tokens }) => { + let cn, template, script, style, scopedStyle, code, sourceCode; + + + tokens.forEach(token => { + if (token.type === 'html_block') { + if (token.content.match(cnReg)) { + cn = getDomHtml(token.content, 'cn'); + token.content = '' + } + /* if (token.content.match(usReg)) { + us = getDomHtml(token.content, 'us'); + token.content = ''; + } */ + } + if (token.info === 'tpl') { + sourceCode = token.content; + code = '````html\n' + token.content + '````'; + template = getDomHtml(token.content, 'template'); + script = getDomHtml(token.content, 'script'); + style = getDomHtml(token.content, 'style'); + scopedStyle = getDomHtml(token.content, 'style', true); + token.content = ''; + token.type = 'html_block'; + } + }); + if (template) { + let data = { html: template, script, style, cn, sourceCode, }; + + data = md.utils.escapeHtml(JSON.stringify(data)); + + const codeHtml = code ? md.render(code) : ''; + + const cnHtml = cn ? md.render(cn) : ''; + + let newContent = ` + + + ${template} + ${cnHtml} + ${codeHtml} + + `; + newContent += script + ? ` + + ` + : ''; + newContent += style ? `` : ''; + newContent += scopedStyle ? `` : ''; + const tk = new Token('html_block', '', 0); + tk.content = newContent; + tokens.push(tk); + } + }); +} + +//options + + +const replaceDelimiters = function (str) { + return str.replace(/({{|}})/g, '$1'); +}; + +var renderHighlight = function (str, lang) { + if (!(lang && hljs.getLanguage(lang))) { + return ''; + } + + try { + return replaceDelimiters(hljs.highlight(lang, str, true).value); + } catch (err) { } +}; + +var markdown = require('markdown-it')({ + html: true, + breaks: true, + highlight: renderHighlight, +}) +markdown + .use(anchor, { + level: 2, + slugify: string => string.trim().split(' ').join('-'), + permalink: true, + permalinkClass: 'anchor', + permalinkSymbol: '#', + permalinkBefore: false, + }) + .use(render) + +markdown = Object.assign(markdown, { + raw: true, + wrapper: 'div' +}) + +module.exports = markdown \ No newline at end of file diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js old mode 100644 new mode 100755 index ba6bf9c6ece0430e4291a4bc99999fb149185fe7..1c2397d528c5a9842f19eb9fdac7777680dbdbe4 --- a/build/webpack.base.conf.js +++ b/build/webpack.base.conf.js @@ -1,43 +1,85 @@ +const webpack = require('webpack') const path = require('path'); +const VueLoaderPlugin = require('vue-loader/lib/plugin') +const pkg = require('../package.json'); +const markdown = require('./md-loader/render') + +const vueLoaderOptions = { + loaders: { + js: [ + { + loader: 'babel-loader', + options: { + presets: ['env'], + plugins: ['transform-vue-jsx', 'transform-object-rest-spread'], + }, + }, + ], + }, +}; module.exports = { + bail: true, module: { rules: [ { - test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader', - /* query: { - presets: ['es2015', 'stage-3'], - plugins: ['transform-runtime'] - } */ + test: /\.md$/, + use: [ + { loader: 'vue-loader', }, + { loader: './build/md-loader', options: markdown }, + { loader: 'kui-loader', options: { prefix: false } } + ] }, - { test: /\.s(a|c)ss$/, use: ['style-loader', 'css-loader', 'sass-loader'] }, - { test: /\.styl(us)?$/, use: ['style-loader', 'css-loader', 'stylus-loader'] }, { test: /\.css$/, - use: ['style-loader', 'css-loader', /* 'postcss-loader' */] + use: ['vue-style-loader', 'css-loader'], }, { - test: /\.less$/, - use: ['style-loader', 'css-loader', 'less-loader'], + test: /\.vue$/, + use: [{ + loader: 'vue-loader', + options: vueLoaderOptions + // options: { + // loaders: { + // css: 'vue-style-loader!css-loader', + // less: 'vue-style-loader!css-loader!less-loader' + // }, + // } + }, + { loader: 'kui-loader', options: { prefix: false } } + ] }, { - test: /\.(png|jpg|gif)$/, - loader: 'url-loader', - query: { limit: 13000, name: 'img/[name].[ext]?[hash:7]' } + test: /\.(js|jsx)$/, exclude: /node_modules/, loader: 'babel-loader', }, { - test: /\.(eot|woff|woff2|svg|ttf)([\?]?.*)$/, + test: /\.(png|jpg|gif)$/, loader: 'file-loader', - query: { limit: 10000, name: 'fonts/[name].[ext]?[hash:7]', prefix: 'font' } + options: { limit: 8192, name: 'img/[name].[ext]?[hash:7]', esModule: false } }, ] }, resolve: { - extensions: ['.js', '.vue', '.json', '.less'], + extensions: ['.js', '.jsx', '.vue', '.json', '.less', '.md'], alias: { 'vue': 'vue/dist/vue.esm.js', - '@': path.resolve(__dirname, '../src'), + '@': path.join(__dirname, '../'), }, - } + }, + plugins: [ + new VueLoaderPlugin(), + new webpack.BannerPlugin(`${pkg.name} v${pkg.version} +Copyright 2017-present, kui-vue. +All rights reserved. +Author: chuchur@qq.com / www.chuchur.com + `), + new webpack.ContextReplacementPlugin( + /moment[\\\/]locale$/, + /^\.\/(zh-cn)$/ + ), + ], + + + } \ No newline at end of file diff --git a/build/webpack.dev.conf.js b/build/webpack.dev.conf.js old mode 100644 new mode 100755 index a4b0a7396895c55079f181d9d0f7a6c1d59afa5a..49fe10ddacd64c001c0bee214f95d547f771b278 --- a/build/webpack.dev.conf.js +++ b/build/webpack.dev.conf.js @@ -2,77 +2,57 @@ * by chuchur /chuchur@qq.com * 打包vue 组件 */ -const webpack = require('webpack') const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const merge = require('webpack-merge'); const webpackBaseConfig = require('./webpack.base.conf.js'); -const VueLoaderPlugin = require('vue-loader/lib/plugin') +// const webpack = require('webpack') -module.exports = merge(webpackBaseConfig, { - mode: 'development', - devServer: { - contentBase: path.resolve(__dirname, 'docs'), - port: 7005, - clientLogLevel: 'none', - hot: true, - // open: false, - inline: true, - compress: true, - historyApiFallback: true, - }, - entry: { - index: ['./docs/src/main.js'], - vendors: ['vue', 'vue-router'] - }, - output: { - path: path.resolve(__dirname, 'docs'), - filename: '[name].[hash:5].js', - publicPath: '/', - chunkFilename: '[name].[chunkhash:5].js', - }, - module: { - rules: [ - { - test: /\.vue$/, - use: [{ - loader: 'vue-loader', - options: { - loaders: { - css: 'vue-style-loader!css-loader', - less: 'vue-style-loader!css-loader!less-loader' - }, - } - }, - { loader: 'kui-loader', options: { prefix: false } } - ] - }, - ] - }, - optimization: { - minimize: false, - }, - plugins: [ - new VueLoaderPlugin(), //for vue-loader 15 - new webpack.HotModuleReplacementPlugin(), - new webpack.DefinePlugin({ DEVELOPMENT: JSON.stringify(true) }), - // 位于开发环境下 - // 自动生成html插件,如果创建多个HtmlWebpackPlugin的实例,就会生成多个页面 - new HtmlWebpackPlugin({ - favicon: path.join(__dirname, '../docs/src/assets/favicon.png'), - // 生成html文件的名字,路径和生产环境下的不同,要与修改后的publickPath相结合,否则开启服务器后页面空白 - filename: 'index.html', - // 源文件,路径相对于本文件所在的位置 - template: path.resolve(__dirname, '../docs/src/index.html'), - // 需要引入entry里面的哪几个入口,如果entry里有公共模块,记住一定要引入 - chunks: ['vendors', 'index'], - // 要把 +``` \ No newline at end of file diff --git a/components/affix/demo/container.md b/components/affix/demo/container.md new file mode 100755 index 0000000000000000000000000000000000000000..dcce161753960444acb4705c64bf4874113b14f6 --- /dev/null +++ b/components/affix/demo/container.md @@ -0,0 +1,31 @@ ++#### 基本 +最简单的用法。 + + +```tpl + +++ + + +``` diff --git a/components/affix/demo/index.vue b/components/affix/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..e221de993db9954e0dd794c54d01ff6610a7883c --- /dev/null +++ b/components/affix/demo/index.vue @@ -0,0 +1,23 @@ + \ No newline at end of file diff --git a/components/affix/demo/info.md b/components/affix/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..aed0a3017399c2c6d0f6bed5e3822a04bfb54824 --- /dev/null +++ b/components/affix/demo/info.md @@ -0,0 +1,8 @@ +## Affix 固钉 +将页面元素钉在可视范围。 + +## 何时使用 +当内容区域比较长,需要滚动页面时,这部分内容对应的操作或者导航需要在滚动范围内始终展现。常用于侧边菜单和按钮组合。 +页面可视范围过小时,慎用此功能以免遮挡页面内容。 + +## 代码演示 \ No newline at end of file diff --git a/components/affix/index.js b/components/affix/index.js new file mode 100755 index 0000000000000000000000000000000000000000..da7cf069d50e45eb25bb50b9e82132e41a36c6cc --- /dev/null +++ b/components/affix/index.js @@ -0,0 +1,2 @@ +import Affix from './affix.jsx' +export default Affix \ No newline at end of file diff --git a/components/affix/index.md b/components/affix/index.md new file mode 100755 index 0000000000000000000000000000000000000000..c05c0946142bb8505e068b1cb515c290971304f5 --- /dev/null +++ b/components/affix/index.md @@ -0,0 +1,6 @@ +## API +| 属性 | 说明 | 类型 | 默认值 | +|--------------|------------------------------------|---------------|-----| +| offsetTop | 距离窗口顶部达到指定偏移量后触发 | String,Number | 0 | +| offsetBottom | 距离窗口底部达到指定偏移量后触发 | String,Number | - | +| change | 在固定状态发生改变时触发,返回当前固定状态 `false` , `true` | Function | - | \ No newline at end of file diff --git a/components/affix/styles/index.less b/components/affix/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..0ca3bb5b300e25c8b14eb8a8f7abc1bc7ac31dc8 --- /dev/null +++ b/components/affix/styles/index.less @@ -0,0 +1,4 @@ +.k-affix { + position: fixed; + z-index: 1000; +} \ No newline at end of file diff --git a/components/alert/alert.jsx b/components/alert/alert.jsx new file mode 100755 index 0000000000000000000000000000000000000000..571ae064fa386d20be2682ae8cb94fa4fd459bb4 --- /dev/null +++ b/components/alert/alert.jsx @@ -0,0 +1,59 @@ + +import Icon from "../icon"; +import { getTranstionProp } from '../_tool/transition' +export default { + components: { Icon }, + name: "Alert", + props: { + type: { type: String, default: "warning" }, + closable: Boolean, + showIcon: Boolean, + message: String, + description: String, + }, + data() { + return { + closed: false + }; + }, + methods: { + close() { + this.closed = true; + this.$emit("close"); + } + }, + render() { + + let { closed, showIcon, closable, close, $slots, type, description, message } = this + const classes = [ + "k-alert", { + [`k-alert-${this.type}`]: type, + 'k-alert-has-icon': showIcon, + 'k-alert-has-close': closable, + 'k-alert-has-description': description + } + ]; + let icons = { + info: "ios-information-circle", + error: "ios-close-circle", + success: "ios-checkmark-circle", + warning: "ios-alert" + }; + const iconNode = showIcon ?+++ + +: null + const closeIcon = closable ? : null + description = {description}+ const msg = + const aniprop = getTranstionProp('k-alert-slide') + // console.log(aniprop) + return ( ++ + ) + } +}; \ No newline at end of file diff --git a/components/alert/demo/base.md b/components/alert/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..32458c3d87307cd38a33154ea76d4c697437a6ec --- /dev/null +++ b/components/alert/demo/base.md @@ -0,0 +1,15 @@ ++ {iconNode} + {msg} + {description} + {closeIcon} +++#### 基本用法 +通过 `type` 来控制展示类型 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/alert/demo/close.md b/components/alert/demo/close.md new file mode 100755 index 0000000000000000000000000000000000000000..65942aa1fca69438a6fe8f779f3b0ddf7376a9b3 --- /dev/null +++ b/components/alert/demo/close.md @@ -0,0 +1,21 @@ +Success Text +Info Text +Warning Text +Error Text ++#### 可关闭 +`closable` 来控制是否显示可关闭按钮,平滑、自然隐藏关闭 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/alert/demo/icon.md b/components/alert/demo/icon.md new file mode 100755 index 0000000000000000000000000000000000000000..253b6d2d3379051f9268143100b1947b061665cf --- /dev/null +++ b/components/alert/demo/icon.md @@ -0,0 +1,36 @@ +Success Text +Info Text +Warning Text +Error Text ++ +#### 图标 +`showIcon` 来设置是否显示图标 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/alert/demo/index.vue b/components/alert/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..f07a46448bdcd15322efbc17257f40fd156d41b6 --- /dev/null +++ b/components/alert/demo/index.vue @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/components/alert/demo/info.md b/components/alert/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..70ef2436e85d5228088c7233173f87b41c20b1d7 --- /dev/null +++ b/components/alert/demo/info.md @@ -0,0 +1,8 @@ +# Alert 警告提示 +警告提示,展现需要关注的信息。 + +## 何时使用 +- 当某个页面需要向用户显示警告的信息时。 +- 非浮层的静态展现形式,始终展现,不会自动消失,用户可以点击关闭。 + +## 代码演示 \ No newline at end of file diff --git a/src/components/alert/index.js b/components/alert/index.js old mode 100644 new mode 100755 similarity index 69% rename from src/components/alert/index.js rename to components/alert/index.js index 1ad979f54fcaeec8124d853fc57f3e04178432e8..033791d07ebc595c079524cb0e3f95aea57d8e7c --- a/src/components/alert/index.js +++ b/components/alert/index.js @@ -1,3 +1,2 @@ -import './alert.less' import Alert from './alert' export default Alert; \ No newline at end of file diff --git a/components/alert/index.md b/components/alert/index.md new file mode 100755 index 0000000000000000000000000000000000000000..fa2b9a9a5cfbe3ab1675b6046163630e26b5be81 --- /dev/null +++ b/components/alert/index.md @@ -0,0 +1,9 @@ +### API +| 属性 | 说明 | 类型 | 默认值 | +|-------------|----------------------------------------------------|-------------|---------| +| type | 按钮类型,可选值为 `success`、`info`、`warning`、`error` 或者不设置 | String | warning | +| message | 警告提示内容 | String,Slot | - | +| description | 警告提示的辅助性文字介绍 | String | - | +| show-icon | 是否显示图标 | Boolean | false | +| closable | 是否显示关闭按钮 | Boolean | false | +| close | 关闭时触发的回调函数 | Function | - | \ No newline at end of file diff --git a/components/alert/styles/index.less b/components/alert/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..dd2cffdd7c910b4288311e3904faed53245f5682 --- /dev/null +++ b/components/alert/styles/index.less @@ -0,0 +1,102 @@ +@import '../../styles/global.less'; +.k-alert { + border-radius: @radius; + margin-bottom: 16px; + padding: 8px 15px; + box-sizing: border-box; + position: relative; + line-height: 1.5; + font-size: 12px; + transition: all .3s; + overflow: hidden; + background: tint(@warning, 90%); + border: 1px solid tint(@warning, 70%); + &-icon { + color: @warning; + position: absolute; + top: 8px; + left: 10px; + font-size: 20px; + } + &-has-icon { + padding-left: 38px; + } + &-has-close { + padding-right: 30px; + } + &-has-description { + padding: 15px; + .k-alert-icon { + font-size: 30px; + top: 15px; + } + .k-alert-close { + font-size: 18px; + } + .k-alert-message { + font-size: 14px; + font-weight: 500; + margin-bottom: 5px; + } + .k-alert-description { + font-size: 14px; + } + &.k-alert-has-icon { + padding-left: 50px; + } + &.k-alert-has-close { + padding-right: 35px; + } + } + &-close { + font-size: 16px; + position: absolute; + right: 4px; + top: 8px; + cursor: pointer; + text-decoration: none; + color: @color; + padding: 0px 5px; + &:hover { + text-decoration: none; + color: @danger; + } + } + &-success { + background: tint(@success, 90%); + border-color: tint(@success, 70%); + .k-alert-icon { + color: @success; + } + } + &-error { + background: tint(@danger, 90%); + border-color: tint(@danger, 70%); + .k-alert-icon { + color: @danger; + } + } + &-info { + background: tint(@main, 90%); + border-color: tint(@main, 70%); + .k-alert-icon { + color: @main; + } + } + &-slide-leave-to { + animation: k-alert-slide-out 0.3s ease-in-out; + animation-fill-mode: both; + } + @keyframes k-alert-slide-out { + 0% { + transform: scaleY(1); + transform-origin: 0% 0%; + opacity: 1; + } + 100% { + transform: scaleY(0); + transform-origin: 0% 0%; + opacity: 0; + } + } +} \ No newline at end of file diff --git a/src/components/backtop/backTop.vue b/components/backtop/backtop.jsx old mode 100644 new mode 100755 similarity index 75% rename from src/components/backtop/backTop.vue rename to components/backtop/backtop.jsx index 6ff0a560aba7a359e0dc9bba5897e3c5658fe0f3..68b4d293cb5e95a0fc6415b36ba7b1fd2ec32630 --- a/src/components/backtop/backTop.vue +++ b/components/backtop/backtop.jsx @@ -1,18 +1,8 @@ - -Success Text +Info Text +Warning Text +Error Text + ++ + + + -- - +}; \ No newline at end of file diff --git a/components/backtop/demo/base.md b/components/backtop/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..c4ec07b51f5b135c301db5694075ec35d395cbc3 --- /dev/null +++ b/components/backtop/demo/base.md @@ -0,0 +1,13 @@ +- ---- +#### 基础用法 +默认位置距离页面右部和底部 50px,滚动至距顶端 400px 时显示。 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/docs/src/code/backtop.js b/components/backtop/demo/custom.md old mode 100644 new mode 100755 similarity index 31% rename from docs/src/code/backtop.js rename to components/backtop/demo/custom.md index 01f5dfd3fdfd4be3e6be20f1f67b08fda184e695..194e759d5f3dc4d6242772336cfe0fe6beae9ec7 --- a/docs/src/code/backtop.js +++ b/components/backtop/demo/custom.md @@ -1,9 +1,17 @@ -let code = {} -code.base = `+ 向下滚动页面,灰色的按钮为默认效果。 + ` + +#### 基础用法 +可以自定义回到顶部按钮的样式 `bottom` 为 `100px` + -code.custom = `- +```tpl + +UP-++ -` -export default code \ No newline at end of file + +``` \ No newline at end of file diff --git a/components/backtop/demo/index.vue b/components/backtop/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..7cf49cc05403c4f6bc5b2b6dc2eef1630e533da2 --- /dev/null +++ b/components/backtop/demo/index.vue @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/components/backtop/demo/info.md b/components/backtop/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..ae7e091a755936b32f6c4dc70bcc9171df0ed825 --- /dev/null +++ b/components/backtop/demo/info.md @@ -0,0 +1,7 @@ +## BackTop 回到顶部 +返回页面顶部的操作按钮。 + +## 何时使用 +- 当页面内容区域比较长时; +- 当用户需要频繁返回顶部查看相关内容时。 +## 代码演示 \ No newline at end of file diff --git a/components/backtop/index.js b/components/backtop/index.js new file mode 100755 index 0000000000000000000000000000000000000000..2dc41b0bdff09b7a9405459ae96890af7a20d6c8 --- /dev/null +++ b/components/backtop/index.js @@ -0,0 +1,2 @@ +import BackTop from './backtop.jsx' +export default BackTop \ No newline at end of file diff --git a/components/backtop/index.md b/components/backtop/index.md new file mode 100755 index 0000000000000000000000000000000000000000..5a6667b1d6519fae839d4ef11d0fa2050619459b --- /dev/null +++ b/components/backtop/index.md @@ -0,0 +1,7 @@ +## API +| 属性 | 说明 | 类型 | 默认值 | +|--------|-----------------------------|---------------|-----| +| height | 页面滚动高度达到该值时才显示 `BackTop` 组件 | String,Number | 400 | +| bottom | 组件距离底部的距离 | String,Number | 40 | +| right | 组件距离右部的距离 | String,Number | 40 | +| click | 点击按钮时触发 | Function | - | \ No newline at end of file diff --git a/components/backtop/styles/index.less b/components/backtop/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..8d49f0c8d32ceadfa1ff31cf3c16cb5bd053bab8 --- /dev/null +++ b/components/backtop/styles/index.less @@ -0,0 +1,59 @@ +@import '../../styles/global.less'; +.k-backtop { + box-sizing: border-box; + margin: 0; + padding: 0; + list-style: none; + z-index: 10; + position: fixed; + right: 50px; + bottom: 50px; + height: 40px; + width: 40px; + cursor: pointer; + display: block; + overflow: hidden; + border-radius: @radius; + &-content { + background-color: rgba(0, 0, 0, .45); + opacity: .5; + height: 40px; + transition: opacity .3s ease-in-out; + text-align: center; + line-height: 40px; + color: #fff; + &:hover { + opacity: 1; + } + .k-ion { + font-size: 20px; + color: #fff; + } + } +} + +@keyframes k-backtop-fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes k-backtop-fade-out { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +.k-backtop-fade-enter-active { + animation: k-backtop-fade-in .4s; +} + +.k-backtop-fade-leave-active { + animation: k-backtop-fade-out .4s; +} \ No newline at end of file diff --git a/components/badge/badge.jsx b/components/badge/badge.jsx new file mode 100755 index 0000000000000000000000000000000000000000..551fc5e2b7a5966bae1f13540f79c8e9a5ef7a9d --- /dev/null +++ b/components/badge/badge.jsx @@ -0,0 +1,57 @@ +export default { + name: "Badge", + props: { + count: [String, Number], + dot: Boolean, + color: String, + status: { + type: String, + // validator: (value) => { + // ['default', 'success', 'error', 'warning'].indexOf(value) > -1 + // }, + default: 'default' + }, + text: String, + maxCount: { type: Number, default: 99 } + }, + render() { + const { $slots, maxCount, count, dot, color, status, text } = this + let innerText = null, statusNode = []; + + if (typeof count === 'number' && count !== 0) { + innerText = count > maxCount ? maxCount + '+' : count + } else if (typeof count === 'string') { + innerText = count + } else if (status && !dot && !$slots.default) { + const props = { + class: ['k-badge-status-dot', { + [`k-badge-status-${status}`]: status, + [`k-badge-status-${color}`]: color && !/^#/.test(color) + }], + style: { + backgroundColor: /^#/.test(color)?color:null + } + } + statusNode.push() + if (text) + statusNode.push({text}) + } + + const props = { + class: { + 'k-badge-count': count !== undefined, + 'k-badge-dot': dot, + [`k-badge-${status}`]: status, + }, + style: { backgroundColor: color } + } + const supNode = (innerText !== null || dot) ? {innerText} : null + return ( ++ + 自定义按钮为蓝色的按钮 +UP++ {$slots.default} + {supNode} + {statusNode} ++ ) + } +}; diff --git a/components/badge/demo/base.md b/components/badge/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..5c3fb5093a2c150204bebc752153a6ca09248b9e --- /dev/null +++ b/components/badge/demo/base.md @@ -0,0 +1,17 @@ ++#### 基本用法 +`Badge` 基础使用 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/badge/demo/color.md b/components/badge/demo/color.md new file mode 100644 index 0000000000000000000000000000000000000000..641deebf845d55a282e9654c4c7337b64efb38df --- /dev/null +++ b/components/badge/demo/color.md @@ -0,0 +1,65 @@ ++ + ++ + ++#### 多彩徽标 +多种预设色彩的徽标样式,用作不同场景使用。如果预设值不能满足你的需求,可以设置为具体的色值。 + + +```tpl + +++ + + +``` \ No newline at end of file diff --git a/components/badge/demo/dot.md b/components/badge/demo/dot.md new file mode 100755 index 0000000000000000000000000000000000000000..fa3ccd4bd9ebe931a080617c488d60bcbb35a1d9 --- /dev/null +++ b/components/badge/demo/dot.md @@ -0,0 +1,31 @@ ++ Presets: +
++++++ + Custom: +
++++
++
++
++ +#### 点 +设置 `dot` 来展示一个点 + + +```tpl + + + + +``` \ No newline at end of file diff --git a/components/badge/demo/dynamic.md b/components/badge/demo/dynamic.md new file mode 100755 index 0000000000000000000000000000000000000000..74a065523a7cb84a3118298a672d369d21650f2c --- /dev/null +++ b/components/badge/demo/dynamic.md @@ -0,0 +1,51 @@ ++#### 可控 +动态控制 + + +```tpl + + + + + +``` \ No newline at end of file diff --git a/components/badge/demo/index.vue b/components/badge/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..c3152b4f14cfedfebedf902c373b2bd25a91abc9 --- /dev/null +++ b/components/badge/demo/index.vue @@ -0,0 +1,29 @@ + \ No newline at end of file diff --git a/components/badge/demo/info.md b/components/badge/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..086087df4f5c9fb473324a68da1d6a690eb127c4 --- /dev/null +++ b/components/badge/demo/info.md @@ -0,0 +1,7 @@ +# Badge徽标数 +图标右上角的圆形徽标数字。 + +## 何时使用 +一般出现在通知图标或头像的右上角,用于显示需要处理的消息条数,通过醒目视觉形式吸引用户处理。 + +## 代码演示 \ No newline at end of file diff --git a/components/badge/demo/mark.md b/components/badge/demo/mark.md new file mode 100644 index 0000000000000000000000000000000000000000..96d79b2355b7baa531a1ca6aa87b2604a733ee22 --- /dev/null +++ b/components/badge/demo/mark.md @@ -0,0 +1,15 @@ ++#### 独立使用 +不包裹任何元素即是独立使用,可自定样式展现。 +在右上角的 badge 则限定为红色。 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/badge/demo/max.md b/components/badge/demo/max.md new file mode 100755 index 0000000000000000000000000000000000000000..160043af18f5808177aa9a8197e5195db2ea5536 --- /dev/null +++ b/components/badge/demo/max.md @@ -0,0 +1,41 @@ ++ + + +#### 最大值 / 自定义 +设置 `max-count` 配合 `count` ,数字模式超出隐藏,`count` 不为数字时将不进行计算 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/badge/demo/status.md b/components/badge/demo/status.md new file mode 100644 index 0000000000000000000000000000000000000000..dde0b212dd43c41efe1e9d67142bda817a5614c3 --- /dev/null +++ b/components/badge/demo/status.md @@ -0,0 +1,34 @@ ++ + ++ + ++ + ++ + ++ + ++ + ++#### 状态点 +用于表示状态的小圆点。 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/badge/index.js b/components/badge/index.js new file mode 100755 index 0000000000000000000000000000000000000000..10678bdb736401d5732f3364d27da1ed67856190 --- /dev/null +++ b/components/badge/index.js @@ -0,0 +1,2 @@ +import Badge from './badge.jsx' +export default Badge \ No newline at end of file diff --git a/components/badge/index.md b/components/badge/index.md new file mode 100755 index 0000000000000000000000000000000000000000..fa2c59979dfa9cd7245368a4f85613ad9c999662 --- /dev/null +++ b/components/badge/index.md @@ -0,0 +1,7 @@ +### API +| 属性 | 说明 | 类型 | 默认值 | +|-----------|-----------------------------------------|----------------|--------| +| count | 显示的文字 | String,Number | - | +| color | 徽标颜色 | String | - | +| max-count | 展示封顶的数字值,高于的部分会以+号显示 | Number | 99 | +| dot | 不展示数字,只有一个小红点 | Boolean | false | \ No newline at end of file diff --git a/src/components/badge/badge.less b/components/badge/styles/index.less old mode 100644 new mode 100755 similarity index 36% rename from src/components/badge/badge.less rename to components/badge/styles/index.less index c95a371a0f23a3386a51d57bdac72f1dffab0d6d..9134dde167133aa97a9e33ceac51f9af72f78216 --- a/src/components/badge/badge.less +++ b/components/badge/styles/index.less @@ -4,28 +4,27 @@ display: inline-block; line-height: 1; vertical-align: middle; - .k-badge-count { + &-count { position: absolute; - transform: translateY(-50%) translateX(100%); + transform: translate(50%, -50%); + transform-origin: 100% 0; top: 0px; - right: 10px; + right: 0; height: 20px; border-radius: 10px; min-width: 20px; background: #ed3f14; - border: 1px solid transparent; color: #fff; line-height: 18px; text-align: center; padding: 0 6px; font-size: 12px; white-space: nowrap; - transform-origin: -10% center; z-index: 10; box-shadow: 0 0 0 1px #fff; box-sizing: border-box; } - .k-badge-mark { + &-mark { display: inline-block; border-radius: 10px; min-width: 20px; @@ -40,18 +39,91 @@ box-sizing: border-box; white-space: nowrap; box-shadow: 0 0 0 2px #fff; + top: 0; + bottom: 0; } - .k-badge-dot { + &-dot { position: absolute; - transform: translateX(-50%); - transform-origin: 0 center; - top: -4px; - right: -8px; - height: 8px; - width: 8px; - border-radius: 100%; + // transform: translateX(-50%); + // transform-origin: 0 center; + // top: -4px; + // right: -8px; + top: 0; + right: 0; + transform: translate(50%, -50%); + transform-origin: 100% 0; + height: 6px; + width: 6px; + border-radius: 50%; background: @danger; z-index: 10; box-shadow: 0 0 0 1px #fff; } + &-status-dot { + position: relative; + top: -1px; + display: inline-block; + width: 6px; + height: 6px; + vertical-align: middle; + border-radius: 50%; + } + &-status-text { + color: @color; + font-size: 14px; + margin-left: 8px; + } + &-status-success { + background-color: @success; + } + &-status-error { + background-color: @danger; + } + &-status-warning { + background-color: @warning; + } + &-status-default { + background-color: #ddd; + } + + + &-status-pink { + background-color: @pink; + } + &-status-red { + background-color: @red; + } + &-status-yellow { + background-color: @yellow; + } + &-status-orange { + background-color: @orange; + } + &-status-cyan { + background-color: @cyan; + } + &-status-green { + background-color: @green; + } + &-status-blue { + background-color: @blue; + } + &-status-purple { + background-color: @purple; + } + &-status-geekblue { + background-color: @geekblue; + } + &-status-magenta { + background-color: @magenta; + } + &-status-volcano { + background-color: @volcano; + } + &-status-gold { + background-color: @gold; + } + &-status-lime { + background-color: @lime; + } } \ No newline at end of file diff --git a/components/base/input.jsx b/components/base/input.jsx new file mode 100644 index 0000000000000000000000000000000000000000..06dcb640692902870f3d3dfa47360b96fcf9ef30 --- /dev/null +++ b/components/base/input.jsx @@ -0,0 +1,200 @@ +import Icon from '../icon' +import { isNotEmpty } from '../_tool/utils' +export default { + name: "baseInput", + props: { + maxlength: Number, + clearable: Boolean, + mini: Boolean, + large: Boolean, + value: [String, Number], + placeholder: String, + disabled: Boolean, + readonly: Boolean, + type: { + validator(value) { + return (["text", "textarea", "password", "url", "email", "date", "search"].indexOf(value) >= 0); + }, + default: 'text' + }, + icon: String, + autofocus: Boolean, + iconAlign: String, + rows: { type: Number, default: 2 }, + name: String, + number: Boolean, + }, + data() { + return { + currentValue: this.value, + isFocus: false, + isEnter: false, + isPassword: true, + }; + }, + inject: { + FormItem: { default: null }, + }, + watch: { + value(value) { + this.currentValue = value + this.FormItem && this.FormItem.testValue(value) + } + }, + methods: { + clear() { + this.setValue('') + this.$nextTick(e => this.$refs.input.focus()) + }, + iconClick() { + !this.disabled && this.$emit("icon-click"); + }, + handleFocus(e) { + this.isFocus = true + this.$emit('focus', e) + }, + handleBlur(e) { + this.isFocus = false + this.$emit('blur', e) + this.FormItem && this.FormItem.testValue(this.value, 'blur') + }, + handleInput(e) { + this.setValue(e.target.value, e) + }, + showPassword() { + let type = '' + if (!this.isPassword) { + type = 'password' + } else { + type = 'text' + } + this.isPassword = !this.isPassword + this.$refs.input.type = type + }, + setValue(value, e) { + // console.log(value) + //todo: 数值过大 会有bug + // if (this.number && /^(-?\d+)(\.\d+)?$/.test(value)) { + // value = parseFloat(value) + // } + // if (!hasProp(this, 'value')) { + this.currentValue = value + // } + this.$emit('input', value) + this.$emit('change', e) + }, + getSuffix() { + let { $listeners } = this + const Search = ('search' in $listeners) + ?+ + + +
++
++
++
++ : null + const Password = + + (this.type == 'password') + ? : null + + return Password || Search || this.$slots.suffix + }, + renderInput() { + const { + disabled, placeholder, type, maxlength, readonly, autofocus, + currentValue, + icon, clearable + } = this + + let suffix = this.getSuffix() + const hasChild = suffix || clearable || icon + const inputProps = { + domProps: { + value: currentValue + }, + class: [ + 'k-input', + { + ["k-input-disabled"]: disabled, + ["k-input-mini"]: !hasChild ? this.mini : null, + ["k-input-lg"]: this.large + } + ], + ref: 'input', + attrs: { + ...this.$attrs, + disabled, placeholder, type, maxlength, readonly, autofocus, + }, + on: { + ...this.$listeners, + focus: this.handleFocus, + blur: this.handleBlur, + input: this.handleInput + } + } + + const props = this.getProp(hasChild) + + // console.log(currentValue, 'currentValue') + + const clearableShow = clearable && (this.isFocus || this.isEnter) && isNotEmpty(currentValue) + + + // console.log(inputProps) + + return ( + hasChild ? + + {icon ?+ : + ) + }, + renderTextArea() { + const { + $attrs, $listeners, currentValue, + rows, disabled, placeholder, maxlength, readonly, autofocus, + } = this + const inputProps = { + domProps: { + value: currentValue + }, + class: 'k-textarea', + attrs: { + ...$attrs, + rows, disabled, placeholder, maxlength, readonly, autofocus + }, + ref: 'input', + on: { + ...$listeners, + input: this.handleInput + } + } + return + }, + getProp(hasChild) { + const { type, $listeners, mini, large } = this + let isSuffix = ('search' in $listeners) || this.$slots.suffix || type == 'password' + const props = { + class: [ + 'k-input-wrapper', + { + ["k-input-has-suffix"]: isSuffix, + ["k-input-mini"]: hasChild && mini, + ["k-input-lg"]: hasChild && large, + ["k-input-has-clear"]: this.clearable, + } + ], + on: { + mouseenter: e => this.isEnter = true, + mouseleave: e => this.isEnter = false + } + } + return props + }, + }, + + render() { + const { type, renderTextArea, renderInput } = this + const Input = type == 'textarea' ? renderTextArea() : renderInput() + return Input + } +}; \ No newline at end of file diff --git a/components/base/pop.jsx b/components/base/pop.jsx new file mode 100755 index 0000000000000000000000000000000000000000..00d0bfc5aa72d69bd753e37f21df76c18d1892ac --- /dev/null +++ b/components/base/pop.jsx @@ -0,0 +1,235 @@ +import Button from "../button"; +import Icon from "../icon"; +import transfer from "../_tool/transfer"; +import resize from "../_tool/resize"; +import outsideclick from "../_tool/outsiteclick"; +import { getElementPos, cloneVNode, isVnode } from "../_tool/utils"; + +export default { + directives: { transfer, resize, outsideclick }, + name: 'BasePop', + props: { + preCls: String, + trigger: { type: String, default: "hover" }, + confirm: Boolean, + dark: Boolean, + transfer: { type: Boolean, default: true }, + title: String, + width: [Number, String], + placement: { + validator(value) { + return ( + ["top", "top-left", "top-right", "bottom", "bottom-left", "bottom-right", "left", "left-bottom", "left-top", "right", "right-top", "right-bottom"].indexOf(value) >= 0 + ); + }, + default: "top" + }, + okText: { type: String, default: "确定" }, + cancelText: { type: String, default: "取消" }, + }, + data() { + return { + showPop: false, + left: 0, + top: 0, + showInit: false, + timer: null + }; + }, + methods: { + setShowPop() { + this.showPop = !this.showPop; + this.$nextTick(e => this.setPosition()) + }, + setPosition() { + // let rel = this.$refs.rel; + let dom = this.$refs.dom; + // let rel = this.$refs.rel.children[0] || this.$refs.rel + let rel = this.$el + if (!dom) return; + let top = 0, left = 0; + + if (this.transfer) { + let pos = getElementPos(this.$el) + top = pos.top + left = pos.left + } + let p = this.placement; + if (p.slice(0, 3) == 'top') { top -= dom.offsetHeight; } + if (p.slice(0, 6) == 'bottom') { top += rel.offsetHeight; } + if (p == 'left' || p == 'right') { top -= (dom.offsetHeight - rel.offsetHeight) / 2 } + if (p.slice(-7) == '-bottom') { top -= (dom.offsetHeight - rel.offsetHeight); } + + if (p.slice(0, 4) == 'left') { left -= dom.offsetWidth; } + if (p.slice(0, 5) == 'right') { left += rel.offsetWidth; } + if (p == 'top' || p == 'bottom') { left -= (dom.offsetWidth - rel.offsetWidth) / 2; } + if (p.slice(-6) == '-right') { left -= (dom.offsetWidth - rel.offsetWidth); } + + this.top = top + this.left = left + }, + hidedrop(e) { + if (this.transfer) { + // if (this.$refs.dom && !this.$refs.dom.contains(e.target) && !this.$refs.rel.contains(e.target)) { + if (this.$refs.dom && !this.$refs.dom.contains(e.target) && !this.$el.contains(e.target)) { + this.showPop = false + } + } else { + this.showPop = false + } + }, + ok() { + this.showPop = false; + this.$emit("ok"); + }, + cancel() { + this.showPop = false; + this.$emit("cancel"); + }, + setPopShow() { + if (!this.showInit) { + this.showInit = true + this.$nextTick(e => { + this.showPop = !this.showPop; + this.$nextTick(e => this.setPosition()) + }) + } else { + this.showPop = !this.showPop; + this.$nextTick(e => this.setPosition()) + } + }, + domMouseLeave(e) { + // if (!this.$refs.rel.contains(e.target) && !this.confirm && this.trigger == 'hover') { + if (!this.$el.contains(e.target) && !this.confirm && this.trigger == 'hover') { + clearTimeout(this.timer) + this.timer = setTimeout(() => { + this.showPop = false + }, 200); + } + }, + domMouseEnter(e) { + if (this.$refs.dom.contains(e.target) && !this.confirm && this.trigger == 'hover') { + clearTimeout(this.timer) + } + }, + mouseEnter() { + clearTimeout(this.timer) + if (this.trigger == "hover" && !this.confirm && !this.showPop) { + this.setPopShow() + } + }, + mouseLeave(e) { + if (this.trigger == 'hover' && !this.confirm && this.showPop) { + clearTimeout(this.timer) + this.timer = setTimeout(() => { + this.showPop = false + }, 200); + } + }, + relClick() { + if (this.trigger == "click" || this.confirm) { + this.setPopShow() + } + }, + getOrigin() { + let origins = { + top: 'center bottom', 'top-left': 'left bottom', 'top-right': 'right bottom', + left: 'right center', 'left-top': 'right top', 'left-bottom': 'right bottom', + right: 'left center', 'right-top': 'left top', 'right-bottom': 'left bottom', + bottom: 'center top', 'bottom-left': 'left top', 'bottom-right': 'right top' + } + return origins[this.placement] + }, + renderPopup() { + let { placement, title, preCls, $slots } = this + let footerNode, titleNode, contentNode, cnode = [], drop = null, inner = []; + title = title || $slots.title + + if (this.confirm) { + let fnode = [] + fnode.push() + fnode.push() + footerNode = + cnode.push(: null} + + {suffix ? {suffix}: null} + {clearableShow ?: null} + , {title}) + } else { + titleNode = title ?{title}: '' + $slots.content && cnode.push($slots.content) + } + // cnode.push(this.$slots.content) + contentNode = cnode.length ?{cnode}: null + inner.push(titleNode, contentNode, footerNode) + if (this.showInit) { + const dropStyle = { + left: `${this.left}px`, + top: `${this.top}px`, + width: `${this.width}px`, + transformOrigin: this.getOrigin() + } + let dropClass = [`k-${preCls}-content`, + { + // [`k-${preCls}-confirm`]: confirm, + // ["k-${preCls}-dark"]: this.dark + } + ]; + const props = { + class: dropClass, + style: dropStyle, + ref: 'dom', + attrs: { + 'k-placement': placement + }, + on: { + mouseenter: e => this.domMouseEnter(e), + mouseleave: e => this.domMouseLeave(e) + } + } + drop = ( ++ + ) + } + return drop + }, + }, + + render() { + let { $slots } = this + + let child = ($slots.default || []).filter(c => c.tag || c.text.trim() !== ''); + child = child.length === 1 ? child[0] : child; + if (!child) { + return null; + }; + child = isVnode(child) ? child : {child}; + let popup = this.renderPopup() + + + const props = { + children: popup, + on: { + 'mouseenter': e => { + this.mouseEnter() + }, + 'mouseleave': e => { + this.mouseLeave() + }, + 'click': e => { + this.relClick() + } + } + } + return cloneVNode(child, props) + // return ( + //+ ++{inner}++ //+ // ) + } +}; \ No newline at end of file diff --git a/components/breadcrumb/breadcrumb.jsx b/components/breadcrumb/breadcrumb.jsx new file mode 100755 index 0000000000000000000000000000000000000000..bf2697727ccfdef158dd5df3496b20506753bd9f --- /dev/null +++ b/components/breadcrumb/breadcrumb.jsx @@ -0,0 +1,11 @@ +import { getChild } from '../_tool/utils' +export default { + name: 'Breadcrumb', + render() { + return ( + + ) + } +} diff --git a/components/breadcrumb/breadcrumbItem.jsx b/components/breadcrumb/breadcrumbItem.jsx new file mode 100755 index 0000000000000000000000000000000000000000..fb6d7bc7403bb10d73de530faa99693d87e6b063 --- /dev/null +++ b/components/breadcrumb/breadcrumbItem.jsx @@ -0,0 +1,27 @@ +import Icon from "../icon"; +export default { + name: 'BreadcrumbItem', + props: { + separator: { type: String, default: '/' }, + to: String, + replace: Boolean, + icon: String + }, + methods: { + toPath() { + this.to && this.replace ? this.$router.replace({ path: this.replace }) : this.$router.push({ path: this.to }) + } + }, + render() { + const { $slots, toPath, icon, separator } = this + return ( + + ) + } +} \ No newline at end of file diff --git a/components/breadcrumb/demo/base.md b/components/breadcrumb/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..4d546f5e2f1e91598c2aa79ca695e7331cbaec79 --- /dev/null +++ b/components/breadcrumb/demo/base.md @@ -0,0 +1,16 @@ ++ // {$slots.default} + //+ // {drop} + //+#### 基础用法 +通过 `to` 添加跳转链接 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/breadcrumb/demo/icon.md b/components/breadcrumb/demo/icon.md new file mode 100755 index 0000000000000000000000000000000000000000..5f1c0dd8c250ae79a1050edf4d110e788093693c --- /dev/null +++ b/components/breadcrumb/demo/icon.md @@ -0,0 +1,16 @@ ++ +Home +breadcrumb +other ++#### 设置图标 +通过 `icon` 设置图标 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/breadcrumb/demo/index.vue b/components/breadcrumb/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..cdee0adc55b22f39319cb37595061711602eb2ce --- /dev/null +++ b/components/breadcrumb/demo/index.vue @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/components/breadcrumb/demo/info.md b/components/breadcrumb/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..50aca4da0398c899b3f1dfd653598683cf51cd86 --- /dev/null +++ b/components/breadcrumb/demo/info.md @@ -0,0 +1,9 @@ +# Breadcrumb面包屑 +显示当前页面在系统层级结构中的位置,并能向上返回。 + +## 何时使用 +- 当系统拥有超过两级以上的层级结构时; +- 当需要告知用户『你在哪里』时; +- 当需要向上导航的功能时。 + +## 代码演示 \ No newline at end of file diff --git a/components/breadcrumb/demo/separator.md b/components/breadcrumb/demo/separator.md new file mode 100755 index 0000000000000000000000000000000000000000..512358fdb844a9cce7614bd481fc598c823b882b --- /dev/null +++ b/components/breadcrumb/demo/separator.md @@ -0,0 +1,16 @@ ++ +Home +breadcrumb +other ++#### 分隔符 +通过 `separator` 设置分隔符 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/breadcrumb/index.js b/components/breadcrumb/index.js new file mode 100755 index 0000000000000000000000000000000000000000..14814e0e8814280f068038f5787a951175a0daca --- /dev/null +++ b/components/breadcrumb/index.js @@ -0,0 +1,3 @@ +import Breadcrumb from './breadcrumb.jsx' +import BreadcrumbItem from './breadcrumbItem.jsx' +export { Breadcrumb, BreadcrumbItem } \ No newline at end of file diff --git a/components/breadcrumb/index.md b/components/breadcrumb/index.md new file mode 100755 index 0000000000000000000000000000000000000000..dc60c1db42018cd388cf29fc4e026abc402893c1 --- /dev/null +++ b/components/breadcrumb/index.md @@ -0,0 +1,7 @@ +### BreadcrumbItem API +| 属性 | 说明 | 类型 | 默认值 | +|-----------|-----------------------------------------|---------|-------| +| separator | 自定义分隔符 | String | / | +| to | 自定义链接函数,和 `vue-router` 配合使用 | String | - | +| replace | 路由跳转时,开启 `replace` 将不会向 `history` 添加新记录 | Boolean | false | +| icon | 按钮的图标 | String | - | \ No newline at end of file diff --git a/components/breadcrumb/styles/index.less b/components/breadcrumb/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..a10bb8b91f723dd85dd0d73a8143524391549bb9 --- /dev/null +++ b/components/breadcrumb/styles/index.less @@ -0,0 +1,32 @@ +@import '../../styles/global.less'; +.k-breadcrumb { + line-height: 1.5; + box-sizing: border-box; + margin: 0; + padding: 0; + list-style: none; + color: rgba(0, 0, 0, .45); + font-size: 14px; + &-item { + .k-icon { + margin-right: 4px; + } + &:hover { + color: @main; + } + } + &-link { + cursor: pointer; + } + >span { + &:last-child { + color: rgba(0, 0, 0, .65); + .k-breadcrumb-separator { + display: none; + } + } + } + &-separator { + margin: 0 5px; + } +} \ No newline at end of file diff --git a/src/components/button/button.vue b/components/button/button.jsx old mode 100644 new mode 100755 similarity index 33% rename from src/components/button/button.vue rename to components/button/button.jsx index d23870c0a515733eb5a43d6150b41322130070fe..ad1fba89f97b95c7d23822571b331f9c7f1259eb --- a/src/components/button/button.vue +++ b/components/button/button.jsx @@ -1,18 +1,7 @@ - - - - \ No newline at end of file +}; \ No newline at end of file diff --git a/src/components/button/buttonGroup.vue b/components/button/buttonGroup.jsx old mode 100644 new mode 100755 similarity index 43% rename from src/components/button/buttonGroup.vue rename to components/button/buttonGroup.jsx index ec5b5aa41d0f4183835c099527096f0329b322fb..2896ffa9c1a2019e73aa06fd52d76b9f07763fa8 --- a/src/components/button/buttonGroup.vue +++ b/components/button/buttonGroup.jsx @@ -1,9 +1,4 @@ - -+ +Home +breadcrumb +other +-- - diff --git a/components/button/demo/base.md b/components/button/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..746b90725c4de4facba03d5d2dcf38892f3a21dc --- /dev/null +++ b/components/button/demo/base.md @@ -0,0 +1,17 @@ +- +#### 基本用法 +使用 `type`、`hollow`、`circle` 属性来定义 `Button` 的样式。 + + +```tpl + ++ + + + + + ++ +``` \ No newline at end of file diff --git a/components/button/demo/disabled.md b/components/button/demo/disabled.md new file mode 100755 index 0000000000000000000000000000000000000000..1a1ca071b0016f45a609541c905d6293c8c8b777 --- /dev/null +++ b/components/button/demo/disabled.md @@ -0,0 +1,13 @@ ++#### 禁用 +通过添加 `disabled` 属性可将按钮设置为不可用状态。 + + +```tpl + ++ + ++ +``` \ No newline at end of file diff --git a/components/button/demo/group.md b/components/button/demo/group.md new file mode 100755 index 0000000000000000000000000000000000000000..9ea32a1d09f106aa5cd8ecc0ea51d546e5f87c2c --- /dev/null +++ b/components/button/demo/group.md @@ -0,0 +1,27 @@ ++#### 按钮组合 +将多个 `Button` 放入 `ButtonGroup` 内,可实现按钮组合的效果。 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/button/demo/index.vue b/components/button/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..61ed3dd708e97291fbb250a026f433a144ab3d3f --- /dev/null +++ b/components/button/demo/index.vue @@ -0,0 +1,39 @@ + + \ No newline at end of file diff --git a/components/button/demo/info.md b/components/button/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..26c42f3204db1b18012bb425e7613671d9e5ccca --- /dev/null +++ b/components/button/demo/info.md @@ -0,0 +1,12 @@ +# Button 按钮 +按钮用于开始一个即时操作。 + +## 何时使用 +标记了一个(或封装一组)操作命令,响应用户点击行为,触发相应的业务逻辑。 + +## 组件注册 +```js +import { Button } from 'kui-vue'; +Vue.use(Button); +``` +## 代码演示 \ No newline at end of file diff --git a/components/button/demo/loading.md b/components/button/demo/loading.md new file mode 100755 index 0000000000000000000000000000000000000000..69a9c68288ecf8faef0e749bf98db5bb2a0f1431 --- /dev/null +++ b/components/button/demo/loading.md @@ -0,0 +1,34 @@ ++ + + + ++ + + + +
+
++ + + ++#### 加载中状态 +添加 `loading` 属性即可让按钮处于加载状态 + + +```tpl + ++ + + + + + ++ + +``` \ No newline at end of file diff --git a/components/button/demo/size.md b/components/button/demo/size.md new file mode 100755 index 0000000000000000000000000000000000000000..44205e11ca66131a624385422c6eb9e68eb2e9bd --- /dev/null +++ b/components/button/demo/size.md @@ -0,0 +1,14 @@ +
+ ++#### 尺寸 +`mini` 为小尺寸, `large` 为大尺寸 + + +```tpl + ++ + + ++ +``` \ No newline at end of file diff --git a/components/button/demo/with-icon.md b/components/button/demo/with-icon.md new file mode 100755 index 0000000000000000000000000000000000000000..0a75656062ea9729cc38f19da8cb995bca61e483 --- /dev/null +++ b/components/button/demo/with-icon.md @@ -0,0 +1,17 @@ ++#### 带图标 +通过添加 `icon` 属性 设置按钮按钮图标。 + + +```tpl + ++ + + + + + ++ +``` \ No newline at end of file diff --git a/components/button/index.js b/components/button/index.js new file mode 100755 index 0000000000000000000000000000000000000000..208c6f9e517937704ad9f22adeae1b8068e5fd4b --- /dev/null +++ b/components/button/index.js @@ -0,0 +1,11 @@ +// import './button.less' +import Button from './button' +import ButtonGroup from './buttonGroup' + +Button.Group = ButtonGroup + +Button.install = function (vue) { + vue.component(Button.name, Button) + vue.component(ButtonGroup.name, ButtonGroup) +} +export default Button \ No newline at end of file diff --git a/components/button/index.md b/components/button/index.md new file mode 100755 index 0000000000000000000000000000000000000000..c1acb9a20414fc1813db1f4160190a4181e77704 --- /dev/null +++ b/components/button/index.md @@ -0,0 +1,11 @@ +## API + +| 属性 | 说明 | 类型 | 默认值 | +|---------|--------------------------------------------------------------|---------|-------| +| type | 按钮类型,可选值为 `primary`、`link`、`success`、`warning`、`danger`、`gray`或者不设置 | String | - | +| mini | 按钮显示小尺寸 | Boolean | false | +| large | 按钮显示大尺寸 | Boolean | false | +| circle | 按钮是否圆角 | Boolean | false | +| hollow | 按钮是否颜色镂空 | Boolean | false | +| icon | 按钮的图标 | String | - | +| loading | 按钮是否进入加载模式 | Boolean | false | \ No newline at end of file diff --git a/components/button/styles/index.less b/components/button/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..e4cfae07d137b5c72dc59952fe6d41b79d03190c --- /dev/null +++ b/components/button/styles/index.less @@ -0,0 +1,235 @@ +@import '../../styles/global.less'; +.k-btn { + color: #fff; + font-size: 12px; + height: 32px; + line-height: 30px; + padding: 0 15px; + box-sizing: border-box; + border-radius: @radius; + display: inline-block; + vertical-align: middle; // transition: opacity .2s ease-in-out; + user-select: none; + z-index: 9; + outline: none; + border: 1px solid transparent; + &:hover { + opacity: .8; + zoom: 0%; + } + &:active { + opacity: 1; + } + &>.k-icon +span, span +.k-icon { + margin-left: 4px; + } + .k-icon { + font-size: 16px; + vertical-align: middle; + margin-top: -2px; + } +} + +.k-btn-block { + width: 100%; +} + +.k-btn-default { + color: #333; + background: #f9f9f9; + border: 1px solid @border-color; + z-index: 0; + &:focus { + z-index: 1; + border-color: @main; + color: @main; + } +} + +.k-btn-loading { + opacity: .8; + &:hover { + opacity: .8; + } +} + +.k-btn-mini { + height: 25px; + line-height: 23px; + font-size: 12px; + padding: 0 8px; + [class^="k-ion"] { + font-size: 12px; + } +} + +.k-btn-lg { + height: 40px; + line-height: 38px; + font-size: 14px; + padding: 0 15px; + .k-icon { + font-size: 20px; + } +} + +.k-btn-circle { + border-radius: 30px; +} + +.k-btn-success { + background-color: @success; + border-color: @success; +} + +.k-btn-primary { + background: @main; + border-color: @main; +} + +.k-btn-link { + background: none; + border: none !important; + color: @main; + &[disabled='disabled']{ + background: none; + } +} + +.k-btn-danger { + border-color: @danger; + background: @danger; + .badge-count { + border-color: @danger; + color: @danger; + } +} + +.k-btn-warning { + background: @warning; + border-color: @warning; +} + +.k-btn-gray { + background-color: @gray; + border-color: @gray; +} + +.k-btn-primary.k-btn-hollow { + color: tint(@main, -10%); + background: tint(@main, 90%); + border-color: tint(@main, 70%); + &:focus { + border-color: @main; + color: @main; + } +} + +.k-btn-success.k-btn-hollow { + color: tint(@success, -10%); + background: tint(@success, 90%); + border-color: tint(@success, 70%); + &:focus { + border-color: @success; + color: @success; + } +} + +.k-btn-gray.k-btn-hollow { + color: tint(@gray, -10%); + background: tint(@gray, 90%); + border-color: tint(@gray, 70%); + &:focus { + border-color: @gray; + color: @gray; + } +} + +.k-btn-warning.k-btn-hollow { + color: tint(@warning, -10%); + background: tint(@warning, 90%); + border-color: tint(@warning, 70%); + &:focus { + border-color: @warning; + color: @warning; + } +} + +.k-btn-danger.k-btn-hollow { + color: tint(@danger, -10%); + background: tint(@danger, 90%); + border-color: tint(@danger, 70%); + &:focus { + border-color: @danger; + color: @danger; + } +} + +.k-btn-group { + position: relative; + display: inline-block; + vertical-align: middle; + white-space: nowrap; + .k-btn { + margin-left: -1px; + position: relative; + margin-right: 0; + border-radius: 0; + } +} + +.k-btn-icon-only { + padding: 0; + height: 32px; + width: 32px; +} + +.k-btn-icon-only.k-btn-lg { + padding: 0; + height: 40px; + width: 40px; +} + +.k-btn-icon-only.k-btn-mini { + padding: 0; + height: 25px; + width: 25px; +} + +.k-btn-group-mini { + .k-btn { + height: 25px; + line-height: 23px; + font-size: 12px; + padding: 0 8px; + } +} + +.k-btn-group-lg { + .k-btn { + height: 40px; + line-height: 38px; + font-size: 14px; + padding: 0 15px; + } +} + +.k-btn-group-circle { + .k-btn { + &:first-child { + border-top-left-radius: 30px; + border-bottom-left-radius: 30px; + } + &:last-child { + border-top-right-radius: 30px; + border-bottom-right-radius: 30px; + } + } +} + +button[disabled='disabled'] { + cursor: not-allowed; + color: @disable-color; + background: @disable-back; + border-color: @disable-border; +} \ No newline at end of file diff --git a/components/card/card.jsx b/components/card/card.jsx new file mode 100755 index 0000000000000000000000000000000000000000..022008079a7d99fc4902bed8fa2ab450be917fc0 --- /dev/null +++ b/components/card/card.jsx @@ -0,0 +1,24 @@ +import Icon from "../icon"; +export default { + name: 'Card', + props: { + bordered: Boolean, + title: String, + icon: String + }, + render() { + const { title, icon, $slots, bordered } = this + const classes = ['k-card', { + ['k-card-bordered']: bordered + }] + const extra = $slots.extra ?{$slots.extra}: null + const iconNode = icon ?: null + const titleNode = title ? {title} : $slots.title || null + return ( + ++ ) + } +} \ No newline at end of file diff --git a/components/card/demo/base.md b/components/card/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..28b0dc06a98b07e54398a7e75def29cc0e272e9e --- /dev/null +++ b/components/card/demo/base.md @@ -0,0 +1,22 @@ +{iconNode}{titleNode}{extra}+ {$slots.default ?{$slots.default}: null} ++#### 基本用法 +通过 `title` 和 `icon` 可设置标题和图标 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/card/demo/border.md b/components/card/demo/border.md new file mode 100755 index 0000000000000000000000000000000000000000..01e99b76f97b436dc970a3a53573d0062d6c2c59 --- /dev/null +++ b/components/card/demo/border.md @@ -0,0 +1,28 @@ ++ ++++ card content
+card content
+card content
+card content
+card content
+card content
++#### 边框 +`bordered` 可以设置是否显示边框 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/card/demo/index.vue b/components/card/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..44a934af65060159e816488263419cc7caa78be1 --- /dev/null +++ b/components/card/demo/index.vue @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/components/card/demo/info.md b/components/card/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..520aaee065006665c0bb9c7f7cafdc738ee8568d --- /dev/null +++ b/components/card/demo/info.md @@ -0,0 +1,7 @@ +# Card 卡片 +通用卡片容器 + +## 何时使用 +最基础的卡片容器,可承载文字、列表、图片、段落,常用于后台概览页面。 + +## 代码演示 \ No newline at end of file diff --git a/components/card/index.js b/components/card/index.js new file mode 100755 index 0000000000000000000000000000000000000000..a439d75b72fb162482a0cf253cde886d3280c91f --- /dev/null +++ b/components/card/index.js @@ -0,0 +1,2 @@ +import Card from './card.jsx' +export default Card \ No newline at end of file diff --git a/components/card/index.md b/components/card/index.md new file mode 100755 index 0000000000000000000000000000000000000000..6743fc5c2c49827ae17f4c3819efa8d18adf4a55 --- /dev/null +++ b/components/card/index.md @@ -0,0 +1,7 @@ +### API +| 属性 | 说明 | 类型 | 默认值 | +|----------|----------|-------------|-------| +| title | 卡片的标题 | String、slot | slot | +| icon | 卡片标题的图标 | String | - | +| bordered | 卡片是否显示边框 | Boolean | false | +| extra | 卡片标题扩展 | slot | - | \ No newline at end of file diff --git a/components/card/styles/index.less b/components/card/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..bb10aba289f3d0bdf5d1355d1f01d317f2807b3a --- /dev/null +++ b/components/card/styles/index.less @@ -0,0 +1,44 @@ +@import '../../styles/global.less'; +.k-card { + background: #fff; + position: relative; + border-radius: @radius; + .k-card-head { + position: relative; + border-bottom: 1px solid #e9eaec; + padding: 14px 16px; + line-height: 1; + .k-icon { + vertical-align: middle; + margin-right: 6px; + font-size: 14px; + } + .k-card-title { + font-weight: 700; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 80%; + display: inline-block; + font-size: 14px; + vertical-align: middle; + } + } + .k-card-extra { + position: absolute; + right: 16px; + cursor: default; + top: 50%; + font-size: 12px; + transform: translate3d(0, -50%, 0); + user-select: none; + } + .k-card-body { + padding: 16px; + font-size: 12px; + } +} + +.k-card-bordered { + border: 1px solid #eee; +} \ No newline at end of file diff --git a/components/carousel/carousel.jsx b/components/carousel/carousel.jsx new file mode 100755 index 0000000000000000000000000000000000000000..1c01ef81314222343bcc13e53ed73f2539ebfa19 --- /dev/null +++ b/components/carousel/carousel.jsx @@ -0,0 +1,146 @@ +import Icon from "../icon"; +import resize from '../_tool/resize' +import { getChild } from '../_tool/utils' +export default { + name: 'Carousel', + directives: { resize }, + props: { + value: { type: [Number, String], default: 0 }, + loop: Boolean, + autoplay: Boolean, + delay: { type: [String, Number], default: 3000 }, + vertical: Boolean, + dots: { type: Boolean, default: true } + }, + data() { + return { + currentIndex: this.value, + autotimer: null, + width: 0, + height: 0, + animate: this.value > 0 ? false : true, + resizing: false, + playing: false, + } + }, + provide() { + return { + Carousel: this + } + }, + watch: { + value(v) { + this.currentIndex = v + }, + }, + beforDestory() { + clearInterval(this.autotimer) + }, + methods: { + next() { + this.change('right') + }, + prev() { + this.change('left') + }, + autoToPlay() { + clearInterval(this.autotimer) + this.autotimer = setInterval(() => { + this.change('right') + }, parseInt(this.delay)); + }, + change(type) { + if (this.playing) return; + this.animate = true + let index = this.currentIndex + if (type == 'left') { + index -= 1 + index = Math.max(0, index) + } else if (type == 'right') { + let length = getChild(this.$slots.default).length + if (!this.loop) { + if (index == length - 1) { + index = 0 + } else + index += 1 + index = Math.min(length - 1, index) + } + } else { + index = type + } + this.currentIndex = index + this.playing = true + setTimeout(() => { + this.playing = false + }, 600); + }, + resize() { + this.animate = false + let carousel = this.$refs.carousel + this.width = carousel.offsetWidth + this.height = carousel.offsetHeight + } + }, + + mounted() { + this.$nextTick(e => { + this.resize() + this.autoplay && this.autoToPlay() + }) + }, + render() { + let { currentIndex, change, vertical } = this + let kid = getChild(this.$slots.default) + currentIndex = Math.min(kid.length - 1, currentIndex) + currentIndex = Math.max(0, currentIndex) + const classes = ['k-carousel', { + 'k-carousel-vertical': vertical + }] + + const dotsNode = ( ++ ++ 年-月-日 ++card content
+card content
+card content
+card content
+card content
+card content
++ {kid.map((e, i) =>
+ ) + + let offsetX = 0, offsetY = 0; + if (!vertical) { + offsetX = currentIndex * this.width + } else { + offsetY = currentIndex * this.height + } + const warpperCls = { + class: 'k-carousel-warpper', + style: { + transform: `translateX(-${offsetX}px) translateY(-${offsetY}px)`, + width: !vertical ? kid.length * this.width + 'px' : '', + height: vertical ? kid.length * this.height + 'px' : '', + transitionDuration: !this.animate ? '0s' : '' + } + } + const arrowLeft = change('left')}> +- change(i)}>
)} ++ + const arrowRight = change('right')}> + + + const props = { + class: classes, + ref: 'carousel', + on: { + mouseenter: e => clearInterval(this.autotimer), + mouseleave: e => { this.autoplay && this.autoToPlay() } + } + } + return ( + ++ ) + } +} diff --git a/components/carousel/carouselItem.jsx b/components/carousel/carouselItem.jsx new file mode 100755 index 0000000000000000000000000000000000000000..83d512fefadc4f88ac90e5ad9e0580bcb78eaf85 --- /dev/null +++ b/components/carousel/carouselItem.jsx @@ -0,0 +1,19 @@ +export default { + name: 'CarouselItem', + inject: { + Carousel: { default: null } + }, + render() { + let width, height, carousel = this.Carousel + if (carousel) { + width = carousel.width + height = carousel.height + } + let styles = { width: `${width}px`, height: `${height}px` } + return ( ++ {kid} ++ {!vertical ? arrowLeft : null} + {!vertical ? arrowRight : null} + {this.dots ? dotsNode : null} ++ {this.$slots.default} ++ ) + } +} diff --git a/components/carousel/demo/autoplay.md b/components/carousel/demo/autoplay.md new file mode 100755 index 0000000000000000000000000000000000000000..083eab71b3afdb42ff403ee57b7dddcf1c6cf438 --- /dev/null +++ b/components/carousel/demo/autoplay.md @@ -0,0 +1,17 @@ ++#### 自动播放 +通过设置 `autoplay` ,可实现定时自动播放,通过 `delay` 设置间隔播放时间,默认 `3000` ,单位毫秒 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/carousel/demo/base.md b/components/carousel/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..9b64339d51db003615ada83fe172775df0fd57d7 --- /dev/null +++ b/components/carousel/demo/base.md @@ -0,0 +1,17 @@ ++ +1 +2 +3 +4 ++#### 基本用法 +最简单的用法,可以通过 `value(v-model)` 指定初始值 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/carousel/demo/index.vue b/components/carousel/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..d5bf6dd3b97c145f0415573721b865a16824841d --- /dev/null +++ b/components/carousel/demo/index.vue @@ -0,0 +1,35 @@ + + \ No newline at end of file diff --git a/components/carousel/demo/info.md b/components/carousel/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..f22aa57f34a6c4bf3971a27a6e7a8350c994d0da --- /dev/null +++ b/components/carousel/demo/info.md @@ -0,0 +1,9 @@ +# Carousel 走马灯 +旋转木马,一组轮播的区域。 + +## 何时使用 +- 当有一组平级的内容。 +- 当内容空间不足时,可以用走马灯的形式进行收纳,进行轮播展现。 +- 常用于一组图片或卡片轮播。 + +## 代码演示 \ No newline at end of file diff --git a/components/carousel/demo/vertical.md b/components/carousel/demo/vertical.md new file mode 100755 index 0000000000000000000000000000000000000000..d4d4b0649a362645a543f5f010d68f4a69c7fce9 --- /dev/null +++ b/components/carousel/demo/vertical.md @@ -0,0 +1,17 @@ ++ +1 +2 +3 +4 ++#### 垂直 +通过设置 `vertical` 呈现垂直模式,此时不显示左右箭头 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/carousel/index.js b/components/carousel/index.js new file mode 100755 index 0000000000000000000000000000000000000000..09fa4e42105bf2e2135b978064e18d097a5b56b4 --- /dev/null +++ b/components/carousel/index.js @@ -0,0 +1,3 @@ +import Carousel from './carousel.jsx' +import CarouselItem from './carouselItem.jsx' +export { Carousel, CarouselItem } \ No newline at end of file diff --git a/components/carousel/index.md b/components/carousel/index.md new file mode 100755 index 0000000000000000000000000000000000000000..db0620bf7678703ff86e8e4b9a2bef0122823288 --- /dev/null +++ b/components/carousel/index.md @@ -0,0 +1,8 @@ +### API +| 属性 | 说明 | 类型 | 默认值 | +|-----------|-------------------------------------|---------------|-------| +| value | 幻灯片的索引,从 0 开始,可以使用 `v-model` 双向绑定数据 | String,Number | 0 | +| loop | 是否开启循环 | Boolean | true | +| vertical | 是否垂直模式显示 | Boolean | false | +| autoplay | 是否自动切换 | Boolean | false | +| speed | 自动切换的时间间隔,单位为毫秒 | Number | 2000 | \ No newline at end of file diff --git a/components/carousel/styles/index.less b/components/carousel/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..f2eb540b0bde0447da960b2d04bdb091fb844343 --- /dev/null +++ b/components/carousel/styles/index.less @@ -0,0 +1,127 @@ +@import '../../styles/global.less'; +.k-carousel { + position: relative; + display: block; + overflow: hidden; + width: 100%; + &:hover { + [class*='k-carousel-arrow'] { + opacity: .2; + } + } + .k-carousel-warpper { + transition: transform .5s ease-in-out; + width: 100%; + height: 100%; + } + .k-carousel-item { + float: left; + height: 100%; + min-height: 1px; + display: block; + } + .k-carousel-dots { + width: 100%; + text-align: center; + list-style: none; + z-index: 10; + position: absolute; + line-height: 1; + bottom: 10px; + left: 0; + li { + display: inline-block; + background: #fff; + width: 16px; + height: 3px; + margin: 0 3px; + opacity: .3; + border-radius: 1px; + transition: all .5s ease-in-out; + cursor: pointer; + &:hover { + opacity: .8; + } + } + .k-carousel-dots-active { + width: 25px; + opacity: 1; + } + } + .k-carousel-dots-radius { + li { + width: 8px; + height: 8px; + border-radius: 50%; + } + .k-carousel-dots-active { + width: 8px; + opacity: 1; + } + } + [class*='k-carousel-arrow'] { + position: absolute; + top: 50%; + z-index: 100; + left: 10px; + background: #000; + border-radius: 50%; + display: block; + height: 36px; + width: 36px; + text-align: center; + line-height: 36px; + opacity: 0; + margin-top: -18px; + cursor: pointer; + color: #fff; + transition: opacity .3s ease-in-out; + &:hover { + opacity: .5; + } + } + .k-carousel-arrow-right { + left: auto; + right: 10px; + } +} + +.k-carousel-vertical { + .k-carousel-item { + float: auto; + width: 100%; + height: auto; + } + .k-carousel-dots { + bottom: auto; + top: 50%; + transform: translateY(-50%); + right: 0; + height: auto; + width: 17px; + left: auto; + li { + width: 3px; + height: 16px; + margin: 5px 0; + display: block; + } + .k-carousel-dots-active { + height: 25px; + width: 3px; + opacity: 1; + } + } + .k-carousel-dots-radius { + li { + width: 8px; + height: 8px; + border-radius: 50%; + } + .k-carousel-dots-active { + height: 8px; + width: 8px; + opacity: 1; + } + } +} \ No newline at end of file diff --git a/components/checkbox/checkbox.jsx b/components/checkbox/checkbox.jsx new file mode 100755 index 0000000000000000000000000000000000000000..2f761e36a23e03527993d8b8a00b9ae149542d18 --- /dev/null +++ b/components/checkbox/checkbox.jsx @@ -0,0 +1,77 @@ +import { hasProp } from '../_tool/utils' +import Icon from '../icon' +export default { + name: "Checkbox", + props: { + value: [String, Number, Boolean], + disabled: Boolean, + label: { type: [String, Number] }, + indeterminate: Boolean, + checked: [Boolean, Number] + }, + model: { + prop: 'checked', + // event: 'change' + }, + inject: { + FormItem: { default: null }, + groupContext: { default: null }, + }, + data() { + const checked = hasProp(this, 'checked') ? this.checked : (this.value === true && !this.indeterminate) + return { + isChecked: checked, + } + }, + methods: { + change(e) { + let { disabled, value, $slots, label, groupContext } = this + if (disabled) { + return false; + } + const checked = e.target.checked; + this.isChecked = checked; + if (groupContext) { + label = label || $slots.default.text + this.groupContext.change({ label, value }) + } else { + this.$emit("input", checked); + this.$emit("change", e); + this.FormItem && this.FormItem.testValue(checked) + } + } + }, + render() { + let { disabled, change, $slots, label, groupContext, value, indeterminate, checked, isChecked } = this + + if (groupContext) { + checked = groupContext.value.indexOf(value) !== -1 + disabled = disabled || groupContext.disabled + } else { + if (!hasProp(this, 'checked')) { + checked = isChecked + } + } + // console.log(checked) + const wpclasses = ["k-checkbox-wrapper", { ["k-checkbox-disabled"]: disabled }]; + + const classes = [ + "k-checkbox", + { + ["k-checkbox-checked"]: checked && !indeterminate, + ["k-checkbox-indeterminate"]: indeterminate + } + ]; + let inner = checked ?+ +1 +2 +3 +4 +: null + const labelNode = label || $slots.default + return ( + + ) + } +} diff --git a/components/checkbox/demo/base.md b/components/checkbox/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..ef8d97befd35dccf242fa76cdbbde52f505b8ac9 --- /dev/null +++ b/components/checkbox/demo/base.md @@ -0,0 +1,26 @@ + +#### 基础用法 +单独使用 `checked` 表示是否为选中状态 ,使用 `v-model` 可以双向绑定数据。 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/checkbox/demo/check-all.md b/components/checkbox/demo/check-all.md new file mode 100755 index 0000000000000000000000000000000000000000..87e69a4a8b6d0e6286740213f69fcf4fd826bcf7 --- /dev/null +++ b/components/checkbox/demo/check-all.md @@ -0,0 +1,48 @@ +{{checked}}
+Checkbox + +
+
++ +#### 全选 +全选组合 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/checkbox/demo/disabled.md b/components/checkbox/demo/disabled.md new file mode 100755 index 0000000000000000000000000000000000000000..5e619a83d0b5aa7cf1856604a9358b46a59cede6 --- /dev/null +++ b/components/checkbox/demo/disabled.md @@ -0,0 +1,29 @@ +Check all +
++ +#### 可不用 / 可控 +通过 `disabled` 设置不可用 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/checkbox/demo/group.md b/components/checkbox/demo/group.md new file mode 100755 index 0000000000000000000000000000000000000000..82f71e7162e5ddcf1079472cad0147c2ba461318 --- /dev/null +++ b/components/checkbox/demo/group.md @@ -0,0 +1,45 @@ +disabled +disabled +indeterminate +
+
+Checkbox + + ++#### 组合使用 +组合使用可以直接使用 `CheckboxGroup` 的 `options` 来赋值,或者结合 `Checkbox` 来组合使用,通过 `disabled` 可以设置组件是否被禁用 +**`CheckboxGroup` 可以直接使用 `options` 来组合,3.0版本增加** + + +```tpl + +++ + +``` diff --git a/components/checkbox/demo/index.vue b/components/checkbox/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..a8dac1cc469f7e9a7341166c8431f462aeb44931 --- /dev/null +++ b/components/checkbox/demo/index.vue @@ -0,0 +1,22 @@ + \ No newline at end of file diff --git a/components/checkbox/demo/info.md b/components/checkbox/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..f0e5685538d0b3ad0f6c7b6338b2ddf528a7e085 --- /dev/null +++ b/components/checkbox/demo/info.md @@ -0,0 +1,7 @@ +# Checkbox多选框 +多选框 + +## 何时使用 +- 在一组可选项中进行多项选择时; +- 单独使用可以表示两种状态之间的切换,和 switch 类似。区别在于切换 switch 会直接触发状态改变,而 checkbox 一般用于状态标记,需要和提交操作配合。 +## 代码演示 \ No newline at end of file diff --git a/components/checkbox/group.jsx b/components/checkbox/group.jsx new file mode 100755 index 0000000000000000000000000000000000000000..afdb0f4c874513459d106e6b6fc3799cb84b8b7a --- /dev/null +++ b/components/checkbox/group.jsx @@ -0,0 +1,48 @@ +import Checkbox from './checkbox'; +import { getChild } from '../_tool/utils' +export default { + name: "CheckboxGroup", + props: { + disabled: Boolean, + options: Array, + value: Array, + }, + provide() { + return { + groupContext: this, + } + }, + inject: { + FormItem: { default: null }, + }, + methods: { + change(data) { + let value = this.value + let index = value.indexOf(data.value) + if (index < 0) { + value.push(data.value); + } else { + value.splice(index, 1); + } + this.$emit("input", value); + this.$emit("change", value); + this.FormItem && this.FormItem.testValue(value) + } + }, + render() { + const { options, $slots } = this + let kid = getChild($slots.default) + + if (options && options.length) { + kid = options.map(option => ( +{{data}}
++ + + ++ + + + +
+
+{{cities}}
++ + )) + } + return ( {kid}) + } +} diff --git a/components/checkbox/index.js b/components/checkbox/index.js new file mode 100755 index 0000000000000000000000000000000000000000..a4d3d880234ad85c73630d32d7cba4a940e8ab4f --- /dev/null +++ b/components/checkbox/index.js @@ -0,0 +1,3 @@ +import Checkbox from './checkbox.jsx' +import CheckboxGroup from './group.jsx' +export { Checkbox, CheckboxGroup } \ No newline at end of file diff --git a/components/checkbox/index.md b/components/checkbox/index.md new file mode 100755 index 0000000000000000000000000000000000000000..7ed02bc553870745f18beb9c76dacafabd098dd6 --- /dev/null +++ b/components/checkbox/index.md @@ -0,0 +1,16 @@ +### API +| 属性 | 说明 | 类型 | 默认值 | +|---------------|------------------------------|-----------------|-------------------| +| checked | 是否选中状态,可以使用 `v-model` 双向绑定数据 | Boolean | false | +| label | 显示的文字 | String 、 Number | - | +| disabled | 是否禁用当前项 | Boolean | false | +| indeterminate | 组合辅助选项控制半选状态 | Boolean | false | +| change | 在选项状态发生改变时回调 | - | Function(e:Event) | +| value | 组合使用时表示的值 | String、Number | - | +### CheckboxGroup API +| 属性 | 说明 | 类型 | 默认值 | +|----------|-----------------------|---------------------------------------------------|---------| +| value | 可以使用 `v-model` 双向绑定数据 | Boolean | false | +| disabled | 是否禁用组件 | Boolean | false | +| change | 在选项状态发生改变时触发,返回当前选中的值 | Function | [value] | +| options | 可以指定子项 `checkbox` | Array <{label:string/number,value:string/number}> | - | \ No newline at end of file diff --git a/components/checkbox/styles/index.less b/components/checkbox/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..8f09260e1cccde82f2233b115448ef5926b7f6b2 --- /dev/null +++ b/components/checkbox/styles/index.less @@ -0,0 +1,119 @@ +@import '../../styles/global.less'; +.k-checkbox-wrapper { + cursor: pointer; + font-size: 12px; + display: inline-block; + user-select: none; + line-height: 1; + .k-checkbox { + display: inline-block; + vertical-align: middle; + white-space: nowrap; + cursor: pointer; + outline: 0; + line-height: 1; + position: relative; + margin: 0; + box-sizing: content-box; + font-size: 0; + .k-checkbox-inner { + box-sizing: content-box; + display: inline-block; + width: 14px; + height: 14px; + position: relative; + top: 0; + left: 0; + border: 1px solid @border-color; + border-radius: 2px; + background-color: #fff; + transition: border-color .2s ease-in-out, background-color .2s ease-in-out; + overflow: hidden; + color: #fff; + .k-icon { + font-size: 18px; + position: absolute; + left: 50%; + top: 50%; + transform: translate3d(-50%, -50%, 0); + } + } + .k-checkbox-input { + width: 100%; + height: 100%; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + z-index: 1; + cursor: pointer; + opacity: 0; + &:focus { + +.k-checkbox-inner { + border: 1px solid @main; + box-shadow: 0 0 5px fade(@main, 75%); + } + } + } + } + .k-checkbox-checked { + .k-checkbox-inner { + background: @main; + border-color: @main; + position: relative; + } + } + .k-checkbox-indeterminate { + .k-checkbox-inner { + // background: @main; + // border-color: @main; + position: relative; + &:after { + box-sizing: content-box; + background-color: @main; + position: absolute; + width: 8px; + height: 8px; + content: ''; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + transition: all .2s ease-in-out; + // border-radius: 2px; + } + } + } + &:hover .k-checkbox-inner { + border-color: @main; + } + .k-checkbox-label { + padding: 0 8px; + } +} + +.k-checkbox-disabled { + cursor: not-allowed; + color: @disable-color; + .k-checkbox { + .k-checkbox-input { + cursor: not-allowed; + } + .k-checkbox-inner { + background: @disable-back; + border-color: @disable-border; + color: @disable-color; + &:after { + background-color: @disable-back; + color: @disable-color; + } + } + } + .k-checkbox-indeterminate .k-checkbox-inner:after { + background-color: @disable-border; + } +} + +.k-checkbox-group { + display: inline-block; +} \ No newline at end of file diff --git a/components/collapse/collapse.jsx b/components/collapse/collapse.jsx new file mode 100755 index 0000000000000000000000000000000000000000..ec13a363383ef87c905e7347fa073f467a0582e3 --- /dev/null +++ b/components/collapse/collapse.jsx @@ -0,0 +1,47 @@ +import { getChild, hasProp } from '../_tool/utils' +export default { + name: 'Collapse', + props: { + value: Array, + accrodion: Boolean, + sample: Boolean + }, + provide() { + return { + Collapse: this + } + }, + data() { + return { + currentValue: (!hasProp(this, 'value')) ? [] : this.value + } + }, + watch: { + value(v) { + if (v !== undefined && v !== null && v !== '') + this.currentValue = v + } + }, + methods: { + change(name) { + let value = this.currentValue + let index = value.indexOf(name) + + if (index >= 0) { + this.accrodion ? value = [] : value.splice(index, 1) + } else { + this.accrodion ? value = [name] : value.push(name) + } + this.currentValue = value + this.$emit('change', name) + this.$emit('input', value) + } + }, + render() { + const classes = ['k-collapse', { + ['k-collaplse-sample']: this.sample + }] + const kid = getChild(this.$slots.default) + return ({kid}) + } +} \ No newline at end of file diff --git a/components/collapse/demo/accrodion.md b/components/collapse/demo/accrodion.md new file mode 100755 index 0000000000000000000000000000000000000000..aa8a1b5a5597565b2115b779c24bf3f8318ba966 --- /dev/null +++ b/components/collapse/demo/accrodion.md @@ -0,0 +1,28 @@ ++#### 手风琴 +设置 `accrodion` 只允许同时展开一个面板 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/collapse/demo/base.md b/components/collapse/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..b6867e3fd766c4de5590af4e7715064a184f25e6 --- /dev/null +++ b/components/collapse/demo/base.md @@ -0,0 +1,28 @@ ++ ++ +this is content....
+this is content....
+this is content....
++ +this is content....
+this is content....
+this is content....
++ +this is content....
+this is content....
+this is content....
++#### 基本用法 +默认可以同时展开一个或者多个面板 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/collapse/demo/index.vue b/components/collapse/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..22dc965b59c6ced4fc18f1a5cea072a2bfccf206 --- /dev/null +++ b/components/collapse/demo/index.vue @@ -0,0 +1,22 @@ + \ No newline at end of file diff --git a/components/collapse/demo/info.md b/components/collapse/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..701ca791427de1e46cd46279034687feeec9b54f --- /dev/null +++ b/components/collapse/demo/info.md @@ -0,0 +1,7 @@ +# Collapse折叠面板 +可以折叠/展开的内容区域。 + +## 何时使用 +- 对复杂区域进行分组和隐藏,保持页面的整洁。 +- ‘手风琴’ 是一种特殊的折叠面板,只允许单个内容区域展开。 +## 代码演示 \ No newline at end of file diff --git a/components/collapse/demo/nesting.md b/components/collapse/demo/nesting.md new file mode 100755 index 0000000000000000000000000000000000000000..5fdf0d803a73b5978f462fa2054795b75023503c --- /dev/null +++ b/components/collapse/demo/nesting.md @@ -0,0 +1,40 @@ ++ ++ +this is content....
+this is content....
+this is content....
++ +this is content....
+this is content....
+this is content....
++ +this is content....
+this is content....
+this is content....
++#### 嵌套面板 +嵌套折叠面板。 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/collapse/demo/sample.md b/components/collapse/demo/sample.md new file mode 100755 index 0000000000000000000000000000000000000000..71db39e295772d3503a0c086a8c531ad7dcf97df --- /dev/null +++ b/components/collapse/demo/sample.md @@ -0,0 +1,28 @@ ++ ++ +this is content....
+this is content....
+this is content....
++ ++ +this is content....
+this is content....
+this is content....
++ +this is content....
+this is content....
+this is content....
++ +this is content....
+this is content....
+this is content....
++ +this is content....
+this is content....
+this is content....
++#### 简洁模式 +设置 `sample` 呈现没有边框的简洁样式。 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/collapse/index.js b/components/collapse/index.js new file mode 100755 index 0000000000000000000000000000000000000000..dc82949dcc2f105dd4322bfb40ed84b0c2f2c1e3 --- /dev/null +++ b/components/collapse/index.js @@ -0,0 +1,3 @@ +import Collapse from './collapse.jsx' +import Panel from './panel.jsx' +export { Collapse, Panel } \ No newline at end of file diff --git a/components/collapse/index.md b/components/collapse/index.md new file mode 100755 index 0000000000000000000000000000000000000000..4eefa7ab7440a3f81df5a451c2d827563a04e703 --- /dev/null +++ b/components/collapse/index.md @@ -0,0 +1,7 @@ +### API +| 属性 | 说明 | 类型 | 默认值 | +|-----------|---------------------------------|----------------|-------| +| value | 当前激活的面板的 `name`,可以使用 `v-model` 双向绑定 | Array , String | - | +| accordion | 是否开启手风琴模式,开启后每次至多展开一个面板 | Boolean | false | +| sample | 是否开启简洁模式 | Boolean | false | +| change | 切换面板时触发回调,返回当前选项卡的 `name` | Function | - | \ No newline at end of file diff --git a/components/collapse/panel.jsx b/components/collapse/panel.jsx new file mode 100755 index 0000000000000000000000000000000000000000..996d33a3a7360d1cc51f433bcb7ae0023fe9f254 --- /dev/null +++ b/components/collapse/panel.jsx @@ -0,0 +1,45 @@ +import Icon from "../icon"; +import { getTranstionProp } from '../_tool/transition' +export default { + name: 'Panel', + props: { + title: String, + name: { type: String, required: true }, + }, + inject: { + Collapse: { default: null } + }, + methods: { + handelClick() { + if (this.Collapse) { + this.Collapse.change(this.name) + } + } + }, + render() { + let active = false + let { Collapse, name } = this + if (Collapse) { + active = Collapse.currentValue.indexOf(name) >= 0 + } + const classes = ['k-collapse-item', { + ['k-collapse-item-active']: active + }] + const aniprop = getTranstionProp('k-collaplse-slide') + return ( ++ ++ +this is content....
+this is content....
+this is content....
++ +this is content....
+this is content....
+this is content....
++ +this is content....
+this is content....
+this is content....
+++ ) + } +} \ No newline at end of file diff --git a/components/collapse/styles/index.less b/components/collapse/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..6777d7ce3d942e0286533f25a32465c9f99cdd20 --- /dev/null +++ b/components/collapse/styles/index.less @@ -0,0 +1,99 @@ +@import '../../styles/global.less'; +.k-collapse { + background-color: @back-color; + border: 1px solid @border-color; + border-radius: @radius; + border-bottom: 0; + overflow: hidden; + &>.k-collapse-item { + border-bottom: 1px solid @border-color; + &>.k-collapse-header { + line-height: 22px; + padding: 12px 0 12px 40px; + cursor: pointer; + position: relative; + color:@title-color; + font-size: 14px; + &>i { + position: absolute; + left: 16px; + top: 0; + line-height: 46px; + transform: rotate(0); + transition: transform .3s ease-in-out; + } + } + .k-collapse-content { + background-color: #fff; + border-top: 1px solid @border-color; + padding: 0 16px; + transition: all .3s ease-in-out; + box-sizing: border-box; + overflow: hidden; + .k-collapse-content-box { + padding: 16px 0; + } + } + } + &>.k-collapse-item-active { + &>.k-collapse-header>i { + transform: rotate(90deg); + } + } +} + +.k-collaplse-sample { + border: none; + background: none; + .k-collapse-item { + background: @light; + border: none; + margin-bottom: 10px; + border-radius: @radius; + overflow: hidden; + .k-collapse-content { + border: none; + background: none; + } + } +} + +.k-alert-info { + background: tint(@main, 90%); + border-color: tint(@main, 70%); + .k-alert-icon { + color: @main; + } +} +.k-collaplse-slide-enter-actived { + animation: slideIn 0.3s ease-in-out; + animation-fill-mode: both; +} +.k-collaplse-slide-leave-actived { + animation: slideOut 0.3s ease-in-out; + animation-fill-mode: both; +} +@keyframes slideIn { + 0% { + transform: scaleY(0); + transform-origin: 0% 0%; + opacity: 0; + } + 100% { + transform: scaleY(1); + transform-origin: 0% 0%; + opacity: 1; + } +} +@keyframes slideOut { + 0% { + transform: scaleY(1); + transform-origin: 0% 0%; + opacity: 1; + } + 100% { + transform: scaleY(0); + transform-origin: 0% 0%; + opacity: 0; + } +} \ No newline at end of file diff --git a/components/colorPicker/canvasHelper.js b/components/colorPicker/canvasHelper.js new file mode 100755 index 0000000000000000000000000000000000000000..ef821d4fe8b7be267fab94164fbbfa66667ae710 --- /dev/null +++ b/components/colorPicker/canvasHelper.js @@ -0,0 +1,274 @@ +const COLOR_NAMES = { 'aliceblue': '#F0F8FF', 'antiquewhite': '#FAEBD7', 'aqua': '#00FFFF', 'aquamarine': '#7FFFD4', 'azure': '#F0FFFF', 'beige': '#F5F5DC', 'bisque': '#FFE4C4', 'black': '#000000', 'blanchedalmond': '#FFEBCD', 'blue': '#0000FF', 'blueviolet': '#8A2BE2', 'brown': '#A52A2A', 'burlywood': '#DEB887', 'cadetblue': '#5F9EA0', 'chartreuse': '#7FFF00', 'chocolate': '#D2691E', 'coral': '#FF7F50', 'cornflowerblue': '#6495ED', 'cornsilk': '#FFF8DC', 'crimson': '#DC143C', 'cyan': '#00FFFF', 'darkblue': '#00008B', 'darkcyan': '#008B8B', 'darkgoldenrod': '#B8860B', 'darkgray': '#A9A9A9', 'darkgrey': '#A9A9A9', 'darkgreen': '#006400', 'darkkhaki': '#BDB76B', 'darkmagenta': '#8B008B', 'darkolivegreen': '#556B2F', 'darkorange': '#FF8C00', 'darkorchid': '#9932CC', 'darkred': '#8B0000', 'darksalmon': '#E9967A', 'darkseagreen': '#8FBC8F', 'darkslateblue': '#483D8B', 'darkslategray': '#2F4F4F', 'darkslategrey': '#2F4F4F', 'darkturquoise': '#00CED1', 'darkviolet': '#9400D3', 'deeppink': '#FF1493', 'deepskyblue': '#00BFFF', 'dimgray': '#696969', 'dimgrey': '#696969', 'dodgerblue': '#1E90FF', 'firebrick': '#B22222', 'floralwhite': '#FFFAF0', 'forestgreen': '#228B22', 'fuchsia': '#FF00FF', 'gainsboro': '#DCDCDC', 'ghostwhite': '#F8F8FF', 'gold': '#FFD700', 'goldenrod': '#DAA520', 'gray': '#808080', 'grey': '#808080', 'green': '#008000', 'greenyellow': '#ADFF2F', 'honeydew': '#F0FFF0', 'hotpink': '#FF69B4', 'indianred ': '#CD5C5C', 'indigo ': '#4B0082', 'ivory': '#FFFFF0', 'khaki': '#F0E68C', 'lavender': '#E6E6FA', 'lavenderblush': '#FFF0F5', 'lawngreen': '#7CFC00', 'lemonchiffon': '#FFFACD', 'lightblue': '#ADD8E6', 'lightcoral': '#F08080', 'lightcyan': '#E0FFFF', 'lightgoldenrodyellow': '#FAFAD2', 'lightgray': '#D3D3D3', 'lightgrey': '#D3D3D3', 'lightgreen': '#90EE90', 'lightpink': '#FFB6C1', 'lightsalmon': '#FFA07A', 'lightseagreen': '#20B2AA', 'lightskyblue': '#87CEFA', 'lightslategray': '#778899', 'lightslategrey': '#778899', 'lightsteelblue': '#B0C4DE', 'lightyellow': '#FFFFE0', 'lime': '#00FF00', 'limegreen': '#32CD32', 'linen': '#FAF0E6', 'magenta': '#FF00FF', 'maroon': '#800000', 'mediumaquamarine': '#66CDAA', 'mediumblue': '#0000CD', 'mediumorchid': '#BA55D3', 'mediumpurple': '#9370DB', 'mediumseagreen': '#3CB371', 'mediumslateblue': '#7B68EE', 'mediumspringgreen': '#00FA9A', 'mediumturquoise': '#48D1CC', 'mediumvioletred': '#C71585', 'midnightblue': '#191970', 'mintcream': '#F5FFFA', 'mistyrose': '#FFE4E1', 'moccasin': '#FFE4B5', 'navajowhite': '#FFDEAD', 'navy': '#000080', 'oldlace': '#FDF5E6', 'olive': '#808000', 'olivedrab': '#6B8E23', 'orange': '#FFA500', 'orangered': '#FF4500', 'orchid': '#DA70D6', 'palegoldenrod': '#EEE8AA', 'palegreen': '#98FB98', 'paleturquoise': '#AFEEEE', 'palevioletred': '#DB7093', 'papayawhip': '#FFEFD5', 'peachpuff': '#FFDAB9', 'peru': '#CD853F', 'pink': '#FFC0CB', 'plum': '#DDA0DD', 'powderblue': '#B0E0E6', 'purple': '#800080', 'rebeccapurple': '#663399', 'red': '#FF0000', 'rosybrown': '#BC8F8F', 'royalblue': '#4169E1', 'saddlebrown': '#8B4513', 'salmon': '#FA8072', 'sandybrown': '#F4A460', 'seagreen': '#2E8B57', 'seashell': '#FFF5EE', 'sienna': '#A0522D', 'silver': '#C0C0C0', 'skyblue': '#87CEEB', 'slateblue': '#6A5ACD', 'slategray': '#708090', 'slategrey': '#708090', 'snow': '#FFFAFA', 'springgreen': '#00FF7F', 'steelblue': '#4682B4', 'tan': '#D2B48C', 'teal': '#008080', 'thistle': '#D8BFD8', 'tomato': '#FF6347', 'turquoise': '#40E0D0', 'violet': '#EE82EE', 'wheat': '#F5DEB3', 'white': '#FFFFFF', 'whitesmoke': '#F5F5F5', 'yellow': '#FFFF00', 'yellowgreen': '#9ACD32' }; +export function rgbToHex(r, g, b) { + [r, g, b] = [limit(r, 0, 255), limit(g, 0, 255), limit(b, 0, 255)]; + return "#" + ("000000" + ((r << 16) | (g << 8) | b).toString(16)).slice(-6); +} +export function hslToRgb(h, s, l) { + let r, g, b; + [h, s, l] = [limit(h, 0, 360) / 360, limit(s, 0, 100) / 100, limit(l, 0, 100) / 100]; + + if (s == 0) { + r = g = b = l; // achromatic + } else { + const hue2rgb = (p, q, t) => { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + }; + + const q = l < 0.5 ? l * (1 + s) : l + s - l * s; + const p = (2 * l) - q; + + r = hue2rgb(p, q, h + (1 / 3)); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - (1 / 3)); + } + + return [r * 255, g * 255, b * 255].map(Math.round); +} +export function rgbToHsl(r, g, b) { + [r, g, b] = [limit(r, 0, 255) / 255, limit(g, 0, 255) / 255, limit(b, 0, 255) / 255]; + + const max = Math.max(r, g, b), + min = Math.min(r, g, b); + let h, s, l = (max + min) / 2; + + if (max == min) { + h = s = 0; // achromatic + } else { + const d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: + h = ((g - b) / d) + (g < b ? 6 : 0); + break; + case g: + h = ((b - r) / d) + 2; + break; + case b: + h = ((r - g) / d) + 4; + break; + } + + h /= 6; + } + + return [h * 360, s * 100, l * 100].map(Math.round); +} +export function rgbToHsv(r, g, b) { + [r, g, b] = [limit(r, 0, 255) / 255, limit(g, 0, 255) / 255, limit(b, 0, 255) / 255]; + const max = Math.max(r, g, b), + min = Math.min(r, g, b); + let h, s, v = max; + let d = max - min; + s = max === 0 ? 0 : d / max; + if (max == min) { + h = 0; + } else { + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return [h, s, v]; +} +export function rgbToInt(r, g, b) { + return (r << 16) | (g << 8) | b; +} + +export function intToRgb(int) { + return [ + (int >> 16) & 255, //r + (int >> 8) & 255, //g + int & 255 //b + ]; +} +export function parseColor(color, outFormat = 'rgb') { + if (color !== null && color !== undefined) { + let pp; + if ((pp = parseColorToRgba(color)) || + ((pp = parseColorToHsla(color)) && (pp = [...hslToRgb(...pp), pp[3]]))) { + + // se outFormat è un plain object quindi {} oppure new Object() + // if (typeof outFormat === 'object') { + let isobject = outFormat != null && typeof outFormat === 'object' && Array.isArray(outFormat) === false + if (isobject) { + return ['rgb', 'rgbcss', 'rgbcss4', 'rgba', 'rgbacss', + 'hsl', 'hslcss', 'hslcss4', 'hsla', 'hslacss', + 'hex', 'hexcss4', 'int'].reduce((m, f) => { m[f] = formatColor(pp, f); return m; }, outFormat || {}); + } else { + // per sicurezza trasformo in stringa (potrebbe essere un numero) + return formatColor(pp, outFormat.toString().toLowerCase()); + } + } + } + + return undefined; +} +export function formatColor(pp, outFormat) { + switch (outFormat) { + case 'rgb': + default: + return pp.slice(0, 3); + case 'rgbcss': + return `rgb(${pp[0]}, ${pp[1]}, ${pp[2]})`; + case 'rgbcss4': + return `rgb(${pp[0]}, ${pp[1]}, ${pp[2]}, ${pp[3]})`; + case 'rgba': + return pp; + case 'rgbacss': + return `rgba(${pp[0]}, ${pp[1]}, ${pp[2]}, ${pp[3]})`; + case 'hsl': + return rgbToHsl(...pp); + case 'hslcss': + pp = rgbToHsl(...pp); + return `hsl(${pp[0]}, ${pp[1]}, ${pp[2]})`; + case 'hslcss4': + const hh = rgbToHsl(...pp); + return `hsl(${hh[0]}, ${hh[1]}, ${hh[2]}, ${pp[3]})`; + case 'hsla': + return [...rgbToHsl(...pp), pp[3]]; + case 'hslacss': + const ha = rgbToHsl(...pp); + return `hsla(${ha[0]}, ${ha[1]}, ${ha[2]}, ${pp[3]})`; + case 'hex': + return rgbToHex(...pp); + case 'hexcss4': + return rgbToHex(...pp) + ('00' + parseInt(pp[3] * 255).toString(16)).slice(-2); + case 'int': + return rgbToInt(...pp); + } +} +export function nvl(value, def) { + return value === null || value === undefined ? def : value; +} +export function parseColorToHsla(color) { + if (Array.isArray(color)) { + color = [ + limit(color[0], 0, 360), + limit(color[1], 0, 100), + limit(color[2], 0, 100), + limit(nvl(color[3], 1), 0, 1) + ]; + return color; + } else { + const parsed = cssHslaToHsla(color); + if (parsed && parsed.length === 3) { + parsed.push(1); + } + return parsed; + } +} +export function cssRgbaToRgba(rgba) { + if (rgba) { + // in CSS Colors Level 4 rgba() è un alias di rgb() + // rgb[a](int, int, int[, dec]) + const [m, r, g, b, , a] = /^rgba?\((\d+)\s*[\s,]\s*(\d+)\s*[\s,]\s*(\d+)(\s*[\s,]\s*(\d*(.\d+)?))?\)/i.exec(rgba) || []; + return m ? [limit(r, 0, 255), limit(g, 0, 255), limit(b, 0, 255), limit(nvl(a, 1), 0, 1)] : undefined; + } + return undefined; +} +export function cssColorToRgba(color) { + if (color) { + const colorByName = COLOR_NAMES[color.toString().toLowerCase()]; + // considero sia il formato esteso #RRGGGBB[AA] che quello corto #RGB[A] + // provo a estrarre i valori da colorByName solo se questo è valorizzato, altrimenti uso direttamente color + const [, , , r, g, b, a, , rr, gg, bb, aa] = /^\s*#?((([0-9A-F])([0-9A-F])([0-9A-F])([0-9A-F])?)|(([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})?))\s*$/i.exec(colorByName || color) || []; + if (r !== undefined) { + return [ + parseInt(r + r, 16), + parseInt(g + g, 16), + parseInt(b + b, 16), + a ? +((parseInt(a + a, 16)) / 255).toFixed(2) : 1 + ]; + } else if (rr !== undefined) { + return [ + parseInt(rr, 16), + parseInt(gg, 16), + parseInt(bb, 16), + aa ? +((parseInt(aa, 16)) / 255).toFixed(2) : 1 + ]; + } + } + return undefined; +} + +export function parseColorToRgba(color) { + if (Array.isArray(color)) { + color = [ + limit(color[0], 0, 255), + limit(color[1], 0, 255), + limit(color[2], 0, 255), + limit(nvl(color[3], 1), 0, 1) + ]; + return color; + } else { + const parsed = cssColorToRgba(color) || cssRgbaToRgba(color); + if (parsed && parsed.length === 3) { + parsed.push(1); + } + return parsed; + } +} +export function cssHslToHsl(hsl) { + if (hsl) { + // hsl(int, int, int) + const [m, h, s, l] = /^hsl\((\d+)[\s,](\d+)[\s,](\d+)\)/i.exec(hsl) || []; + return m ? [limit(h, 0, 360), limit(s, 0, 100), limit(l, 0, 100)] : undefined; + } + return undefined; +} + +export function cssHslaToHsla(hsla) { + if (hsla) { + // in CSS Colors Level 4 hsla() è un alias di hsl() + // hsl[a](int, int, int[, dec]) + const [m, h, s, l, , a] = /^hsla?\((\d+)\s*[\s,]\s*(\d+)\s*[\s,]\s*(\d+)(\s*[\s,]\s*(\d*(.\d+)?))?\)/i.exec(hsla) || []; + return m ? [limit(h, 0, 255), limit(s, 0, 255), limit(l, 0, 255), limit(nvl(a, 1), 0, 1)] : undefined; + } + return undefined; +} + +export function limit(value, min, max) { + value = +value; + return isNaN(value) ? min : (value < min ? min : (value > max ? max : value)); +} + +export function canvasHelper(canvas) { + const ctx = canvas.getContext('2d'), + width = canvas.width, + height = canvas.height; + + const WBG = ctx.createLinearGradient(1, 1, 1, height - 1); + WBG.addColorStop(0, 'white') + WBG.addColorStop(1, 'black') + + return { + setHue(hue) { + const colorGradient = ctx.createLinearGradient(1, 0, width - 1, 0) + colorGradient.addColorStop(0, `hsla(${hue},100%,50%,0)`) + colorGradient.addColorStop(1, `hsla(${hue},100%,50%,1)`) + ctx.fillStyle = WBG; + ctx.fillRect(0, 0, width, height) + ctx.fillStyle = colorGradient + ctx.globalCompositeOperation = 'multiply' + ctx.fillRect(0, 0, width, height) + ctx.globalCompositeOperation = 'source-over' + }, + grabColor(x, y) { + return ctx.getImageData(x, y, 1, 1).data + }, + findColor(r, g, b) { + const [, s, v] = rgbToHsv(r, g, b) + const x = s * width + const y = height - (v * height) + return [x, y] + } + } +} \ No newline at end of file diff --git a/components/colorPicker/colorpicker.jsx b/components/colorPicker/colorpicker.jsx new file mode 100755 index 0000000000000000000000000000000000000000..b1040195c43668d42d6407d97a59729b6dcaa293 --- /dev/null +++ b/components/colorPicker/colorpicker.jsx @@ -0,0 +1,460 @@ +import { canvasHelper, limit, hslToRgb, rgbToHsl, parseColor, rgbToHex, cssColorToRgba } from './canvasHelper' +import { Input } from '../input' +import Button from '../button' +import Icon from '../icon' + +import { getElementPos } from '../_tool/utils' + +import transfer from "../_tool/transfer"; +import Resize from "../_tool/resize"; +import outsideclick from "../_tool/outsiteclick"; + +const modes = ['rgba', 'hex', 'hsla'] + +export default { + name: 'ColorPicker', + directives: { transfer, Resize, outsideclick }, + props: { + value: String, + transfer: { type: Boolean, default: true }, + showMode: Boolean, + large: Boolean, + mini: Boolean, + mode: { + type: String, default: 'hex', validator: function (value) { + return modes.indexOf(value) !== -1 + } + }, + defalutColors: { + type: Array, default: () => ['#f44336', '#e91e63', '#9c27b0', '#673ab7', '#3f51b5', '#2196f3', '#03a9f4', '#00bcd4', '#009688', '#4caf50', '#8bc34a', '#cddc39', '#ffeb3b', '#ffc107', '#ff9800', '#ff5722', '#795548', '#9e9e9e', '#607d8b', '#000'], + validator: function (value) { return value.length <= 20 } + } + }, + watch: { + value(v1, v2) { + if (v1 != this.currentColor) { + this.valueChange('COLOR', v1) + } + } + }, + data() { + return { + currentMode: this.mode, + currentColor: this.value || '#000', + paintHelper: null, + hueHelper: null, + H: 0, S: 0, L: 0, A: 1, + R: 0, G: 0, B: 0, + HEX: '', + huePointer: { + x: 0 + }, + alphaPointer: { + x: 0, + }, + paintPointer: { + x: 0, y: 0 + }, + placement: 'bottom', + showDrop: false, + showDropInit: false, + left: 0, + top: 0, + isMouseDown: false + } + }, + methods: { + setPosition() { + let top = 0, left = 0, height = this.$el.offsetHeight, offset = 3; + + if (this.transfer) { + let pos = getElementPos(this.$el) + top = pos.top + height + offset + left = pos.left + 1 + } else { + top = height + offset + } + if (this.$refs.dom) { + let clientH = document.body.scrollHeight + let domH = this.$refs.dom.offsetHeight + if (clientH - top - height - offset < domH + 5) { + top = this.transfer ? top - domH - offset : -(domH + 3) + this.placement = 'top' + } else { + this.placement = 'bottom' + } + } + + this.top = top + this.left = left + }, + hidedrop(e) { + if (this.showDropInit && this.showDrop && !this.isMouseDown && !this.$el.contains(e.target) && !this.$refs.dom.contains(e.target)) { + this.showDrop = false + this.currentColor = this.value || '#000' + } + }, + toggleDrop() { + if (this.disabled) { + return false; + } + if (!this.showDropInit) { + + this.showDropInit = true + this.$nextTick(e => { + this.setShowDrop() + + let { paint, hue, alpha } = this.$refs + this.paintHelper = canvasHelper(paint) + + this.initHueCanvas(hue) + this.initAlphaCanvas(alpha) + this.initPaintCanvas(paint) + + this.valueChange('COLOR', this.value) + }) + } else { + this.setShowDrop() + } + }, + setShowDrop() { + this.showDrop = !this.showDrop; + if (this.showDrop) { + this.$nextTick(e => this.setPosition()) + } else { + this.currentColor = this.value || '#000' + } + }, + updatePostion() { + //alpha + { + const x = 170 * this.A; + this.alphaPointer.x = (x - 7); + } + //updaet hue pointer + { + const x = 170 * this.H / 360; + this.huePointer.x = (x - 7); + } + //paint + { + const [r, g, b] = hslToRgb(this.H, this.S, this.L); + const [x, y] = this.paintHelper.findColor(r, g, b); + if (x >= 0) { + this.paintPointer.x = (x - 7); + this.paintPointer.y = (y - 7); + } + } + + }, + valueChange(prop, value) { + switch (prop) { + case 'COLOR': + [this.R, this.G, this.B, this.A] = parseColor(value, 'rgba') || [0, 0, 0, 1]; + [this.H, this.S, this.L] = rgbToHsl(this.R, this.G, this.B); + this.paintHelper.setHue(this.H); + this.updatePostion() + this.alphaCanvsSetHue(this.$refs.alpha) + break; + case 'HUE': + this.H = value; + [this.R, this.G, this.B] = hslToRgb(this.H, this.S, this.L); + this.paintHelper.setHue(value); + this.alphaCanvsSetHue(this.$refs.alpha); + break; + case 'RGB': + [this.R, this.G, this.B] = value; + [this.H, this.S, this.L] = rgbToHsl(this.R, this.G, this.B); + // let colors = rgbToHsl(this.R, this.G, this.B); + // [this.H, this.S, this.L] = colors + this.alphaCanvsSetHue(this.$refs.alpha) + break; + case 'ALPHA': + this.A = value; + break; + } + this.setHEX() + }, + setHEX() { + if (this.A != 1) { + this.HEX = parseColor([this.R, this.G, this.B, this.A], 'hexcss4'); + } else { + this.HEX = rgbToHex(this.R, this.G, this.B); + } + this.currentColor = this.HEX + }, + updateValue() { + let { currentMode, R, G, B, A, H, S, L, } = this, value = null; + if (currentMode == 'hex') { + value = this.HEX + } else if (currentMode == 'rgba') { + value = `rgba(${R},${G},${B},${A})` + } else { + value = A < 1 ? `hsla(${H},${S}%,${L}%,${A})` : `hsl(${H},${S}%,${L}%)` + } + // console.log(value) + this.$emit('input', value) + this.$emit('change', value) + this.currentColor = value + this.showDrop = false + }, + setMode() { + let i = modes.indexOf(this.currentMode) + 1 + i = i > 2 ? 0 : i + this.currentMode = modes[i] + }, + initHueCanvas(canvas) { + const ctx = canvas.getContext('2d'), + setp = 1 / 360, + width = canvas.width, + height = canvas.height, + gradient = ctx.createLinearGradient(0, 0, width, 0); + + for (let i = 0; i <= 1; i += setp) { + gradient.addColorStop(i, `hsl(${360 * i},100%,50%)`) + } + ctx.fillStyle = gradient + ctx.fillRect(0, 0, width, height) + + const onMouseMove = e => { + const x = limit(e.clientX - canvas.getBoundingClientRect().left, 0, width), + hue = Math.round(x * 360 / width) + this.huePointer.x = x - 7 + this.valueChange('HUE', hue) + } + + const onMouseUp = () => { + setTimeout(() => { + this.isMouseDown = false + }, 300); + document.removeEventListener('mousemove', onMouseMove); + document.removeEventListener('mouseup', onMouseUp) + } + + canvas.addEventListener('mousedown', e => { + this.isMouseDown = true + onMouseMove(e) + document.addEventListener('mousemove', onMouseMove) + document.addEventListener('mouseup', onMouseUp) + e.preventDefault() + }) + }, + alphaCanvsSetHue(canvas) { + const ctx = canvas.getContext('2d'), + { width, height } = canvas, + gradient = ctx.createLinearGradient(0, 0, width - 1, 0); + let { H, S, L } = this + ctx.clearRect(0, 0, width, height) + gradient.addColorStop(0, `hsla(${H},${S}%,${L}%,0)`) + gradient.addColorStop(1, `hsla(${H},${S}%,${L}%,1)`) + ctx.fillStyle = gradient + ctx.fillRect(0, 0, width, height) + }, + initAlphaCanvas(canvas) { + this.alphaCanvsSetHue(canvas) + const { width, height } = canvas; + const onMouseMove = (e) => { + const x = limit(e.clientX - canvas.getBoundingClientRect().left, 0, width), + alpha = +(x / width).toFixed(2); + this.alphaPointer.x = (x - 7) + this.valueChange('ALPHA', alpha) + } + + const onMouseUp = () => { + setTimeout(() => { + this.isMouseDown = false + }, 300); + + document.removeEventListener('mousemove', onMouseMove); + document.removeEventListener('mouseup', onMouseUp) + } + + canvas.addEventListener('mousedown', e => { + this.isMouseDown = true + + onMouseMove(e); + document.addEventListener('mousemove', onMouseMove); + document.addEventListener('mouseup', onMouseUp) + e.preventDefault() + + }) + + }, + initPaintCanvas(canvas) { + const { width, height } = canvas; + const onMouseMove = e => { + const x = limit(e.clientX - canvas.getBoundingClientRect().left, 0, width - 1), + y = limit(e.clientY - canvas.getBoundingClientRect().top, 0, height - 1), + color = this.paintHelper.grabColor(x, y) + + this.paintPointer.x = x - 7 + this.paintPointer.y = y - 7 + this.valueChange('RGB', color) + + } + const onMouseUp = () => { + setTimeout(() => { + this.isMouseDown = false + }, 300); + + document.removeEventListener('mousemove', onMouseMove); + document.removeEventListener('mouseup', onMouseUp) + } + + canvas.addEventListener('mousedown', e => { + this.isMouseDown = true + + onMouseMove(e) + document.addEventListener('mousemove', onMouseMove) + document.addEventListener('mouseup', onMouseUp) + e.preventDefault() + }) + }, + renderPaint() { + let prop = { + class: 'k-color-picker-paint', + attrs: { width: 254, height: 136 }, + ref: 'paint' + } + return + }, + renderAlpha() { + let prop = { + class: 'k-color-picker-alpha', + attrs: { width: 170, height: 13 }, + ref: 'alpha' + } + return + }, + renderHue() { + let prop = { + class: 'k-color-picker-hue', + attrs: { width: 170, height: 13 }, + ref: 'hue' + } + return + }, + renderValueInput(key) { + let prop = { + attrs: { + maxlength: key == 'HEX' ? 9 : 4 + }, + props: { + value: this[key] + ('SL'.indexOf(key) >= 0 ? '%' : ''), + mini: true, + }, + on: { + "input": e => { + let value = e.replace('%', '') + if (!value) return; + if (key == 'HEX') { + value = value.toString().toLowerCase() + if (/^#([0-9A-F]{6}|[0-9A-F]{3}|[0-9A-F]{8})$/i.test(value)) { + [this.R, this.G, this.B, this.A] = cssColorToRgba(value) || [this.R, this.G, this.B, this.A]; + [this.H, this.S, this.L] = rgbToHsl(this.R, this.G, this.B); + } else { + return; + } + } else if (key == 'A') { + if (!/^\d(.)\d*$/.test(value) || value > 1) return; + } else { + if (!/^\d*$/.test(value)) return; + } + + this[key] = value + // console.log(e,key) + if ('RGB'.indexOf(key) >= 0) { + [this.H, this.S, this.L] = rgbToHsl(this.R, this.G, this.B); + } + this.updatePostion() + this.paintHelper.setHue(this.H) + this.alphaCanvsSetHue(this.$refs.alpha) + } + } + } + return + }, + renderValue() { + if (this.showMode) { + let { currentMode, renderValueInput } = this, node = [] + if (currentMode == 'rgba') { + let keys = ['R', 'G', 'B', 'A'] + let v =+++ {this.title} + + ++++ {this.$slots.default} ++{keys.map(k => renderValueInput(k))}+ let k ={keys.map(k => {k})}+ node.push(v, k) + } else if (currentMode == 'hsla') { + let keys = ['H', 'S', 'L', 'A'] + let v ={keys.map(k => renderValueInput(k))}+ let k ={keys.map(k => {k})}+ node.push(v, k) + } else { //hex + let v ={renderValueInput('HEX')}+ let k =HEX+ node.push(v, k) + } + let btn = + node.push(btn) + return{node}+ } + }, + renderDefaultColor() { + let color = this.defalutColors.map(c => this.valueChange('COLOR', c)}>) + let okBtn = + return{[color, okBtn]}+ }, + renderDrop() { + let paint = this.renderPaint() + let alpha = this.renderAlpha() + let hue = this.renderHue() + // let colors = this.renderDefaultColor() + let valueNode = this.renderValue() + + const dropStyle = { + left: `${this.left}px`, + top: `${this.top}px`, + transformOrigin: this.placement == 'top' ? 'center bottom' : '' + } + return ( ++ {paint} + < span class="k-color-picker-paint-dot" style={'left:' + this.paintPointer.x + 'px;top:' + this.paintPointer.y + 'px'} > ++ ) + } + }, + + render() { + let drop; + if (this.showDropInit) { + drop = + {valueNode} + {this.renderDefaultColor()} +{this.renderDrop()} + } + let style = [ + 'k-color-picker', + { + 'k-color-picker-mini': this.mini, + 'k-color-picker-large': this.large && !this.mini + }, + ] + return (+) + } +} \ No newline at end of file diff --git a/components/colorPicker/demo/base.md b/components/colorPicker/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..97ddb61b90504b3b650fa5feafb5fee6b1a75149 --- /dev/null +++ b/components/colorPicker/demo/base.md @@ -0,0 +1,21 @@ +++ {drop} ++ +++ +#### 基本用法 +默认可以同时展开一个或者多个面板 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/colorPicker/demo/colors.md b/components/colorPicker/demo/colors.md new file mode 100755 index 0000000000000000000000000000000000000000..0fadaa913e095e7b0013e6e32f70f41db123ec48 --- /dev/null +++ b/components/colorPicker/demo/colors.md @@ -0,0 +1,22 @@ ++ +#### 自定义颜色盘 +可以定义默认的颜色盘 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/colorPicker/demo/index.vue b/components/colorPicker/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..46587052bbec6fe1bd50be305ad9ed1ca022e003 --- /dev/null +++ b/components/colorPicker/demo/index.vue @@ -0,0 +1,22 @@ + \ No newline at end of file diff --git a/components/colorPicker/demo/info.md b/components/colorPicker/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..c743b5035ef793b34483aad601194f8c030dadb1 --- /dev/null +++ b/components/colorPicker/demo/info.md @@ -0,0 +1,6 @@ +# ColorPicker 颜色选择器 +可以自由的输出颜色。 + +## 何时使用 +- 需要自定义颜色时 +## 代码演示 \ No newline at end of file diff --git a/components/colorPicker/demo/mode.md b/components/colorPicker/demo/mode.md new file mode 100755 index 0000000000000000000000000000000000000000..57d625c7be8b416e383e329ae4642d38c4c188e3 --- /dev/null +++ b/components/colorPicker/demo/mode.md @@ -0,0 +1,25 @@ ++ +#### 颜色模式 +可以切换颜色模式,使用 `show-mode` 来展示 颜色模式 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/colorPicker/demo/size.md b/components/colorPicker/demo/size.md new file mode 100755 index 0000000000000000000000000000000000000000..7030712c0664b50eed608baae7de072cb339a258 --- /dev/null +++ b/components/colorPicker/demo/size.md @@ -0,0 +1,25 @@ ++ + + +#### 尺寸大小 +`mini` 为小尺寸, `large` 为大尺寸 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/colorPicker/index.js b/components/colorPicker/index.js new file mode 100755 index 0000000000000000000000000000000000000000..93ecc5f0bd8a002892899fbaa5df74a84f27a95b --- /dev/null +++ b/components/colorPicker/index.js @@ -0,0 +1,2 @@ +import ColorPicker from './colorpicker.jsx' +export default ColorPicker \ No newline at end of file diff --git a/components/colorPicker/index.md b/components/colorPicker/index.md new file mode 100755 index 0000000000000000000000000000000000000000..eb793a4ff72e3ae9fb16cc330b3e30454707d547 --- /dev/null +++ b/components/colorPicker/index.md @@ -0,0 +1,8 @@ +### API +| 属性 | 说明 | 类型 | 默认值 | +|----------------|---------------------------------------|----------|-------| +| value | 当前激活的面板的 `name`,可以使用 `v-model` 双向绑定 | String | - | +| mode | 颜色展示类型,提供3种模式(`hex` 、 `rgba` 、`hsla`) | String | 'hex' | +| default-colors | 自定义颜色盘,最多20种 | Array | [...] | +| show-mode | 是否展示颜色模式 | Boolean | false | +| change | 颜色值改变的时候触发,返回颜色的值 | Function | - | \ No newline at end of file diff --git a/components/colorPicker/styles/index.less b/components/colorPicker/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..1e6694dd67c20577e1927a7f3261503cb2708970 --- /dev/null +++ b/components/colorPicker/styles/index.less @@ -0,0 +1,194 @@ +@import '../../styles/global.less'; +.k-color-picker { + width: 55px; + height: 30px; + border: 1px solid @border-color; + border-radius: @radius; + position: relative; + display: inline-block; + .k-color-picker-color { + height: 26px; + width: 26px; + border-radius: @radius; + margin: 2px; + overflow: hidden; + background-image: linear-gradient(-45deg, #cdcdcd 25%, transparent 0), linear-gradient(45deg, #cdcdcd 25%, transparent 0), linear-gradient(-45deg, transparent 75%, #cdcdcd 0), linear-gradient(45deg, transparent 75%, #cdcdcd 0); + background-size: 11px 11px; + background-position: 0 0, 0 -5.5px, -5.5px 5.5px, 5.5px 0; + .k-color-picker-color-inner { + height: 100%; + width: 100%; + } + } + .k-icon { + position: absolute; + right: 5px; + top: 50%; + transform: translateY(-50%); + font-size: 16px; + color: @icon-color; + } +} + +.k-color-picker-large { + width: 70px; + height: 40px; + .k-color-picker-color { + width: 35.5px; + height: 35.5px; + } + .k-icon { + font-size: 22px; + } +} + +.k-color-picker-mini { + width: 45px; + height: 25px; + .k-color-picker-color { + width: 21px; + height: 21px; + } + .k-icon { + font-size: 14px; + } +} + +.k-color-picker-dropdown { + width: 254px; + font-size: 0; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + position: relative; + border-radius: @radius; + background: #fff; + .k-color-picker-paint-dot { + width: 15px; + height: 15px; + display: block; + position: absolute; + background: #fff; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); + border-radius: 50%; + top: 10px; + left: 10px; + pointer-events: none; + } + .k-color-picker-paint { + width: 254px; + height: 136px; + } + .k-color-picker-bar { + padding: 14px 16px 0 16px; + display: inline-block; + } + .k-color-picker-avatar { + width: 36px; + height: 36px; + border-radius: 50%; + float: left; + background-image: linear-gradient(-45deg, #cdcdcd 25%, transparent 0), linear-gradient(45deg, #cdcdcd 25%, transparent 0), linear-gradient(-45deg, transparent 75%, #cdcdcd 0), linear-gradient(45deg, transparent 75%, #cdcdcd 0); + background-size: 11px 11px; + background-position: 0 0, 0 -5.5px, -5.5px 5.5px, 5.5px 0; + .k-color-picker-avatar-inner { + border-radius: 50%; + width: 100%; + height: 100%; + } + } + .k-color-picker-bar-box { + margin-left: 16px; + width: 170px; + float: right; + position: relative; + canvas { + height: 13px; + width: 170px; + border-radius: 2px; + } + .k-color-picker-alpha { + margin-top: 10px; + background-image: linear-gradient(-45deg, #cdcdcd 25%, transparent 0), linear-gradient(45deg, #cdcdcd 25%, transparent 0), linear-gradient(-45deg, transparent 75%, #cdcdcd 0), linear-gradient(45deg, transparent 75%, #cdcdcd 0); + background-size: 11px 11px; + background-position: 0 0, 0 -5.5px, -5.5px 5.5px, 5.5px 0; + } + span { + width: 15px; + height: 15px; + display: block; + position: absolute; + background: #fff; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); + border-radius: 50%; + pointer-events: none; + } + .k-color-picker-hue-dot { + top: -1px; + } + .k-color-picker-alpha-dot { + top: 22px; + } + } + .k-color-picker-mode { + position: relative; + margin-left: 16px; + margin-top: 16px; + .k-btn { + position: absolute; + z-index: 1; + right: 10px; + top: 10px; + } + .k-input { + text-align: center; + } + .k-color-picker-key { + text-align: center; + font-size: 12px; + line-height: 1; + width: 195px; + } + } + .k-color-picker-rgba, .k-color-picker-hsla { + .k-input { + width: 44px; + margin-right: 4px; + } + .k-color-picker-key { + span { + width: 44px; + display: inline-block; + margin-right: 4px; + color: #8b8b8b; + } + } + } + .k-color-picker-hex { + .k-input { + width: 188px; + } + } + .k-color-picker-val { + margin: 0 0 9px 0; + } + .k-coclor-picker-defaults { + position: relative; + box-sizing: border-box; + padding: 13px 40px 10px 16px; + margin-top: 13px; + min-height: 62px; + border-top: 1px solid @border-color; + span { + display: inline-block; + width: 13px; + height: 13px; + border-radius: 2px; + margin: 0 6px 6px 0; + cursor: pointer; + } + .k-btn { + position: absolute; + top: 14px; + right: 10px; + } + } +} \ No newline at end of file diff --git a/components/datePicker/datecalendar.jsx b/components/datePicker/datecalendar.jsx new file mode 100755 index 0000000000000000000000000000000000000000..26b52cab94681d75a4f3ac2468c31b406c1e2995 --- /dev/null +++ b/components/datePicker/datecalendar.jsx @@ -0,0 +1,504 @@ + +import Button from '../button' +import moment from 'moment' +import animate from '../_tool/animate' +export default { + name: "Calendar", + props: { + value: [String, Date, Number], + showTime: Boolean, + disabledDate: { type: Function, default: e => { } }, + disabledTime: { type: Function, default: e => { } }, + mode: { type: String, default: 'date' }, + format: { type: String, default: 'YYYY-MM-DD' }, + float: String, + }, + data() { + return { + showYears: false, + showMonths: false, + showTimes: false, + currentValue: this.value ? new Date(this.value) : '', + today: new Date(), + year: null, + month: null, + day: null, + hour: null, + minute: null, + second: null, + + monthsHead: "1.2.3.4.5.6.7.8.9.10.11.12".split("."), + months: "一.二.三.四.五.六.七.八.九.十.十一.十二".split("."), // months of panel + weeks: "一.二.三.四.五.六.日".split("."), // weeks + years: [], + + }; + }, + inject: { + DatePicker: { default: {} } + }, + watch: { + value(val) { + this.currentValue = val + this.init() + }, + showTimes(show) { + // console.log(show) + if (show) { + this.$nextTick(e => { + let d = [this.hour, this.minute, this.second].map(x => x * 24) + let kid = this.$refs.timepicker.children; + [0, 1, 2].map((e, i) => kid[i].scrollTop = d[i]) + }) + } + } + }, + computed: { + days() { + const days = []; + const year = this.year; + const month = this.month; + const time = new Date(year, month, 1); + const dow = 1 // Monday is the first day of the week + time.setDate(0); // switch to the last day of last month + let lastDay = time.getDate(); + const week = time.getDay() || 7; + let count = dow <= week ? week - dow + 1 : week + (7 - dow + 1); + while (count > 0) { + days.push({ + d: lastDay - count + 1, + y: month > 0 ? year : year - 1, + m: month > 0 ? month - 1 : 11, + p: true + }); + count--; + } + time.setMonth(time.getMonth() + 2, 0); // switch to the last day of the current month + lastDay = time.getDate(); + let i = 1; + for (i = 1; i <= lastDay; i++) { + days.push({ d: i, y: year, m: month }); + } + for (i = 1; days.length < 42; i++) { + days.push({ + d: i, + y: month < 11 ? year : year + 1, + m: month < 11 ? month + 1 : 0, + n: true + }); + } + return days; + }, + }, + methods: { + init() { + let d = new Date(this.currentValue || this.today) + + if (this.mode == 'range' && this.float == 'right') { + let value = this.DatePicker.currentValue || [] + if (new Date(value[1] - value[0]).getMonth() == 0 || !value[1]) { + let v = new Date(value[0] || this.today) + v.setMonth(v.getMonth() + 1) + d = v + } + } + this.year = d.getFullYear() + this.month = d.getMonth() + this.day = d.getDate() + this.setYears(this.year); + if (this.showTime && this.currentValue) { + this.hour = d.getHours() + this.minute = d.getMinutes() + this.second = d.getSeconds() + } + }, + setYears(year) { + const arr = []; + let start = year - 1; + while (arr.length < 12) { + arr.push(start++); + } + this.years = arr + }, + nextMonth() { + if (this.month < 11) { + this.month++; + } else { + this.month = 0; + this.year++; + this.setYears(this.year) + } + }, + prevMonth() { + if (this.month > 0) { + this.month--; + } else { + this.month = 11; + this.year--; + this.setYears(this.year) + } + }, + classes(Y, M, D, out, format) { + const time = new Date(Y, M, D), fmtTime = moment(time).format(format) + // console.log(format, fmtTime) + let istoday = fmtTime == moment(this.today).format(format), + isselected = false, + on = false; + if (this.mode == 'range') { + let values = this.DatePicker.currentValue || [], + float = this.float, + temp = this.DatePicker.temp_range_one, + temp_left = this.DatePicker.temp_range_left, + temp_right = this.DatePicker.temp_range_right, + isDay = format == 'YYYYMMDD' + + //set on + //range click selected and out + if (isDay) + isselected = fmtTime == moment(temp_left).format(format) || fmtTime == moment(temp_right).format(format) + else + isselected = fmtTime == moment(this.currentValue).format(format) + if (temp) { + // default and not out + // isselected = fmtTime == moment(this.currentValue).format(format) || isselected + // hover selected + if (!temp_left || !temp_right) { + let { y, m, d } = this.DatePicker.temp_date_hover, + date = new Date(y, m, d); + if (!out && isDay) { + isselected = isselected || (Y == y && M == m && D == d) + } + isDay && (on = (time > temp && time < date) || (time > date && time < temp)) + } + } else { + if (temp_left || temp_right) { + isDay && (on = (time > temp_left && time < temp_right) || (time > temp_right && time < temp_left)) + } else if (values.length == 2 && isDay) { + isselected = isselected || + (values[0] && fmtTime == moment(values[0]).format(format)) || + (values[1] && fmtTime == moment(values[1]).format(format)); + isDay && (on = time > new Date(values[0]) && time < new Date(values[1])) + } + } + } else { + isselected = fmtTime == moment(this.currentValue).format(format) + } + let disabled = this.disabledDate(time) + + let classes = { + 'k-calendar-date': true, + 'k-calendar-date-today': istoday, + 'k-calendar-date-on': on && !out && !disabled, + 'k-calendar-date-selected': isselected && !out, + 'k-calendar-date-disabled': disabled, + 'k-calendar-date-out': out + } + return classes + }, + setMonth(e, m) { + if (e.target.className.indexOf('k-calendar-date-disabled') >= 0) { + return + } + this.month = m + this.currentValue = new Date(this.currentValue).setMonth(m) + if (this.mode == 'month') { + this.setDate() + } else + this.showMonths = 0 + }, + setYear(e, y) { + if (e.target.className.indexOf('k-calendar-date-disabled') >= 0) { + return + } + this.year = y + if (this.years.indexOf(y) == 0) { + this.setYears(y - 10) + return; + } + if (this.years.indexOf(y) == 11) { + this.setYears(y) + return; + } + this.currentValue = new Date(this.currentValue).setYear(y) + this.showYears = 0 + if (this.mode == 'year') { + this.$emit('input', this.currentValue) + } + }, + setDay(e, j) { + if (e.target.className.indexOf('k-calendar-date-disabled') >= 0) { + return + } + let { y, m, d, p, n } = j + if (this.mode == 'range') { + // let value = this.DatePicker.currentValue || []; + let date = new Date(y, m, d, this.hour, this.minute, this.second) + let time = []; + let temp = this.DatePicker.temp_range_one + let float = this.float + + if (!temp) { + this.DatePicker.temp_range_left = date + this.DatePicker.temp_range_right = null + this.DatePicker.temp_range_one = date + // this.DatePicker.currentValue = [] + + } else { + this.DatePicker.temp_range_right = date + this.DatePicker.temp_range_one = null + if (!this.showTime) { + time = temp < date ? [temp, date] : [date, temp] + // this.DatePicker.currentValue = time + this.$emit('input', time) + } + } + if ((float == 'right' && n) || (float == 'left' && p)) { + this.$nextTick(e => { + this.currentValue = date + this.year = y; + this.month = m + this.day = d + }) + } + + } else { + this.year = y + this.month = m + this.day = d + this.currentValue = new Date(y, m, d) + if (!this.showTime) { + this.setDate() + } + } + }, + fix(v) { + return ('0' + v).slice(-2) + }, + timeClass(v, f, d = []) { + let date = new Date('', '', '', this.hour, this.minute, this.second) + let isselected = this.fix(v) == moment(date).format(f) + let classes = { + 'k-calendar-time-selected': isselected, + 'k-calendar-time-disabled': d.indexOf(v) >= 0, + } + return classes + }, + getTime(l, t) { + let { disabledHours, disabledMinutes, disabledSeconds } = this.disabledTime() || {} + let x = { HH: disabledHours, mm: disabledMinutes, ss: disabledSeconds } + let d; + if (typeof x[t] == 'function') { + d = x[t]() + } + return new Array(l).fill('').map((i, j) => ++ + + this.setTime(j, t, e)} class={this.timeClass(j, t, d)}>{this.fix(j)} ) + }, + setShowTime() { + this.showMonths = 0 + this.showYears = 0 + if (this.mode == 'range') { + this.DatePicker.temp_range_showtime = !this.DatePicker.temp_range_showtime + this.showTimes = this.DatePicker.temp_range_showtime + } else { + this.showTimes = !this.showTimes + } + }, + setShowYear() { + !this.showTimes && (this.showYears = true) + }, + setShowMonth() { + !this.showTimes && (this.showMonths = 1) + }, + setTime(v, t, e) { + if (e.target.className.indexOf('k-calendar-time-disabled') >= 0) { + return; + } + let date = new Date(); + if (this.mode == 'range') { + let values = this.DatePicker.currentValue + date = this.float == 'left' ? this.DatePicker.temp_range_left || values[0] : this.DatePicker.temp_range_right || values[1] + } + switch (t) { + case 'HH': + this.hour = v; + this.currentValue = new Date(this.currentValue).setHours(v) + date.setHours(v) + break; + case 'mm': + this.minute = v; + this.currentValue = new Date(this.currentValue).setMinutes(v) + date.setMinutes(v) + break; + case 'ss': + this.second = v; + this.currentValue = new Date(this.currentValue).setSeconds(v) + date.setSeconds(v) + break; + default: ; + } + + this.setTimeScroll() + }, + setTimeScroll() { + let d = [this.hour, this.minute, this.second].map(x => x * 24) + let kid = this.$refs.timepicker.children; + animate({ + draw: function (progress) { + [0, 1, 2].map((e, i) => kid[i].scrollTop += progress * (d[i] - kid[i].scrollTop)) + } + }) + }, + setDate() { + if (this.mode == 'range') { + let values = this.DatePicker.currentValue; + let t1 = this.DatePicker.temp_range_left || values[0], + t2 = this.DatePicker.temp_range_right || values[1]; + let date = t1 > t2 ? [t2, t1] : [t1, t2] + this.$emit('input', date) + } else { + let date = new Date(this.year, this.month, this.day, this.hour, this.minute, this.second) + this.showTimes = false + this.showMonths = false + this.showYears = false + this.currentValue = date + this.$emit('input', date) + } + }, + setToday() { + this.currentValue = new Date() + this.init() + this.setDate() + }, + nextYear() { + let y = this.year + (this.showMonths ? 1 : 10) + this.year = y + this.setYears(y) + }, + prevYear() { + let y = this.year - (this.showMonths ? 1 : 10) + this.year = y + this.setYears(y) + } + }, + mounted() { + this.init() + }, + render() { + let { classes, year, month, day, hour, minute, second, showYears, showMonths, disabledDate, + showTimes, getTime, mode, DatePicker, float, currentValue } = this + let isRange = mode == 'range', values = DatePicker.currentValue || []; + let temp_left, temp_right; + if (isRange) { + showTimes = DatePicker.temp_range_showtime + temp_left = DatePicker.temp_range_left || values[0] + temp_right = DatePicker.temp_range_right || values[1] + } + if (mode == 'month') { + this.showMonths = true + } + if (mode == 'year') { + this.showYears = true + } + let showArrow = true + // 为range 时,不可联动选择 + if (isRange) { + if (float == 'left') { + + } else if (float == 'right') { + + } + } + //header + let headNode = [] + if (!showTimes || !showArrow) + headNode.push(«) + if ((!showYears && !showMonths && !showTimes) || !showArrow) + headNode.push(‹) + headNode.push({year}年) + if (!showYears && !showMonths) { + headNode.push({month + 1}月) + if (!showTimes || !showArrow) + headNode.push( ) + else + headNode.push({day}日) + } + if (!showTimes || !showArrow) + headNode.push( ) + + //body + const bodyNode = [] + if (mode == 'date' || isRange) { + let weekNode = this.weeks.map(w => {w}) + const getDay = (j, x) => { + const props = { + domProps: { innerHTML: j.d }, + class: classes(j.y, j.m, j.d, j.p || j.n, 'YYYYMMDD'), + on: { + click: e => this.setDay(e, j), + mouseenter: e => this.DatePicker.temp_date_hover = j + }, + key: x + } + return + } + let dayNode = this.days.map((j, x) => getDay(j, x)) + const daysNode ={weekNode}{dayNode}+ bodyNode.push(daysNode) + } + if (showMonths) { + const m = this.months.map((i, j) => this.setMonth(e, j)}>{i}月) + const mouthNode ={m}+ bodyNode.push(mouthNode) + } + if (showYears) { + const y = this.years.map((i, j) => this.setYear(e, i)}>{i}) + const yearNode ={y}+ bodyNode.push(yearNode) + } + //footer + let footerNode = [] + + if (showTimes) { + let time = [] + //hours + let h = getTime(24, 'HH') + time.push(h) + //m + let m = getTime(60, 'mm') + time.push(m) + //s + let s = getTime(60, 'ss') + time.push(s) + let picker = time.map(t =>) + + let timeNode ={t}
{picker}+ + bodyNode.push(timeNode) + + } + if ((this.showTime && !isRange) || (this.showTime && isRange && float == 'right')) { + + //footer + // let disabled = moment() + let disabled = disabledDate(new Date()) + let time_disabled = isRange ? !(temp_left && temp_right) : (!currentValue); + + !isRange && footerNode.push() + footerNode.push() + footerNode.push() + } else if (mode == 'date') { + let disabled = disabledDate(new Date()) + footerNode.push() + } + footerNode = footerNode.length || (isRange && this.showTime) ? : null + + + return ( +++ ) + } +}; \ No newline at end of file diff --git a/components/datePicker/datepicker.jsx b/components/datePicker/datepicker.jsx new file mode 100755 index 0000000000000000000000000000000000000000..944ac7a6f7f8c49f2d8e96dd6a8a0797e731b962 --- /dev/null +++ b/components/datePicker/datepicker.jsx @@ -0,0 +1,279 @@ +import Calendar from './datecalendar' +import transfer from "../_tool/transfer"; +import Resize from "../_tool/resize"; +import outsideclick from "../_tool/outsiteclick"; +import Icon from "../icon"; +import { isNotEmpty, getElementPos } from '../_tool/utils' +import moment from 'moment' + +export default { + name: 'DatePicker', + directives: { transfer, Resize, outsideclick }, + props: { + value: [String, Date, Number, Array], + mode: { type: String, default: 'date' }, + showTime: Boolean, + disabled: Boolean, + transfer: { type: Boolean, default: true }, + disabledDate: { type: Function, default: e => { } }, + disabledTime: { type: Function, default: e => { } }, + format: { type: String, default: 'YYYY-MM-DD' }, + clearable: { type: Boolean, default: true }, + mini: Boolean, + large: Boolean, + placeholder: [String, Array] + }, + provide() { + return { + DatePicker: this, + } + }, + inject: { + FormItem: { default: null }, + }, + data() { + return { + showDropInit: false, + showDrop: false, + left: 0, + top: 0, + currentValue: this.value, + leftPicker: null, + rightPicker: null, + temp_date_hover: {}, //range hover date + temp_range_one: null, //range one select + temp_range_left: null, // range left value + temp_range_right: null, // range right value + temp_range_showtime: false, //range showtime + } + }, + computed: { + label() { + return this.getDate(this.currentValue) + }, + }, + watch: { + value(v) { + if (this.v != this.currentValue) { + this.currentValue = v + this.FormItem && this.FormItem.testValue(v) + } + } + }, + methods: { + getDate(value) { + let { format, mode } = this + let isDefaultFormat = format == 'YYYY-MM-DD' + if (mode == 'range') { + if (isDefaultFormat) { + if (this.showTime) { + format = 'YYYY-MM-DD HH:mm:ss' + } + } + value = value || [] + let label = [] + let v1 = value[0] || '', v2 = value[1] || '' + if (v1) label[0] = moment(v1).format(format) + if (v2) label[1] = moment(v2).format(format) + return label + } else { + if (isDefaultFormat) { + if (mode == 'month') { + format = 'YYYY-MM' + } + if (mode == 'year') { + format = 'YYYY' + } + if (this.showTime) { + format = 'YYYY-MM-DD HH:mm:ss' + } + } + return value ? moment(value).format(format) : '' + } + }, + updateValue(value) { + let date = this.getDate(value) + this.$emit('input', date) + this.$emit('change', date) + this.currentValue = date + this.showDrop = false + this.temp_date_hover = {}; + this.temp_range_one = null + this.temp_range_left = null + this.temp_range_right = null + this.temp_range_showtime = false + }, + clear(e) { + if (Array.isArray(this.currentValue)) { + this.currentValue = [] + this.temp_range_one = null + } else { + this.currentValue = '' + } + this.$emit("input", this.currentValue); + this.$emit("change", this.currentValue); + e.stopPropagation() + }, + hidedrop(e) { + if (this.showDropInit && typeof (e.target.className) === 'string') { + if (!this.$el.contains(e.target) && + !this.$refs.dom.contains(e.target) && + e.target.className.indexOf('k-calendar-date') < 0 && + e.target.className.indexOf('k-calendar-month-select') < 0 + ) { + this.showDrop = false + this.temp_date_hover = {}; + this.temp_range_one = null + this.temp_range_left = null + this.temp_range_right = null + this.temp_range_showtime = false + } + } + }, + toggleDrop() { + if (this.disabled) { + return false; + } + if (!this.showDropInit) { + this.showDropInit = true + this.$nextTick(e => this.setShowDrop()) + } else { + this.setShowDrop() + } + }, + setShowDrop() { + this.showDrop = !this.showDrop; + this.$nextTick(e => this.setPosition()) + }, + setPosition() { + let top = 0, left = 0, height = this.$el.offsetHeight, offset = 3; + // this.selectWidth = this.$el.offsetWidth + + if (this.transfer) { + let pos = getElementPos(this.$el) + top = pos.top + height + offset + left = pos.left + 1 + } else { + top = height + offset + } + if (this.$refs.dom) { + let clientH = document.body.scrollHeight + let domH = this.$refs.dom.offsetHeight + if (clientH - top - height - offset < domH + 5) { + top = this.transfer ? top - domH - offset : -(domH + 3) + this.placement = 'top' + } else { + this.placement = 'bottom' + } + } + + this.top = top + this.left = left + }, + }, + render() { + let { currentValue, placeholder, disabled, clearable, showDrop, mini, label, mode } = this + let childNode = [], isRange = mode == 'range'; + + childNode.push({headNode}+{bodyNode}+ {footerNode} +) + if (isRange) { + placeholder = placeholder || [] + if (placeholder && !Array.isArray(placeholder)) { + console.error('Please set placeholder as array !') + placeholder = [] + } + let p1 = placeholder[0] || '开始日期', p2 = placeholder[1] || '结束日期' + let v1 = label[0], v2 = label[1] + if (v1) { + childNode.push( {v1}) + } else { + childNode.push({p1}) + } + childNode.push(~) + if (v2) { + childNode.push({v2}) + } else { + childNode.push({p2}) + } + } else { + placeholder = placeholder || '请选择日期' + if (label) { + childNode.push({label}) + } else if (placeholder) { + childNode.push({placeholder}) + } + } + + let drop; + const dropStyle = { + left: `${this.left}px`, + top: `${this.top}px`, + transformOrigin: this.placement == 'top' ? 'center bottom' : '' + } + if (this.showDropInit) { + let { format, mode, disabledTime, disabledDate, showTime } = this.$props + let calendar = [] + if (isRange) { + currentValue = currentValue || [] + let v1 = currentValue[0] || '', v2 = currentValue[1] || ''; + let leftProps = { + props: { format, mode, disabledTime, disabledDate, showTime, float: 'left', value: v1 }, + on: { + input: e => this.updateValue(e) + } + } + let rightProps = { + props: { format, mode, disabledTime, disabledDate, showTime, float: 'right', value: v2 }, + on: { + input: e => this.updateValue(e) + } + }; + + calendar.push(, ) + } else { + const props = { + props: { format, mode, disabledTime, disabledDate, showTime, value: currentValue }, + on: { + input: e => { + this.$emit('input', e) + this.$emit('change', e) + this.currentValue = e + this.showDrop = false + } + } + } + calendar.push( ) + } + const dropClass = ['k-datepicker-dropdown', { 'k-datepicker-range-dropdown': isRange }] + drop = ( + + + ) + } + let showClear = !disabled && clearable && isNotEmpty(label) + showClear && childNode.push(+ {calendar} ++) + const selectCls = [ + "k-datepicker-selection", { + "k-datepicker-has-clear": showClear + } + ] + const classes = ['k-datepicker', + { 'k-datepicker-open': showDrop }, + { 'k-datepicker-range': isRange }, + { 'k-datepicker-mini': mini }, + { 'k-datepicker-large': this.large && !mini }, + { 'k-datepicker-disabled': disabled }, + ] + return ( + ++ ) + } +} \ No newline at end of file diff --git a/components/datePicker/demo/base.md b/components/datePicker/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..773e95d39684e81c08323e3ce15dd3649ce1a4e9 --- /dev/null +++ b/components/datePicker/demo/base.md @@ -0,0 +1,16 @@ ++ {childNode} ++ {drop} ++#### 基础用法 +通过 `v-model` 进行数据双向绑定 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/datePicker/demo/disabled-date.md b/components/datePicker/demo/disabled-date.md new file mode 100755 index 0000000000000000000000000000000000000000..941a20750f6b42475ae8b3b6f3853bf54a0bdaf0 --- /dev/null +++ b/components/datePicker/demo/disabled-date.md @@ -0,0 +1,36 @@ ++
++
++ +#### 不可选择日期和时间 +可用 `disabledDate` 和 `disabledTime` 分别禁止选择部分日期和时间,其中 `disabledTime` 需要和 `showTime` 一起使用。 + + +```tpl + +++ + +``` diff --git a/components/datePicker/demo/disabled.md b/components/datePicker/demo/disabled.md new file mode 100755 index 0000000000000000000000000000000000000000..2c805612a096bd980bbf2c7e029278efe3186858 --- /dev/null +++ b/components/datePicker/demo/disabled.md @@ -0,0 +1,16 @@ ++
++
++ +#### 禁用 +选择框的不可用状态。通过 `disabled` 设置 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/datePicker/demo/format.md b/components/datePicker/demo/format.md new file mode 100755 index 0000000000000000000000000000000000000000..04e079343ae04e2de3b4f397b7d45d3386b8ad8d --- /dev/null +++ b/components/datePicker/demo/format.md @@ -0,0 +1,32 @@ ++
++
++ +#### 日期格式 +使用 `format` 属性,可以自定义日期显示格式,详见 [moment.js](http://momentjs.com/)。 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/datePicker/demo/index.vue b/components/datePicker/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..f30d2b0970a7fed89fef8852ed002df13e84232a --- /dev/null +++ b/components/datePicker/demo/index.vue @@ -0,0 +1,33 @@ + + \ No newline at end of file diff --git a/components/datePicker/demo/info.md b/components/datePicker/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..9b0a856537fe4be415c8e3188d6d87bc79074642 --- /dev/null +++ b/components/datePicker/demo/info.md @@ -0,0 +1,7 @@ +# DatePicker 日期选择框 +输入或选择日期的控件。 + +## 何时使用 +当用户需要输入一个日期,可以点击标准输入框,弹出日期面板进行选择。 + +## 代码演示 \ No newline at end of file diff --git a/components/datePicker/demo/mode.md b/components/datePicker/demo/mode.md new file mode 100755 index 0000000000000000000000000000000000000000..e84f71711c3af49b6e7fe183409c5bf364e5fa8a --- /dev/null +++ b/components/datePicker/demo/mode.md @@ -0,0 +1,22 @@ ++
++
++
++ +#### 年/月/日/时间 +使用 `mode` 属性,可以自定义日期显示类型,提供 `year` `month` `date` `range`。 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/datePicker/demo/size.md b/components/datePicker/demo/size.md new file mode 100755 index 0000000000000000000000000000000000000000..f05e7729b2ea0cd7919c1f0f64d96f2fc86b2d4d --- /dev/null +++ b/components/datePicker/demo/size.md @@ -0,0 +1,39 @@ ++
++
++
++
++
++ +#### 尺寸 +通过 `mini` `large` 来设置选择框的大小呈现 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/datePicker/index.js b/components/datePicker/index.js new file mode 100755 index 0000000000000000000000000000000000000000..2cb85fc8e6ddd9cec8b69537fbef0f00e2586b89 --- /dev/null +++ b/components/datePicker/index.js @@ -0,0 +1,4 @@ +import DatePicker from './datepicker.jsx' +export default DatePicker +// import DatePicker from './datecalendar.jsx' +// export default DatePicker \ No newline at end of file diff --git a/components/datePicker/index.md b/components/datePicker/index.md new file mode 100755 index 0000000000000000000000000000000000000000..26b0bc6f0f5208f6712128d0560c08607e61bfee --- /dev/null +++ b/components/datePicker/index.md @@ -0,0 +1,15 @@ +## API +| 属性 | 说明 | 类型 | 默认值 | +|--------------|----------------------------------------------------------------------------|---------------------|------------| +| value | 默认时间值 | Date, Array, String | - | +| mode | 使用 `mode` 属性,可以自定义日期显示类型,提供 `year` `month` `date` `range`。 | String | date | +| disabled | 是否禁用组件 | Boolen | false | +| mini | 组件是否呈现小尺寸 | Boolean | false | +| large | 组件是否呈现大尺寸 | Boolean | false | +| clearable | 是否显示清除图标 | Boolean | true | +| placeholder | 提示语 | String, Array | - | +| transfer | 是否将弹层放置于 body 内,在 Tabs、带有 fixed 的 Table 列内使用时,建议添加此属性,它将不受父级样式影响,从而达到更好的效果 | Boolean | false | +| disabledDate | 不可选择的日期 | Function | - | +| disabledTime | 不可选择的时间 | Function | - | +| format | 设置日期格式,为数组时支持多格式匹配,展示以第一个为准。配置参考 [moment.js](http://momentjs.com/) | String | YYYY-MM-DD | +| change | 默认值改变之后的回调,返回当前选择的时间,字符串 | Function | - | diff --git a/components/datePicker/styles/calendar.less b/components/datePicker/styles/calendar.less new file mode 100755 index 0000000000000000000000000000000000000000..00910698df5f1dd57403d19a5db2eca5287755af --- /dev/null +++ b/components/datePicker/styles/calendar.less @@ -0,0 +1,237 @@ +@import '../../styles/global.less'; +.k-calendar { + display: inline-block; + user-select: none; + float: left; + // box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + &+.k-calendar { + // border-left: solid 1px #eaeaea; + // margin-left: 5px; + // padding-left: 5px; + // .k-calendar-time { + // border-left: solid 5px #efefef; + // box-sizing: content-box; + // } + .k-calendar-time-picker { + border-left: 1px solid @border-color; + } + } + .k-calendar-body { + width: 215px; + position: relative; + height: 215px; + } + .k-calendar-head { + line-height: 32px; + height: 32px; + text-align: center; + position: relative; + span { + color: @color; + cursor: pointer; + display: inline-block; + text-align: center; + &:hover { + color: @main; + } + } + .k-calendar-prev-month-btn, .k-calendar-next-month-btn, .k-calendar-prev-year-btn, .k-calendar-next-year-btn { + position: absolute; + color: @icon-color; + padding: 0 5px; + font-size: 16px; + } + .k-calendar-year-select, .k-calendar-month-select, .k-calendar-day-select { + font-size: 12px; + padding: 0 2px; + position: relative; + font-weight: bold; + } + .k-calendar-prev-year-btn { + left: 6px; + } + .k-calendar-prev-month-btn { + left: 24px; + } + .k-calendar-next-year-btn { + right: 6px; + } + .k-calendar-next-month-btn { + right: 24px; + } + .k-calendar-body { + position: relative; + width: 215px; + } + } + .k-calendar-days { + font-size: 0; + padding-bottom: 5px; + span { + width: 25px; + height: 25px; + line-height: 23px; + margin: 5px 0 0 5px; + font-size: 12px; + display: inline-block; + text-align: center; + box-sizing: border-box; + // + } + } + .k-calendar-years, .k-calendar-months { + width: 100%; + height: 100%; + position: absolute; + background: #fff; + left: 0; + top: 0; + font-size: 0; + text-align: center; + span { + font-size: 12px; + width: 56px; + margin: 15px 6px + } + } + .k-calendar-footer { + border-top: 1px solid @border-color; + position: relative; + z-index: 1; + padding: 5px 8px; + text-align: right; + height: 26px; + .k-calendar-btn-today { + float: left; + } + } + .k-calendar-week { + font-weight: 500; + } + .k-calendar-date { + cursor: pointer; + color: @color; + border-radius: @radius; + position: relative; + display: inline-block; + text-align: center; + overflow: hidden; + border: 1px solid transparent; + &:hover { + background: fade(@main, 15%); + } + } + .k-calendar-date-on { + background: fade(@main, 15%); + } + .k-calendar-date-out { + color: @icon-color; + background: none; + } + span.k-calendar-date-today { + border: 1px solid @main; + &:after { + content: ''; + position: absolute; + width: 5px; + height: 5px; + background: @main; + right: 1px; + top: 1px; + border-radius: 50%; + } + } + span.k-calendar-date-selected { + color: #fff; + font-weight: bold; + background: @main; + border-radius: @radius; + &.k-calendar-date-disabled { + border: 1px solid @disable-border; + box-sizing: border-box; + &::after { + background: @disable-border; + } + } + &:hover { + background: @main; + } + &::after { + background: #fff; + } + } + span.k-calendar-date-disabled { + cursor: not-allowed; + color: @disable-color; + background: @disable-back; + &.k-calendar-date-today { + border-color: @disable-border; + &::after{ + background: @disable-border; + } + } + &:hover { + background: @disable-back; + } + } + .k-calendar-time-picker { + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + background: #fff; + border-top: 1px solid @border-color; + .k-calendar-time-picker-select { + width: 33.333%; + font-size: 0; + overflow: hidden; + height: 215px; + border-right: 1px solid @border-color; + box-sizing: border-box; + float: left; + &:hover { + overflow-y: auto; + } + ul { + padding: 0; + margin: 0; + list-style: none; + width: 100%; + box-sizing: border-box; + li { + display: block; + font-size: 12px; + box-sizing: content-box; + width: 100%; + height: 24px; + margin: 0; + padding-left: 30px; + line-height: 24px; + list-style: none; + cursor: pointer; + &:hover { + background: @light ; + } + &:last-child::after { + display: block; + height: 192px; + content: ''; + } + } + } + &:last-child { + border: none; + } + li.k-calendar-time-disabled { + color: @disable-color; + cursor: not-allowed; + } + } + .k-calendar-time-selected { + color: @main; + font-weight: bold; + background: @light; + } + } +} \ No newline at end of file diff --git a/components/datePicker/styles/datepicker.less b/components/datePicker/styles/datepicker.less new file mode 100755 index 0000000000000000000000000000000000000000..37d65593423a2dddf41833dda3da9a4cc29d1496 --- /dev/null +++ b/components/datePicker/styles/datepicker.less @@ -0,0 +1,146 @@ +@import '../../styles/global.less'; +.k-datepicker { + display: inline-block; + // width: 100%; + max-width: 100%; + box-sizing: border-box; + vertical-align: middle; + color: #495060; + background: #fff; + font-size: 12px; + position: relative; + border: 1px solid @border-color; + min-height: 32px; + border-radius: @radius; + cursor: default; + user-select: none; + min-width: 175px; + transition: all .3s; + outline: none; + &:hover { + border-color: @main; + } + .k-datepicker-selection { + padding: 0 30px 0 9px; + } + .k-icon { + position: absolute; + right: 8px; + top: 50%; + transform: translateY(-50%); + color: @icon-color; + font-size: 14px; + transition: all .3s; + } + .k-datepicker-placeholder, .k-datepicker-value { + transition: all .3s; + line-height: 30px; + color: @disable-color; + box-sizing: border-box; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: 12px; + } + .k-datepicker-value { + color: @color; + } + .k-datepicker-has-clear { + .k-datepicker-clearable { + display: none; + &:hover { + color: @color; + } + } + &:hover { + .k-datepicker-clearable { + display: block; + } + .k-icon-calendar { + display: none; + } + } + } +} + +.k-datepicker-range { + min-width: 307px; + .k-datepicker-placeholder, .k-datepicker-value { + display: inline-block; + // padding: 0 9px; + vertical-align: middle; + min-width: 130px; + text-align: center; + } + .k-datepicker-separator { + display: inline-block; + vertical-align: middle; + padding: 0 5px; + } + &.k-datepicker-large { + min-width: 347px; + } +} + +.k-datepicker-range-dropdown { + width: 430px; +} + +.k-datepicker:focus, .k-datepicker-open { + border-color: @main; + box-shadow: 0 0 5px fade(@main, 75%); +} + +.k-datepicker-dropdown { + position: absolute; + z-index: 1003; + background: #fff; +} + +.k-datepicker-mini { + min-height: 25px; + .k-datepicker-placeholder, .k-datepicker-value { + line-height: 23px; + } + .k-icon { + font-size: 12px; + } + .k-datepicker-selection { + padding: 0 23px 0 9px; + } +} + +.k-datepicker-large { + min-height: 40px; + min-width: 190px; + .k-datepicker-placeholder, .k-datepicker-value { + line-height: 38px; + font-size: 14px; + } + .k-icon { + font-size: 16px; + right: 10px; + } + .k-datepicker-selection { + padding: 0 38px 0 9px; + } +} + +.k-datepicker-disabled { + border-color: @disable-border; + color: @disable-color; + cursor: not-allowed; + background: @disable-back; + &:hover { + border-color: @disable-border; + } + .k-datepicker-value { + color: @disable-color; + } +} + +.k-datepicker-dropdown { + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + border-radius: @radius; + overflow: hidden; +} \ No newline at end of file diff --git a/components/datePicker/styles/index.less b/components/datePicker/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..a3810856e2c378080d2be0dd2a51f4276e44116b --- /dev/null +++ b/components/datePicker/styles/index.less @@ -0,0 +1,2 @@ +@import './datepicker.less'; +@import './calendar.less'; \ No newline at end of file diff --git a/components/drawer/demo/base.md b/components/drawer/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..9b5ab2cc395e6b00ad481701fdc365ef1bc29fd7 --- /dev/null +++ b/components/drawer/demo/base.md @@ -0,0 +1,23 @@ + ++ ++ + +
++
++
++ +#### 基本用法 +通过 `v-model` 双向绑定 `Drawer` 是否展示 + + +```tpl + ++ ++ + +``` \ No newline at end of file diff --git a/components/drawer/demo/custom.md b/components/drawer/demo/custom.md new file mode 100755 index 0000000000000000000000000000000000000000..5112d485607e6e605acefdc1cdedb0ea146b707a --- /dev/null +++ b/components/drawer/demo/custom.md @@ -0,0 +1,29 @@ ++ +#### 自定义 +通过 `title` 来设置标题, `width` 控制宽度, 还有 `placement` 控制方向 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/drawer/demo/form.md b/components/drawer/demo/form.md new file mode 100755 index 0000000000000000000000000000000000000000..a9f0b7a5977dbabe58a0e9028e6d3132d5c20034 --- /dev/null +++ b/components/drawer/demo/form.md @@ -0,0 +1,133 @@ ++ + ++ + + + My name is chuchur. ++#### 表单模式 +内容将呈现表单模式,有页头和页尾, 可自定义页尾 + + +```tpl + ++ + ++ + +``` \ No newline at end of file diff --git a/components/drawer/demo/index.vue b/components/drawer/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..c2897283c18aa42d7099c1464b64eb50f024d212 --- /dev/null +++ b/components/drawer/demo/index.vue @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/components/drawer/demo/info.md b/components/drawer/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..556e2cb8d02ce9ee918aa6ce14fc5b967fe44dbb --- /dev/null +++ b/components/drawer/demo/info.md @@ -0,0 +1,9 @@ +# Drawer 抽屉 +屏幕边缘滑出的浮层面板。 + +## 何时使用 +- 抽屉从父窗体边缘滑入,覆盖住部分父窗体内容。用户在抽屉内操作时不必离开当前任务,操作完成后,可以平滑地回到到原任务。 +- 当需要一个附加的面板来控制父窗体内容,这个面板在需要时呼出。比如,控制界面展示样式,往界面中添加内容。 +- 当需要在当前任务流中插入临时任务,创建或预览附加内容。比如展示协议条款,创建子对象。 + +## 代码演示 \ No newline at end of file diff --git a/components/drawer/drawer.jsx b/components/drawer/drawer.jsx new file mode 100755 index 0000000000000000000000000000000000000000..784ba3b65d0d4b964de0c009f33fc8cc012fe685 --- /dev/null +++ b/components/drawer/drawer.jsx @@ -0,0 +1,104 @@ +import Button from "../button"; +import Icon from "../icon"; +import transfer from "../_tool/transfer"; +export default { + name: "Drawer", + directives: { transfer }, + props: { + value: Boolean, + title: { default: "Title", type: String }, + width: { default: 520, type: [Number, String] }, + height: { default: 256, type: [Number, String] }, + okText: { type: String, default: "确定" }, + cancelText: { type: String, default: "取消" }, + placement: { type: String, default: 'right' }, + closable: { type: Boolean, default: true }, + footer: Boolean, + maskClosable: { type: Boolean, default: true }, + }, + watch: { + value(v) { + // this.visible = v + document.body.style.overflow = v ? 'hidden' : '' + this.init = true + this.$nextTick(e => this.visible = v) + }, + }, + data() { + return { + visible: this.value, + init: false + }; + }, + methods: { + ok() { + this.$emit("ok"); + }, + onKeyUp(e) { + if (this.visible) { + if (e.keyCode == 27) this.close(); + } + }, + cancel() { + this.$emit("cancel"); + this.close(); + }, + close() { + this.visible = false; + this.$emit("input", false); + this.$emit("close"); + }, + maskToClose() { + if (this.maskClosable) { + this.close() + } + } + }, + render() { + const { title, visible, cancelText, okText, ok, + placement, cancel, $slots, + closable, close, } = this + const hasFooter = this.footer || $slots.footer + const canelBtn = + const okBtn = + const footNode = ( + hasFooter ? : null + ) + const closeNode = closable + ?+ + ++ +我是自定义内容
++ + + +++ : null + const transitionName = `k-drawer-${placement}` + + const classes = ['k-drawer', `k-drawer-${placement}`, + { 'k-drawer-open': visible }, + { 'k-drawer-has-footer': hasFooter }, + ] + let styles = {} + if (placement == 'left' || placement == 'right') styles.width = this.width + 'px' + if (placement == 'top' || placement == 'bottom') styles.height = this.height + 'px' + // const wrapCls = + return ( + this.init ? +: '' + ) + } +}; \ No newline at end of file diff --git a/components/drawer/index.js b/components/drawer/index.js new file mode 100755 index 0000000000000000000000000000000000000000..81b7e2b93e67fd7dbf32b2c6063faf04783c0fe6 --- /dev/null +++ b/components/drawer/index.js @@ -0,0 +1,2 @@ +import Drawer from './drawer' +export default Drawer; \ No newline at end of file diff --git a/components/drawer/index.md b/components/drawer/index.md new file mode 100755 index 0000000000000000000000000000000000000000..a57d38e1787d007698b813abcced696264f18e21 --- /dev/null +++ b/components/drawer/index.md @@ -0,0 +1,15 @@ +#### API +| 属性 | 说明 | 类型 | 默认值 | +|--------------|------------------------------------------------------|---------------|-------| +| title | 抽屉标题 | String | - | +| width | 抽屉宽度 `placement`为 `left` 或 `right` 时使用 | Number,String | 520 | +| height | 抽屉高度 `placement`为 `top` 或 `bottom` 时使用 | Number,String | 256 | +| placement | 抽屉显示方向,提供 `left` , `top` , `right` , `bottom` 4种展示方式 | String | right | +| footer | 是否展示页脚 | Boolean | false | +| closable | 是否显示关闭按钮 | Boolean | true | +| mas-closable | 点击蒙层是否允许关闭 | Boolean | true | +| okText | 确定按钮文字 | String | 确定 | +| cancelText | 取消按钮文字 | String | 取消 | +| ok | 点击确定的回调 | Function | - | +| cancel | 点击取消的回调 | Function | - | +| close | 抽屉关闭的回调 | Function | - | \ No newline at end of file diff --git a/components/drawer/styles/animal.less b/components/drawer/styles/animal.less new file mode 100755 index 0000000000000000000000000000000000000000..35d40adec642f9f8118718459029fe3d36c507e4 --- /dev/null +++ b/components/drawer/styles/animal.less @@ -0,0 +1,137 @@ +@keyframes fadeInRight { + from { + opacity: 0; + transform: translate3d(100%, 0, 0); + } + to { + opacity: 1; + } +} + +@keyframes fadeOutRight { + from { + opacity: 1; + } + to { + opacity: 0; + transform: translate3d(100%, 0, 0); + } +} + +@keyframes fadeInLeft { + from { + opacity: 0; + transform: translate3d(-100%, 0, 0); + } + to { + opacity: 1; + } +} + +@keyframes fadeOutLeft { + from { + opacity: 1; + } + to { + opacity: 0; + transform: translate3d(-100%, 0, 0); + } +} + +@keyframes fadeInTop { + from { + opacity: 0; + transform: translate3d(0, -100%, 0); + } + to { + opacity: 1; + } +} + +@keyframes fadeOutTop { + from { + opacity: 1; + } + to { + opacity: 0; + transform: translate3d(0, -100%, 0); + } +} + +@keyframes fadeInBottom { + from { + opacity: 0; + transform: translate3d(0, 100%, 0); + } + to { + opacity: 1; + } +} + +@keyframes fadeOutBottom { + from { + opacity: 1; + } + to { + opacity: 0; + transform: translate3d(0, 100%, 0); + } +} + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes fadeOut { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +.k-drawer-left-enter-active { + animation: fadeInLeft .2s linear; +} + +.k-drawer-left-leave-active { + animation: fadeOutLeft .2s linear; +} + +.k-drawer-right-enter-active { + animation: fadeInRight .2s linear; +} + +.k-drawer-right-leave-active { + animation: fadeOutRight .2s linear; +} + +.fade-enter-active { + animation: fadeIn .4s linear; +} + +.fade-leave-active { + animation: fadeOut .4s linear; +} + +.k-drawer-top-enter-active { + animation: fadeInTop .2s linear; +} + +.k-drawer-top-leave-active { + animation: fadeOutTop .2s linear; +} + +.k-drawer-bottom-enter-active { + animation: fadeInBottom .2s linear; +} + +.k-drawer-bottom-leave-active { + animation: fadeOutBottom .2s linear; +} \ No newline at end of file diff --git a/src/components/drawer/drawer.less b/components/drawer/styles/index.less old mode 100644 new mode 100755 similarity index 46% rename from src/components/drawer/drawer.less rename to components/drawer/styles/index.less index c4bbcbab3420d9a812801f24fb4746322fabb7ad..4b8cc47c6869c95cf516df28512c0af88d3cde21 --- a/src/components/drawer/drawer.less +++ b/components/drawer/styles/index.less @@ -1,42 +1,24 @@ @import '../../styles/global.less'; +@import './animal.less'; .k-drawer { + position: fixed; + z-index: 1002; .k-drawer-mask { position: fixed; top: 0; bottom: 0; left: 0; right: 0; - background-color: rgba(55, 55, 55, .6); + background-color: @mask-color; height: 100%; z-index: 1000; // animation: mmask .5s ease-in-out; overflow: hidden; } - .k-drawer-wrap { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1000; - overflow: hidden; - outline: 0; - -webkit-overflow-scrolling: touch; - } - .drawer { + .k-drawer-box { position: absolute; z-index: 1001; outline: 0; - top: 0; - right: 0; - bottom: 0; width: 520px; // animation: fadeIn .5s ease-in-out; - transition: transform .3s ease-in-out; - } - .k-drawer-left { - .drawer { - left: 0; - right: auto; - } } .k-drawer-content { position: relative; @@ -47,11 +29,9 @@ .k-drawer-close { position: absolute; right: 16px; - overflow: hidden; cursor: pointer; font-size: 20px; - color: #999; - // padding: 5px 0 9px; + color: @color; line-height: 43px; width: 43px; right: 0; @@ -64,41 +44,100 @@ } } .k-drawer-header { - border-bottom: 1px solid #e9eaec; - padding: 14px 16px; + border-bottom: 1px solid @border-color; + padding: 14px 35px 14px 16px; line-height: 1; font-size: 14px; - font-weight: 700; + font-weight: 600; + color: @title-color; user-select: none; .k-drawer-header-inner { - width: 90%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } } - .k-drawer-body { - padding: 16px; - font-size: 12px; - line-height: 1.5; - height: calc(100% - 43px); - overflow: auto; - } - .k-drawer-footer { - border-top: 1px solid #e9eaec; - padding: 10px 16px; - text-align: right; - display: inline-block; - width: 100%; - box-sizing: border-box; - .k-btn { - margin-left: 8px; - } - } } - .k-drawer-form { - .k-drawer-body { - height: calc(100% - 43px - 53px); + .k-drawer-body { + padding: 16px; + font-size: 12px; + line-height: 1.5; + height: calc(100% - 43px); + overflow: auto; + box-sizing: border-box; + } + .k-drawer-footer { + border-top: 1px solid @border-color; + padding: 10px 16px; + text-align: right; + display: inline-block; + width: 100%; + box-sizing: border-box; + .k-btn { + margin-left: 8px; } } +} + +.k-drawer-has-footer { + .k-drawer-body { + height: calc(100% - 43px - 53px); + } +} + +.k-drawer-open { + &.k-drawer-left, &.k-drawer-right { + width: 100%; + } + &.k-drawer-top, &.k-drawer-bottom { + height: 100%; + } +} + +.k-drawer-right { + width: 0%; + height: 100%; + right: 0; + .k-drawer-box { + top: 0; + bottom: 0; + right: 0; + } +} + +.k-drawer-left { + width: 0%; + height: 100%; + left: 0; + .k-drawer-box { + top: 0; + bottom: 0; + left: 0; + } +} + +.k-drawer-top { + width: 100%; + height: 0; + top: 0; + .k-drawer-box { + top: 0; + left: 0; + width: 100%; + height: 0; + } +} + +.k-drawer-bottom { + width: 100%; + height: 0; + bottom: 0; + right: 0; + left: 0; + .k-drawer-box { + width: 100%; + height: 0; + left: 0; + bottom: 0; + } } \ No newline at end of file diff --git a/components/dropdown/demo/base.md b/components/dropdown/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..413ca308e6110b08350f6aaa69cf40e20d1a41af --- /dev/null +++ b/components/dropdown/demo/base.md @@ -0,0 +1,33 @@ ++ + ++ ++++ {closeNode} +++{title}+ {$slots.default} ++ {footNode} ++#### 基础用法 +通过 `v-model` 进行数据双向绑定 + + +```tpl + ++ {{date}} ++ + +``` \ No newline at end of file diff --git a/docs/src/views/dropdown.vue b/components/dropdown/demo/dropdown.vue old mode 100644 new mode 100755 similarity index 100% rename from docs/src/views/dropdown.vue rename to components/dropdown/demo/dropdown.vue diff --git a/components/dropdown/demo/index.vue b/components/dropdown/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..043062e1650796af79bde51d38a82e761d4f43e1 --- /dev/null +++ b/components/dropdown/demo/index.vue @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/components/dropdown/demo/info.md b/components/dropdown/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..413ca308e6110b08350f6aaa69cf40e20d1a41af --- /dev/null +++ b/components/dropdown/demo/info.md @@ -0,0 +1,33 @@ +
++
+
+
++ +#### 基础用法 +通过 `v-model` 进行数据双向绑定 + + +```tpl + ++ {{date}} ++ + +``` \ No newline at end of file diff --git a/src/components/dropdown/dropdown.vue b/components/dropdown/dropdown.vue old mode 100644 new mode 100755 similarity index 96% rename from src/components/dropdown/dropdown.vue rename to components/dropdown/dropdown.vue index 388d0b6ce326e14a6cd097055e65af9e431dff93..133397c63d89d74177d5544b457305ea47045af1 --- a/src/components/dropdown/dropdown.vue +++ b/components/dropdown/dropdown.vue @@ -12,8 +12,8 @@ +``` \ No newline at end of file diff --git a/components/form/demo/base.md b/components/form/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..9cd4a579e755920e248223ec484fee5be5124fc5 --- /dev/null +++ b/components/form/demo/base.md @@ -0,0 +1,65 @@ +
++
+
+
++ +#### 典型表单 +包括各种表单项,比如输入框、选择器、开关、单选框、多选框等。 + + +```tpl + ++ ++ + +``` \ No newline at end of file diff --git a/components/form/demo/customvalid.md b/components/form/demo/customvalid.md new file mode 100644 index 0000000000000000000000000000000000000000..e26c7cf4cbe5200d017c8c163420d8d89ec53e8c --- /dev/null +++ b/components/form/demo/customvalid.md @@ -0,0 +1,85 @@ ++#### 自定义校验规则 +自定义验证规则来完成表单验证。 + + +```tpl + ++ ++ + +``` \ No newline at end of file diff --git a/components/form/demo/dynamicvalid.md b/components/form/demo/dynamicvalid.md new file mode 100644 index 0000000000000000000000000000000000000000..324309b0afc87e0e979271c9b30a826b3b911821 --- /dev/null +++ b/components/form/demo/dynamicvalid.md @@ -0,0 +1,78 @@ ++#### 动态校验规则 +根据不同情况执行不同的校验规则。 + + +```tpl + ++ ++ + +``` \ No newline at end of file diff --git a/components/form/demo/index.vue b/components/form/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..0bf2a9a9f3bba0a2cd7cf7478f12c635ecad81e6 --- /dev/null +++ b/components/form/demo/index.vue @@ -0,0 +1,26 @@ + \ No newline at end of file diff --git a/components/form/demo/info.md b/components/form/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..31179d55f33923c3d87711912c932278acc5e062 --- /dev/null +++ b/components/form/demo/info.md @@ -0,0 +1,8 @@ +# Form 表单 +具有数据收集、校验和提交功能的表单,包含复选框、单选框、输入框、下拉选择框等元素。 + +## 何时使用 +- 用于创建一个实体或收集信息。 +- 需要对输入的数据类型进行校验时。 + +## 代码演示 \ No newline at end of file diff --git a/components/form/demo/valid.md b/components/form/demo/valid.md new file mode 100644 index 0000000000000000000000000000000000000000..111e1d7c924197c6a8de2d4b79ca85e706d9b4ee --- /dev/null +++ b/components/form/demo/valid.md @@ -0,0 +1,190 @@ ++#### 表单验证 +在防止用户犯错的前提下,尽可能让用户更早地发现并纠正错误。 + + +```tpl + ++ ++ + +``` \ No newline at end of file diff --git a/components/form/form.jsx b/components/form/form.jsx new file mode 100644 index 0000000000000000000000000000000000000000..1975c29d1853099d150fc5ed7e4d6cc61ccb9d4d --- /dev/null +++ b/components/form/form.jsx @@ -0,0 +1,114 @@ +export default { + name: "Form", + props: { + labelAlign: { type: String, default: 'right' }, + model: { type: Object }, + // value: Object, + rules: { type: Object, default: () => { } }, + labelWidth: { type: Number, default: 80 } + }, + // model: { + // prop: 'model', + // // event: 'change' + // event: 'input' + // }, + provide() { + return { + Form: this, + collectFormItems: (context, type) => { + const items = this.FormItems + type === 'delete' ? items.splice(items.indexOf(context), 1) : items.push(context) + if (type === 'add' && context.prop && this.model) { + this.testProp(context.prop) + } + } + } + }, + created() { + this.clearing = false + this.FormItems = new Array() + }, + render() { + const classes = ["k-form", { [`k-form-label-${this.labelAlign}`]: this.labelAlign }]; + return ( + + ) + }, + methods: { + clearObject(model) { + if (!model) return; + for (let key in model) { + let value = model[key] + if (Array.isArray(value)) { + value.forEach(item => { + this.clearObject(item) + }) + } else if (typeof value === 'boolean') { + model[key] = false + } else { + model[key] = '' + } + } + }, + reset() { + // this.$refs.form.reset() + let model = this.model + this.clearing = true + + this.clearObject(model) + this.$nextTick(e => { + this.FormItems.forEach((item) => { + item.reset() + }) + this.clearing = false + }) + + }, + testProp(path) { + let keys = path.replace(/\[(\w+)\]/g, '.$1').replace(/^\./, '').split('.') + let model = this.model + let len = keys.length - 1 + if (len <= 0 && this.model[path] === undefined) { + throw new Error('请传入正确的prop值:' + path) + } + for (let i = 0; i < len; i++) { + let key = keys[i] + if (key in model) { + model = model[key] + } else { + throw new Error('请传入正确的prop值:' + path) + } + } + // return { + // model, + // key: keys[len], + // value: model[keys[len]] + // }; + }, + test(key) { + let item = this.FormItems.filter(item => item.prop == key)[0] + if (item) { + let rules = item.rules || (this.rules || {})[item.prop] + if (rules) { + return item.validate(rules) + } + } + }, + validate(callback) { + var result = true + this.FormItems.forEach((item) => { + let rules = item.rules || (this.rules || {})[item.prop] + if (rules) { + let valid = item.validate(rules) + if (!valid) result = valid + } + }) + + if (typeof callback == 'function') { + callback(result) + } + }, + } +} \ No newline at end of file diff --git a/components/form/formitem.jsx b/components/form/formitem.jsx new file mode 100644 index 0000000000000000000000000000000000000000..9c37b9bc8af712af143d02ae4f8ac692efdf7afd --- /dev/null +++ b/components/form/formitem.jsx @@ -0,0 +1,189 @@ +export default { + name: "FormItem", + props: { + label: String, + prop: String, + rules: [Array, Object] + }, + provide() { + return { + FormItem: this + } + }, + inject: { + FormItem: { default: null }, + Form: { default: () => { } }, + collectFormItems: { default: () => { } } + }, + data() { + return { + valid: true, + itemValue: null, + errorMessage: '', + }; + }, + beforeDestroy() { + this.collectFormItems(this, 'delete') + }, + created() { + //valid prop + if (this.prop) { + this.collectFormItems(this, 'add') + } + }, + + render() { + const { label, Form, prop, valid } = this + const width = Form.labelAlign != 'top' && !this.FormItem ? `${Form.labelWidth}px` : null + const rules = this.rules || (Form.rules || {})[prop] || [] + const required = rules.constructor === Object ? rules.required : rules.filter(r => r.required).length > 0 + + const classes = [ + "k-form-item", + { + "k-form-item-required": required, + "k-form-item-error": !valid + } + ] + return ( ++ {label ? : null} ++ ) + }, + methods: { + testValue(value, trigger) { + this.itemValue = value + + // 正在清理中,这时不进行验证 + if (this.Form.clearing === true) return; + if (this.prop) { + const rules = this.rules || (this.Form.rules || {})[this.prop] + rules && this.validate(rules, trigger) + } + }, + reset() { + if (this.prop) { + // if (Array.isArray(this.itemValue)) { + // // prop.model[prop.key] = [] + // this.itemValue = [] + // } else { + // // prop.model[prop.key] = '' + // this.itemValue = '' + // } + this.valid = true + } + }, + test(rule, trigger = 'change') { + let { valid, itemValue } = this + let message = rule.message + // console.log(rule,valid) + + // todo: + // if (trigger == 'blur' && rule.trigger !== trigger) { + // return; + // } + if (rule.required) { + valid = (itemValue !== null && itemValue !== undefined && itemValue !== '') || (Array.isArray(itemValue) && itemValue.length > 0) + message = message || 'This field is required' + // console.log(valid, message) + } else { + //valid custom pattern + if (rule.pattern) { + valid = rule.pattern.test(itemValue) + } + //valid type + else if (rule.type) { + switch (rule.type) { + case 'mail': + valid = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(itemValue) + message = message || 'Incorrect email format' + break; + case 'mobile': + valid = /^[1][3,4,5,6,7,8][0-9]{9}$/.test(itemValue) + message = message || 'Incorrect mobile phone number format' + break; + case 'number': + // valid = typeof itemValue === 'number' && !isNaN(itemValue) + valid = /^(-?\d+)(\.\d+)?$/.test(itemValue) + message = message || 'Incorrect number format' + // let { min, max } = rule + // if (min !== undefined && min !== null && min !== '') { + // valid = itemValue <= min + // } + break; + default: + break; + + } + // console.log(valid, prop, message) + + } + //valid custom validator + else if (typeof rule.validator === 'function') { + rule.validator(rule, itemValue, error => { + // console.log('error',error) + valid = error === undefined + if (error) { + message = error.message + } + }) + } + //valid length (min or max) + else if (rule.min !== undefined || rule.max !== undefined) { + const _type = typeof itemValue + //min + if (rule.min !== undefined) { + if (Array.isArray(itemValue)) { + valid = itemValue.length >= rule.min + } else if (_type === 'string') { + valid = itemValue.replace(/[\u0391-\uFFE5]/g, "aa").length >= rule.min + } else if (_type === 'number') { + valid = itemValue >= rule.min + } + } + + //max + if (rule.max !== undefined && valid) { + if (Array.isArray(itemValue)) { + valid = itemValue.length <= rule.max + } else if (_type === 'string') { + valid = itemValue.replace(/[\u0391-\uFFE5]/g, "aa").length <= rule.max + } else if (_type === 'number') { + valid = itemValue <= rule.max + } + } + message = message || 'Incorrect length' + + } + } + + this.errorMessage = message + + this.valid = valid + // console.log(itemValue, valid, this.prop, message) + // callback && callback(valid) + + return valid + }, + validate(rules, trigger) { + if (rules.constructor === Object) return this.test(rules, trigger) + // 有 required 排前面 + rules = rules.sort((a, b) => a.required ? -1 : 0) + for (let i = 0; i < rules.length; i++) { + + if (!this.test(rules[i], trigger)) { + // 有一条规则不通过就跳出 + break; + } + } + return this.valid + } + } +} \ No newline at end of file diff --git a/components/form/index.js b/components/form/index.js new file mode 100755 index 0000000000000000000000000000000000000000..9ebc6ff5141264c4c95fc48bd3cfec9401d2b2db --- /dev/null +++ b/components/form/index.js @@ -0,0 +1,3 @@ +import Form from './form.jsx' +import FormItem from './formitem.jsx' +export { Form, FormItem } \ No newline at end of file diff --git a/components/form/index.md b/components/form/index.md new file mode 100755 index 0000000000000000000000000000000000000000..441b62e8bfa33f88733064959d59908d9b592cd3 --- /dev/null +++ b/components/form/index.md @@ -0,0 +1,31 @@ +## Form API +| 属性 | 说明 | 类型 | 默认值 | +|---------------|---------------------------------------------------------------------------------------------|---------------|--------| +| model | 表单数据对象 | Object | - | +| rules | 表单验证规则, | Boolean | false | +| label-width | 表单域标签的宽度,所有的 FormItem 都会继承 Form 组件的 label-width 的值 | Number,String | - | +| label-align | 表单域标签的位置,可选值为 left、right、top | String | right | +| validate | 对整个表单进行校验,参数为检验完的回调,会返回一个 Boolean 表示成功与失败,暂不支持异步验证 | Function | - | +| test | 对表单单个字段进行校验的方法 | Function | - | +| reset | 对整个表单进行重置,将所有字段值重置为空并移除校验结果 | Function | - | + +## FormItem API + +| 属性 | 说明 | 类型 | 默认值 | +|-------|---------------------------------------------|--------|--------| +| prop | 对应表单域 model 里的字段,表单验证必须字段 | String | - | +| label | 标签文本 | String | - | +| rules | 表单验证规则 | Array | - | + +## rules API + +| 属性 | 说明 | 类型 | 默认值 | +|-----------|------------------------------------------------------------------------------------------------------------------------|----------|--------| +| required | 是否必填字段 | Boolean | false | +| trigger | 校验触发方式,提供 `blur`失去焦点, `change`值被改变两种方式触发 | String | blur | +| message | 校验不通过提示语 | String | - | +| validator | 自定义校验方法,可参见示例 | Function | - | +| type | 数据类型校验,提供三种校验方式 `mobile`手机, `mail`邮箱, `number`数字类型判断 | String | - | +| pattern | 自定义正则校验,比喻密码强度包含数字,字母,特殊符号可以这么写 `/(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[^a-zA-Z0-9]).{6,20}/` | String | - | +| min | 字段长度最小值校验 | String | - | +| max | 字段长度最大值校验 | String | - | \ No newline at end of file diff --git a/components/form/styles/index.less b/components/form/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..caaaae9594632b730c495dcea9c813b9a71c8a01 --- /dev/null +++ b/components/form/styles/index.less @@ -0,0 +1,101 @@ +@import '../../styles/global.less'; +.k-form { + .k-form-item { + margin-bottom: 24px; + vertical-align: top; + zoom: 1; + // margin-bottom: 5px; + &::before, &::after { + content: ''; + display: table; + clear: both; + } + .k-form-item { + margin: 0; + } + } + .k-form-item-label { + float: left; + text-align: right; + vertical-align: middle; + padding: 10px 12px 10px 0; + box-sizing: border-box; + line-height: 1; + font-size: 14px; + line-height: 1; + } + .k-form-item-content { + position: relative; + line-height: 32px; + } + .k-form-item-error-tip { + position: absolute; + top: 100%; + left: 0; + color: @danger; + line-height: 1.5; + margin: 0; + font-size: 12px; + line-height: 1.5; + } + .k-form-item-required { + .k-form-item-label { + &::before { + content: "*"; + display: inline; + margin-right: 4px; + line-height: 1; + font-family: SimSun; + font-size: 12px; + color: @danger; + } + } + } + .k-form-item-error { + .k-input, .k-textarea, .k-datepicker { + border: 1px solid @danger; + &:focus { + border: 1px solid @danger; + box-shadow: 0 0 5px fade(@danger, 75%); + } + } + .k-select { + .k-select-selection { + border: 1px solid @danger; + } + .k-select-arrow { + color: @danger; + } + } + .k-select-open .k-select-selection { + box-shadow: 0 0 5px fade(@danger, 75%); + } + .k-datepicker-open { + box-shadow: 0 0 5px fade(@danger, 75%); + } + } +} + +.k-form-label-right { + .k-form-item-label { + text-align: right + } +} + +.k-form-label-left { + .k-form-item-label { + text-align: left + } +} + +.k-form-label-top { + .k-form-item-label { + float: none; + display: inline-block; + padding: 0 0 10px; + text-align: left; + } + .k-form-item-content { + margin-left: 0; + } +} \ No newline at end of file diff --git a/components/grid/col.jsx b/components/grid/col.jsx new file mode 100755 index 0000000000000000000000000000000000000000..c2f725cc10402208b4a1785d5b5d8fcbbe261fda --- /dev/null +++ b/components/grid/col.jsx @@ -0,0 +1,43 @@ + +export default { + name: "Col", + props: { + span: Number, + offset: Number, + flex: [String, Number], + }, + inject: { + Row: { default: () => { } } + }, + methods: { + parseFlex(flex) { + if (typeof flex === 'number') { + return `${flex} ${flex} auto`; + } + if (/^\d+(\.\d+)?(px|em|rem|%)$/.test(flex)) { + return `0 0 ${flex}`; + } + return flex; + }, + }, + render() { + let { offset, span, $slots, flex } = this + const gutter = this.Row.gutter + const props = { + class: [`k-col`, { + [`k-col-${span}`]: span, + [`k-col-offset-${offset}`]: offset > 0 && offset <= 24 + }], + style: { + paddingLeft: `${gutter / 2}px`, + paddingRight: `${gutter / 2}px`, + flex: flex ? this.parseFlex(flex) : null + } + } + return ( ++ {this.$slots.default} +++ {!valid ? +{this.errorMessage}: null} ++ {$slots.default} ++ ) + } +}; \ No newline at end of file diff --git a/components/grid/demo/align.md b/components/grid/demo/align.md new file mode 100644 index 0000000000000000000000000000000000000000..086d3641253edbf45c5adb1d03538e98b5a0aee5 --- /dev/null +++ b/components/grid/demo/align.md @@ -0,0 +1,32 @@ ++#### Flex 对齐 +Flex 子元素垂直对齐。 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/grid/demo/base.md b/components/grid/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..d14e404309ced1d7da31303999ae10b4adbc47d2 --- /dev/null +++ b/components/grid/demo/base.md @@ -0,0 +1,27 @@ +Align Top
++
+col-4+col-4+col-4+col-4+Align Middle
++
+col-4+col-4+col-4+col-4+Align Bottom
++
+col-4+col-4+col-4+col-4++#### 基本用法 +`col` 必须放在 `row` 里面 + + +```tpl + +++ +``` + diff --git a/components/grid/demo/fill.md b/components/grid/demo/fill.md new file mode 100644 index 0000000000000000000000000000000000000000..fcc841f51d74b6677eaa5f5a8837fa8acee389e2 --- /dev/null +++ b/components/grid/demo/fill.md @@ -0,0 +1,26 @@ ++
+col-12 + col-12 + +
+col-8 + col-8 + col-8 + +
+col-6 + col-6 + col-6 + col-6 + +#### Flex 填充 +Col 提供 flex 属性以支持填充。 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/grid/demo/flex.md b/components/grid/demo/flex.md new file mode 100644 index 0000000000000000000000000000000000000000..f90eb8f873ac688797ef05f819a1e3cadcc5d45c --- /dev/null +++ b/components/grid/demo/flex.md @@ -0,0 +1,47 @@ +Percentage columns
++
+3/8+5/8+Fill rest
++
+100px+auto+Raw flex style
++
+1 1 128px+0 1 256px++#### Flex 布局 +Flex 布局基础。 +使用 `row-flex` 定义 `flex` 布局,其子元素根据不同的值 `start`,`center`,`end`,`space-between`,`space-around`,分别定义其在父节点里面的排版方式。 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/grid/demo/gutter.md b/components/grid/demo/gutter.md new file mode 100755 index 0000000000000000000000000000000000000000..a27b5fc04478cc89e7266e1da783e69aebf81949 --- /dev/null +++ b/components/grid/demo/gutter.md @@ -0,0 +1,25 @@ +start
++
+col-4+col-4+col-4+col-4+center
++
+col-4+col-4+col-4+col-4+end
++
+col-4+col-4+col-4+col-4+space-around
++
+col-4+col-4+col-4+col-4+space-between
++
+col-4+col-4+col-4+col-4++#### 分栏间隔 +使用 `gutter` 熟悉来设置分栏的间隔 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/grid/demo/index.vue b/components/grid/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..1e6e604f06187f99dad5739aa09f820940f97a6c --- /dev/null +++ b/components/grid/demo/index.vue @@ -0,0 +1,79 @@ + + \ No newline at end of file diff --git a/components/grid/demo/info.md b/components/grid/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..733645c92c89916bf356686374e36a5be9a442f1 --- /dev/null +++ b/components/grid/demo/info.md @@ -0,0 +1,11 @@ +### Grid 栅格 +采用了24栅格系统,将区域进行24等分,这样可以轻松应对大部分布局问题 +两个概念,行 `row` 和列 `col` ,具体使用方法如下: +- 使用 `row` 在水平方向创建一行 +- 将一组 `col` 插入在 `row` 中 +- 在每个 `col` 中,键入自己的内容 +- 通过设置 `col` 的 `span` 参数,指定跨越的范围,其范围是1到24 +- 每个 `row` 中的 `col` 总和应该为24 + +> 注意:非 template/render 模式下,需使用 k-col。 +### 代码示例 \ No newline at end of file diff --git a/components/grid/demo/offset.md b/components/grid/demo/offset.md new file mode 100755 index 0000000000000000000000000000000000000000..eb292186a76e2acf34247b525bd9dabb42a68854 --- /dev/null +++ b/components/grid/demo/offset.md @@ -0,0 +1,23 @@ ++
++ col-6+ ++ col-6+ ++ col-6+ ++ col-6+ ++#### 栅格偏移 +通过设置 `offset` 属性,将列进行左右偏移,偏移栅格数为 `offset` 的值。 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/grid/index.js b/components/grid/index.js new file mode 100755 index 0000000000000000000000000000000000000000..6c40b708829d35042df650c89752e8994b124c3f --- /dev/null +++ b/components/grid/index.js @@ -0,0 +1,4 @@ +import Row from './row.jsx'; +import Col from './col.jsx'; + +export { Row, Col }; \ No newline at end of file diff --git a/components/grid/index.md b/components/grid/index.md new file mode 100755 index 0000000000000000000000000000000000000000..96da6fcd519134863fcab1020cc0c967886f9c08 --- /dev/null +++ b/components/grid/index.md @@ -0,0 +1,13 @@ +### Row API +| 属性 | 说明 | 类型 | 默认值 | +|---------|----------------------------------------------------------------------------------|---------|--------| +| align | flex 布局下的垂直对齐方式:`top` `middle` `bottom` | string | `top` | +| justify | flex 布局下的水平排列方式:`start` `end` `center` `space-around` `space-between` | `start` | 0 | +| gutter | 栅格间距,单位 px,左右平分 | Number | 0 | +| type | 布局模式,可选 flex,现代浏览器 下有效 | string | | +### Col API +| 属性 | 说明 | 类型 | 默认值 | +|--------|----------------------------------------|---------------|--------| +| span | 栅格的占位格数,可选值为0~24的整数 | Number | - | +| offset | 栅格左侧的间隔格数,可选值为1~24的整数 | Number | - | +| flex | flex 布局填充 | Number,String | - | \ No newline at end of file diff --git a/components/grid/row.jsx b/components/grid/row.jsx new file mode 100755 index 0000000000000000000000000000000000000000..2427822421e03f2afa297cf7cd7a472e69180888 --- /dev/null +++ b/components/grid/row.jsx @@ -0,0 +1,41 @@ + +export default { + name: "Row", + props: { + gutter: Number, + type: String, + justify: { + type: String, + validator: (value) => { + return ['start', 'end', 'center', 'space-around', 'space-between'].indexOf(value) > -1 + } + }, + align: { + type: String, + validator: (value) => { + return ['top', 'middle', 'bottom'].indexOf(value) > -1 + } + } + }, + provide() { + return { + Row: this + } + }, + render() { + let { $slots, align, justify, gutter } = this + let props = { + class: ['k-row', { + 'k-row-flex': this.type == 'flex', + [`k-row-flex-${justify}`]: justify, + [`k-row-flex-${align}`]: align, + + }], + style: { + marginLeft: gutter / -2 + "px", + marginRight: gutter / -2 + "px" + } + } + return (+
+col-8 + col-8 | offset-8 + +
+col-6 + col-6 | offset-6 + col-6 + +
+col-12 offset-12 + {$slots.default}) + } +}; \ No newline at end of file diff --git a/components/grid/styles/index.less b/components/grid/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..46795f2e5b8cd362a8f453e2ace2b920237e37a0 --- /dev/null +++ b/components/grid/styles/index.less @@ -0,0 +1,77 @@ +@import '../../styles/global.less'; +.k-row { + position: relative; + margin-left: 0; + margin-right: 0; + height: auto; + zoom: 1; + display: block; + box-sizing: border-box; + &:after, &:before { + content: ""; + display: table; + box-sizing: border-box; + } + &:after { + clear: both; + visibility: hidden; + font-size: 0; + height: 0; + } +} + +@fix :~'k-col'; +@counts :24; +.makecol(@index) when(@index>0) { + .@{fix}-@{index} { + display: block; + float: left; + box-sizing: border-box; + width: percentage((@index / @counts)); + } + .@{fix}-offset-@{index} { + margin-left: percentage((@index / @counts)); + } + .makecol((@index - 1)); +} + +.makecol(@counts); +.k-row-flex { + display: flex; + flex-flow: row wrap; + &::after,&::before{ + display: none; + } +} + +.k-row-flex-top { + align-items: flex-start; +} + +.k-row-flex-middle { + align-items: center; +} + +.k-row-flex-bottom { + align-items: flex-end; +} + +.k-row-flex-start { + justify-content: flex-start; +} + +.k-row-flex-end { + justify-content: flex-end; +} + +.k-row-flex-center { + justify-content: center; +} + +.k-row-flex-space-around { + justify-content: space-around; +} + +.k-row-flex-space-between { + justify-content: space-between; +} \ No newline at end of file diff --git a/components/icon/demo/base.md b/components/icon/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..31f45dce23c1942a024c6efd3fa40ce25b961ecb --- /dev/null +++ b/components/icon/demo/base.md @@ -0,0 +1,15 @@ ++#### 基本用法 +可以通过 `type`、`size` 、`color` 属性分别设置图标的类型、大小、颜色,也可以通过设置 `spin` 属性来实现动画旋转效果。 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/docs/src/code/icon.js b/components/icon/demo/icon.js old mode 100644 new mode 100755 similarity index 97% rename from docs/src/code/icon.js rename to components/icon/demo/icon.js index b3e2b5534299bc211fbf65b5a69483b43c7227ed..6fa1473517d52d1e60d35cfeb6b8c6f9cbe07536 --- a/docs/src/code/icon.js +++ b/components/icon/demo/icon.js @@ -1,12 +1,5 @@ -let code = {} -code.base = `+ + + + - - - ` -let icons = {} - -icons.ios = [ +export const ios = [ 'ios-add', 'ios-add-circle', 'ios-add-circle-outline', @@ -326,7 +319,7 @@ icons.ios = [ 'ios-woman', ] -icons.md = [ +export const md = [ 'md-add', 'md-add-circle', 'md-add-circle-outline', @@ -646,7 +639,7 @@ icons.md = [ 'md-woman' ] -icons.logo = [ +export const logo = [ 'logo-android', 'logo-angular', 'logo-apple', @@ -710,7 +703,3 @@ icons.logo = [ 'logo-yen', 'logo-youtube', ] - -code.icons = icons - -export default code \ No newline at end of file diff --git a/components/icon/demo/index.vue b/components/icon/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..d988892eeb7089bb51c82681802977a35c19d2b0 --- /dev/null +++ b/components/icon/demo/index.vue @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/components/icon/demo/info.md b/components/icon/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..5080a19350993f359a8a6e1453859e38d9ca9d80 --- /dev/null +++ b/components/icon/demo/info.md @@ -0,0 +1,12 @@ +## Icon 图标 + +kui 的图标使用开源项目 [ionicons](http://ionicons.com/) 前版本5.0 +>3.x 版本以后不再支持`webfont` 使用 `svg`代替 + + +新版本的 图标库,在之前的基础上 增加了一些 图标: +### 代码示例 \ No newline at end of file diff --git a/docs/src/views/icon.vue b/components/icon/demo/search.vue old mode 100644 new mode 100755 similarity index 41% rename from docs/src/views/icon.vue rename to components/icon/demo/search.vue index 58432f80424135b172fa41591a1f420e303c6bec..5be9ac6d21d34c661a60f310c16f88b82c81960e --- a/docs/src/views/icon.vue +++ b/components/icon/demo/search.vue @@ -1,79 +1,25 @@
+企业类:`360`、`百度`、 `支付宝`、`微信`、`华为`、`小米`、`OPPO`、`Skyworth`、`淘宝`、`TCL`、`vivo`、`饿了么`
+社交媒体:`钉钉`、`微信`、`QQ`、`飞书`、`抖音`、`优酷`、`搜狐`、`腾讯视频`、`爱奇艺`、`新浪微博`、`网易云`、`语雀`
+码农:`vue` 、`react` 、`Gitee`、 +-+ + + }, +} + \ No newline at end of file diff --git a/components/icon/icon.jsx b/components/icon/icon.jsx new file mode 100755 index 0000000000000000000000000000000000000000..d47c3a52e639ae5ddbb7cb7f1a046ef1140020b9 --- /dev/null +++ b/components/icon/icon.jsx @@ -0,0 +1,35 @@ +import icons from 'kui-icons' + +export default { + name: "Icon", + props: { + type: String, + size: [String, Number], + color: { type: String, default: 'currentColor' }, + spin: Boolean, + }, + render() { + const { $listeners, click, type, spin, color, size } = this + const classes = ['k-icon', { 'k-load-loop': spin }]; + const styles = { + fontSize: `${size}px`, + }; + // let s = root.getElementsByTagName('glyph') + const props = { + style: styles, + class: classes, + on: { + ...$listeners, + click: e => this.$emit('click', e) + } + } + // const pathNode = icons[type].map(d => { + // if (Array.isArray(d)) + // return d.map(c=>Icon 图标
-kui 的图标使用开源项目 - ionicons,当前版本4.5.10 -
-代码示例
-- ---- - - - 可以通过 --type
, -size
-color
属性分别设置图标的类型、大小、颜色,也可以通过设置spin
属性来实现动画旋转效果。{{code.base}}-API
----
-- -属性 -说明 -类型 -默认值 -- -type -图标的名称 -String -- -- -size -图标的大小,单位是 px -String,Number -- -- -color -图标的颜色 -String -- -- -spin -图标是否选择 -Boolen -false -图标列表
+图标快速检索
+
- -) + // else + // return + // }) + const pathNode = + return () + } +}; diff --git a/src/components/icon/index.js b/components/icon/index.js old mode 100644 new mode 100755 similarity index 39% rename from src/components/icon/index.js rename to components/icon/index.js index 3d93f0a6b9392f1694d1479706dc84f9b002a8fa..28f7a16c735056b7467fa69dc35811460755c1c2 --- a/src/components/icon/index.js +++ b/components/icon/index.js @@ -1,3 +1,7 @@ -import './icon.less' import Icon from './icon' + +Icon.install = function (vue) { + vue.component(Icon.name, Icon) +} + export default Icon \ No newline at end of file diff --git a/components/icon/index.md b/components/icon/index.md new file mode 100755 index 0000000000000000000000000000000000000000..6f23d841e582ee1c821187e356444febdfc15ea5 --- /dev/null +++ b/components/icon/index.md @@ -0,0 +1,8 @@ +### API +| 属性 | 说明 | 类型 | 默认值 | +|-------|------------------------------|---------------|--------| +| type | 图标类型。遵循图标的命名规范 | String | - | +| size | 图标的大小,单位是 px | String,Number | - | +| color | 图标的颜色 | String | - | +| spin | 是否有旋转动画 | Boolen | false | + \ No newline at end of file diff --git a/components/icon/styles/index.less b/components/icon/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..ef5febf7fc080e9ab2340f0164d4c4f789ed78e8 --- /dev/null +++ b/components/icon/styles/index.less @@ -0,0 +1,31 @@ +@keyframes loadloop { + 0% { + transform: rotate(0) + } + 50% { + transform: rotate(180deg) + } + to { + transform: rotate(1turn) + } +} + +.k-load-loop { + animation: loadloop 1s linear infinite; +} + +.k-icon { + display: inline-block; + font-style: normal; + line-height: 0; + text-align: center; + text-transform: none; + vertical-align: -0.125em; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + *{ + line-height: 1; + display: inline-block; + } +} \ No newline at end of file diff --git a/docs/src/views/image-preview.vue b/components/imagePreview/demo/image-preview.vue old mode 100644 new mode 100755 similarity index 100% rename from docs/src/views/image-preview.vue rename to components/imagePreview/demo/image-preview.vue diff --git a/docs/src/code/imagepreview.js b/components/imagePreview/demo/imagepreview.js old mode 100644 new mode 100755 similarity index 100% rename from docs/src/code/imagepreview.js rename to components/imagePreview/demo/imagepreview.js diff --git a/src/components/imagePreview/imagePreview.vue b/components/imagePreview/imagePreview.vue old mode 100644 new mode 100755 similarity index 97% rename from src/components/imagePreview/imagePreview.vue rename to components/imagePreview/imagePreview.vue index 36ef030d6b7ca57e3dfdc5b7039fb6f7fca1e9ee..ae1e2bcc4ff63638c9f635477e2f6297caa0ddf8 --- a/src/components/imagePreview/imagePreview.vue +++ b/components/imagePreview/imagePreview.vue @@ -9,7 +9,7 @@ +``` \ No newline at end of file diff --git a/components/input/demo/clearable.md b/components/input/demo/clearable.md new file mode 100755 index 0000000000000000000000000000000000000000..14130cfbc0718fecb16a6f3203b8c8bcc8a12b27 --- /dev/null +++ b/components/input/demo/clearable.md @@ -0,0 +1,12 @@ + +#### 可清除 +通过设置 `clearable` 属性可控制是否显示清空按钮 + + +```tpl + ++ ++ +``` \ No newline at end of file diff --git a/components/input/demo/icon.md b/components/input/demo/icon.md new file mode 100755 index 0000000000000000000000000000000000000000..175d0f85b173a62adafee41f129a82687c8ac6eb --- /dev/null +++ b/components/input/demo/icon.md @@ -0,0 +1,57 @@ ++#### 带图标 +通过设置 `icon` 属性,可设置输入框图标,只对 `input` 有效。可以快速的实现 ,密码显示隐藏,搜索 + + +```tpl + ++ + + + + 获取验证码 + {{time}}(s) + + + + ++ + +``` \ No newline at end of file diff --git a/components/input/demo/index.vue b/components/input/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..0eb3404dcec5bffb48103d78e470df0489f49e48 --- /dev/null +++ b/components/input/demo/index.vue @@ -0,0 +1,38 @@ + + \ No newline at end of file diff --git a/components/input/demo/info.md b/components/input/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..69e3dfd435c58477c496ecbb15d1d6ddd1fa10d4 --- /dev/null +++ b/components/input/demo/info.md @@ -0,0 +1,10 @@ +# Input 输入框 + +通过鼠标或键盘输入内容,是最基础的表单域的包装。 + +## 何时使用 + +- 需要用户输入表单域内容时。 +- 提供组合型输入框,带搜索的输入框,还可以进行大小选择。 + +## 代码演示 \ No newline at end of file diff --git a/components/input/demo/size.md b/components/input/demo/size.md new file mode 100755 index 0000000000000000000000000000000000000000..3760b601887ef522a4074a27ea28193c06c5c5d2 --- /dev/null +++ b/components/input/demo/size.md @@ -0,0 +1,14 @@ ++ + + ++ + +#### 尺寸 +`large` 为大尺寸, `mini` 为小尺寸 + + +```tpl + ++ + + ++ +``` \ No newline at end of file diff --git a/components/input/demo/textarea.md b/components/input/demo/textarea.md new file mode 100755 index 0000000000000000000000000000000000000000..f64ae304c6abddf5e7b2cb7374744406782f15d5 --- /dev/null +++ b/components/input/demo/textarea.md @@ -0,0 +1,14 @@ ++#### 文本域 +通过设置 `rows` 来控制行数 + + +```tpl + ++ + + ++ +``` \ No newline at end of file diff --git a/components/input/index.js b/components/input/index.js new file mode 100755 index 0000000000000000000000000000000000000000..edca04d678e245fbc962246f671a0b5524b4ba2d --- /dev/null +++ b/components/input/index.js @@ -0,0 +1,3 @@ +import Input from './input.jsx' +import TextArea from './textarea.jsx' +export { Input, TextArea } \ No newline at end of file diff --git a/components/input/index.md b/components/input/index.md new file mode 100755 index 0000000000000000000000000000000000000000..bfd71c0c58fcbe761d29157ca852e9ba27782e6c --- /dev/null +++ b/components/input/index.md @@ -0,0 +1,14 @@ +### API +| 属性 | 说明 | 类型 | 默认值 | +|-------------|--------------------------------------------------------------|-----------------|-------| +| type | 输入框类型,可选值为 `text`、`password`、`textarea`、`url`、`email`、`date` | String | text | +| width | 组件的宽度 | String,Number | 200 | +| value | 绑定的值,可使用 `v-model` 双向绑定 | String 、 Number | - | +| mini | 是否展示小尺寸,仅在 `text` 类型下有效 | Boolean | false | +| large | 是否展示大尺寸,仅在 `text` 类型下有效 | Boolean | false | +| icon | 输入框图标,仅在 `text` 类型下有效 | String | - | +| icon-align | 输入框图标位置,可选值为 `left`、`right`,仅在 `type=text` 类型下有效 | String | right | +| placeholder | 占位文本 | String | - | +| rows | 文本域默认行数,仅在 `textarea` 类型下有效 | Number | 2 | +| number | 将用户的输入转换为 `Number` 类型 | Boolean | false | +| icon-click | `icon` 的点击事件 | Function | - | \ No newline at end of file diff --git a/components/input/input.jsx b/components/input/input.jsx new file mode 100755 index 0000000000000000000000000000000000000000..ff63958c6623fe8e3fc32fae3a29db78240e3d8a --- /dev/null +++ b/components/input/input.jsx @@ -0,0 +1,52 @@ +import BaseInput from '../base/input' +export default { + name: 'TextArea', + props: { + clearable: Boolean, + mini: Boolean, + large: Boolean, + value: [String, Number], + placeholder: String, + disabled: Boolean, + readonly: Boolean, + type: { + validator(value) { + return (["text", "password", "url", "email", "date", "search"].indexOf(value) >= 0); + }, + default: 'text' + }, + icon: String, + autofocus: Boolean, + iconAlign: String, + name: String, + number: Boolean, + maxlength: Number + }, + methods: { + focus() { + this.$nextTick(e => { + this.$refs.baseInput.$refs.input.focus() + }) + }, + blur() { + this.$nextTick(e => { + this.$refs.baseInput.$refs.input.blur() + }) + } + }, + render() { + const props = { + props: { ...this.$props }, + attrs: { ...this.$attrs }, + on: { + ...this.$listeners + }, + ref: 'baseInput' + } + return+ + {this.$slots.suffix} + + + } +} \ No newline at end of file diff --git a/components/input/styles/index.less b/components/input/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..d05acdb44c6a84aa94bcfb85b2757ac3ffab7dc8 --- /dev/null +++ b/components/input/styles/index.less @@ -0,0 +1,185 @@ +@import '../../styles/global.less'; +.k-input-wrapper { + position: relative; + display: inline-block; + width: 100%; + max-width: 100%; + .k-input-icon { + position: absolute; + top: 0; + left: 7px; + top: 50%; + transform: translateY(-50%); + font-size: 20px; + color: @icon-color; + z-index: 1; + &+.k-input { + padding-left: 32px; + } + } +} + +.k-input, .k-textarea { + box-sizing: border-box; + display: inline-block; + width: 100%; + height: 32px; + line-height: 1.5; + padding: 4px 7px; + font-size: 12px; + margin: 0; + border: 1px solid @border-color; + border-radius: @radius; + color: @color; + background-color: #fff; + background-image: none; + position: relative; + cursor: text; + transition: border .2s ease-in-out, background-color .2s ease-in-out, box-shadow .2s ease-in-out; + &:focus { + // box-shadow: 0 0 5px rgba(59, 180, 242, 0.55); + box-shadow: 0 0 5px fade(@main, 75%); + border-color: @main; + outline: none; + } + &:hover { + border-color: @main; + } + &:disabled { + cursor: not-allowed; + color: @disable-color; + background: @disable-back; + border-color: @disable-border; + &::placeholder { + color: @disable-color; + } + &:hover { + border-color: @disable-border; + } + } +} + +.k-textarea { + max-width: 100%; + height: auto; + vertical-align: bottom; + font-size: 12px; + resize: none; + outline: none; +} + +.k-input-has-suffix, .k-input-has-clear { + .k-input { + padding-right: 32px; + } +} + +.k-input-suffix { + position: absolute; + right: 12px; + top: 50%; + font-size: 12px; + transform: translateY(-50%); + line-height: 1; + cursor: pointer; + user-select: none; + // background: #fff; + &:hover { + color: @color; + } + .k-icon { + font-size: 16px; + } +} + +.k-input-clearable { + position: absolute; + right: 8px; + cursor: pointer; + z-index: 10; + top: 50%; + font-size: 15px; + transform: translateY(-50%); + color: @gray; + &:hover { + color: @color; + } +} + +input.k-input-mini { + padding: 2px 7px; + height: 25px; + line-height: 23px; +} + +.k-input-mini { + .k-input { + padding: 2px 7px; + height: 25px; + line-height: 23px; + } + .k-input-clearable { + right: 9px; + font-size: 11px; + } + .k-input-icon { + left: 5px; + font-size: 16px; + &+.k-input { + padding-left: 24px; + } + } + &.k-input-has-clear .k-input { + padding-right: 25px; + } + .k-input-suffix { + right: 5px; + .k-icon { + font-size: 12px; + } + } +} + +input.k-input-lg { + padding: 2px 7px; + height: 40px; + line-height: 38px; + font-size: 14px; +} + +.k-input-lg { + .k-input { + padding: 2px 7px; + height: 40px; + line-height: 38px; + font-size: 14px; + } + .k-input-clearable { + right: 10px; + font-size: 18px; + } + .k-input-icon { + font-size: 25px; + left: 8px; + &+.k-input { + padding-left: 40px; + } + } + &.k-input-has-clear .k-input { + padding-right: 40px; + } + .k-input-suffix { + right: 15px; + .k-icon { + font-size: 18px; + } + } +} + +::-ms-clear { + display: none; +} + +::-ms-reveal { + display: none; +} \ No newline at end of file diff --git a/components/input/textarea.jsx b/components/input/textarea.jsx new file mode 100644 index 0000000000000000000000000000000000000000..adf5355915bae26a9264815d4d0ea68ebcf73559 --- /dev/null +++ b/components/input/textarea.jsx @@ -0,0 +1,24 @@ +import BaseInput from '../base/input' +export default { + name: 'TextArea', + props: { + value: [String, Number], + placeholder: String, + disabled: Boolean, + readonly: Boolean, + autofocus: Boolean, + rows: { type: Number, default: 2 }, + name: String, + maxlength: Number + }, + render() { + const props = { + props: { ...this.$props, type: 'textarea' }, + attrs: { ...this.$attrs }, + on: { + ...this.$listeners + } + } + return+ } +} \ No newline at end of file diff --git a/components/layout/demo/base.md b/components/layout/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..eb69153aa24997156bdf519a95925c37a8fe1fd2 --- /dev/null +++ b/components/layout/demo/base.md @@ -0,0 +1,64 @@ + +#### 典型布局 +典型的页面布局。 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/layout/demo/index.vue b/components/layout/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..e5b0b2342a969a37b61a9ef08ab6b5f4fc63cf41 --- /dev/null +++ b/components/layout/demo/index.vue @@ -0,0 +1,27 @@ + diff --git a/components/layout/demo/info.md b/components/layout/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..ffccaf841f77cead56863338c43c0e41d14eb273 --- /dev/null +++ b/components/layout/demo/info.md @@ -0,0 +1,40 @@ +## Layout 布局 +协助进行页面级整体布局。 + +### 设计规则 +#### 尺寸 +一级导航项偏左靠近 logo 放置,辅助菜单偏右放置。 +- 顶部导航(大部分系统):一级导航高度 64px,二级导航 48px。 +- 顶部导航(展示类页面):一级导航高度 80px,二级导航 56px。 +- 顶部导航高度的范围计算公式为:48+8n。 +- 侧边导航宽度的范围计算公式:200+8n。 +#### 交互 +- 一级导航和末级的导航需要在可视化的层面被强调出来; +- 当前项应该在呈现上优先级最高; +- 当导航收起的时候,当前项的样式自动赋予给它的上一个层级; +- 左侧导航栏的收放交互同时支持手风琴和全展开的样式,根据业务的要求进行适当的选择。 +#### 视觉 +导航样式上需要根据信息层级合理的选择样式: + +- 大色块强调 +建议用于底色为深色系时,当前页面父级的导航项。 + +- 高亮火柴棍 +当导航栏底色为浅色系时使用,可用于当前页面对应导航项,建议尽量在导航路径的最终项使用。 + +- 字体高亮变色 +从可视化层面,字体高亮的视觉强化力度低于大色块,通常在当前项的上一级使用。 + +- 字体放大 +12px、14px 是导航的标准字号,14 号字体用在一、二级导航中。字号可以考虑导航项的等级做相应选择。 + +### 组件概述 +- `Layout`:布局容器,其下可嵌套 `Header` `Sider` `Content` `Footer` 或 `Layout` 本身,可以放在任何父容器中。 +- `Header`:顶部布局,自带默认样式,其下可嵌套任何元素,只能放在 `Layout` 中。 +- `Sider`:侧边栏,自带默认样式及基本功能,其下可嵌套任何元素,只能放在 `Layout` 中。 +- `Content`:内容部分,自带默认样式,其下可嵌套任何元素,只能放在 `Layout` 中。 +- `Footer`:底部布局,自带默认样式,其下可嵌套任何元素,只能放在 `Layout` 中。 + + ++ +Header +Content + ++ +Header ++ + +Sider +Content ++ + +Header ++ + +Content +Sider ++ +Sider ++ +Header +Content + +功能不多,他就是简单的布局。未采用 `flex`+>3.0 版本以后使用 `flex` 布局,请注意[浏览器兼容性](http://caniuse.com/#search=flex) \ No newline at end of file diff --git a/components/layout/demo/layout1.md b/components/layout/demo/layout1.md new file mode 100644 index 0000000000000000000000000000000000000000..a2316d0c4b2c0a81bc4cfc1354771e3cc1d9f19d --- /dev/null +++ b/components/layout/demo/layout1.md @@ -0,0 +1,107 @@ ++#### 顶部-侧边布局-通栏 +同样拥有顶部导航及侧边栏,区别是两边未留边距,多用于应用型的网站。 + + +```tpl + +++ + + +``` \ No newline at end of file diff --git a/components/layout/demo/layout2.md b/components/layout/demo/layout2.md new file mode 100644 index 0000000000000000000000000000000000000000..ae4c59ca9944e23d1f7abac9c4e63fefaf3e5b5c --- /dev/null +++ b/components/layout/demo/layout2.md @@ -0,0 +1,109 @@ ++ ++ + + ++ ++ + ++ ++ +Home +List +App ++ Content + ++#### 顶部-侧边布局 +拥有顶部导航及侧边栏的页面,多用于展示类网站。 + + +```tpl + +++ + + +``` \ No newline at end of file diff --git a/components/layout/demo/layout3.md b/components/layout/demo/layout3.md new file mode 100644 index 0000000000000000000000000000000000000000..dc94538989ec4d026ddbd8ffaffce8b5af179ab3 --- /dev/null +++ b/components/layout/demo/layout3.md @@ -0,0 +1,77 @@ ++ ++ + + ++ + ++ +Home +List +App ++ ++ + +Conent ++#### 上中下布局 +最基本的『上-中-下』布局。 +一般主导航放置于页面的顶端,从左自右依次为:logo、一级导航项、辅助菜单(用户、设置、通知等)。通常将内容放在固定尺寸(例如:1200px)内,整个页面排版稳定,不受用户终端显示器影响;上下级的结构符合用户上下浏览的习惯,也是较为经典的网站导航模式。页面上下切分的方式提高了主工作区域的信息展示效率,但在纵向空间上会有一些牺牲。此外,由于导航栏水平空间的限制,不适合那些一级导航项很多的信息结构。 + + +```tpl + +++ + + +``` \ No newline at end of file diff --git a/components/layout/demo/layout4.md b/components/layout/demo/layout4.md new file mode 100644 index 0000000000000000000000000000000000000000..0724167bb9a4e15c09d0a9921bc1986bc6dbdf17 --- /dev/null +++ b/components/layout/demo/layout4.md @@ -0,0 +1,74 @@ ++ ++ + + ++ + ++ +Home +List +App +Conent ++#### 固定侧边栏 +当内容较长时,使用固定侧边栏可以提供更好的体验。 + + +```tpl + +++ + + +``` \ No newline at end of file diff --git a/components/layout/demo/layout5.md b/components/layout/demo/layout5.md new file mode 100644 index 0000000000000000000000000000000000000000..1ea21a8c9a4a934f66b5a368bcb62f757e098f3d --- /dev/null +++ b/components/layout/demo/layout5.md @@ -0,0 +1,104 @@ ++ ++ + + ++ ++ +Home +List +App +我是打酱油的+ ++#### 侧边布局/折叠模式 +侧边两列式布局。页面横向空间有限时,侧边导航可收起。 +侧边导航在页面布局上采用的是左右的结构,一般主导航放置于页面的左侧固定位置,辅助菜单放置于工作区顶部。内容根据浏览器终端进行自适应,能提高横向空间的使用率,但是整个页面排版不稳定。侧边导航的模式层级扩展性强,一、二、三级导航项目可以更为顺畅且具关联性的被展示,同时侧边导航可以固定,使得用户在操作和浏览中可以快速的定位和切换当前位置,有很高的操作效率。但这类导航横向页面内容的空间会被牺牲一部份。 + + +```tpl + +++ + + +``` \ No newline at end of file diff --git a/components/layout/demo/layout6.md b/components/layout/demo/layout6.md new file mode 100644 index 0000000000000000000000000000000000000000..4890f29899d927da3f4d9f4721cd73d025f4f0d7 --- /dev/null +++ b/components/layout/demo/layout6.md @@ -0,0 +1,144 @@ ++ ++ + + + ++ + ++ +Home +List +App +我是打酱油的+ ++#### 侧边布局/收藏模式 +侧边两列式布局。页面横向空间有限时,侧边导航可收起。 +侧边导航在页面布局上采用的是左右的结构,一般主导航放置于页面的左侧固定位置,辅助菜单放置于工作区顶部。内容根据浏览器终端进行自适应,能提高横向空间的使用率,但是整个页面排版不稳定。侧边导航的模式层级扩展性强,一、二、三级导航项目可以更为顺畅且具关联性的被展示,同时侧边导航可以固定,使得用户在操作和浏览中可以快速的定位和切换当前位置,有很高的操作效率。但这类导航横向页面内容的空间会被牺牲一部份。 + + +```tpl + +++ + + +``` \ No newline at end of file diff --git a/components/layout/index.js b/components/layout/index.js new file mode 100755 index 0000000000000000000000000000000000000000..b5617b4131afac03fe9b6611e2c1099d8569c783 --- /dev/null +++ b/components/layout/index.js @@ -0,0 +1,12 @@ +import Layout from './layout.jsx' +// import Header from './header.jsx' +// import Footer from './footer.jsx' +// import Sider from './sider.jsx' +// import Content from './content.jsx' + +const Header = Layout.Header +const Footer = Layout.Footer +const Sider = Layout.Sider +const Content = Layout.Content + +export { Layout, Header, Footer, Sider, Content } \ No newline at end of file diff --git a/components/layout/index.md b/components/layout/index.md new file mode 100755 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/components/layout/layout.jsx b/components/layout/layout.jsx new file mode 100755 index 0000000000000000000000000000000000000000..7650841072e3781e8d77f575969d82d8c1b785a6 --- /dev/null +++ b/components/layout/layout.jsx @@ -0,0 +1,99 @@ +function createComponent(suffixCls, name) { + return Component => { + return { + name, + render() { + const prop = { + props: { suffixCls }, + } + return ( ++ ++ + + ++ + ++ +Home +List +App +我是打酱油的+ +{this.$slots.default} + ) + } + } + } +} +const Base = { + props: { suffixCls: String }, + render() { + const { $slots, suffixCls } = this + const prop = { + class: `k-${suffixCls}` + } + return ( +{$slots.default}+ ) + } +} + +const Content = createComponent('layout-content', 'Content')(Base) +const Header = createComponent('layout-header', 'Header')(Base) +const Footer = createComponent('layout-footer', 'Footer')(Base) + +const layoutBase = { + props: { suffixCls: String }, + data() { + return { + siders: 0 + } + }, + provide() { + return { + addSider: e => { + this.siders++ + }, + removeSider: e => { + this.siders-- + } + } + }, + computed: { + classes() { + const { suffixCls, siders } = this + return [`k-${suffixCls}`, { 'k-layout-has-sider': siders > 0 }] + } + }, + render() { + const { $slots, classes } = this + const prop = { + class: classes + } + return ( +{$slots.default}+ ) + } +} + +const Layout = createComponent('layout', 'Layout')(layoutBase) + +const siderBase = { + props: { suffixCls: String }, + inject: { + addSider: { default: e => { } }, + removeSider: { default: e => { } } + }, + mounted() { + this.addSider() + }, + beforeDestroy() { + this.removeSider() + }, + render() { + const { $slots, suffixCls } = this + const prop = { + class: `k-${suffixCls}` + } + return ( +{$slots.default}+ ) + } +} + +const Sider = createComponent('layout-sider', 'Sider')(siderBase) + +Layout.Sider = Sider +Layout.Content = Content +Layout.Header = Header +Layout.Footer = Footer + +export default Layout \ No newline at end of file diff --git a/src/components/layout/layout.less b/components/layout/styles/index.less old mode 100644 new mode 100755 similarity index 65% rename from src/components/layout/layout.less rename to components/layout/styles/index.less index 2693802c717956155444c100c3eb98dae6d93035..29f74186d33e82c52e98ff67076a093553d393db --- a/src/components/layout/layout.less +++ b/components/layout/styles/index.less @@ -1,7 +1,8 @@ .k-layout { background: #f0f2f5; - position: relative; box-sizing: border-box; + display: flex; + flex-direction: column; &::before { content: ""; display: table; @@ -18,33 +19,30 @@ height: 64px; line-height: 64px; padding: 0 50px; + background: #22303f; + box-sizing: border-box; } - .k-layout-header, - .k-layout-sider { - background: #646d82; - } - .k-layout-sider { - width: 200px; - height: 100%; - float: left; - position: absolute; - bottom: 0; + .k-layout-content { + flex: 1; overflow: hidden; - &+.k-layout-content, - &+.k-layout { - margin-left: 200px; - } } - .k-layout-content { - box-sizing: border-box; - margin-left: 0; - &+.k-layout-sider { - right: 0; - } + .k-layout-sider { + position: relative; + min-width: 0; + transition: all 0.2s; + background: #646d82; } .k-layout-footer { background: #f0f2f5; padding: 24px 50px; font-size: 14px; } +} + +.k-layout-has-sider { + flex-direction: row; + width: 100%; + .k-layout { + flex: 1; + } } \ No newline at end of file diff --git a/docs/src/code/loading.js b/components/loading/demo/loading.js old mode 100644 new mode 100755 similarity index 100% rename from docs/src/code/loading.js rename to components/loading/demo/loading.js diff --git a/docs/src/views/loading.vue b/components/loading/demo/loading.vue old mode 100644 new mode 100755 similarity index 100% rename from docs/src/views/loading.vue rename to components/loading/demo/loading.vue diff --git a/src/components/loading/index.js b/components/loading/index.js old mode 100644 new mode 100755 similarity index 99% rename from src/components/loading/index.js rename to components/loading/index.js index a86ff7f139627049a3243c8e11587f11dc33eca3..854e07dedb05c593ba4948e7aea95c68c2576379 --- a/src/components/loading/index.js +++ b/components/loading/index.js @@ -1,4 +1,3 @@ -import './loading.less' import Load from './loading.vue' import Vue from 'vue'; diff --git a/src/components/loading/loading.vue b/components/loading/loading.vue old mode 100644 new mode 100755 similarity index 97% rename from src/components/loading/loading.vue rename to components/loading/loading.vue index c455a0cb475942d859f7dccf8fc86ed9425814d1..932412f34cd733e230f9786d1c8e3f849a26d51e --- a/src/components/loading/loading.vue +++ b/components/loading/loading.vue @@ -13,7 +13,7 @@ export default { props: { type: {type:String,default:'line'}, - loadingText: { type: String }, + loadingText: String, height: { type: [String, Number], default: 2 }, color: String }, diff --git a/components/loading/styles/index.less b/components/loading/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..5d22f773720b4aa08b0cc22bd53b3b03aaa8a673 --- /dev/null +++ b/components/loading/styles/index.less @@ -0,0 +1,33 @@ +@import '../../styles/global.less'; + +.k-loading-warp{ + position: fixed; + z-index: 1001; + left: 0; + top:0; + bottom: 0; + right: 0; + background: rgba(255, 255, 255, 0.6); + .k-loading-line{ + height: 100%; + transition:width .2s ease-in-out; + background-color: @main; + } + .k-loading-line-error{ + background-color: @danger !important; + } + .k-loading-inner{ + margin: 0 auto; + position: relative; + text-align: center; + top: 50%; + margin-top: -17.5px; + } + .k-loading-animate{ + width: 35px; + height: 35px; + margin: 0 auto; + } + +} + diff --git a/components/menu/demo/accrodion.md b/components/menu/demo/accrodion.md new file mode 100644 index 0000000000000000000000000000000000000000..1f8bf7f458ec3e9bf5d7d9ca87afda4d2aee985b --- /dev/null +++ b/components/menu/demo/accrodion.md @@ -0,0 +1,62 @@ ++#### 只展开当前父级菜单 +点击菜单,收起其他展开的所有菜单,保持菜单聚焦简洁。 + + +```tpl + ++ ++ + +``` diff --git a/components/menu/demo/base.md b/components/menu/demo/base.md new file mode 100644 index 0000000000000000000000000000000000000000..d7adbaf309ae33e0f29cd02d8032eb087ab368d6 --- /dev/null +++ b/components/menu/demo/base.md @@ -0,0 +1,53 @@ ++#### 顶部导航 +水平的顶部导航菜单。 + + +```tpl + ++ ++ + +``` diff --git a/components/menu/demo/collapsed.md b/components/menu/demo/collapsed.md new file mode 100644 index 0000000000000000000000000000000000000000..313e04073c442c320c33541bee8e772d2f8f6ec8 --- /dev/null +++ b/components/menu/demo/collapsed.md @@ -0,0 +1,58 @@ ++#### 缩起内嵌菜单 +内嵌菜单可以被缩起/展开。 + + +```tpl + ++ ++ + +``` diff --git a/components/menu/demo/index.vue b/components/menu/demo/index.vue new file mode 100644 index 0000000000000000000000000000000000000000..4326bb3a439850b6da2f4acdbda877bb458788bc --- /dev/null +++ b/components/menu/demo/index.vue @@ -0,0 +1,31 @@ + diff --git a/components/menu/demo/info.md b/components/menu/demo/info.md new file mode 100644 index 0000000000000000000000000000000000000000..05ec30222280a3b181ddfcba151cf790321b2602 --- /dev/null +++ b/components/menu/demo/info.md @@ -0,0 +1,7 @@ +## Menu 导航菜单 +为页面和功能提供导航的菜单列表。 + +### 何时使用 +导航菜单是一个网站的灵魂,用户依赖导航在各个页面中进行跳转。一般分为顶部导航和侧边导航,顶部导航提供全局性的类目和功能,侧边导航提供多级结构来收纳和排列网站架构。 + +### 代码演示 \ No newline at end of file diff --git a/components/menu/demo/inline.md b/components/menu/demo/inline.md new file mode 100644 index 0000000000000000000000000000000000000000..d5a479f78e29261da04db60784e90facfc1ebb9e --- /dev/null +++ b/components/menu/demo/inline.md @@ -0,0 +1,60 @@ +
+
+ ++#### 内嵌菜单 +垂直菜单,子菜单内嵌在菜单区域。 + + +```tpl + ++ ++ + +``` diff --git a/components/menu/demo/mode.md b/components/menu/demo/mode.md new file mode 100644 index 0000000000000000000000000000000000000000..b157bd2c83f26f4ee1382650d6160f29ffd41f4d --- /dev/null +++ b/components/menu/demo/mode.md @@ -0,0 +1,63 @@ ++#### 切换菜单类型 +展示动态切换模式。 + + +```tpl + +++ + +``` diff --git a/components/menu/demo/theme.md b/components/menu/demo/theme.md new file mode 100644 index 0000000000000000000000000000000000000000..c2cd50602b16ebde940233d6e4c7a2087032d0f2 --- /dev/null +++ b/components/menu/demo/theme.md @@ -0,0 +1,58 @@ +Change Mode + Change Theme +
+
+ ++#### 主题 +内建了两套主题 `light|dark`,默认 `light`。 + + +```tpl + +++ + +``` diff --git a/components/menu/demo/vertical-affix.md b/components/menu/demo/vertical-affix.md new file mode 100644 index 0000000000000000000000000000000000000000..6bbee30aff4bb09ba6ac9c19b5cdbd25921e94b2 --- /dev/null +++ b/components/menu/demo/vertical-affix.md @@ -0,0 +1,78 @@ ++
+
+ ++#### 收藏模式 +适用于菜单单繁杂的情况,可以尝试,把重要的经常使用的功能收藏起来直接展示,方便查找和使用 + + +```tpl + ++ ++ + +``` diff --git a/components/menu/demo/vertical.md b/components/menu/demo/vertical.md new file mode 100644 index 0000000000000000000000000000000000000000..fa79f0049867990dada10246aa38e67b5c6ddf6c --- /dev/null +++ b/components/menu/demo/vertical.md @@ -0,0 +1,49 @@ ++#### 垂直菜单 +子菜单是弹出的形式。 + + +```tpl + ++ ++ + +``` diff --git a/components/menu/index.js b/components/menu/index.js new file mode 100755 index 0000000000000000000000000000000000000000..19e34ebbfdc64c8ea956d374879e495bb3ada523 --- /dev/null +++ b/components/menu/index.js @@ -0,0 +1,10 @@ +import Menu from './menu.jsx' +import MenuGroup from './menugroup.jsx' +import MenuItem from './menuitem.jsx' +import SubMenu from './submenu.jsx' +export { + Menu, + MenuGroup, + MenuItem, + SubMenu +} \ No newline at end of file diff --git a/components/menu/index.md b/components/menu/index.md new file mode 100644 index 0000000000000000000000000000000000000000..3710d35a9a798e3a66fe1ef103bdb94f1d4ac9f7 --- /dev/null +++ b/components/menu/index.md @@ -0,0 +1,39 @@ +## API + +### Menu + +| 属性 | 说明 | 类型 | 默认值 | +|------------------|------------------------------------------|---------------------------------------------------|----------| +| theme | 主题颜色 | String: light dark | light | +| openKeys | 当前展开的 SubMenu 菜单项 key 数组 | String[] | - | +| value | 当前选中的菜单项,可使用v-model绑定 | String[] | - | +| mode | 菜单类型,支持垂直、水平、和内嵌模式三种 | String: vertical vertical-right horizontal inline | vertical | +| click | 点击 MenuItem 调用此函数 | Fun({key, keyPath, item }) | - | +| openChange | SubMenu 展开/关闭的回调 | Fun(openKeys: String[]) | - | +| accordion | 是否只允许菜单展开一项 | Boolean | false | +| inline-collapsed | inline 时菜单是否收起状态 | Boolean | false | +| vertical-affixed | 菜单是否支持收藏 (vertical模式有效) | Boolean | false | + +### Menu.Item + +| 属性 | 说明 | 类型 | 默认值 | +|----------|--------------------------|---------|--------| +| icon | item的图标 | String | - | +| disabled | 是否禁用 | Boolean | false | +| affixed | 是否收藏 | Boolean | false | +| key | item 的唯一标志 | String | - | +| title | 设置收缩时展示的悬浮标题 | String | - | + +### Menu.SubMenu + +| 属性 | 说明 | 类型 | 默认值 | +|----------|-----------------|--------------|--------| +| disabled | 是否禁用 | Boolean | false | +| key | item 的唯一标志 | String | - | +| title | 子菜单项值 | String,slots | - | + +### Menu.MenuGroup + +| 属性 | 说明 | 类型 | 默认值 | +|-------|----------|--------------|--------| +| title | 分组标题 | String,slots | - | \ No newline at end of file diff --git a/components/menu/menu.jsx b/components/menu/menu.jsx new file mode 100644 index 0000000000000000000000000000000000000000..795cb8eea1eb046a1db2a53f4ff98d542fd9e30d --- /dev/null +++ b/components/menu/menu.jsx @@ -0,0 +1,69 @@ + +export default { + name: "Menu", + props: { + theme: { type: String, default: "light" }, + mode: { type: String, default: "vertical" }, + value: { type: Array, default: () => [] }, + accordion: Boolean, + inlineCollapsed: Boolean, + verticalAffixed: Boolean, + openKeys: { type: Array, default: () => [] }, + }, + inject: { + Menu: { default: null }, + SubMenu: { default: null } + }, + provide() { + return { + Menu: this + } + }, + watch: { + mode(mode) { + this.currentMode = mode + }, + inlineCollapsed(collapsed) { + // if (this.defaultOpenKeys.length) + // this.originOpenKeys = JSON.parse(JSON.stringify(this.defaultOpenKeys)) + + if (!this.originMode) this.originMode = this.currentMode + this.defaultOpenKeys = collapsed ? [] : this.originOpenKeys + clearTimeout(this.timer) + this.timer = setTimeout(() => { + this.currentMode = collapsed ? 'vertical' : this.originMode + }, 300); + } + }, + data() { + return { + selectedKeys: this.value, + defaultOpenKeys: this.openKeys, + currentMode: this.mode, + originOpenKeys: [], + originMode: null + }; + }, + render() { + const { theme, currentMode } = this + const cls = [`k-menu k-menu-${theme} k-menu-${currentMode}`, { + 'k-menu-inline-collapased': this.inlineCollapsed + }]; + return ({this.$slots.default}
) + }, + methods: { + openChange(openKeys) { + this.defaultOpenKeys = openKeys + this.$emit('open-change', openKeys) + }, + handleClick(options) { + let parent = this.SubMenu || this.Menu + if (parent) { + parent.handleClick(options) + } else { + this.selectedKeys = options.keyPath + this.$emit('click', options) + } + } + }, +}; \ No newline at end of file diff --git a/components/menu/menugroup.jsx b/components/menu/menugroup.jsx new file mode 100644 index 0000000000000000000000000000000000000000..88d1bf7bd38eeef9f9fae451288bfc0b219003cb --- /dev/null +++ b/components/menu/menugroup.jsx @@ -0,0 +1,19 @@ + +export default { + name: "MenuGroup", + props: { + title: { type: String, required: true } + }, + render() { + return ( ++ + ) + }, + methods: { + }, +}; diff --git a/components/menu/menuitem.jsx b/components/menu/menuitem.jsx new file mode 100644 index 0000000000000000000000000000000000000000..91d851865cede3485fad32935228727709f608b8 --- /dev/null +++ b/components/menu/menuitem.jsx @@ -0,0 +1,92 @@ +import Icon from "../icon"; +import { getParent } from './utils.js' +import Tooltip from '../tooltip' +// import PopBase from '../base/pop' +export default { + name: "MenuItem", + props: { + icon: String, + disabled: Boolean, + affixed: Boolean + }, + inject: { + Menu: { default: null }, + SubMenu: { default: null }, + collectAffixItem: { default: () => { } } + }, + data() { + return { + active: false, + selected: false, + currentAffixed: this.affixed, + }; + }, + created() { + if (this.affixed) { + this.collectAffixItem(this, 'add') + } + }, + methods: { + starClick(e) { + e.stopPropagation(); + this.collectAffixItem(this, this.currentAffixed ? 'delete' : 'add') + this.currentAffixed = !this.currentAffixed + } + }, + render() { + + const { icon, disabled, Menu, SubMenu } = this + let selected, root = {} + if (Menu) { + root = getParent(Menu, 'Menu') + // console.log(root.mode, root.selectedKeys, 'item') + selected = root.selectedKeys.indexOf(this.$vnode.key) >= 0 + this.selected = selected + } + const item = this + const props = { + class: ["k-menu-item", { + ["k-menu-item-active"]: this.active, + ["k-menu-item-selected"]: selected, + ["k-menu-item-disabled"]: disabled + }], + on: { + mouseenter: () => { + if (disabled) return; + this.active = true + }, + mouseleave: () => { + this.active = false + }, + click: (e) => { + if (!disabled) { + this.selected = true + let key = this.$vnode.key + + let options = { + key, + keyPath: [key], + item, + event: e + } + let parent = SubMenu || Menu + if (parent) { + parent.handleClick(options) + } + } + }, + } + } + const showTooltip = this.$parent == root && root.inlineCollapsed + return ( + + ++ + ) + }, +}; \ No newline at end of file diff --git a/components/menu/styles/index.less b/components/menu/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..74f308223d0b6e6c52d36c12a069e51be7b413e0 --- /dev/null +++ b/components/menu/styles/index.less @@ -0,0 +1,523 @@ +@import '../../styles/global.less'; +.k-menu { + display: block; + margin: 0; + padding: 0; + outline: 0; + font-size: 14px; + position: relative; + zoom: 1; + background: #fff; + list-style: none; + transition: background .3s cubic-bezier(.645, .045, .355, 1), width .3s cubic-bezier(.645, .045, .355, 1); + ol, ul { + list-style: none !important; + } + &:after, &:before { + content: ""; + display: table; + } + .k-menu-item-icon, .k-menu-submenu-inner .k-icon { + margin-right: 8px; + // vertical-align: middle; + } + &-submenu-arrow { + transition: all .3s; + // position: absolute; + // right: 16px; + margin-left: 6px; + width: 14px; + height: 14px; + text-indent: 0; + } + .k-icon { + &+span { + opacity: 1; + transition: opacity .3s cubic-bezier(.645, .045, .355, 1), width .3s cubic-bezier(.645, .045, .355, 1); + } + } + &-item, .k-menu-submenu-title { + cursor: pointer; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + position: relative; + transition: font-size .3s cubic-bezier(.215, .61, .355, 1), padding .3s cubic-bezier(.215, .61, .355, 1); + // transition: all .3s cubic-bezier(.215, .61, .355, 1); + } + .k-menu-submenu-affix { + padding-left: 16px; + line-height: 1; + .k-menu-submenu-affix-item { + width: 50%; + display: inline-block; + line-height: 1; + height: auto; + margin: 6px 0; + cursor: default; + .k-menu-submenu-affix-item-text { + font-size: 12px; + box-sizing: border-box; + padding: 3px 5px; + display: inline-block; + max-width: 100%; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + border-radius: 2px; + cursor: pointer; + } + } + .k-menu-submenu-affix-item-active { + .k-menu-submenu-affix-item-text { + border: 1px solid @main; + color: @main; + } + } + } + &-inline { + border-right: 1px solid @border-color; + width: 100%; + .k-menu-item, .k-menu-submenu { + line-height: 40px; + font-size: 14px; + list-style: none; + } + .k-menu { + border: 0; + list-style: none; + margin: 0; + padding: 0; + } + .k-menu-item { + padding: 0 24px; + width: calc(100% + 1px); + box-sizing: border-box; + position: relative; + &::after { + content: ''; + position: absolute; + width: 0; + height: 0; + top: 50%; + right: 0; + transition: all .3s cubic-bezier(.215, .61, .355, 1); + } + } + .k-menu-submenu { + .k-menu-item { + padding: 0 24px 0 48px; + } + .k-menu-submenu { + //doto: + text-indent: 12px; + } + } + .k-menu-submenu-title { + padding: 0 36px 0 24px; + position: relative; + .k-menu-submenu-arrow { + position: absolute; + right: 16px; + top: 50%; + transform: translateY(-50%); + } + } + .k-menu-item-group-title { + padding: 0 16px 0 32px; + } + .k-menu-item-group-list { + margin: 0; + } + .k-menu-popup { + transition: all 0.3s cubic-bezier(.215, .61, .355, 1); + } + >.k-menu-submenu-opened>.k-menu-submenu-title>.k-menu-submenu-arrow { + transform: rotate(-180deg) translateY(50%); + } + } + &-vertical { + border-right: 1px solid @border-color; + width: 100%; + .k-menu-submenu-inner { + white-space: nowrap; + } + >.k-menu-item, >.k-menu-submenu { + line-height: 40px; + position: relative; + cursor: pointer; + font-size: 14px; + z-index: 3; + list-style: none; + } + .k-menu-item, .k-menu-submenu-title { + padding: 0 34px 0 16px; + line-height: 40px; + } + .k-menu-item-icon-affix { + position: absolute; + right: 10px; + width: 20px; + height: 20px; + top: 50%; + transform: translateY(-50%); + font-size: 16px; + color: @color + } + .k-menu-popup { + position: absolute; + top: 0; + box-sizing: content-box; + position: absolute; + z-index: 1001; + min-width: 160px; + box-shadow: 0 1px 6px rgba(0, 0, 0, .2); + border-radius: @radius; + margin-left: 5px; + >.k-menu { + border-radius: @radius; + border: none; + margin: 0; + list-style: none; + .k-menu-item-group-title { + line-height: 32px; + padding: 0 12px; + } + .k-menu-item-group-list .k-menu-item { + position: relative; + } + .k-menu-item { + line-height: 40px; + &:first-child { + border-top-left-radius: @radius; + border-top-right-radius: @radius; + } + &:last-child { + border-bottom-left-radius: @radius; + border-bottom-right-radius: @radius; + } + } + } + .k-menu-submenu { + position: relative; + } + } + >.k-menu-submenu>.k-menu-submenu-title>.k-menu-submenu-arrow { + position: absolute; + right: 16px; + top: 50%; + transform: translateY(-50%); + } + } + &-horizontal { + border-bottom: 1px solid @border-color; + white-space: nowrap; + font-size: 0; + line-height: 40px; + >.k-menu-item, >.k-menu-submenu { + // line-height: 40px; + padding: 0 16px; + position: relative; + cursor: pointer; + font-size: 14px; + z-index: 3; + display: inline-block; + list-style: none; + } + >.k-menu-item, >.k-menu-submenu { + top: 1px; + vertical-align: bottom; + border-bottom: 2px solid transparent; + } + .k-menu-popup { + position: absolute; + left: 0; + margin-top: 5px; + box-sizing: content-box; + position: absolute; + z-index: 1001; + // width: 100%; + min-width: 160px; + box-shadow: 0 1px 6px rgba(0, 0, 0, .2); + border-radius: @radius; + .k-menu-item-group-list{ + margin: 0; + } + .k-menu { + border-radius: @radius; + margin: 0; + >.k-menu-item { + line-height: 40px; + &:first-child { + border-top-left-radius: @radius; + border-top-right-radius: @radius; + } + &:last-child { + border-bottom-left-radius: @radius; + border-bottom-right-radius: @radius; + } + } + .k-menu-item-group { + line-height: 40px; + &:last-child { + .k-menu-item { + &:last-child { + border-bottom-left-radius: @radius; + border-bottom-right-radius: @radius; + } + } + } + } + } + } + .k-menu-submenu { + .k-menu-item, .k-menu-submenu { + display: block; + } + .k-menu-submenu { + position: relative; + .k-menu-submenu-arrow { + transform: rotate(-90deg) translateX(50%); + top: 50%; + position: absolute; + right: 16px; + } + .k-menu-popup { + top: 0; + // transform: translateX(100%); + margin-left: 5px; + } + } + } + >.k-menu-submenu>.k-menu-submenu-title>.k-menu-submenu-arrow { + // top: 50%; + // transform: translateY(-50%); + } + >.k-menu-submenu-active>.k-menu-submenu-title>.k-menu-submenu-arrow { + transform: rotate(-180deg); + } + .k-menu-item-group-title { + font-size: 12px; + line-height: 35px; + padding: 0 12px; + } + } + &-light { + .k-menu-item-group-title { + font-size: 12px; + color: @icon-color; + } + .k-menu-item-active, .k-menu-item-selected { + color: @main; + a { + color: @main; + } + } + >.k-menu-submenu-selected, >.k-menu-submenu-active { + >.k-menu-submenu-title { + color: @main; + } + } + &.k-menu-horizontal { + >.k-menu-item-selected, >.k-menu-submenu-selected, >.k-menu-item-active, >.k-menu-submenu-active { + border-bottom-color: @main; + } + .k-menu-submenu { + .k-menu-item-selected { + background-color: tint(@main, 90); + } + } + } + &.k-menu-inline { + .k-menu-item-selected { + background-color: tint(@main, 90); + &::after { + top: 0; + height: 100%; + border-right: 3px solid @main; + } + } + } + &.k-menu-vertical { + .k-menu-item-selected { + background-color: tint(@main, 90); + } + } + >.k-menu-item>a { + color: @color; + display: block; + &:hover { + color: @main; + } + } + .k-menu-item-disabled, .k-menu-submenu-disabled { + color: @disable-color; + cursor: not-allowed; + } + } + &-dark { + background-color: @dark-back; + color: @color-light; + .k-menu-item-group-title { + font-size: 12px; + color: @color-light; + } + .k-menu-item-active, .k-menu-submenu-active .k-menu-submenu-title{ + color: #fff; + } + .k-menu-submenu-selected { + color: #fff; + a { + color: #fff; + } + } + .k-menu-item-selected { + // color: #fff; + background-color: @main; + a { + color: #fff; + } + } + &.k-menu-inline { + border-right: 0; + .k-menu-item, .k-menu-submenu { + width: 100%; + } + } + .k-menu-inline { + background-color: #161f29; + } + &.k-menu-vertical { + border-right: 0; + .k-menu-item-icon-affix { + color: #fff; + } + .k-menu-submenu-affix-item-active { + .k-menu-submenu-affix-item-text { + background-color: #fff; + color: #333; + border: none; + } + } + } + &.k-menu-horizontal { + border-bottom: 0; + .k-menu-item, .k-menu-submenu { + top: 0; + margin-top: 0; + border-color: @dark-back; + border-bottom: 0; + } + } + .k-menu-submenu-opened { + // color: #fff; + } + >.k-menu-item>a { + color: @color-light; + display: block; + &:hover { + color: #fff; + } + } + .k-menu-item-disabled, .k-menu-submenu-disabled { + color: @disable-light-color; + cursor: not-allowed; + } + } + &-inline-collapased { + width: 80px; + >.k-menu-submenu { + padding: 0; + } + >.k-menu-item, >.k-menu-submenu >.k-menu-submenu-title { + padding: 0 32px; + text-overflow: clip; + overflow: hidden; + .k-icon { + font-size: 16px; + } + } + &>.k-menu-submenu>.k-menu-submenu-title>.k-menu-submenu-arrow { + display: none; + } + .k-icon { + &+span { + max-width: 0; + opacity: 0; + display: inline-block; + } + } + } +} + +.k-collaplse-slide-enter-active { + animation: slideIn 0.15s ease-in-out; + animation-fill-mode: both; +} + +.k-collaplse-slide-leave-active { + animation: slideOut 0.3s ease-in-out; + animation-fill-mode: both; +} + +@keyframes slideIn { + 0% { + transform: scaleY(0); + transform-origin: 0% 0%; + opacity: 0; + } + 100% { + transform: scaleY(1); + transform-origin: 0% 0%; + opacity: 1; + } +} + +@keyframes slideOut { + 0% { + transform: scaleY(1); + transform-origin: 0% 0%; + opacity: 1; + } + 100% { + transform: scaleY(0); + transform-origin: 0% 0%; + opacity: 0; + } +} + +.k-menu-submenu-fade-enter-active { + animation: k-menu-zoom-in 0.2s cubic-bezier(.215, .61, .355, 1); + animation-fill-mode: both; +} + +.k-menu-submenu-fade-leave-active { + animation: k-menu-zoom-out 0.2s cubic-bezier(.215, .61, .355, 1); + animation-fill-mode: both; +} + +@keyframes k-menu-zoom-in { + 0% { + transform: scale(.8); + transform-origin: top left; + opacity: 0; + } + 100% { + transform: scale(1); + transform-origin: top left; + opacity: 1; + } +} + +@keyframes k-menu-zoom-out { + 0% { + transform: scale(1); + transform-origin: top left; + opacity: 1; + } + 100% { + transform: scale(.8); + transform-origin: top left; + opacity: 0; + } +} \ No newline at end of file diff --git a/components/menu/submenu.jsx b/components/menu/submenu.jsx new file mode 100644 index 0000000000000000000000000000000000000000..0a5748254bbc265bbbf94b110a5b4f52130da6fa --- /dev/null +++ b/components/menu/submenu.jsx @@ -0,0 +1,208 @@ +import Collapse from '../_tool/collapse' +import Menu from './menu.jsx' +import { getParent } from './utils.js' +import Icon from '../icon' +const animateNames = { + horizontal: 'dropdown', + inline: 'k-collaplse-slide', + vertical: 'k-menu-submenu-fade' +} + +export default { + name: "SubMenu", + props: { + disabled: Boolean + }, + provide() { + return { + SubMenu: this, + collectAffixItem: (context, type) => { + const childs = this.affixChilds + type === 'delete' ? childs.splice(childs.indexOf(context), 1) : childs.push(context) + } + } + }, + inject: { + Menu: { default: null }, + SubMenu: { default: null }, + }, + data() { + return { + active: false, + opened: false, + left: null, + minWidth: null, + currentMode: null, + affixChilds: [] + }; + }, + render() { + const { $slots, disabled } = this + + let selected, root = getParent(this.Menu, 'Menu'), opened = this.opened; + const { currentMode, theme, selectedKeys } = root + if (selectedKeys) { + // console.log(this.Menu.selectedKeys, 'submenu') + selected = selectedKeys.indexOf(this.$vnode.key) >= 0 + } + if (currentMode == 'inline') { + opened = root.defaultOpenKeys.indexOf(this.$vnode.key) >= 0 + } + // opened = true + let mode = currentMode + if (currentMode == 'horizontal') { + this.currentMode = 'vertical' + // this.left = null + } else { + this.currentMode = mode + } + const props = { + class: [ + "k-menu-submenu", + { + ["k-menu-submenu-active"]: this.active, + ["k-menu-submenu-selected"]: selected, + ["k-menu-submenu-opened"]: opened, + ["k-menu-submenu-disabled"]: disabled + } + ], + on: { + mouseenter: () => { + this.showPopupMenu(currentMode) + }, + mouseleave: () => this.hidePopupMenu(currentMode) + } + } + let groupProps = { + class: "k-menu-submenu-title", + on: { + mouseenter: () => { this.showPopupMenu(currentMode) }, + click: e => this.openChange() + } + } + // console.log(subProps) + let aniName = currentMode == 'horizontal' && !this.SubMenu ? 'dropdown' : animateNames[this.currentMode] + const hasRenderAffix = this.$parent == root && root.mode == 'vertical' && root.verticalAffixed + return ( ++ {icon ? + {showTooltip ? {this.$slots.default} : null} +: null} + {this.$slots.default} + {root.mode == 'vertical' && root.verticalAffixed && SubMenu ? : null} + + + ) + }, + methods: { + hidePopupMenu(currentMode) { + this.active = false + if (currentMode == 'inline') return; + clearTimeout(this.timer) + this.timer = setTimeout(() => { + this.opened = false + }, 300); + }, + showPopupMenu(currentMode) { + if (this.disabled) return; + this.active = true + if (currentMode == 'inline') return; + let width = this.$el.offsetWidth + this.minWidth = null + this.left = null + if (currentMode == 'vertical') { + this.left = width + } else if (this.currentMode == 'vertical') { + this.left = !this.SubMenu ? null : width + if (!this.SubMenu) { + this.minWidth = width + } + } + this.opened = true; + clearTimeout(this.timer) + }, + renderAffix(isRender, root, currentMode) { + const itemClick = (item, e) => { + if (!item.disabled) { + // this.selected = true + let key = item.$vnode.key + + let options = { + key, + keyPath: [key], + item, + event: e + } + let parent = this.SubMenu || this.Menu + if (parent) { + parent.handleClick(options) + } + } + } + const child = this.affixChilds.map(item => { + return++ ++ + + {this.renderAffix(hasRenderAffix, root, currentMode)} + += 0 }]} key={item.$vnode.key}> + + }) + if (isRender) { + const props = { + class: "k-menu-submenu-affix", + on: { + mouseenter: e => { + e.stopPropagation() + this.hidePopupMenu(currentMode) + } + } + } + return +{child}+ } + return null + }, + openChange() { + if (this.Menu) { + let root = getParent(this.Menu, 'Menu') + if (root.currentMode != 'inline') return; + let openKeys = root.defaultOpenKeys + let key = this.$vnode.key + let index = openKeys.indexOf(key) + //accordion + if (root.accordion) { + let rootSub = getParent(this.SubMenu, 'SubMenu') + if (!rootSub._uid) { + root.openChange(index >= 0 ? [] : [key]) + return; + } + } + + // console.log(openKeys, index) + if (index >= 0) { + openKeys.splice(index, 1) + } else { + openKeys.push(key) + } + root.openChange(openKeys) + } + }, + closeSub() { + this.opened = false + if (this.SubMenu) this.SubMenu.closeSub() + }, + handleClick(options) { //item click event + + options.keyPath.unshift(this.$vnode.key) + let parent = this.SubMenu || this.Menu + if (parent) { + parent.handleClick(options) + } + + let root = getParent(this.Menu, 'Menu') + if (root.currentMode == 'horizontal' || root.currentMode == 'vertical') { + this.closeSub() + } + } + } +}; \ No newline at end of file diff --git a/components/menu/utils.js b/components/menu/utils.js new file mode 100644 index 0000000000000000000000000000000000000000..16f145bf16ffa65c4be1a0ab9890026f4f8640ae --- /dev/null +++ b/components/menu/utils.js @@ -0,0 +1,7 @@ +export function getParent(vnode, key) { + let node = vnode || {} + if (vnode && vnode[key]) { + node = getParent(vnode[key], key) + } + return node +} \ No newline at end of file diff --git a/components/message/demo/base.md b/components/message/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..83a8f807c451d6112327ab6990262f9a185820a8 --- /dev/null +++ b/components/message/demo/base.md @@ -0,0 +1,23 @@ ++#### 普通提示 +信息提醒反馈。 + + +```tpl + ++ ++ + +``` \ No newline at end of file diff --git a/components/message/demo/close.md b/components/message/demo/close.md new file mode 100755 index 0000000000000000000000000000000000000000..ccdea4ecb0707d40ae19649f765fb01df2d39a31 --- /dev/null +++ b/components/message/demo/close.md @@ -0,0 +1,39 @@ ++#### 自定义时长 +可以自定义配置,其中 `duration` 来控制自动关闭时长,默认 `3s` , `closable` 显示关闭按钮 + + +```tpl + ++ + + ++ + +``` \ No newline at end of file diff --git a/components/message/demo/index.vue b/components/message/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..08fa37c71c1239c959218ea9dd1e027bd144dc49 --- /dev/null +++ b/components/message/demo/index.vue @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/components/message/demo/info.md b/components/message/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..bdfdc27408fe391a29a3d9f1f63ac8c4016dc09e --- /dev/null +++ b/components/message/demo/info.md @@ -0,0 +1,8 @@ +# 全局提示 +全局展示操作反馈信息。 + +## 何时使用 +- 可提供成功、警告和错误等反馈信息。 +- 顶部居中显示并自动消失,是一种不打断用户操作的轻量级提示方式。 + +## 代码演示 \ No newline at end of file diff --git a/components/message/demo/types.md b/components/message/demo/types.md new file mode 100755 index 0000000000000000000000000000000000000000..bd8e769e70db520a3b9490fc2cf33a476b137399 --- /dev/null +++ b/components/message/demo/types.md @@ -0,0 +1,29 @@ ++#### 提示类型 +通过 `type` 来设置提示类型 + + +```tpl + ++ + + ++ + +``` \ No newline at end of file diff --git a/components/message/index.js b/components/message/index.js new file mode 100755 index 0000000000000000000000000000000000000000..424daf51a0619bcf4629e1ca8928be3d150ce761 --- /dev/null +++ b/components/message/index.js @@ -0,0 +1,30 @@ +import Notices from './notices.jsx' + +let messageInstance; + +const getInstance = (type) => { + messageInstance = messageInstance || Notices.newInstance({ type }) + return messageInstance +}; + +let Message = { + name: 'Message', + config(options = {}) { + options.noticeType = 'message' + getInstance('message').add(options); + }, + destroy() { + if (messageInstance) { + messageInstance.destroy() + messageInstance = null; + document.body.removeChild(document.getElementsByClassName('k-message')); + } + } +}; +['info', 'success', 'warning', 'error'].forEach(type => { + Message[type] = (content, duration, onClose) => { + return Message.config({ type, content, duration, onClose }) + } +}) + +export default Message; \ No newline at end of file diff --git a/components/message/index.md b/components/message/index.md new file mode 100755 index 0000000000000000000000000000000000000000..a04d941c0ba7169d616c6e97438ef02d7f5662a7 --- /dev/null +++ b/components/message/index.md @@ -0,0 +1,27 @@ +### API +组件提供了一些静态方法,使用方式如下 + + +- `this.$Message.info(content, [duration], onClose)` +- `this.$Message.success(content, [duration], onClose)` +- `this.$Message.warning(content, [duration], onClose)` +- `this.$Message.error(content, [duration], onClose)` + + + +另外提供了全局配置和全局销毁的方法: + + +- `this.$Message.config(options)` +- `this.$Message.destroy()` + + +参数 `options` 为对象,具体说明如下: + +| 属性 | 说明 | 类型 | 默认值 | +|----------|---------------------------------------------------|----------|-------| +| type | 提示类型,提供 `info`、`success`、`error`、`warning` 四种可选类型 | String | info | +| content | 提示内容 | String | - | +| duration | 自动关闭的延时,单位秒,0为 不自动关闭 | Number | 3 | +| closable | 是否可手动关闭 | Boolean | false | +| close | 关闭时的回调 | Function | - | diff --git a/components/message/notice.jsx b/components/message/notice.jsx new file mode 100755 index 0000000000000000000000000000000000000000..b4cd1f7c5eda665906f6e3fd64964a69c2e25281 --- /dev/null +++ b/components/message/notice.jsx @@ -0,0 +1,50 @@ +import Icon from '../icon' +export default { + props: { + type: { type: String, default: "info" }, + title: String, + name: String, + content: String, + closable: Boolean, + noticeType: { type: String, default: "message" }, + onClose: { type: Function, default: () => { } } + }, + render() { + let { noticeType, type, content, title, onClose, closable } = this + const classes = [`k-${noticeType}-box`, `k-${noticeType}-${type}`, { + 'k-notice-has-icon': noticeType == 'notice' && type != 'default' + }]; + let childNode; + let icons = { + info: "ios-information-circle", + error: "ios-close-circle", + success: "ios-checkmark-circle", + warning: "ios-alert" + }; + let iconNode = type != 'default' ?: null + if (noticeType == 'message') { + + childNode = ( + + ) + } else { + childNode = ( + + {iconNode} ++ ) + } + return ( +{title}+{content}++ + {childNode} ++ ) + } +} \ No newline at end of file diff --git a/components/message/notices.jsx b/components/message/notices.jsx new file mode 100755 index 0000000000000000000000000000000000000000..32e6fcd822605e6ebdaae3feb65417c3eb0a6d11 --- /dev/null +++ b/components/message/notices.jsx @@ -0,0 +1,77 @@ +import Vue from 'vue'; +import Notice from "./notice.jsx"; +import { getTranstionProp } from '../_tool/transition' + +let count = 0 +const timestamp = Date.now() +function getUuid() { + return `k-message_${timestamp}_${count++}` +} + +const Notices = { + props: { type: String }, + data() { + return { + notices: [] + }; + }, + methods: { + add(options) { + let { duration, close, closable, noticeType } = options + let key = getUuid() + options.name = key + options.duration = isNaN(Number(duration)) ? 3.5 : duration; + let timer; + let callback = () => { + (typeof close) === 'function' && close() + let index = this.notices.map(v => v.name).indexOf(key) + this.notices.splice(index, 1) + clearTimeout(timer); + timer = null; + }; + options.duration > 0 && (timer = setTimeout(callback, options.duration * 1000)); + if ((closable === true && noticeType == "message") || noticeType == "notice") + options.onClose = callback + this.notices.push(options); + } + }, + render() { + const { type } = this + let transition = getTranstionProp() + delete transition.on.enter + delete transition.on.beforeEnter + transition.on.beforeLeave = (el) => { + el.style.height = window.getComputedStyle(el).height + el.style.opacity = 1 + } + let kid = this.notices.map((item, i) => { + let props = { props: { ...item } } + let key = (item.name = item.name) || getUuid() + return+ }) + return ( + ++ ) + } +} + +Notices.newInstance = function (props = {}) { + const Notice = new Vue({ + render(h) { + return h(Notices, { + props: props + }); + } + }); + + const component = Notice.$mount(); + document.body.appendChild(component.$el); + const notice = Notice.$children[0]; + return notice +} + +export default Notices \ No newline at end of file diff --git a/components/message/styles/index.less b/components/message/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..696038b9ab7fdbe40ae6a8a1b334f91765ebbd67 --- /dev/null +++ b/components/message/styles/index.less @@ -0,0 +1,90 @@ +@import '../../styles/global.less'; +.k-message { + font-size: 14px; + line-height: 1.5; + color: @color; + box-sizing: border-box; + margin: 0; + padding: 0; + position: fixed; + z-index: 1010; + width: 100%; + top: 16px; + left: 0; + pointer-events: none; + .k-message-box { + box-sizing: content-box; + padding: 0 12px 14px 12px; + text-align: center; + transition: all .3s; + // margin-top: -8px; + } + .k-message-content { + box-sizing: content-box; + line-height: 1.5; + padding: 10px 16px; + border-radius: @radius; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + background: #fff; + display: inline-block; + pointer-events: all; + .k-message-icon { + margin-right: 8px; + font-size: 18px; + vertical-align: middle; + } + } + .k-message-close { + overflow: hidden; + cursor: pointer; + float: right; + margin-left: 15px; + font-size: 20px; + } +} + +.k-message-success .k-message-icon { + color: @success; +} + +.k-message-error .k-message-icon { + color: @danger; +} + +.k-message-info .k-message-icon { + color: @main; +} + +.k-message-warning .k-message-icon { + color: @warning; +} + +@keyframes msgIn { + from { + opacity: 0; + margin-top: -55px; + } + to { + opacity: 1; + margin-top: 0; + } +} + +@keyframes msgOut { + from { + opacity: 1; + margin-top: -55px; + } + to { + opacity: 0; + margin-top: 0; + } +} + +.k-message-slide-enter-active { + animation: msgIn .3s ease; +} + +.k-message-slide-leave-active { + animation: msgOut .3s ease; +} \ No newline at end of file diff --git a/components/modal/demo/base.md b/components/modal/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..33b9ada86796493373d054b2e78b0882e3dd107f --- /dev/null +++ b/components/modal/demo/base.md @@ -0,0 +1,22 @@ ++ {kid} + ++#### 基础用法 +使用 `v-model` 进行数据双向绑定 + + +```tpl + ++ ++ + +``` \ No newline at end of file diff --git a/components/modal/demo/confrim.md b/components/modal/demo/confrim.md new file mode 100755 index 0000000000000000000000000000000000000000..8ed95d045c0473eef1905c3c535e3095837d97f7 --- /dev/null +++ b/components/modal/demo/confrim.md @@ -0,0 +1,75 @@ +Content ++#### 提示框 +全局的确认提示框,可以异步关闭 + + +```tpl + ++ + + + ++ + +``` diff --git a/components/modal/demo/custom.md b/components/modal/demo/custom.md new file mode 100755 index 0000000000000000000000000000000000000000..0ec1b071ca1e11c44a3c04e5bed2064d3713faaa --- /dev/null +++ b/components/modal/demo/custom.md @@ -0,0 +1,59 @@ ++#### 自定义 +自定义 `Modal` + + +```tpl + ++ + + + ++ + +``` \ No newline at end of file diff --git a/components/modal/demo/global.md b/components/modal/demo/global.md new file mode 100755 index 0000000000000000000000000000000000000000..732948819004ccf582760be922707c83037d6efd --- /dev/null +++ b/components/modal/demo/global.md @@ -0,0 +1,37 @@ ++ + +content
++ + +content
+ + + ++ + +Yes , I'm fine !
++ +Name:
++#### 全局模式 +使用 全局模式 + + +```tpl + ++ + + + + ++ + +``` diff --git a/components/modal/demo/index.vue b/components/modal/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..679ac7ee3c1b6cc066587a9f9f75c0f82ef5ac53 --- /dev/null +++ b/components/modal/demo/index.vue @@ -0,0 +1,25 @@ + \ No newline at end of file diff --git a/components/modal/demo/info.md b/components/modal/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..69e3dfd435c58477c496ecbb15d1d6ddd1fa10d4 --- /dev/null +++ b/components/modal/demo/info.md @@ -0,0 +1,10 @@ +# Input 输入框 + +通过鼠标或键盘输入内容,是最基础的表单域的包装。 + +## 何时使用 + +- 需要用户输入表单域内容时。 +- 提供组合型输入框,带搜索的输入框,还可以进行大小选择。 + +## 代码演示 \ No newline at end of file diff --git a/docs/src/views/modal.vue b/components/modal/demo/modal.vue old mode 100644 new mode 100755 similarity index 100% rename from docs/src/views/modal.vue rename to components/modal/demo/modal.vue diff --git a/components/modal/demo/more.md b/components/modal/demo/more.md new file mode 100755 index 0000000000000000000000000000000000000000..9010a0c5036c797c7f8e47355c03670a2980c52d --- /dev/null +++ b/components/modal/demo/more.md @@ -0,0 +1,49 @@ ++#### 其它属性 +更多属性 + + +```tpl + ++ + + + + + ++ + +``` \ No newline at end of file diff --git a/components/modal/index.js b/components/modal/index.js new file mode 100755 index 0000000000000000000000000000000000000000..34ef5eba218ed62d66d59afb454a5110c893ce53 --- /dev/null +++ b/components/modal/index.js @@ -0,0 +1,146 @@ +import Modal from './modal.jsx' +import Icon from '../icon' +import Vue from 'vue' +import Button from '../button' + +function isPromise(obj) { + return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function'; +} + +let showPoint = {} +let mousedown = e => { + showPoint = { x: e.clientX, y: e.clientY } +} +if (typeof window !== undefined) { + document.addEventListener('mousedown', mousedown) +} + + +let modalList = []; +let createInstance = (props = {}) => { + + const instance = new Vue({ + data: { loading: false, show: false }, + render(h) { + //icons + let { icon, title, content, color, cancelText, okText } = props + let icons = { + info: "ios-information-circle", + error: "ios-close-circle", + success: "ios-checkmark-circle", + warning: "ios-alert", + confirm: 'ios-help-circle' + } + let type = icons[icon] || icon + //header + let header = h('div', { attrs: { class: 'k-toast-header' } }, [ + type ? h(Icon, { style: { color: color }, class: 'k-toast-icon', props: { type } }) : null, + h('div', { attrs: { class: 'k-toast-title' } }, title) + ]) + + //body + let body = h('div', { attrs: { class: 'k-toast-content' } }, [content]) + //footer + let footerNode = [h(Button, { + props: { type: 'primary', loading: this.loading }, + on: { click: this.ok } + }, okText || '确定')] + + if (icon == 'confirm') { + footerNode.unshift(h(Button, { on: { click: this.cancel } }, cancelText || '取消')) + } + let footer = h('div', { attrs: { class: 'k-toast-footer' } }, footerNode) + + let contentNode = h('template', { slot: 'content' }, [header, body, footer]) + let classes = 'k-modal k-toast ' + (icons[icon] ? 'k-toast-' + icon : '') + return h(Modal, { attrs: { class: classes } }, [contentNode]); + }, + methods: { + ok() { + let { onOk } = props; + let fun = onOk ? onOk() : {} + if (isPromise(fun)) { + this.loading = true + fun.then(e => { + this.destroy() + }).catch(e => { + + }) + } else { + this.destroy() + } + }, + cancel() { + let { onCancel } = props; + (typeof onCancel == 'function') && onCancel() + this.destroy() + }, + destroy() { + let instance = this.$children[0] + if (instance) { + instance.show = false + + clearTimeout(this.timer) + this.timer = setTimeout(e => { + instance.showInner = false + instance.$destroy() + setTimeout(() => { + document.body.removeChild(this.$el) + }); + modalList.splice(modalList.indexOf(instance), 1) + + if (modalList.length == 0) { + modal.resetBodyStyle(false) + } + }, 300) + } + } + } + }) + const component = instance.$mount() + document.body.appendChild(component.$el) + + let modal = instance.$children[0] + modal.init = true + + return { + show() { + modal.showPoint = showPoint + modal.$nextTick(e => { + modal.show = true + modal.showInner = true + modal.resetBodyStyle(true) + }) + }, + destroy() { + // document.removeEventListener('mousedown', mousedown) + modal.$parent.destroy() + } + } +} + +let getModal = (props = {}) => { + let instance = createInstance(props) + instance.show() + modalList.push(instance) + return instance +} + +['info', 'success', 'warning', 'error', 'confirm'].forEach(type => { + Modal[type] = (props = {}) => getModal(Object.assign({ icon: type }, props)) +}) + +Modal.show = (props = {}) => { + return getModal(props) +} + +Modal.destroyAll = e => { + modalList.forEach(modal => { + modal.destroy() + }) +} +Modal.install = function (Vue) { + + Vue.component(Modal.name, Modal); +}; +export default Modal \ No newline at end of file diff --git a/components/modal/index.md b/components/modal/index.md new file mode 100755 index 0000000000000000000000000000000000000000..e06e64f3d5f72438158596490c89b773a57a3071 --- /dev/null +++ b/components/modal/index.md @@ -0,0 +1,46 @@ +## API + +| 属性 | 说明 | 类型 | 默认值 | +|---------------|-----------------------------------------------|----------------|--------| +| value | 对话框是否显示,可使用 v-model 双向绑定数据。 | Boolean | false | +| title | 对话框标题 | String | - | +| width | 对话框宽度 | Number, String | 520 | +| ok-text | 确定按钮文字 | String | 确定 | +| cancel-text | 取消按钮文字 | String | 取消 | +| can-move | 弹框是否可拖动, confirm模式不可用 | Boolean | false | +| is-center | 窗口是否可以居中 , confirm模式不可用 | Boolean | false | +| is-max | 弹框是否可以最大化显示 , confirm模式不可用 | Boolean | false | +| mask-closable | 是否点击遮罩关闭弹窗, 为否时Esc键将失效 | Boolean | true | +| ok | 点击确定的回调 | Function | - | +| cancel | 点击取消的回调 | Function | - | +| close | 窗口关闭的回调 | Function | - | + + +## Modal.method() + +组件提供了一些静态方法,使用方式如下 + +* this.$Modal.info(options) +* this.$Modal.success(options) +* this.$Modal.warning(options) +* this.$Modal.error(options) +* this.$Modal.show(options) +* this.$Modal.confirm(options) + +另外提供了全局配置和全局销毁的方法: + +* this.$Modal.show(options) +* this.$Modal.destroy() + +参数 options 为对象,具体说明如下: + +| 属性 | 说明 | 类型 | 默认值 | +|-------------|------------------------------------------------------------------------------------------------------------------------|----------|--------| +| title | 对话框标题 | String | - | +| content | 对话框内容 | String | - | +| ok-text | 确定按钮文字 | String | 确定 | +| cancel-text | 取消按钮文字 | String | 取消 | +| icon | 弹框的图标,type为toast可用 ,默认可选值为success,warning, error, info, 也可以自定义,参照 [Icon](/components/icon)值 | String | - | +| color | 弹框的图标的颜色,type为toast可用 | String | - | +| onOk | 点击确定的回调 | Function | - | +| onCancel | 点击取消的回调 | Function | - | diff --git a/components/modal/modal.jsx b/components/modal/modal.jsx new file mode 100755 index 0000000000000000000000000000000000000000..a72b79fb5d255675871ad59f43a274132a9157cc --- /dev/null +++ b/components/modal/modal.jsx @@ -0,0 +1,210 @@ +import Icon from '../icon' +import Button from '../button' +import transfer from "../_tool/transfer"; +import { measureScrollBar, getOffset } from '../_tool/utils' + +let cacheBodyOverflow = {}; + + +export default { + directives: { transfer }, + props: { + value: Boolean, + title: String, + okText: { type: String, default: '确定' }, + cancelText: { type: String, default: '取消' }, + top: Number, + width: Number, + mask: { type: Boolean, default: true }, + maskClosable: { type: Boolean, default: true }, + isMax: Boolean, + isCenter: Boolean, + canMove: Boolean, + loading: Boolean, + // mode: { type: String, default: 'modal' } + }, + data() { + return { + init: false, + show: this.value, + showInner: this.value, + left: '', + currentTop: this.top, + isMouseDown: false, + startPos: { x: 0, y: 0 }, + showPoint: { x: 0, y: 0 } + } + }, + watch: { + value(value) { + this.updateProp(value) + } + }, + updated() { + if (this.show) { + this.setPos() + } + }, + methods: { + updateProp(visible) { + if (visible) { + this.init = true + this.$nextTick(e => { + this.show = visible + this.showInner = visible + }) + } else { + this.show = false + setTimeout(() => { + this.showInner = false + }, 300); + } + this.resetBodyStyle(visible) + }, + resetBodyStyle(opened) { + if (!this.show && !cacheBodyOverflow.hasOwnProperty('overflow')) { + cacheBodyOverflow = { + width: document.body.width, + overflow: document.body.overflow, + overflowX: document.body.overflowX, + overflowY: document.body.overflowY, + } + } + if (opened) { + let barWidth = measureScrollBar(true) + if (barWidth) { + document.body.style.width = `calc(100% - ${barWidth}px)` + document.body.style.overflow = `hidden` + } + } else { + setTimeout(() => { + Object.keys(cacheBodyOverflow).forEach(key => { + document.body.style[key] = cacheBodyOverflow[key] || '' + delete cacheBodyOverflow[key] + }) + }, 300) + } + }, + setPos() { + if (this.show) { + let { showPoint: { x, y } } = this + // let { x, y } = showPoint + let { left, top } = getOffset(this.$refs.modal) + this.$refs.modal.style['transform-origin'] = `${x - left}px ${y - top}px` + } + }, + ok() { + this.$emit('ok') + this.$nextTick(e => { + if (!this.loading) { + this.close() + } + }) + }, + cancel() { + this.close() + this.$emit('cancel') + }, + close() { + this.$emit('input', false) + this.$emit('close') + }, + clickMaskToClose(e) { + if (!this.loading && this.maskClosable && !this.$refs.modal.contains(e.target)) { + this.close() + } + }, + mousemove(e) { + if (this.isMouseDown && this.canMove) { + let { x, y } = this.startPos + this.left += e.clientX - x + this.currentTop = this.currentTop || 100 + this.currentTop += e.clientY - y + this.startPos = { x: e.clientX, y: e.clientY } + this.setPos() + } + }, + mouseup(e) { + this.isMouseDown = false + document.removeEventListener('mousemove', this.mousemove) + document.removeEventListener('mouseup', this.mouseup) + }, + mousedown(e) { + if (!this.show) { + this.showPoint = { x: e.clientX, y: e.clientY } + } + if (e.button == 0 && this.canMove === true) { + this.isMouseDown = true + this.startPos = { x: e.clientX, y: e.clientY } + this.mousemove(e) + document.addEventListener('mousemove', this.mousemove) + document.addEventListener('mouseup', this.mouseup) + } + } + }, + beforDestory() { + document.removeEventListener('mousedown', this.mousedown) + this.resetBodyStyle(false) + }, + + mounted() { + document.addEventListener('mousedown', this.mousedown) + if (this.value) this.init = true + }, + render() { + let { $slots, show, showInner, canMove } = this + let node = [] + + //mask + let maskNode = null + if (this.mask) { + maskNode =+ + +content
++ + +content
++ + +content
++ + +content
++ +content
++ } + + //content + let contentNode = $slots.content + if (!contentNode) { + const contents = [] + contents.push( ) + contents.push( ) + contents.push({this.title}{$slots.default}) + + //footer + let footer = $slots.footer + if (!footer) { + footer = [, ] + } + const footerNode = + + contents.push(footerNode) + contentNode = + } + + node.push(contentNode) + if (canMove) { + this.left = this.left || (document.body.offsetWidth - (this.width || 520)) / 2 + } + const style = { + width: `${this.width}px`, + top: `${this.currentTop}px`, + left: `${this.left}px`, + } + const classes = [ + 'k-modal', { + 'k-modal-can-move': canMove, + 'k-modal-max': this.isMax, + 'k-modal-center': this.isCenter, + } + ] + return this.init ? (+ {maskNode} +) : null + } +} \ No newline at end of file diff --git a/components/modal/styles/index.less b/components/modal/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..8397c01442eb17584ba7f26625d77d4005bb83c9 --- /dev/null +++ b/components/modal/styles/index.less @@ -0,0 +1,252 @@ +@import '../../styles/global.less'; +.k-modal { + .k-modal-wrap { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1001; + overflow: auto; + outline: 0; + -webkit-overflow-scrolling: touch; + } + .k-modal-mask { + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + background-color: rgba(55, 55, 55, .6); + height: 100%; + z-index: 1001; + overflow: hidden; + } + .k-modal-inner { + position: relative; + background-color: #fff; + z-index: 1001; + outline: 0; + border-radius: @radius; + top: 100px; + overflow: hidden; + margin: 0 auto; + box-shadow: 0 0 10px 3px rgba(55, 55, 55, .2); + width: 520px; // animation: fadeIn .5s ease-in-out; + } + .k-modal-content { + position: relative; + border: 0; + background-clip: padding-box; + height: 100%; + overflow: hidden; + .k-modal-close { + position: absolute; + cursor: pointer; + font-size: 20px; + color: @color; + width: 43px; + height: 43px; + top: 0; + right: 0; + transition: all .3s ease-in-out; + .k-icon { + position: absolute; + top: 50%; + left: 50%; + transform: translateY(-50%) translateX(-50%); + } + &:hover { + color: @danger; + transform: rotate(360deg); + } + } + .k-modal-header { + border-bottom: 1px solid #e9eaec; + padding: 14px 16px; + line-height: 1; + font-size: 14px; + font-weight: 700; + user-select: none; + .k-modal-header-inner { + width: 90%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + } + .k-modal-body { + padding: 16px; + font-size: 12px; + line-height: 1.5; + height: calc(100% - 43px - 45px); + overflow: auto; + box-sizing: border-box; + } + .k-modal-footer { + border-top: 1px solid #e9eaec; + padding: 6px 16px; + text-align: right; + display: inline-block; + width: 100%; + box-sizing: border-box; + .k-btn { + margin-left: 8px; + } + } + } +} + +.k-modal-can-move { + .k-modal-header { + cursor: move; + } + .k-modal-inner { + position: absolute; + } +} + +.k-modal-center { + .k-modal-wrap { + text-align: center; + &::before { + display: inline-block; + width: 0; + height: 100%; + vertical-align: middle; + content: ''; + } + } + .k-modal-inner { + top: 0; + display: inline-block; + text-align: left; + vertical-align: middle; + } +} + +.k-modal-max { + .k-modal-inner { + height: 100%; + width: 100%; + top: 0; + left: 0; + border-radius: 0; + .k-modal-footer { + position: absolute; + width: 100%; + bottom: 0; + left: 0; + background: #fff; + } + } +} + +.k-toast { + .k-modal-inner { + width: 416px; + background: #fff; + border-radius: @radius; + padding: 16px; + overflow: hidden; + } + .k-toast-header { + .k-toast-icon { + font-size: 28px; + margin-right: 12px; + float: left; + } + .k-toast-title { + font-size: 16px; + font-weight: 700; + overflow: hidden; + line-height: 1.5; + } + } + .k-toast-content { + padding-left: 40px; + padding-top: 8px; + font-size: 14px; + } + .k-toast-footer { + float: right; + margin-top: 20px; + .k-btn { + margin-left: 8px; + } + } +} + +.k-toast-success .k-toast-icon { + color: @success; +} + +.k-toast-error .k-toast-icon { + color: @danger; +} + +.k-toast-warning .k-toast-icon { + color: @warning; +} + +.k-toast-info .k-toast-icon { + color: @main; +} + +.k-toast-confirm .k-toast-icon { + color: @warning; +} + +@keyframes fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes fade-out { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +.k-modal-fade-enter-active { + animation: fade-in .4s linear; +} + +.k-modal-fade-leave-active { + animation: fade-out .4s linear; +} + +@keyframes k-modal-zoom-in { + from { + opacity: 0; + transform: scale3d(.3, .3, 0) + } + to { + opacity: 1; + } +} + +@keyframes k-modal-zoom-out { + from { + opacity: 1; + } + to { + opacity: 0; + transform: scale3d(.3, .3, 0); + } +} + +.k-modal-zoom-enter-active { + animation: k-modal-zoom-in .25s cubic-bezier(.78,.14,.15,.86); +} + +.k-modal-zoom-leave-active { + animation: k-modal-zoom-out .25s cubic-bezier(.78,.14,.15,.86); +} \ No newline at end of file diff --git a/components/notice/demo/base.md b/components/notice/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..e014dda12ae1a730fc3a0e32cd0eae73c6aef5f4 --- /dev/null +++ b/components/notice/demo/base.md @@ -0,0 +1,26 @@ + ++++ ++ {node} +++#### 基础用法 +`Notice` 的基本用法 + + +```tpl + ++ ++ + +``` \ No newline at end of file diff --git a/components/notice/demo/icon.md b/components/notice/demo/icon.md new file mode 100755 index 0000000000000000000000000000000000000000..3414f86185d9feec7090cad4506a3f44bafae90e --- /dev/null +++ b/components/notice/demo/icon.md @@ -0,0 +1,28 @@ ++#### 带图标的提醒 +通过调用不同的方法,可展示不同的类型 + + +```tpl + ++ + + + ++ + +``` \ No newline at end of file diff --git a/components/notice/demo/index.vue b/components/notice/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..0fb0fb094dc35ea9fd98fe4400f8ed7081b38f0e --- /dev/null +++ b/components/notice/demo/index.vue @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/components/notice/demo/info.md b/components/notice/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..24cb69768dbea8fee413961fa83f18ac089ad9ec --- /dev/null +++ b/components/notice/demo/info.md @@ -0,0 +1,11 @@ +# 通知提醒框 +全局展示通知提醒信息。 + +## 何时使用 +在系统四个角显示通知提醒信息。经常用于以下情况: + +- 较为复杂的通知内容。 +- 带有交互的通知,给出用户下一步的行动点。 +- 系统主动推送。 + +## 代码演示 \ No newline at end of file diff --git a/components/notice/index.js b/components/notice/index.js new file mode 100755 index 0000000000000000000000000000000000000000..e9eda0c010e73cad69a4a2e0949c921853b0a6f8 --- /dev/null +++ b/components/notice/index.js @@ -0,0 +1,33 @@ +import Notices from '../message/notices.jsx' + +let noticeInstance; + +const getInstance = (type) => { + noticeInstance = noticeInstance || Notices.newInstance({ type }) + return noticeInstance +}; + +let Notice = { + name: 'Notice', + open(options = {}) { + options = Object.assign({ type: 'default', noticeType: 'notice' }, options) + options.noticeType = 'notice' + // options.type = null + getInstance('notice').add(options); + }, + destroy() { + if (noticeInstance) { + noticeInstance.destroy() + noticeInstance = null; + document.body.removeChild(document.getElementsByClassName('k-notice')); + } + } +}; + +['info', 'success', 'warning', 'error'].forEach(type => { + Notice[type] = (options) => { + return Notice.open({ type, ...options }) + } +}); + +export default Notice; \ No newline at end of file diff --git a/components/notice/index.md b/components/notice/index.md new file mode 100755 index 0000000000000000000000000000000000000000..a86eb936c881a4bcc14e939cfdb6f9d7d3cca16c --- /dev/null +++ b/components/notice/index.md @@ -0,0 +1,26 @@ +### API +组件提供了一些静态方法,使用方式如下 + + +- `this.$Notice.info(options)` +- `this.$Notice.success(options)` +- `this.$Notice.warning(options)` +- `this.$Notice.error(options)` + + + +另外提供了全局配置和全局销毁的方法: + + +- `this.$Notice.open(options)` +- `this.$Notice.destroy()` + + +参数 `options` 为对象,具体说明如下: + +| 属性 | 说明 | 类型 | 默认值 | +|----------|----------------------|----------|-----| +| title | 通知提醒的标题 | String | - | +| content | 提示内容 | String | - | +| duration | 自动关闭的延时,单位秒,不关闭可以写 0 | Number | 3 | +| close | 关闭时的回调 | Function | - | \ No newline at end of file diff --git a/components/notice/styles/index.less b/components/notice/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..d940003aa96bb5558d6fc59b33fd23e6248ddeb7 --- /dev/null +++ b/components/notice/styles/index.less @@ -0,0 +1,108 @@ +@import '../../styles/global.less'; +.k-notice { + font-size: 14px; + line-height: 1.5; + color: @color; + -webkit-box-sizing: border-box; + box-sizing: border-box; + margin: 0; + padding: 0; + list-style: none; + position: fixed; + z-index: 1010; + width: 384px; + max-width: calc(100vw - 32px); + margin-right: 24px; + right: 0px; + top: 24px; + bottom: auto; + .k-notice-box { + box-sizing: content-box; + transition: all .3s ease-in-out; + padding: 16px 35px 16px 16px; + border-radius: @radius; + -webkit-box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + background: #fff; + line-height: 1.5; + position: relative; + margin-bottom: 16px; + overflow: hidden; + } + .k-notice-has-icon { + padding-left: 45px; + } + .k-notice-title { + font-size: 16px; + color: @title-color; + margin-bottom: 8px; + line-height: 22px; + vertical-align: middle; + display: inline-block; + } + .k-notice-icon { + font-size: 22px; + margin-right: 8px; + position: absolute; + top: 17px; + left: 16px; + } + .k-notoce-desc { + font-size: 14px; + line-height: 1.5; + } + .k-notice-close { + position: absolute; + right: 8px; + top: 13px; + outline: none; + cursor: pointer; + color: @color; + font-size: 20px; + display: block; + padding: 0 5px; + &:hover { + color: @danger; + } + } + .k-notice-info .k-notice-icon { + color: @main; + } + .k-notice-error .k-notice-icon { + color: @danger; + } + .k-notice-success .k-notice-icon { + color: @success; + } + .k-notice-warning .k-notice-icon { + color: @warning; + } +} + +@keyframes noticeIn { + from { + opacity: 0; + transform: translate3d(100%, 0, 0); + } + to { + opacity: 1; + } +} + +@keyframes noticeOut { + from { + opacity: 1; + } + to { + opacity: 0; + transform: scaleY(.5); + } +} + +.k-notice-slide-enter-active { + animation: noticeIn .3s ease; +} + +.k-notice-slide-leave-active { + animation: noticeOut .3s ease; +} \ No newline at end of file diff --git a/components/page/demo/base.md b/components/page/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..6bc3981590fd832dfd934abd6d6bb1adf00aa5a3 --- /dev/null +++ b/components/page/demo/base.md @@ -0,0 +1,12 @@ ++#### 基本用法 +基础分页。 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/page/demo/elevator.md b/components/page/demo/elevator.md new file mode 100755 index 0000000000000000000000000000000000000000..a88cd1437e627d6cd4feab8a10c9fe6aa48fd0a3 --- /dev/null +++ b/components/page/demo/elevator.md @@ -0,0 +1,12 @@ ++ +#### 跳转 +快速跳转到某一页。 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/page/demo/index.vue b/components/page/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..b7980cb503862296642c19fe04c9d6225a217206 --- /dev/null +++ b/components/page/demo/index.vue @@ -0,0 +1,24 @@ + \ No newline at end of file diff --git a/components/page/demo/info.md b/components/page/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..2ffcce09630349ffd98bad60b470cd6eacc14d7d --- /dev/null +++ b/components/page/demo/info.md @@ -0,0 +1,7 @@ +# Page 分页 +采用分页的形式分隔长列表,每次只加载一个页面。 + +## 何时使用 +- 当加载/渲染所有数据将花费很多时间时; +- 可切换页码浏览数据。 +## 代码演示 \ No newline at end of file diff --git a/components/page/demo/mini.md b/components/page/demo/mini.md new file mode 100755 index 0000000000000000000000000000000000000000..2f4d45c220d3a06bbecb37e3a75d5c2b6362e4d2 --- /dev/null +++ b/components/page/demo/mini.md @@ -0,0 +1,15 @@ ++ +#### 尺寸 +展示小尺寸。 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/page/demo/more.md b/components/page/demo/more.md new file mode 100755 index 0000000000000000000000000000000000000000..96b10fb6577fcfbd14e1a16b09f88c2eef888995 --- /dev/null +++ b/components/page/demo/more.md @@ -0,0 +1,12 @@ ++ + + + +#### 更多 +更多分页。 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/page/demo/size.md b/components/page/demo/size.md new file mode 100755 index 0000000000000000000000000000000000000000..8cac965556a1836ba317f8fc426477a03abb9e23 --- /dev/null +++ b/components/page/demo/size.md @@ -0,0 +1,23 @@ ++ +#### 条目数和自定义条目数 +改变每页显示条目数。 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/src/components/page/index.js b/components/page/index.js old mode 100644 new mode 100755 similarity index 68% rename from src/components/page/index.js rename to components/page/index.js index 624dc19c57adf61f8af86df229bba3eb02242dcd..a20d8b2af4dcfff2e576ce07ee81e07a4fc2c780 --- a/src/components/page/index.js +++ b/components/page/index.js @@ -1,3 +1,2 @@ -import './page.less' import Page from './page' export default Page \ No newline at end of file diff --git a/components/page/index.md b/components/page/index.md new file mode 100755 index 0000000000000000000000000000000000000000..be1446910f428842610aa11d7181ba4717df85b2 --- /dev/null +++ b/components/page/index.md @@ -0,0 +1,13 @@ +## API +| 属性 | 说明 | 类型 | 默认值 | +|------------------|------------------------------------------------|----------|------------------| +| current | 当前页码 | Number | 1 | +| total | 数据总数 | Number | 0 | +| pagesize | 每页条数 | Number | 10 | +| show-sizer | 是否显示页码组 | Boolean | false | +| show-total | 是否显示总数 | Boolean | false | +| show-elevator | 是否显示页码阶梯 | Boolean | false | +| size-data | 自定义页码组数据 | Array | [10,15,20,30,40] | +| mini | 是否呈现迷你模式 | Boolean | false | +| change | 页码改变的回调,返回改变后的页码 | Function | - | +| page-size-change | 切换页码组改变的回调,返回改变后的 `page-size` | Function | - | \ No newline at end of file diff --git a/components/page/page.jsx b/components/page/page.jsx new file mode 100755 index 0000000000000000000000000000000000000000..a0c1ec244a29ecb18f774f3f9cce7cc1ebe61322 --- /dev/null +++ b/components/page/page.jsx @@ -0,0 +1,168 @@ +import { Select, Option } from '../select' +import { Input } from '../input' +import Icon from '../icon' + +export default { + name: "Page", + props: { + showSizer: Boolean, + showTotal: Boolean, + showElevator: Boolean, + sizeData: { type: Array, default: () => [10, 15, 20, 30, 40] }, + mini: { default: false, type: Boolean }, + total: { default: 0, type: Number }, + pageSize: { default: 10, type: Number }, + current: { default: 1, type: Number } + }, + data() { + return { + pageCount: 0, + page: this.current, + defaultPageSize: this.pageSize + } + }, + mounted() { + this.pageCount = Math.ceil(this.total / this.defaultPageSize) || 1; + }, + methods: { + renderPage() { + const groupCount = 7, + page = Number(this.page), + pageCount = Number(this.pageCount); + let showPrevMore = false; + let showNextMore = false; + if (pageCount > groupCount) { + if (page > groupCount - 3) { showPrevMore = true; } + if (page < pageCount - 3) { showNextMore = true; } + } + const array = []; + if (showPrevMore && !showNextMore) { + const startPage = pageCount - (groupCount - 2); + for (let i = startPage; i < pageCount; i++) { + array.push(i); + } + } else if (!showPrevMore && showNextMore) { + for (let i = 2; i < groupCount; i++) { + array.push(i); + } + } else if (showPrevMore && showNextMore) { + const offset = Math.floor(groupCount / 2) - 1; + for (let i = page - offset; i <= page + offset; i++) { + array.push(i); + } + } else { + for (let i = 2; i < pageCount; i++) { + array.push(i); + } + } + let child = array.map((p, i) => { + let prop = { + class: ['k-pager-item', { active: page == p }], + key: i, + on: { click: e => this.toPage(p) } + } + return+ + + {p} + }) + const moreNode =; + + if (showPrevMore) { + child.unshift(moreNode) + } + if (showNextMore) { + child.push(moreNode) + } + return child + }, + prePage() { + this.page > 1 && this.page--; + }, + nextPage() { + this.page < this.pageCount && this.page++; + }, + toPage(page) { + this.page = page + }, + changeSize({ value }) { + console.log(value) + this.defaultPageSize = value + this.pageCount = Math.ceil(this.total / this.defaultPageSize) || 1; + + }, + renderFirst() { + if (this.pageCount > 0) { + return this.toPage(1)} > + 1 + + } + return null + }, + renderLast() { + let { pageCount } = this + if (pageCount > 0) { + returnthis.toPage(pageCount)} > + {pageCount} + + } + return null + }, + renderSize() { + let prop = { + value: this.defaultPageSize, + props: { mini: this.mini }, + on: { + input: e => this.defaultPageSize = e, + change: this.changeSize + } + } + return ( + this.showSizer ? ++ +: null + ) + }, + renderElvator() { + let { mini } = this + let prop = { + class: 'k-page-options-elevator', + props: { mini, value: this.page }, + on: { + blur: e => { + let page = e.target.value + let { pageCount } = this + if (page >= 1 || page <= pageCount) this.page = page + if (page > pageCount) this.page = pageCount + if (page < 1) this.page = 1 + }, + // change: e => this.page = e + } + } + return ( + this.showElevator ? + : null + ) + } + }, + render() { + const classes = ["k-page", { ["k-page-mini"]: this.mini }], + preNode =, + nextNode = , + totalNode = (this.showTotal ? 共{this.total}条: null), + pagerNode = this.renderPage(), + sizeNode = this.renderSize(), + elvatorNode = this.renderElvator(), + firstNode = this.renderFirst(), + lastNode = this.renderLast() + return ( +++ ) + } +} \ No newline at end of file diff --git a/components/page/styles/index.less b/components/page/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..cf8dcd6d804c1d686d9d83b610fd45d8f9aa1d73 --- /dev/null +++ b/components/page/styles/index.less @@ -0,0 +1,115 @@ +@import '../../styles/global.less'; +.k-page { + color: @color; + font-size: 13px; + padding: 20px 0; + user-select: none; + .k-pager { + margin: 0 auto; + display: inline-block; + vertical-align: middle; + .k-pager-item { + background: #fff; + color: @color; + min-width: 30px; + height: 30px; + line-height: 30px; + border-radius: @radius; + margin: 0 8px; + text-align: center; + display: inline-block; + box-sizing: content-box; + border: 1px solid @border-color; + // transition: all 0.2s ease-in-out 0s; + margin-left: -1px; + font-size: 14px; + cursor: pointer; + position: relative; + vertical-align: middle; + &:hover { + border-color: @main; + color: @main; + .k-icon { + color: @main; + } + } + &.active { + border: 1px solid @main; + color: @main; + } + span { + margin: 0 5px; + } + .k-icon { + color: @icon-color; + position: absolute; + top: 50%; + left: 50%; + transform: translateX(-50%) translateY(-50%); + } + } + .k-pager-more { + font-size: 20px; + border-color: transparent; + &:hover { + border-color: transparent; + } + } + .k-pager-item-disabled { + border-color: @disable-border; + cursor: not-allowed; + .k-icon { + color: @disable-color; + } + &:hover { + border-color: @disable-border; + .k-icon { + color: @disable-color; + } + } + } + .k-pager-more { + color: @gray; + } + } + .k-page-sizer { + display: inline-block; + width: 90px; + } + .k-page-number { + margin: 0 4px; + display: inline-block; + font-size: 13px; + } + .k-page-options { + display: inline-block; + font-size: 13px; + span { + padding: 0 5px; + } + .k-page-options-elevator { + width: 50px; + font-size: 13px; + text-align: center; + vertical-align: middle; + } + .k-page-options-action { + vertical-align: middle; + } + } +} + +.k-page-mini { + .k-pager .k-pager-item { + height: 24px; + font-size: 12px; + line-height: 24px; + min-width: 24px; + } + .k-page-sizer { + width: 80px; + } + .k-page-number { + font-size: 12px; + } +} \ No newline at end of file diff --git a/components/popconfirm/demo/base.md b/components/popconfirm/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..73a5b8d8215114b78ce77464c4af4c9c8bd7d109 --- /dev/null +++ b/components/popconfirm/demo/base.md @@ -0,0 +1,28 @@ ++ {[preNode, firstNode, pagerNode, lastNode, nextNode, sizeNode, totalNode, elvatorNode]} +
++#### 基础用法 +最简单的用法。 + + +```tpl + ++ Delete + + +h +``` \ No newline at end of file diff --git a/components/popconfirm/demo/index.vue b/components/popconfirm/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..63c78986ea78a623c6593356fdef376e053314bf --- /dev/null +++ b/components/popconfirm/demo/index.vue @@ -0,0 +1,29 @@ + + \ No newline at end of file diff --git a/components/popconfirm/demo/info.md b/components/popconfirm/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..5db7e3a8ccef67c3a8e269d09bb745c75ff84388 --- /dev/null +++ b/components/popconfirm/demo/info.md @@ -0,0 +1,9 @@ +## Popconfirm 气泡确认框 +点击元素,弹出气泡式的确认框。 + +## 何时使用 +目标元素的操作需要用户进一步的确认时,在目标元素附近弹出浮层提示,询问用户。 + +和 ‘confirm’ 弹出的全屏居中模态对话框相比,交互形式更轻量。 + +## 代码演示 \ No newline at end of file diff --git a/components/popconfirm/demo/local.md b/components/popconfirm/demo/local.md new file mode 100755 index 0000000000000000000000000000000000000000..4446e488ff73dcb7378aff99ba6b8960809487e5 --- /dev/null +++ b/components/popconfirm/demo/local.md @@ -0,0 +1,36 @@ ++#### 国际化 +使用 `okText` 和 `cancelText` 自定义按钮文字。 + + +```tpl + ++ + ++ + + + +``` \ No newline at end of file diff --git a/components/popconfirm/demo/placement.md b/components/popconfirm/demo/placement.md new file mode 100755 index 0000000000000000000000000000000000000000..86fa2abd6a567cce8558b072c99dd54f15db2151 --- /dev/null +++ b/components/popconfirm/demo/placement.md @@ -0,0 +1,110 @@ ++#### 位置 +通过 `placement`控制方向, 位置有十二个方向。 + + +```tpl + ++++ + + +{{title}}
+{{title}}
+ ++ + + +{{title}}
+{{title}}
+ ++ + + +{{title}}
+{{title}}
+ ++++ + + +{{title}}
+{{title}}
+ ++ + + +{{title}}
+{{title}}
+ ++ + + +{{title}}
+{{title}}
+ ++++ + + +{{title}}
+{{title}}
+ ++ + + +{{title}}
+{{title}}
+ ++ + + +{{title}}
+{{title}}
+ +++ + +``` \ No newline at end of file diff --git a/components/popconfirm/index.js b/components/popconfirm/index.js new file mode 100755 index 0000000000000000000000000000000000000000..9f02d1627707816d93083dbcfcf543ca6c3b68b1 --- /dev/null +++ b/components/popconfirm/index.js @@ -0,0 +1,2 @@ +import Popconfirm from './popconfirm.jsx' +export default Popconfirm \ No newline at end of file diff --git a/components/popconfirm/index.md b/components/popconfirm/index.md new file mode 100755 index 0000000000000000000000000000000000000000..5f4b67545d7d647e7b0b95378d4dac47fddd0acc --- /dev/null +++ b/components/popconfirm/index.md @@ -0,0 +1,11 @@ +## API +| 属性 | 说明 | 类型 | 默认值 | +|-------------|----------------------------------------------------------------------------------------------------------------------------------------------------|--------------|-------| +| title | 显示的标题 | String,Slots | - | +| placement | 提示框出现的位置,可选值为`top`,`top-left`,`top-right`,`bottom`,`bottom-left`,`bottom-right`,`left`,`left-top`,`left-bottom`,`right`,`right-top`,`right-bottom` | String | top | +| width | 展示的宽度,默认为内容区域的大小 | String | - | +| transfer | 是否将弹层放置于 `body` 内,在 `Tabs`、带有 `fixed` 的 `Table` 列内使用时,建议添加此属性,它将不受父级样式影响,从而达到更好的效果 | Boolean | true | +| ok-text | 确定按钮的文字, | String | 确定 | +| cancel-text | 取消按钮的文字, | String | 取消 | +| cancel | 点击取消的回调, | Function | - | +| ok | 点击确定的回调, | Function | - | \ No newline at end of file diff --git a/components/popconfirm/popconfirm.jsx b/components/popconfirm/popconfirm.jsx new file mode 100755 index 0000000000000000000000000000000000000000..772460e3ce810b8b47deebddaa8a56074693a32e --- /dev/null +++ b/components/popconfirm/popconfirm.jsx @@ -0,0 +1,35 @@ +import PopBase from '../base/pop' +export default { + name: 'Popconfirm', + props: { + dark: Boolean, + transfer: { type: Boolean, default: true }, + title: String, + width: [Number, String], + okText: { type: String, default: '确定' }, + cancelText: { type: String, default: '取消' }, + placement: { + validator(value) { + return ( + ["top", "top-left", "top-right", "bottom", "bottom-left", "bottom-right", "left", "left-bottom", "left-top", "right", "right-top", "right-bottom"].indexOf(value) >= 0 + ); + }, + default: "top" + }, + }, + render() { + let props = { + props: { preCls: 'popconfirm', ...this.$props, confirm: true }, + on: { + 'ok': e => this.$emit('ok'), + 'cancel': e => this.$emit('cancel') + } + } + return ( ++ + + +{{title}}
+{{title}}
+ ++ + + +{{title}}
+{{title}}
+ ++ + + +{{title}}
+{{title}}
+ ++ {this.$slots.default} + {this.$slots.title} + + ) + } +}; \ No newline at end of file diff --git a/components/popconfirm/styles/index.less b/components/popconfirm/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..ca1635cc28cb044b9186460b053f49ee1282efb8 --- /dev/null +++ b/components/popconfirm/styles/index.less @@ -0,0 +1,185 @@ +@import '../../styles/global.less'; +.k-popconfirm { + display: inline-block; + position: relative; +} + +.k-popconfirm-content { + min-width: 200px; + // max-width: 300px; + font-size: 12px; + line-height: 1.5; + position: absolute; + z-index: 1001; + .k-popconfirm-inner { + background: #fff; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + border-radius: @radius; + } + .k-popconfirm-inner-content { + padding: 18px 18px 10px 18px; + box-sizing: border-box; + position: relative; + } + .k-icon { + position: absolute; + font-size: 18px; + color: @warning; + top: 19px; + } + .k-popconfirm-footer { + text-align: right; + padding-top: 10px; + } + .k-popconfirm-title { + padding: 0 0 0 24px; + font-size: 14px; + } + .k-popconfirm-arrow { + position: absolute; + width: 12px; + height: 12px; + border: 4px solid transparent; + box-sizing: border-box; + transform: rotate(45deg); + background: #fff; + } + .k-popconfirm-footer { + text-align: right; + padding: 8px 16px 16px; + .k-btn { + margin-left: 10px; + } + } + &[k-placement^=top] { + .k-popconfirm-arrow { + bottom: 8px; + box-shadow: 3px 3px 7px rgba(0, 0, 0, 0.07); + } + .k-popconfirm-inner { + margin-bottom: 12px; + } + } + &[k-placement=top] { + .k-popconfirm-arrow { + left: 50%; + transform: translateX(-50%) rotate(45deg); + } + } + &[k-placement=top-right] { + .k-popconfirm-arrow { + right: 10px; + } + } + &[k-placement=top-left] { + .k-popconfirm-arrow { + left: 10px; + } + } + &[k-placement^=bottom] { + .k-popconfirm-arrow { + top: 8px; + box-shadow: -3px -3px 7px rgba(0, 0, 0, 0.07); + } + .k-popconfirm-inner { + margin-top: 12px; + } + } + &[k-placement=bottom] { + .k-popconfirm-arrow { + left: 50%; + } + } + &[k-placement=bottom-left] { + .k-popconfirm-arrow { + left: 10px; + } + } + &[k-placement=bottom-right] { + .k-popconfirm-arrow { + right: 10px; + } + } + &[k-placement^=left] { + .k-popconfirm-arrow { + right: 8px; + box-shadow: 3px -3px 7px rgba(0, 0, 0, 0.07); + } + .k-popconfirm-inner { + margin-right: 12px; + } + } + &[k-placement=left] { + .k-popconfirm-arrow { + top: 50%; + margin-top: -6px; + } + } + &[k-placement=left-bottom] { + .k-popconfirm-arrow { + bottom: 10px; + } + } + &[k-placement=left-top] { + .k-popconfirm-arrow { + top: 10px; + } + } + &[k-placement^=right] { + .k-popconfirm-arrow { + left: 8px; + box-shadow: -3px 3px 7px rgba(0, 0, 0, 0.07); + } + .k-popconfirm-inner { + margin-left: 12px; + } + } + &[k-placement=right] { + .k-popconfirm-arrow { + top: 50%; + transform: translateY(-50%) rotate(45deg); + } + } + &[k-placement=right-top] { + .k-popconfirm-arrow { + top: 10px; + } + } + &[k-placement=right-bottom] { + .k-popconfirm-arrow { + bottom: 10px; + } + } +} + +@keyframes pop-zoom-in { + from { + opacity: 0; + transform: scale(.8, .8); + } + to { + opacity: 1; + transform: scale(1, 1); + } +} + +@keyframes pop-zoom-out { + from { + opacity: 1; + transform: scale(1, 1); + } + to { + opacity: 0; + transform: scale(.8, .8); + } +} + +.k-popconfirm-fade-enter-active { + // transform-origin: center bottom; + animation: pop-zoom-in .3s; +} + +.k-popconfirm-fade-leave-active { + // transform-origin: center bottom; + animation: pop-zoom-out .3s; +} \ No newline at end of file diff --git a/components/poptip/demo/base.md b/components/poptip/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..ecd4c859b422f95bcb68872e0f85ec8dcf935f13 --- /dev/null +++ b/components/poptip/demo/base.md @@ -0,0 +1,16 @@ ++#### 基础用法 +最简单的用法,浮层的大小由内容区域决定。 + + +```tpl + ++ + + +``` \ No newline at end of file diff --git a/components/poptip/demo/index.vue b/components/poptip/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..23ea498c93f7132398edaf765981c8b42018d319 --- /dev/null +++ b/components/poptip/demo/index.vue @@ -0,0 +1,29 @@ + + \ No newline at end of file diff --git a/components/poptip/demo/info.md b/components/poptip/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..02ac5cb2597988bd26f23814be11f547df26f032 --- /dev/null +++ b/components/poptip/demo/info.md @@ -0,0 +1,9 @@ +## Poptip +点击/鼠标移入元素,弹出气泡式的卡片浮层。 + +## 何时使用 +当目标元素有进一步的描述和相关操作时,可以收纳到卡片中,根据用户的操作行为进行展现。 + +和 `Tooltip` 的区别是,用户可以对浮层上的元素进行操作,因此它可以承载更复杂的内容,比如链接或按钮等。 + +## 代码演示 \ No newline at end of file diff --git a/components/poptip/demo/placement.md b/components/poptip/demo/placement.md new file mode 100755 index 0000000000000000000000000000000000000000..33e82664656e146752916deed4e74d5f27010fb7 --- /dev/null +++ b/components/poptip/demo/placement.md @@ -0,0 +1,111 @@ +明月几时有,把酒问青天!
+明月几时有,把酒问青天!
+ + ++#### 位置 +通过 `placement`控制方向, 位置有十二个方向。 + + +```tpl + ++++ + + +{{tip}}
+{{tip}}
+ ++ + + +{{tip}}
+{{tip}}
+ ++ + + +{{tip}}
+{{tip}}
+ ++++ + + +{{tip}}
+{{tip}}
+ ++ + + +{{tip}}
+{{tip}}
+ ++ + + +{{tip}}
+{{tip}}
+ ++++ + + +{{tip}}
+{{tip}}
+ ++ + + +{{tip}}
+{{tip}}
+ ++ + + +{{tip}}
+{{tip}}
+ +++ + +``` \ No newline at end of file diff --git a/components/poptip/demo/trigger.md b/components/poptip/demo/trigger.md new file mode 100755 index 0000000000000000000000000000000000000000..57d86b1fa191c60b9e1a189a908640abb2f74cce --- /dev/null +++ b/components/poptip/demo/trigger.md @@ -0,0 +1,23 @@ ++ + + +{{tip}}
+{{tip}}
+ ++ + + +{{tip}}
+{{tip}}
+ ++ + + +{{tip}}
+{{tip}}
+ ++#### 触发模式 +通过 `trigger`来控制触发模式, 鼠标移入 `hover`、点击 `click`。 + + +```tpl + ++ + +明月几时有,把酒问青天!
+明月几时有,把酒问青天!
+ + ++ + + +``` \ No newline at end of file diff --git a/components/poptip/index.js b/components/poptip/index.js new file mode 100755 index 0000000000000000000000000000000000000000..d07d9c17b33161a8843b4db39a6776e7649ee3ff --- /dev/null +++ b/components/poptip/index.js @@ -0,0 +1,2 @@ +import Poptip from './poptip.jsx' +export default Poptip \ No newline at end of file diff --git a/components/poptip/index.md b/components/poptip/index.md new file mode 100755 index 0000000000000000000000000000000000000000..bf3461ae8212aaf7d2c0471ac17c5972f339eab9 --- /dev/null +++ b/components/poptip/index.md @@ -0,0 +1,9 @@ +## API +| 属性 | 说明 | 类型 | 默认值 | +|-----------|----------------------------------------------------------------------------------------------------------------------------------------------------|---------------|-------| +| trigger | 触发方式,可选值为 `hover`(悬停)`click`(点击) | String | click | +| title | 显示的标题 | String | - | +| content | 显示的正文内容 | slots | - | +| placement | 提示框出现的位置,可选值为`top`,`top-left`,`top-right`,`bottom`,`bottom-left`,`bottom-right`,`left`,`left-top`,`left-bottom`,`right`,`right-top`,`right-bottom` | String | top | +| width | 展示的宽度,默认为内容区域的大小 | String,Number | - | +| transfer | 是否将弹层放置于 `body` 内,在 `Tabs`、带有 `fixed` 的 `Table` 列内使用时,建议添加此属性,它将不受父级样式影响,从而达到更好的效果 | Boolean | true | diff --git a/components/poptip/poptip.jsx b/components/poptip/poptip.jsx new file mode 100755 index 0000000000000000000000000000000000000000..85c4a836de117b35d6464e4d8dabe791020d5161 --- /dev/null +++ b/components/poptip/poptip.jsx @@ -0,0 +1,30 @@ +import BasePop from '../base/pop' +export default { + name: 'Poptip', + props: { + trigger: { type: String, default: "hover" }, + dark: Boolean, + transfer: { type: Boolean, default: true }, + title: String, + width: [Number, String], + placement: { + validator(value) { + return ( + ["top", "top-left", "top-right", "bottom", "bottom-left", "bottom-right", "left", "left-bottom", "left-top", "right", "right-top", "right-bottom"].indexOf(value) >= 0 + ); + }, + default: "top" + }, + }, + render() { + let props = { + props: { preCls: 'poptip', ...this.$props } + } + return ( +明月几时有,把酒问青天!
+明月几时有,把酒问青天!
+ + ++ {this.$slots.default} + {this.$slots.content} + + ) + } +}; \ No newline at end of file diff --git a/components/poptip/styles/index.less b/components/poptip/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..2ed3107292eab76658b29a27fca1acdb5f79f61a --- /dev/null +++ b/components/poptip/styles/index.less @@ -0,0 +1,182 @@ +@import '../../styles/global.less'; +.k-poptip { + display: inline-block; + position: relative; +} + +.k-poptip-content { + min-width: 200px; + // max-width: 300px; + font-size: 12px; + line-height: 1.5; + position: absolute; + z-index: 1001; + .k-poptip-inner { + background: #fff; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + border-radius: @radius; + } + .k-poptip-inner-content { + padding: 8px 16px; + box-sizing: border-box; + } + .k-poptip-title { + font-size: 14px; + font-weight: 500; + color: @color; + margin: 0; + padding: 8px 16px; + position: relative; + border-bottom: 1px solid #eee; + text-overflow: ellipsis; + overflow: hidden; + } + .k-poptip-arrow { + position: absolute; + width: 12px; + height: 12px; + border: 4px solid transparent; + box-sizing: border-box; + transform: rotate(45deg); + background: #fff; + } + &[k-placement^=top] { + .k-poptip-arrow { + bottom: 8px; + box-shadow: 3px 3px 7px rgba(0, 0, 0, 0.07); + } + .k-poptip-inner { + margin-bottom: 12px; + } + } + &[k-placement=top] { + .k-poptip-arrow { + left: 50%; + transform: translateX(-50%) rotate(45deg); + } + } + &[k-placement=top-right] { + .k-poptip-arrow { + right: 10px; + } + } + &[k-placement=top-left] { + .k-poptip-arrow { + left: 10px; + } + } + &[k-placement^=bottom] { + .k-poptip-arrow { + top: 8px; + box-shadow: -3px -3px 7px rgba(0, 0, 0, 0.07); + } + .k-poptip-inner { + margin-top: 12px; + } + } + &[k-placement=bottom] { + .k-poptip-arrow { + left: 50%; + } + } + &[k-placement=bottom-left] { + .k-poptip-arrow { + left: 10px; + } + } + &[k-placement=bottom-right] { + .k-poptip-arrow { + right: 10px; + } + } + &[k-placement^=left] { + .k-poptip-arrow { + right: 8px; + box-shadow: 3px -3px 7px rgba(0, 0, 0, 0.07); + } + .k-poptip-inner { + margin-right: 12px; + } + } + &[k-placement=left] { + .k-poptip-arrow { + top: 50%; + margin-top: -6px; + } + } + &[k-placement=left-bottom] { + .k-poptip-arrow { + bottom: 10px; + } + } + &[k-placement=left-top] { + .k-poptip-arrow { + top: 10px; + } + } + &[k-placement^=right] { + .k-poptip-arrow { + left: 8px; + box-shadow: -3px 3px 7px rgba(0, 0, 0, 0.07); + } + .k-poptip-inner { + margin-left: 12px; + } + } + &[k-placement=right] { + .k-poptip-arrow { + top: 50%; + transform: translateY(-50%) rotate(45deg); + } + } + &[k-placement=right-top] { + .k-poptip-arrow { + top: 10px; + } + } + &[k-placement=right-bottom] { + .k-poptip-arrow { + bottom: 10px; + } + } +} + +.k-poptip-dark { + background-color: @dark; + color: #fff; + .k-poptip-title { + border-bottom: 1px solid rgba(0, 0, 0, .2); + } +} + +@keyframes pop-zoom-in { + from { + opacity: 0; + transform: scale(.8, .8); + } + to { + opacity: 1; + transform: scale(1, 1); + } +} + +@keyframes pop-zoom-out { + from { + opacity: 1; + transform: scale(1, 1); + } + to { + opacity: 0; + transform: scale(.8, .8); + } +} + +.k-poptip-fade-enter-active { + // transform-origin: center bottom; + animation: pop-zoom-in .3s; +} + +.k-poptip-fade-leave-active { + // transform-origin: center bottom; + animation: pop-zoom-out .3s; +} \ No newline at end of file diff --git a/components/progress/demo/base.md b/components/progress/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..5d1975c0498f15782e4963c642f34c28643804cc --- /dev/null +++ b/components/progress/demo/base.md @@ -0,0 +1,14 @@ ++#### 进度条 +标准的进度条。 + + +```tpl + + + + + + + +``` \ No newline at end of file diff --git a/components/progress/demo/circle.md b/components/progress/demo/circle.md new file mode 100755 index 0000000000000000000000000000000000000000..c8ef57d841862f43584253309176bb09acda8012 --- /dev/null +++ b/components/progress/demo/circle.md @@ -0,0 +1,12 @@ ++#### 进度圈 +圆形的进度条。 + + +```tpl + + + + + +``` \ No newline at end of file diff --git a/components/progress/demo/color.md b/components/progress/demo/color.md new file mode 100755 index 0000000000000000000000000000000000000000..1b70f905b39f61f3e68657949add6fd033c98517 --- /dev/null +++ b/components/progress/demo/color.md @@ -0,0 +1,64 @@ ++#### 颜色和格式 +自定义颜色和自定义格式。 + + +```tpl + + + + +
++ + + + + +``` \ No newline at end of file diff --git a/components/progress/demo/dashboard.md b/components/progress/demo/dashboard.md new file mode 100755 index 0000000000000000000000000000000000000000..7c001e35c00cb7dff3857c23f26b4b86c18efb3a --- /dev/null +++ b/components/progress/demo/dashboard.md @@ -0,0 +1,11 @@ ++#### 盘仪表进度条 +盘仪表进度条。 + + +```tpl + + + + +``` \ No newline at end of file diff --git a/components/progress/demo/dynamic.md b/components/progress/demo/dynamic.md new file mode 100755 index 0000000000000000000000000000000000000000..83a7b1b4cd173deb81862606fe68d8b1bd0ee57e --- /dev/null +++ b/components/progress/demo/dynamic.md @@ -0,0 +1,42 @@ ++#### 动态展示 +会动的进度条才是好进度条。 + + +```tpl + + + + +
++ + + + + +``` \ No newline at end of file diff --git a/components/progress/demo/index.vue b/components/progress/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..9e260a010ac7ec20f3ca090e48c7f87281004fc3 --- /dev/null +++ b/components/progress/demo/index.vue @@ -0,0 +1,25 @@ + \ No newline at end of file diff --git a/components/progress/demo/info.md b/components/progress/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..30e4107b999dd0a5f61d9ab3a05fc328fb4276af --- /dev/null +++ b/components/progress/demo/info.md @@ -0,0 +1,10 @@ +## Progress 进度条 +展示操作的当前进度。 + +## 何时使用 +在操作需要较长时间才能完成时,为用户显示该操作的当前进度和状态。 + +- 当一个操作会打断当前界面,或者需要在后台运行,且耗时可能超过2秒时; +- 当需要显示一个操作完成的百分比时。 + +## 代码演示 \ No newline at end of file diff --git a/components/progress/index.js b/components/progress/index.js new file mode 100755 index 0000000000000000000000000000000000000000..aa9f4ce89e709a34b20c4f42ad1aa6e6bb021d06 --- /dev/null +++ b/components/progress/index.js @@ -0,0 +1,2 @@ +import Progress from './progress' +export default Progress \ No newline at end of file diff --git a/components/progress/index.md b/components/progress/index.md new file mode 100755 index 0000000000000000000000000000000000000000..05434abbfb188fc9b6f9bfc1b970df2602ab7fb5 --- /dev/null +++ b/components/progress/index.md @@ -0,0 +1,9 @@ +## API +| 属性 | 说明 | 类型 | 默认值 | +|----------|-------------------------------------------------------|----------|--------| +| percent | 进度百分比 | Number | 0 | +| color | 进度条颜色 | String | - | +| format | 自定义进度条文字 | Function | - | +| status | 进度条状态,提供四种类型: `active`,`exception`,`success`,`normal` | String | normal | +| type | 进度条类型,提供三种类型: `line`,`circle`,`dashboard` | String | - | +| showInfo | 是否显示进度文字 | Boolean | true | diff --git a/components/progress/progress.jsx b/components/progress/progress.jsx new file mode 100755 index 0000000000000000000000000000000000000000..42a3e33c20db45fff8dc44370036a3470a1815f7 --- /dev/null +++ b/components/progress/progress.jsx @@ -0,0 +1,117 @@ +import Icon from '../icon' +export default { + name: 'Progress', + props: { + percent: { type: Number, default: 0 }, + color: String, + format: Function, + status: { + type: String, default: 'normal', validator: function (s) { + return ['active', 'exception', 'success', 'normal'].indexOf(s) >= 0 + } + }, + type: { + type: String, default: 'line', validator: function (s) { + return ['line', 'circle', 'dashboard'].indexOf(s) >= 0 + } + }, + showInfo: { type: Boolean, default: true } + }, + watch: { + percent(v) { + this.currentPercent = v + } + }, + data() { + return { + currentPercent: this.percent + } + }, + methods: { + renderTip() { + + if (!this.showInfo) return null; + + let { currentPercent, status, type, format } = this, + text = `${currentPercent}%`; + if (typeof format == 'function') { + text = format(currentPercent) + } else { + if (type == 'line') { + if (this.currentPercent == 100) { + text =+ } + if (status == 'exception') + text = + } + if (type == 'circle') { + if (this.currentPercent == 100) { + text = + } + if (status == 'exception') + text = + } + } + return {text} + + }, + renderCircle(radius, percent, strokeWidth, strokeColor, gap = 0, dashboard) { + let offsetRadius = radius - strokeWidth / 2, + benginX = 0, + benginY = - offsetRadius, + endX = 0, + endY = -2 * offsetRadius; + + let d = `M ${radius},${radius} + m ${benginX}, ${(dashboard ? -1 : 1) * benginY} + a ${offsetRadius},${offsetRadius} 0 1 1 ${endX}, ${(dashboard ? 1 : -1) * endY} + a ${offsetRadius},${offsetRadius} 0 1 1 ${(dashboard ? 1 : -1) * endX},${(dashboard ? -1 : 1) * endY}`, + len = Math.PI * 2 * radius, + len2 = Math.PI * (dashboard ? 1.5 : 2) * radius, + style = { + strokeDasharray: `${(percent / 100) * (len2 - gap)}px ${len}px`, //长度,间距 + transition: `stroke-dasharray .3s ease 0s,stroke-width 0.06s ease 0.3s`, + strokeDashoffset: dashboard ? -30 : 0, + stroke: strokeColor + }; + let ds = null + if (dashboard) { + ds = { + strokeDasharray: `${(75 / 100) * (len)}px ${len}px`, //长度,间距 + strokeDashoffset: -30, + } + } + + return () + }, + renderGress() { + let { currentPercent, type, color } = this + if (type == 'line') { + return + ++ } else if (type == 'circle') { + return this.renderCircle(50, currentPercent, 6, color, 17) + } else if (type == 'dashboard') { + return this.renderCircle(50, currentPercent, 6, color, 0, true) + } + } + }, + render() { + let { type, status, currentPercent } = this + if (currentPercent == 100) { + status = 'success' + } + let classes = ['k-progress', `k-progress-${type}`, `k-progress-${status}`, { 'k-progress-hide-info': !this.showInfo }] + let tipNode = this.renderTip() + let gress = this.renderGress() + return ( ++ {[gress, tipNode]} ++ ) + } +} \ No newline at end of file diff --git a/components/progress/styles/index.less b/components/progress/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..5988454fe25ea717a2cca03a0c1a9ecec729a644 --- /dev/null +++ b/components/progress/styles/index.less @@ -0,0 +1,115 @@ +@import '../../styles/global.less'; +.k-progress { + .k-progress-inner { + display: inline-block; + border-radius: 10px; + background-color: @disable-back; + stroke: @disable-back; + overflow: hidden; + vertical-align: middle; + width: calc(100% - 38px); + margin-right: 8px; + } + .k-progress-bg { + height: 8px; + border-radius: 10px; + background-color: @main; + stroke: @main; + width: 30%; + transition: all .3s ease-in-out; + } + .k-progress-text { + display: inline-block; + width: 30px; + font-size: 12px; + color: @color; + line-height: 1; + white-space: nowrap; + vertical-align: middle; + .k-icon { + font-size: 20px; + } + } +} + +.k-progress-hide-info { + .k-progress-inner { + width: 100%; + margin-right: 0; + } +} + +.k-progress-circle, .k-progress-dashboard { + width: 120px; + height: 120px; + display: inline-block; + position: relative; + .k-progress-text { + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + text-align: center; + } +} + +@keyframes k-progress-active { + 0% { + width: 0; + opacity: 0; + } + 80% { + opacity: .3; + width: 80%; + } + 100% { + opacity: 0; + width: 100%; + } +} + +.k-progress-active { + .k-progress-bg { + position: relative; + &:before { + content: ''; + position: absolute; + left: 0; + top: 0; + width: 0; + height: 100%; + background-color: #fff; + opacity: 0; + border-radius: 10px; + animation: k-progress-active 2.4s linear infinite; + } + } +} + +.k-progress-exception { + .k-progress-inner { + .k-progress-bg { + background-color: @danger; + } + } + .k-icon { + color: @danger; + } + .k-progress-bg { + stroke: @danger; + } +} + +.k-progress-success { + .k-progress-inner { + .k-progress-bg { + background-color: @success; + } + } + .k-icon { + color: @success; + } + .k-progress-bg { + stroke: @success; + } +} \ No newline at end of file diff --git a/components/radio/button.jsx b/components/radio/button.jsx new file mode 100755 index 0000000000000000000000000000000000000000..c8141be1c0a4b54c4790fb9b8aa431719d12158c --- /dev/null +++ b/components/radio/button.jsx @@ -0,0 +1,51 @@ +import Button from '../button'; +export default { + name: "RadioButton", + props: { + value: { type: [String, Number, Boolean], default: false }, + disabled: Boolean, + label: [String, Number], + }, + inject: { + FormItem: { default: null }, + groupContext: { default: null }, + }, + data() { + return { + checked: false + } + }, + methods: { + change() { + let { value, $slots, label, groupContext } = this + this.checked = true + if (groupContext) { + label = label || $slots.default.text + groupContext.change({ label, value }) + } else { + this.$emit("input", checked); + this.$emit("change", e); + this.FormItem && this.FormItem.testValue(checked) + } + } + }, + + render() { + let { disabled, change, $slots, label, groupContext, value, checked, $attrs } = this + let prop = {} + if (groupContext) { + checked = groupContext.value == value + let { mini, large, hollow } = groupContext + disabled = disabled || groupContext.disabled + prop = { disabled, mini, large, hollow, type: checked ? 'primary' : 'default' } + } + const props = { + attrs: { ...$attrs }, + on: { click: change }, + props: { ...prop } + } + return ( + + ) + } +}; diff --git a/components/radio/demo/base.md b/components/radio/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..615991615764ab965989bc4a53a586b68c28ad86 --- /dev/null +++ b/components/radio/demo/base.md @@ -0,0 +1,26 @@ ++#### 基本用法 +单独使用可使用 `v-model` 双向绑定数据 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/radio/demo/button.md b/components/radio/demo/button.md new file mode 100755 index 0000000000000000000000000000000000000000..8d86618d81fdabda264cb0ebb9aa227082940f75 --- /dev/null +++ b/components/radio/demo/button.md @@ -0,0 +1,57 @@ +{{checked}}
+Radio + +
+
++ +#### 组合Button使用 +结合 `RadioGroup`,`RadioButton` 可以组合使用 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/radio/demo/disabled.md b/components/radio/demo/disabled.md new file mode 100755 index 0000000000000000000000000000000000000000..54d32a5d138a3857727e4eb719674d3504b6e7ff --- /dev/null +++ b/components/radio/demo/disabled.md @@ -0,0 +1,28 @@ ++ +Beijing +Shanghai +Guangzhou +Shenzhen +Wuhan +
+
++ +Beijing +Shanghai +Guangzhou +Shenzhen +Wuhan +
+
++
+
++ +Beijing +Shanghai +Guangzhou +Shenzhen +Wuhan ++#### 可不用 / 可控 +通过 `disabled` 设置不可用 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/radio/demo/group.md b/components/radio/demo/group.md new file mode 100755 index 0000000000000000000000000000000000000000..5a87734bbdd22d70ee402e395ed1fce2e4a7bf03 --- /dev/null +++ b/components/radio/demo/group.md @@ -0,0 +1,44 @@ +disabled +disabled +
+
+Radio + + ++#### 组合使用 +组合使用可以直接使用 `RadioGroup` 的 `options` 来赋值,或者结合 `Radio` 来组合使用,通过 `disabled` 可以设置组件是否被禁用 +**`RadioGroup` 可以直接使用 `options` 来组合,3.0版本增加** + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/radio/demo/index.vue b/components/radio/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..a3818eb39a4d3bf244242b27d73bc3be228f7bef --- /dev/null +++ b/components/radio/demo/index.vue @@ -0,0 +1,23 @@ + diff --git a/components/radio/demo/info.md b/components/radio/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..c5e36ce7780ae189f15625e0a8a120d573d0ea0a --- /dev/null +++ b/components/radio/demo/info.md @@ -0,0 +1,8 @@ +# 单选框 +单选框。 + +## 何时使用 +- 用于在多个备选项中选中单个状态。 +- 和 Select 的区别是,Radio 所有选项默认可见,方便用户在比较中选择,因此选项不宜过多。 + +## 代码演示 \ No newline at end of file diff --git a/components/radio/group.jsx b/components/radio/group.jsx new file mode 100755 index 0000000000000000000000000000000000000000..1baa2eb9fe679bbde4a0d57a67cd3a791c6fee1a --- /dev/null +++ b/components/radio/group.jsx @@ -0,0 +1,65 @@ +import { getChild } from '../_tool/utils' +import Radio from './radio.jsx'; +import Button from './button.jsx'; +export default { + name: "RadioGroup", + props: { + value: { type: [String, Number], default: "" }, + disabled: Boolean, + mini: Boolean, + large: Boolean, + hollow: Boolean, + circle: Boolean, + options: Array, + type: String, + }, + provide() { + return { + groupContext: this, + } + }, + inject: { + FormItem: { default: null }, + }, + methods: { + change(data) { + let value = data.value + this.$emit("input", value); + this.$emit("change", value); + this.FormItem && this.FormItem.testValue(value) + } + }, + render() { + const { options, $slots, type } = this + let kid = getChild($slots.default) + if (options && options.length) { + kid = options.map(option => { + return type == 'button' ? ( + + ) : ( +Selected:{{data}}
++ + + ++ + + + +
+
+{{cities}}
++ + ) + }) + } + const classes = [ + 'k-radio-group', + { 'k-radio-cirle': this.circle } + ] + return ( + + {kid} ++ ) + } +}; diff --git a/components/radio/index.js b/components/radio/index.js new file mode 100755 index 0000000000000000000000000000000000000000..7c332e803231bd9a94f2b9f783a1a84ddbb728a4 --- /dev/null +++ b/components/radio/index.js @@ -0,0 +1,4 @@ +import Radio from './radio.jsx' +import RadioGroup from './group.jsx' +import RadioButton from './button.jsx' +export { Radio, RadioGroup, RadioButton } \ No newline at end of file diff --git a/components/radio/index.md b/components/radio/index.md new file mode 100755 index 0000000000000000000000000000000000000000..0e86455fd5b567489049c9ab76c13080f5f4b66a --- /dev/null +++ b/components/radio/index.md @@ -0,0 +1,17 @@ +### Radio API +| 属性 | 说明 | 类型 | 默认值 | +|----------|------------------------------|-----------------|-------------------| +| checked | 是否选中状态,可以使用 `v-model` 双向绑定数据 | Boolean | false | +| label | 文字提示 | String 、 Number | - | +| disabled | 是否禁用当前项 | Boolean | false | +| change | 在选项状态发生改变时回调 | - | Function(e:Event) | +### RadioGroup API +| 属性 | 说明 | 类型 | 默认值 | +|---------|--------------------------------------------------------|---------------------------------------------------|-------| +| value | 只在单独使用时有效。可以使用 `v-model` 双向绑定数据 | Boolean | false | +| mini | 针对 `radio-button` 的属性 ,显示迷你模式 | Boolean | false | +| large | 针对 `radio-button` 的属性,显示大尺寸 | Boolean | false | +| circle | 针对 `radio-button` 的属性 ,显示圆角 | Boolean | false | +| change | 在选项状态发生改变时触发,返回当前选中的项 | Function | - | +| options | 可以指定子项 `radio` | Array <{label:string/number,value:string/number}> | - | +| type | 如果使用 `options` 来渲染子集,并且子集为 `button`,需要指定 `type=button` | String | - | \ No newline at end of file diff --git a/components/radio/radio.jsx b/components/radio/radio.jsx new file mode 100755 index 0000000000000000000000000000000000000000..dbbe0f2f85d77c999ac4903106b543f4aa951f69 --- /dev/null +++ b/components/radio/radio.jsx @@ -0,0 +1,69 @@ +import { hasProp } from '../_tool/utils' +export default { + name: "Radio", + props: { + value: { type: [String, Number, Boolean], default: false }, + disabled: Boolean, + checked: [Boolean, Number], + label: [String, Number] + }, + inject: { + FormItem: { default: null }, + groupContext: { default: null }, + }, + model: { + prop: 'checked', + }, + data() { + const checked = hasProp(this, 'checked') ? this.checked : this.value === true + return { + isChecked: checked, + } + }, + methods: { + change(e) { + let { disabled, value, $slots, label, groupContext } = this + if (disabled) { + return false; + } + const checked = e.target.checked; + this.isChecked = checked; + if (groupContext) { + label = label || $slots.default.text + this.groupContext.change({ label, value }) + } else { + this.$emit("input", checked); + this.$emit("change", e); + this.FormItem && this.FormItem.testValue(checked) + } + } + }, + + render() { + let { disabled, change, $slots, label, groupContext, value, checked, isChecked } = this + if (groupContext) { + checked = groupContext.value == value + disabled = disabled || groupContext.disabled + } else { + if (!hasProp(this, 'checked')) { + checked = isChecked + } + } + const wpclasses = [ + "k-radio-wrapper", { ["k-radio-disabled"]: disabled } + ]; + const classes = [ + "k-radio", { ["k-radio-checked"]: checked } + ]; + const labelNode = label || $slots.default + return ( + + ) + } +}; diff --git a/src/components/radio/radio.less b/components/radio/styles/index.less old mode 100644 new mode 100755 similarity index 70% rename from src/components/radio/radio.less rename to components/radio/styles/index.less index 16eb239236de6a904840f03a2a5793e097004542..a77b85ca71185a0eabbb565fa80f4a8f878c01b9 --- a/src/components/radio/radio.less +++ b/components/radio/styles/index.less @@ -2,37 +2,49 @@ .k-radio-group { display: inline-block; font-size: 0; - vertical-align: middle; + // vertical-align: middle; + white-space: nowrap; .k-btn { position: relative; margin-left: -1px !important; z-index: 0; border-radius: 0; - float: left; + &:focus { + z-index: 2; + } &:first-child { border-top-left-radius: @radius; border-bottom-left-radius: @radius; - border-top-right-radius: 0; - border-bottom-right-radius: 0; } &:last-child { border-top-right-radius: @radius; border-bottom-right-radius: @radius; - border-top-left-radius: 0; - border-bottom-left-radius: 0; } } - .k-btn-primary { - z-index: 1 + .k-btn-primary.k-btn-hollow { + z-index: 1; + color: @main; + border-color: @main; + } +} + +.k-radio-cirle { + .k-btn:first-child { + border-top-left-radius: 30px; + border-bottom-left-radius: 30px; + } + .k-btn:last-child { + border-top-right-radius: 30px; + border-bottom-right-radius: 30px; } } -.k-radio-wp { +.k-radio-wrapper { user-select: none; cursor: pointer; font-size: 12px; display: inline-block; - margin-right: 8px; + line-height: 1; .k-radio { display: inline-block; vertical-align: middle; @@ -41,7 +53,8 @@ outline: 0; line-height: 1; position: relative; - margin-right: 5px; + margin: 0; + font-size: 0; .k-radio-inner { box-sizing: content-box; display: inline-block; @@ -50,7 +63,7 @@ position: relative; top: 0; left: 0; - border: 1px solid #dddee1; + border: 1px solid @border-color; border-radius: 2px; background-color: #fff; transition: border-color .2s ease-in-out, background-color .2s ease-in-out; @@ -81,6 +94,12 @@ z-index: 1; cursor: pointer; opacity: 0; + &:focus { + +.k-radio-inner { + border: 1px solid @main; + box-shadow: 0 0 5px fade(@main, 75%); + } + } } } .k-radio-checked { @@ -97,29 +116,24 @@ } } } - .k-radio-disabled { - cursor: not-allowed; - .k-radio-inner { - background: #f3f3f3; - &:after { - background-color: #f3f3f3; - } - } + .k-radio-label { + padding: 0 8px; } } .k-radio-disabled { cursor: not-allowed; - opacity: .5; + // opacity: .5; + color: @disable-color; .k-radio { .k-radio-input { cursor: not-allowed; } .k-radio-inner { - background: #f3f3f3; - border-color: #d0d0d0; + background: @disable-back; + border-color: @disable-border; &:after { - background-color: #999; + background-color: @disable-border; } } } diff --git a/components/select/demo/base.md b/components/select/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..8850cc09ff437f962edccebef850e479414bdd37 --- /dev/null +++ b/components/select/demo/base.md @@ -0,0 +1,42 @@ ++#### 基础用法 +通过 `v-model` 进行数据双向绑定 + + +```tpl + ++ + + ++ + +``` \ No newline at end of file diff --git a/components/select/demo/clearable.md b/components/select/demo/clearable.md new file mode 100755 index 0000000000000000000000000000000000000000..38c2e7d57a18033ceb0597d479a905d566c5231b --- /dev/null +++ b/components/select/demo/clearable.md @@ -0,0 +1,36 @@ +
+ +
+ ++#### 可清除 +通过 `clearable` 可控制组件是否显示清除按钮 + + +```tpl + ++ + {{value1}} ++ + +``` \ No newline at end of file diff --git a/components/select/demo/filterable.md b/components/select/demo/filterable.md new file mode 100755 index 0000000000000000000000000000000000000000..6da5296f5938c786d1e32e63345ef659572cba43 --- /dev/null +++ b/components/select/demo/filterable.md @@ -0,0 +1,53 @@ +
+ + {{value2}} ++#### 过滤 +通过设置 `filterable` 值来呈现过滤模式 + + +```tpl + +++ + + +``` \ No newline at end of file diff --git a/components/select/demo/index.vue b/components/select/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..aca77ed93ecf92c539329de03fa871a729362d7a --- /dev/null +++ b/components/select/demo/index.vue @@ -0,0 +1,33 @@ + + \ No newline at end of file diff --git a/components/select/demo/info.md b/components/select/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..91b418d2fdaa776e6d906eaad23f8ead93e3c1d4 --- /dev/null +++ b/components/select/demo/info.md @@ -0,0 +1,8 @@ +# Select 选择器 +下拉选择器。 + +## 何时使用 +- 弹出一个下拉菜单给用户选择操作,用于代替原生的选择器,或者需要一个更优雅的多选器时。 +- 当选项少时(少于 5 项),建议直接将选项平铺,使用 Radio 是更好的选择。 + +## 代码演示 \ No newline at end of file diff --git a/components/select/demo/multiple.md b/components/select/demo/multiple.md new file mode 100755 index 0000000000000000000000000000000000000000..f9d87985f411ee4a0a93aa158a6d7379fa647613 --- /dev/null +++ b/components/select/demo/multiple.md @@ -0,0 +1,50 @@ +Selected value:{{data}}
+ +Selected value:{{data2}}
+ +Selected value:{{data3}}
+ ++#### 多选 +通过设置 `multiple` 值来呈现多选模式 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/select/demo/search.md b/components/select/demo/search.md new file mode 100755 index 0000000000000000000000000000000000000000..2d0b79a1eb5ee82aabef53b7cac17d64416b649a --- /dev/null +++ b/components/select/demo/search.md @@ -0,0 +1,70 @@ +Select value:{{data}}
+ + + +
+ +
+ ++#### 远程搜索 +通过设置 `search` 值来呈现过滤模式,设置 `loading` 展示加载模式 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/select/demo/size.md b/components/select/demo/size.md new file mode 100755 index 0000000000000000000000000000000000000000..e9f2505555af326749af34e23cf561995aaf549c --- /dev/null +++ b/components/select/demo/size.md @@ -0,0 +1,29 @@ +Selected value:{{s1}}
+ +Selected value:{{s2}}
+ ++#### 尺寸 +通过 `width` 和 `mini` 可控制组件尺寸大小 + + +```tpl + ++ + + ++ +``` \ No newline at end of file diff --git a/components/select/index.js b/components/select/index.js new file mode 100755 index 0000000000000000000000000000000000000000..bd69eaee46ec8015bed0d57f61978dd7d8c9e1cd --- /dev/null +++ b/components/select/index.js @@ -0,0 +1,3 @@ +import Select from './select.jsx' +import Option from './option.jsx' +export { Select, Option } \ No newline at end of file diff --git a/components/select/index.md b/components/select/index.md new file mode 100755 index 0000000000000000000000000000000000000000..adb281af49e3bd94be1cfd7223440ae02cb07c39 --- /dev/null +++ b/components/select/index.md @@ -0,0 +1,20 @@ +### Select API +| 属性 | 说明 | 类型 | 默认值 | +|-------------|--------------------------------------------------------------------------|---------------|-------------| +| value | 指定选中项目的 `value` 值,可以使用 `v-model` 双向绑定数据 | String,Number | - | +| width | 组件宽度 | String,Number | - | +| placeholder | 选择框默认文字 | String | 请选择 | +| disabled | 是否禁用当前项 | Boolean | false | +| mini | 组件尺寸大小 | Boolean | false | +| multiple | 是否呈现多选模式 | Boolean | false | +| loading | 是否显示异步加载 | Boolean | false | +| clearable | 是否可以清空选项 | Boolean | false | +| change | 在选项状态发生改变时触发,返回选择项{value:xx,label:xx} | Function | - | +| open-change | 下拉框展开或收起时触发 | Function | true, false | +| transfer | 是否将弹层放置于 `body` 内,在 `Tabs` 带有 `fixed` 的 `Table` 列内使用时,建议添加此属性,它将不受父级样式影响 | Boolean | false | +### Option API +| 属性 | 说明 | 类型 | 默认值 | +|----------|---------------------|---------------|-------| +| value | 选项值,默认根据此属性值进行筛选,必填 | String,Number | - | +| label | 选项显示的内容 | String,Number | - | +| disabled | 是否禁用当前项 | Boolean | false | \ No newline at end of file diff --git a/components/select/option.jsx b/components/select/option.jsx new file mode 100755 index 0000000000000000000000000000000000000000..3310de0561c96bdec6bac386c7987a31f9daf266 --- /dev/null +++ b/components/select/option.jsx @@ -0,0 +1,58 @@ +import { hasProp } from "../_tool/utils"; +import Icon from '../icon' +export default { + name: "Option", + props: { + value: { type: [String, Number], required: true }, + label: { type: [String, Number] }, + disabled: Boolean + }, + inject: { + groupContext: { default: null } + }, + methods: { + select() { + let { value, label, disabled, groupContext, $slots } = this + if (disabled) return; + if (groupContext) { + label = label || $slots.default + // if (groupContext.multiple) { + + // } else { + groupContext.change({ label, value }) + // } + } + }, + }, + render() { + let { disabled, groupContext, value, label, $slots, select } = this + let selected = false; + label = label || $slots.default + let iconNode = null + if (groupContext) { + let _value = groupContext.value + if (!hasProp(groupContext, 'value')) { + _value = groupContext.currentValue + } + if (groupContext.multiple) { + selected = _value.indexOf(value) !== -1 + + iconNode =+ } else { + selected = _value === value + } + } + const classes = [ + "k-select-item", + { + ["k-select-item-selected"]: selected, + ["k-select-item-disabled"]: disabled + } + ]; + const kid = {label}{iconNode} + + return ( + {kid} + ) + } +} \ No newline at end of file diff --git a/components/select/select.jsx b/components/select/select.jsx new file mode 100755 index 0000000000000000000000000000000000000000..e226d4cdeab72691a1e09b280445a4a9c6a752a9 --- /dev/null +++ b/components/select/select.jsx @@ -0,0 +1,418 @@ +import transfer from "../_tool/transfer"; +import Resize from "../_tool/resize"; +import Option from './option' +import outsideclick from "../_tool/outsiteclick"; +import Icon from "../icon"; +import Empty from '../empty'; +import { hasProp, getElementPos, getChild, isNotEmpty } from '../_tool/utils' +let timestamp = Date.now() +let count = 0 +function getUuid() { + return `k-select-lable__${timestamp}__${count++}` +} +export default { + directives: { transfer, Resize, outsideclick }, + name: "Select", + props: { + placeholder: { type: String, default: "请选择" }, + mini: Boolean, + large: Boolean, + transfer: { type: Boolean, default: true }, + width: [Number, String], + value: [String, Number, Array], + clearable: Boolean, + filterable: Boolean, + disabled: Boolean, + multiple: Boolean, + loading: Boolean, + options: Array + }, + provide() { + return { + groupContext: this + } + }, + inject: { + FormItem: { default: null }, + }, + data() { + return { + left: 0, + top: 0, + label: "", + showDrop: false, + showDropInit: false, + currentValue: this.value || '', + placement: 'bottom', + showSearch: false, + queryKey: '', + selectWidth: this.width + }; + }, + watch: { + value(value) { + if (isNotEmpty(value)) { + this.currentValue = value + this.setLabel() + } else { + this.label = '' + this.currentValue = '' + } + this.FormItem && this.FormItem.testValue(value) + } + }, + methods: { + hidedrop(e) { + if (this.showDropInit && !this.$el.contains(e.target) && !this.$refs.dom.contains(e.target)) { + if (this.showSearch) { + this.queryKey = '' + this.$refs.search.value = '' + this.$refs.search.style.width = '' + } + this.showDrop = false + this.showSearch = false + } + }, + setLabel() { + let currentValue = this.value || this.currentValue + // if (!isNotEmpty(currentValue) || currentValue.length == 0) return; + let kid = this.getOptions() + if (kid) { + let currentLabel = this.label || '' + if (this.multiple) { + currentLabel = currentLabel || [] + currentValue = currentValue || [] + } + kid.forEach(c => { + if (c.tag) { + let { value, label } = c.componentOptions.propsData + label = label || (c.componentOptions.children[0].text || '').trim() + if (this.multiple) { + let index = currentLabel.map(v => v.label).indexOf(label) + if (currentValue.indexOf(value) >= 0) { + if (index === -1) { + let key = getUuid() + currentLabel.push({ label, key }) + } + } else { + if (index >= 0) { + currentLabel.splice(index, 1) + } + } + } else if (currentValue === value) { + currentLabel = label + return false + } + } + }) + this.label = currentLabel + } + setTimeout(e => { this.setPosition() }, 230); + + }, + clear(e) { + this.label = '' + this.currentValue = '' + this.$emit("input", ""); + this.$emit("change", {}); + e.stopPropagation() + }, + showDrops() { + let isSearch = ('search' in this.$listeners) + + this.showDrop = !this.showDrop; + if (this.filterable || isSearch) { + if (this.showDrop) { + this.showSearch = true + this.$nextTick(e => this.$refs.search.focus()) + } else { + this.showSearch = false + this.$refs.search.blur() + } + } + + this.$nextTick(e => this.setPosition()) + }, + toggleDrop() { + if (this.disabled) { + return false; + } + let isSearch = ('search' in this.$listeners) + if (isSearch) { + if (!this.showDropInit) { + this.showDropInit = true + this.$nextTick(e => { + this.showSearch = true + this.$nextTick(e => this.$refs.search.focus()) + }) + } else { + this.showSearch = true + this.$nextTick(e => this.$refs.search.focus()) + } + return; + } + if (!this.showDropInit) { + this.showDropInit = true + this.$nextTick(e => this.showDrops()) + } else { + this.showDrops() + } + }, + setPosition() { + let top = 0, left = 0, height = this.$el.offsetHeight, offset = 3; + if (!hasProp(this, 'width')) { + this.selectWidth = this.$el.offsetWidth + } + if (this.transfer) { + let pos = getElementPos(this.$el) + top = pos.top + height + offset + left = pos.left + 1 + } else { + top = height + offset + } + if (this.$refs.dom) { + let clientH = document.body.scrollHeight + let domH = this.$refs.dom.offsetHeight + if (clientH - top - height - offset < domH + 5) { + top = this.transfer ? top - domH - offset : -(domH + 3) + this.placement = 'top' + } else { + this.placement = 'bottom' + } + } + + this.top = top + this.left = left + }, + change(item) { + let { multiple, value, currentValue } = this + if (this.showSearch) { + this.queryKey = '' + this.$refs.search.value = '' + this.$refs.search.style.width = '' + } + if (!multiple) { + this.showDrop = false + this.showSearch = false + } else { + this.$nextTick(e => this.$refs.search.focus()) + } + let hasValue = hasProp(this, 'value') + + //set value + if (multiple) { + if (!hasValue) { + value = currentValue || [] + } + let index = value.indexOf(item.value) + if (index === -1) { + value.push(item.value) + } else { + value.splice(index, 1) + } + + } else { + value = item.value + } + this.currentValue = value + + //set label + if (!hasValue) { + if (multiple) { + let currentLabel = this.label || [] + let index = currentLabel.map(x => x.label).indexOf(item.label) + if (index === -1) { + currentLabel.push({ label: item.label, key: getUuid() }) + } else { + currentLabel.splice(index, 1) + } + this.label = currentLabel + } else { + this.label = item.label + } + setTimeout(e => { this.setPosition() }, 230); + } else { + + this.$nextTick(e => this.setPosition()) + } + this.$emit("input", value); + this.$emit("change", item); + + }, + removeTag(e, i) { + let values = this.currentValue || [] + let labels = this.label || [] + this.change({ value: values[i], label: labels[i].label }) + e.stopPropagation() + }, + searchInput(e) { + this.queryKey = e.target.value + this.$nextTick(k => { + e.target.style.width = this.$refs.mirror.offsetWidth + 'px' + this.setPosition() + }) + if ('search' in this.$listeners) { + clearTimeout(this.timer) + this.timer = setTimeout(() => { + // let kid = getChild(this.$slots.default) + // if (kid.length) { + this.showDrop = true; + this.$emit('search', e) + // } + }, 500); + } + }, + searchBlur(e) { + // setTimeout(a => { + // this.queryKey = '' + // e.target.value = '' + // }, 300) + }, + searchFocus(e) { + // e.target.value = '' + // this.queryKey = '' + // e.target.style.width = '' + }, + emptyClick(e) { + if (this.showSearch) { + this.$nextTick(e => this.$refs.search.focus()) + } + }, + getOptions() { + let { queryKey, options, $slots } = this + let kid = null + if (Array.isArray(options)) { + kid = options.map((k, i) => { + let prop = { + props: { ...k }, + key: i + } + return + }) + } else { + kid = getChild($slots.default) + } + if (this.filterable && queryKey) { + let parsedQuery = String(queryKey).replace(/(\^|\(|\)|\[|\]|\$|\*|\+|\.|\?|\\|\{|\}|\|)/g, "\\$1"); + let Reg = new RegExp(parsedQuery, 'i') + + kid = kid.filter(c => { + let label = c.componentOptions.propsData.label || c.componentOptions.children[0].text + return Reg.test(label) + }) + } + return kid + } + }, + mounted() { + if (hasProp(this, 'value')) + this.setLabel() + }, + render() { + // console.log(h) + let { disabled, mini, multiple, + showDrop, showDropInit, placeholder, + clear, removeTag, queryKey, + clearable, label, toggleDrop, transfer } = this + let childNode = [] + + const classes = [ + "k-select", + { + ["k-select-disabled"]: disabled, + ["k-select-open"]: showDrop, + ["k-select-large"]: this.large && !mini, + ["k-select-mini"]: mini + } + ] + + const styles = { width: `${this.width}px` } + let showClear = !disabled && clearable && label && !multiple + const selectCls = [ + "k-select-selection", { + "k-select-has-clear": showClear + } + ] + + const dropStyle = { + width: `${this.selectWidth}px`, + left: `${this.left}px`, + top: `${this.top}px`, + transformOrigin: this.placement == 'top' ? 'center bottom' : '' + } + + const queryProps = { + on: { + input: this.searchInput, + focus: this.searchFocus, + blur: this.searchBlur + }, + ref: 'search', + class: 'k-select-search', + attrs: { + autoComplete: 'off' + } + } + const queryNode ={queryKey}+ + let drop; + if (showDropInit) { + let kid = this.getOptions() + // kid = ( + // !kid.length + // ?+ // : kid + // ) + const loadingNode = 暂无数据
+ drop = ( +加载中... + + ) + } + label = multiple ? (label || []) : label + const placeNode = ((placeholder && ((!label || !label.length) && !queryKey)) + ?+ {this.loading ? loadingNode : (!kid.length ?+: {kid}
)} +{placeholder}+ : null + ) + const tags = multiple ? + label.map((c, i) => { + return {c.label}removeTag(e, i)} /> + }) + : null + + const labelStyle = { + opacity: this.showSearch ? .4 : 1, + display: queryKey.length ? 'none' : '' + } + const labelsNode = (multiple + ? ( +++ ) + :{tags}{queryNode} +{label}+ ) + let isSearch = ('search' in this.$listeners) + childNode.push(labelsNode) + childNode.push(placeNode) + + !isSearch && childNode.push() + + if ((this.filterable || isSearch) && !multiple) { + childNode.push(queryNode) + } + showClear && childNode.push( ) + + return ( + ++ ) + } +}; diff --git a/components/select/styles/index.less b/components/select/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..e7cee0eed1c3accbfa2d33506acc83950d7ae1cc --- /dev/null +++ b/components/select/styles/index.less @@ -0,0 +1,419 @@ +@import '../../styles/global.less'; +.k-select { + display: inline-block; + width: 100%; + max-width: 100%; + box-sizing: border-box; + vertical-align: middle; + color: #495060; + font-size: 12px; + position: relative; + outline: none; + &:focus { + .k-select-selection { + border: 1px solid @border-color; + box-shadow: 0 0 5px fade(@main, 75%); + } + } + &-selection { + border-radius: @radius; + overflow: hidden; + display: block; + box-sizing: border-box; + outline: 0; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + position: relative; + background-color: #fff; + border: 1px solid @border-color; + transition: border-color .2s ease-in-out, background-color .2s ease-in-out; + min-height: 32px; + position: relative; + } + &-search-wrap { + position: absolute; + left: 5px; + z-index: 1; + top: 50%; + background: none; + transform: translateY(-50%); + .k-select-search { + // border: 1px solid #eee; + border: none; + width: 0.75em; + min-width: 0.75em; + height: 20px; + padding: 0; + background: none; + outline: none; + font-size: 12px; + } + } + &-labels { + padding: 3px 32px 0 0; + overflow: hidden; + .k-select-tag { + padding: 2px 22px 2px 5px; + border: 1px solid @border-color; + border-radius: @radius; + margin: 0 0 3px 5px; + float: left; + position: relative; + line-height: 18px; + overflow: hidden; + .k-icon { + position: absolute; + right: 3px; + font-size: 20px; + text-align: center; + display: block; + top: 50%; + transform: translateY(-50%); + &:hover { + color: @danger; + } + } + } + .k-select-search-wrap { + float: left; + position: relative; + transform: none; + top: 0; + // .k-select-search { + // // border: none; + // top: 50%; + // transform: translateY(-50%); + // z-index: 10; + // position: absolute; + // } + } + } + .k-select-search-mirror { + opacity: 0; + white-space: pre; + pointer-events: none; + position: absolute; + left: 0; + top: 0; + z-index: 1; + font-size: 12px; + } + .k-select-placeholder { + position: absolute; + left: 0; + top: 0; + font-size: 12px; + z-index: 0; + padding-left: 9px; + padding-right: 30px; + overflow: hidden; + text-overflow: ellipsis; + color: @disable-color; + top: 50%; + transform: translateY(-50%); + white-space: nowrap; + max-width: 100%; + box-sizing: border-box; + } + /* .k-select-placeholder { + color: #888; + } */ + /* .k-select-placeholder, */ + .k-select-label { + display: block; + height: 30px; + line-height: 30px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + padding-top: -1px; + padding-left: 8px; + padding-right: 32px; + border: none; + background: transparent; + box-sizing: border-box; + width: 100%; + cursor: pointer; + font-size: 12px; + } + .k-select-arrow { + // font-size: 18px; + position: absolute; + top: 50%; + right: 9px; + font-size: 14px; + box-sizing: border-box; + transform: translateY(-50%) rotate(0deg); + transform-origin: center; + transition: transform .3s ease-in-out; + color: @icon-color; + } + .k-select-clearable { + position: absolute; + top: 50%; + right: 9px; + transform: translateY(-50%); + display: none; + font-size: 15px; + color: @icon-color; + &:hover { + color: @color; + } + } + &:hover, &:focus { + .k-select-selection { + border-color: @main; + } + } +} + +.k-select-dropdown { + user-select: none; + border-radius: @radius; + width: inherit; + max-height: 200px; + overflow: auto; + background-color: #fff; + box-sizing: border-box; + box-shadow: 0 1px 6px rgba(0, 0, 0, .2); + position: absolute; + z-index: 1003; + ul { + padding: 0; + margin: 0; + list-style: none; + left: 0; + } + .k-select-loading { + padding: 10px; + font-size: 12px; + .k-icon { + font-size: 14px; + } + span { + margin-left: 8px; + } + } + .k-select-item { + margin: 0; + line-height: normal; + padding: 7px 16px; + clear: both; + color: #495060; + font-size: 12px !important; + white-space: nowrap; + list-style: none; + width: 100%; + box-sizing: border-box; + overflow: hidden; + text-overflow: ellipsis; + cursor: pointer; + position: relative; + &:hover { + background: @light; + } + .k-icon { + position: absolute; + top: 0; + right: 9px; + font-size: 15px; + top: 50%; + transform: translateY(-50%); + display: none; + color: @icon-color; + } + &:hover .k-icon, .k-icon { + display: block; + } + } + .k-select-item-selected { + background: @light; + color: @main; + font-weight: 500; + &:hover { + background: @light; + } + .k-icon { + color: @main; + display: block; + } + } + .k-select-item-disabled { + background: @disable-back; + color: @disable-color; + cursor: not-allowed; + } + // &:hover{ + // overflow: auto; + // } + // &::-webkit-scrollbar { + // width: 8px; + // height: 8px; + // border-left: 1px solid @border-color; + // padding: 0 2px; + // background: rgba(211, 211, 211, 0.568); + // } + // &::-webkit-scrollbar-thumb { + // background: #ddd; + // border-radius: 3px; + // } +} + +.k-select-dropdown-multiple { + .k-select-item { + padding-right: 31px; + } +} + +.k-select-mini { + .k-select-selection { + min-height: 25px; + } + .k-select-arrow { + font-size: 12px; + right: 5px; + } + .k-select-clearable { + right: 5px; + font-size: 12px; + } + .k-select-label { + line-height: 23px; + height: 23px; + padding-right: 23px; + font-size: 12px; + } + .k-select-placeholder { + font-size: 12px; + } + .k-select-labels { + padding: 2px 23px 0 0; + .k-select-tag { + padding: 2px 22px 2px 5px; + margin: 0 0 3px 4px; + line-height: 1; + .k-icon { + font-size: 18px; + } + } + .k-select-search { + height: 18px; + line-height: 18px; + left: 0; + float: left; + } + } +} + +.k-select-large { + .k-select-placeholder { + font-size: 14px; + } + .k-select-selection { + font-size: 14px; + min-height: 40px; + } + .k-select-arrow { + font-size: 18px; + right: 10px; + } + .k-select-clearable { + right: 10px; + font-size: 18px; + } + .k-select-label { + line-height: 38px; + height: 38px; + padding-right: 32px; + font-size: 14px; + } + .k-select-labels { + padding: 4px 32px 0 0; + .k-select-tag { + padding: 8px 28px 8px 5px; + margin: 0 0 3px 4px; + line-height: 1; + .k-icon { + font-size: 22px; + } + } + .k-select-search { + height: 18px; + line-height: 18px; + left: 0; + float: left; + } + } +} + +.k-select-open { + .k-select-selection { + border-color: @main; // border-color: #3bb4f2; + // box-shadow: 0 0 5px rgba(59, 180, 242, 0.55); + box-shadow: 0 0 5px fade(@main, 75%); + } + .k-select-arrow { + transform: translateY(-50%) rotate(180deg); + } +} + +.k-select-disabled { + color: @disable-color; + .k-select-label { + cursor: not-allowed; + } + .k-select-selection { + background: @disable-back; + cursor: not-allowed; + } + .k-select-arrow { + color: @disable-border; + } + &:hover .k-select-selection { + border-color: @disable-border; + } +} + +.k-select-has-clear { + &:hover { + .k-select-clearable { + display: block; + } + .k-select-arrow { + display: none; + } + } +} + +@keyframes zoomIn { + from { + opacity: 0; + transform: scale(0, 0); + } + to { + opacity: 1; + transform: scale(1, 1); + } +} + +@keyframes zoomOut { + from { + opacity: 1; + transform: scale(1, 1); + } + to { + opacity: 0; + transform: scale(0, 0); + } +} + +.k-select-tag-enter-active { + animation: zoomIn .2s ease-out; +} + +.k-select-tag-leave-active { + animation: zoomOut .2s ease-out; +} \ No newline at end of file diff --git a/docs/src/code/slider.js b/components/slider/demo/slider.js old mode 100644 new mode 100755 similarity index 100% rename from docs/src/code/slider.js rename to components/slider/demo/slider.js diff --git a/docs/src/views/slider.vue b/components/slider/demo/slider.vue old mode 100644 new mode 100755 similarity index 100% rename from docs/src/views/slider.vue rename to components/slider/demo/slider.vue diff --git a/src/components/slider/index.js b/components/slider/index.js old mode 100644 new mode 100755 similarity index 68% rename from src/components/slider/index.js rename to components/slider/index.js index 39ad86c63e2e947788b2b3cf88af8e179e1f1b40..b8ffb1b654ba1cf3bc8623e0bbc2510b4b89763c --- a/src/components/slider/index.js +++ b/components/slider/index.js @@ -1,3 +1,2 @@ -import './slider.less' import Slider from './slider' export default Slider \ No newline at end of file diff --git a/src/components/slider/slider.vue b/components/slider/slider.vue old mode 100644 new mode 100755 similarity index 100% rename from src/components/slider/slider.vue rename to components/slider/slider.vue diff --git a/src/components/slider/sliderButton.vue b/components/slider/sliderButton.vue old mode 100644 new mode 100755 similarity index 100% rename from src/components/slider/sliderButton.vue rename to components/slider/sliderButton.vue diff --git a/src/components/slider/slider.less b/components/slider/styles/index.less old mode 100644 new mode 100755 similarity index 100% rename from src/components/slider/slider.less rename to components/slider/styles/index.less diff --git a/components/spin/demo/base.md b/components/spin/demo/base.md new file mode 100644 index 0000000000000000000000000000000000000000..678f7ee38c90d56b284380229e63aaf08adecb82 --- /dev/null +++ b/components/spin/demo/base.md @@ -0,0 +1,12 @@ ++ {childNode} ++ {drop} ++#### 基本用法 +一个简单的 loading 状态。 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/spin/demo/container.md b/components/spin/demo/container.md new file mode 100644 index 0000000000000000000000000000000000000000..6955735c9fc740088cd3dc1a6df8a2e30bc66440 --- /dev/null +++ b/components/spin/demo/container.md @@ -0,0 +1,39 @@ ++ +#### 卡片加载中 +可以直接把内容内嵌到 Spin 中,将现有容器变为加载状态。 + + +```tpl + +++ + +``` + \ No newline at end of file diff --git a/components/spin/demo/index.vue b/components/spin/demo/index.vue new file mode 100644 index 0000000000000000000000000000000000000000..1d7354c3f445802210af3e5b566a5e9b6db27854 --- /dev/null +++ b/components/spin/demo/index.vue @@ -0,0 +1,21 @@ + diff --git a/components/spin/demo/info.md b/components/spin/demo/info.md new file mode 100644 index 0000000000000000000000000000000000000000..4647950e8a8449e035e6930c3bfcaa31f66c62ee --- /dev/null +++ b/components/spin/demo/info.md @@ -0,0 +1,7 @@ +# Spin 加载中 +用于页面和区块的加载中状态。 + +## 何时使用 +页面局部处于等待异步数据或正在渲染过程时,合适的加载动效会有效缓解用户的焦虑。 + +## 代码演示 \ No newline at end of file diff --git a/components/spin/demo/mode.md b/components/spin/demo/mode.md new file mode 100644 index 0000000000000000000000000000000000000000..6c6e4bc43c131142ed7bb2c00a38b49cc83b4867 --- /dev/null +++ b/components/spin/demo/mode.md @@ -0,0 +1,50 @@ ++ ++ 床前明月光,疑是地上霜。+
+ 举头望明月,低头思故乡。 +
+ Loading state:+ +#### Spin类型 +可以直接把内容内嵌到 Spin 中,将现有容器变为加载状态。 + + +```tpl + +++ + +``` + \ No newline at end of file diff --git a/components/spin/index.js b/components/spin/index.js new file mode 100644 index 0000000000000000000000000000000000000000..ffb62aa83f8f5e783db6f425c5821726680ab818 --- /dev/null +++ b/components/spin/index.js @@ -0,0 +1,2 @@ +import Spin from './spin' +export default Spin \ No newline at end of file diff --git a/components/spin/index.md b/components/spin/index.md new file mode 100644 index 0000000000000000000000000000000000000000..bbc8d84b993956ba9fa3a54046f24b69f3ef9b78 --- /dev/null +++ b/components/spin/index.md @@ -0,0 +1,5 @@ +### Radio API +| 属性 | 说明 | 类型 | 默认值 | +|----------|------------------------------|-----------------|-------------------| +| value | 是否加载状态,可以使用 `v-model` 双向绑定数据 | Boolean | false | +| label | 文字提示 | String 、 Number | - | \ No newline at end of file diff --git a/components/spin/spin.jsx b/components/spin/spin.jsx new file mode 100644 index 0000000000000000000000000000000000000000..b9ca578c4755d389f4856004d9d6de9ece306242 --- /dev/null +++ b/components/spin/spin.jsx @@ -0,0 +1,19 @@ +export default { + name: 'Spin', + props: { + value: { type: Boolean, default: true }, + mode: { type: String, default: 'zoom' } + }, + render() { + const classes = [{ + [`k-spin-loading`]: this.value, + [`k-spin-${this.mode}`]: this.mode && this.value, + }] + + const child = this.$slots.default + const spin = + return ( ++ ++ 床前明月光,疑是地上霜。+
+ 举头望明月,低头思故乡。 +
+ Loading state:+
++ ++ + + + {[spin,child]}+ ) + } +} \ No newline at end of file diff --git a/components/spin/styles/index.less b/components/spin/styles/index.less new file mode 100644 index 0000000000000000000000000000000000000000..406601d8772e61c865bc1f2879c1570afc523428 --- /dev/null +++ b/components/spin/styles/index.less @@ -0,0 +1,135 @@ +@import '../../styles/global.less'; +@spinColor: rgba(255, 255, 255, 0.7); +.k-spin { + // min-width: 50px; + // min-height: 50px; + display: inline-block; + position: relative; + &-loading{ + position: absolute; + width: 100%; + height: 100%; + transition: all .3s; + } + &-flip { + background-color: @spinColor; + &::after { + content: ''; + width: 40px; + height: 40px; + position: absolute; + top: 50%; + left: 50%; + margin-left: -20px; + margin-top: -20px; + background-color: @main; + animation: k-spin-animate-flip 3s 0s cubic-bezier(.09, .57, .49, .9) infinite; + } + } + &-bounce { + background-color: @spinColor; + &::before, &::after { + content: ''; + width: 40px; + height: 40px; + border-radius: 50%; + background-color: @main; + opacity: 0.6; + position: absolute; + top: 50%; + left: 50%; + margin-left: -20px; + margin-top: -20px; + animation: k-spin-animate-bounce 2.0s infinite ease-in-out; + } + &::before { + animation-delay: -1.0s; + } + } + &-zoom { + background-color: @spinColor; + &::before, &::after { + content: ''; + width: 40px; + height: 40px; + border-radius: 50%; + background: @main; + opacity: 0.6; + position: absolute; + top: 50%; + left: 50%; + margin-left: -20px; + margin-top: -20px; + animation: k-spin-animate-zoom 2s 0s cubic-bezier(.09, .57, .49, .9) infinite; + // animation: zoom 2.0s infinite ease-in-out; + } + &::before { + animation-delay: -1.0s; + } + } + &-rotate { + background-color: @spinColor; + &::before, &::after { + border: 5px solid tint(@main, 80%); + border-radius: 50%; + content: ''; + width: 40px; + height: 40px; + position: absolute; + top: 50%; + left: 50%; + margin-left: -20px; + margin-top: -20px; + } + &::after { + border: 5px solid transparent; + border-top-color: @main; + animation: k-spin-animate-rotate .5s infinite linear; + box-sizing: content-box; + } + } +} + +@keyframes k-spin-animate-flip { + 25% { + transform: perspective(100px) rotateX(180deg) rotateY(0); + } + 50% { + transform: perspective(100px) rotateX(180deg) rotateY(180deg); + } + 75% { + transform: perspective(100px) rotateX(0) rotateY(180deg); + } + 100% { + transform: perspective(100px) rotateX(0) rotateY(0); + } +} + +@keyframes k-spin-animate-rotate { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} + +@keyframes k-spin-animate-bounce { + 0%, 100% { + transform: scale(0.0); + } + 50% { + transform: scale(1.0); + } +} + +@keyframes k-spin-animate-zoom { + 0% { + transform: scale(0.0); + opacity: 1; + } + 100% { + transform: scale(1.0); + opacity: 0 + } +} \ No newline at end of file diff --git a/docs/src/code/steps.js b/components/steps/demo/steps.js old mode 100644 new mode 100755 similarity index 100% rename from docs/src/code/steps.js rename to components/steps/demo/steps.js diff --git a/docs/src/views/steps.vue b/components/steps/demo/steps.vue old mode 100644 new mode 100755 similarity index 100% rename from docs/src/views/steps.vue rename to components/steps/demo/steps.vue diff --git a/src/components/steps/index.js b/components/steps/index.js old mode 100644 new mode 100755 similarity index 77% rename from src/components/steps/index.js rename to components/steps/index.js index 59814420b32b37aaa2b32e129ad8c28b9c51e311..e0e1377aefc7984c39ed87fa219f3527de0860aa --- a/src/components/steps/index.js +++ b/components/steps/index.js @@ -1,4 +1,3 @@ -import './steps.less' import Steps from './steps' import Step from './step' diff --git a/src/components/steps/step.vue b/components/steps/step.vue old mode 100644 new mode 100755 similarity index 100% rename from src/components/steps/step.vue rename to components/steps/step.vue diff --git a/src/components/steps/steps.vue b/components/steps/steps.vue old mode 100644 new mode 100755 similarity index 100% rename from src/components/steps/steps.vue rename to components/steps/steps.vue diff --git a/src/components/steps/steps.less b/components/steps/styles/index.less old mode 100644 new mode 100755 similarity index 100% rename from src/components/steps/steps.less rename to components/steps/styles/index.less diff --git a/components/styles.js b/components/styles.js new file mode 100755 index 0000000000000000000000000000000000000000..4f7fd5ca9d6c56222523f4b2ff5d88f60f9a47e4 --- /dev/null +++ b/components/styles.js @@ -0,0 +1,46 @@ +import './alert/styles'; +import './affix/styles'; +import './badge/styles'; +import './backtop/styles'; +import './breadcrumb/styles'; +import './button/styles'; +import './card/styles'; +import './colorPicker/styles'; +import './collapse/styles'; +import './carousel/styles'; +import './checkbox/styles'; +import './datePicker/styles'; +import './drawer/styles'; +import './dropdown/styles'; +import './form/styles'; +import './empty/styles'; +import './icon/styles'; +import './grid/styles'; +import './input/styles'; +import './imagePreview/styles'; +// import './loading/styles'; +import './layout/styles'; +import './modal/styles'; +import './message/styles'; +import './message/styles'; +import './menu/styles'; +import './notice/styles'; +import './page/styles'; +import './poptip/styles'; +import './popconfirm/styles'; +import './progress/styles'; +import './radio/styles'; +// import './scroll/scroll'; +import './spin/styles'; +import './select/styles'; +import './switch/styles'; +// import './slider/slider'; +import './steps/styles'; +import './timeline/styles'; +import './tag/styles'; +import './tooltip/styles'; +import './table/styles'; +import './tree/styles'; +// import './treeselect/styles'; +import './tabs/styles'; +// import './upload/styles'; \ No newline at end of file diff --git a/components/styles/global.less b/components/styles/global.less new file mode 100755 index 0000000000000000000000000000000000000000..afef9eb2ab52f22724329bb99664c74f34693b09 --- /dev/null +++ b/components/styles/global.less @@ -0,0 +1,79 @@ +//颜色 +@main: #3a95ff; +// @main:#7546c9; +@primary: #3a95ff; +@success: #00bb5d; +@danger: #ff3300; +@warning: #ffa500; +@pink: lighten( purple, 45%); +@red: lighten(red, 5%); +@yellow: mix(yellow, orange, 50%); +@orange: lighten(orange, 8%); +@cyan: darken(cyan, 10%); +@green: lighten(green, 15%); +@blue: mix(blue, cyan, 50%); +@purple: lighten(mix(purple,blue, 60%),30%); +@geekblue: mix(blue, cyan, 70%); //极客蓝 +@magenta: mix(pink, red, 40%); //洋红 +@volcano: mix(red, orange, 60%); //火红 +@gold: lighten(gold, 10%); +@lime: mix(green, yellow, 40%); //绿黄色 +@gray: #969696; +@light: #f5f5f5; +@dark: rgba(0, 0, 0, .75); +@color: rgba(0, 0, 0, .75); +@color-light: rgba(255, 255, 255, .75); +@title-color: rgba(0, 0, 0, .85); +@back-color: #fafafa; +@mask-color: rgba(0, 0, 0, .6); +@icon-color: rgba(0, 0, 0, .4); +@radius: ~'5px'; +@border-color: #ddd; +@disable-border: #d0d0d0; +@disable-color: rgba(0, 0, 0, .3); +@disable-light-color: rgba(255, 255, 255, .3); +@disable-back: #f3f3f3; +@dark-back: #22303f; +::selection { + background: @main; + color: #fff; +} + +// *, :after, :before { +// box-sizing: border-box; +// margin: 0; +// -webkit-tap-highlight-color: transparent; +// outline: none; +// } +//下拉动画 +@keyframes dropDownIn { + 0% { + opacity: 0; + transform: scaleY(0) + } + to { + opacity: 1; + transform: scaleY(1) + } +} + +@keyframes dropDownOut { + 0% { + opacity: 1; + transform: scaleY(1) + } + to { + opacity: 0; + transform: scaleY(0) + } +} + +.dropdown-enter-active { + transform-origin: 0 0; + animation: dropDownIn .3s; +} + +.dropdown-leave-active { + transform-origin: 0 0; + animation: dropDownOut .3s +} \ No newline at end of file diff --git a/components/switch/demo/base.md b/components/switch/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..be9520556bed02dff880104df03ae3153251f166 --- /dev/null +++ b/components/switch/demo/base.md @@ -0,0 +1,25 @@ ++#### 基本用法 +可使用 `v-model` 进行数据双向绑定 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/switch/demo/color.md b/components/switch/demo/color.md new file mode 100755 index 0000000000000000000000000000000000000000..d66d0f131e49ef281d0434120269004c4bfc516e --- /dev/null +++ b/components/switch/demo/color.md @@ -0,0 +1,28 @@ +value:{{checked}}
++ +
++ +#### 主题 / 尺寸 +设置 `type` 属性可改变组件主题 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/switch/demo/disabled.md b/components/switch/demo/disabled.md new file mode 100755 index 0000000000000000000000000000000000000000..2dc0ecae7cc21ae6023d23e636d354791e055e6d --- /dev/null +++ b/components/switch/demo/disabled.md @@ -0,0 +1,32 @@ ++ + + +
+
++ + +#### 禁用 / 可控 +通过 `disabled` 属性设置组件是否被禁用 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/switch/demo/index.vue b/components/switch/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..31d00cae1b8405437443b2d5393d881f4a3b3d5e --- /dev/null +++ b/components/switch/demo/index.vue @@ -0,0 +1,28 @@ + + \ No newline at end of file diff --git a/components/switch/demo/info.md b/components/switch/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..dace5e41296c476f60e80611ab8d741cb9f7b633 --- /dev/null +++ b/components/switch/demo/info.md @@ -0,0 +1,8 @@ +# Switch 开关 +开关选择器。 + +## 何时使用 +- 需要表示开关状态/两种状态之间的切换时; +- 和 checkbox的区别是,切换 switch 会直接触发状态改变,而 checkbox 一般用于状态标记,需要和提交操作配合。 + +## 代码演示 \ No newline at end of file diff --git a/components/switch/demo/text.md b/components/switch/demo/text.md new file mode 100755 index 0000000000000000000000000000000000000000..b7121f390396d7a6e17b6228ae998e20b3975c5f --- /dev/null +++ b/components/switch/demo/text.md @@ -0,0 +1,40 @@ ++
++ + +
++
++
++ +#### 文字 / 图标 +通过 `true-text` 和 `false-text` 设置选中和非选中呈现文字, 通过设置 `slot` 为 `(checked|unchecked)` 控制内容 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/switch/index.js b/components/switch/index.js new file mode 100755 index 0000000000000000000000000000000000000000..52bce8273c10c8f57c035c22eaff4aa69af364a9 --- /dev/null +++ b/components/switch/index.js @@ -0,0 +1,2 @@ +import Switch from './switch.jsx' +export default Switch \ No newline at end of file diff --git a/components/switch/index.md b/components/switch/index.md new file mode 100755 index 0000000000000000000000000000000000000000..028c41f8b11a1eaeaaf70d760a715fda9c596f2e --- /dev/null +++ b/components/switch/index.md @@ -0,0 +1,11 @@ +### API +| 属性 | 说明 | 类型 | 默认值 | +|-------------|-------------------------------------------------|---------|-------------------| +| checked | 指定当前是否选中,可以使用 `v-model` 双向绑定数据 | Boolean | false | +| disabled | 禁用开关 | Boolean | false | +| type | 主题颜色 可传入 `success`,`warning`,`danger`,`primary` | String | - | +| mini | 是否展示迷你模式 | Boolean | false | +| checked(unchecked) | 选中(非选中)时的内容 | slot | - | +| true-text | 当 `checked` 为 `true` 时 ,显示的文字 | String | - | +| false-text | 当 `checked` 为 `false` 时 ,显示的文字 | String | - | +| change | 当 `checked` 改变时触发,回调 | - | Function(e:Event) | \ No newline at end of file diff --git a/src/components/switch/switch.less b/components/switch/styles/index.less old mode 100644 new mode 100755 similarity index 66% rename from src/components/switch/switch.less rename to components/switch/styles/index.less index e5c1567e7787a5ec794db4013b36f6e36975fa3c..2a9c100b906a9ad087565d401f68f7f81f4d84b5 --- a/src/components/switch/switch.less +++ b/components/switch/styles/index.less @@ -1,55 +1,69 @@ @import '../../styles/global.less'; .k-switch { - width: 48px; + min-width: 44px; height: 24px; line-height: 22px; border-radius: 24px; vertical-align: middle; border: 1px solid #ccc; background-color: #ccc; + font-size: 12px; position: relative; cursor: pointer; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; - transition: all .2s ease-in-out; + transition: all .36s cubic-bezier(.78, .14, .15, .86); display: inline-block; box-sizing: border-box; overflow: hidden; - .k-switch-button { + outline: none; + &:focus { + // border: 1px solid @main; + box-shadow: 0 0 5px fade(@main, 75%); + } + .k-icon { + font-size: 22px; + } + &:after { + content: ''; width: 20px; height: 20px; border-radius: 20px; background-color: #fff; position: absolute; left: 1px; - top: 1px; + top: 50%; cursor: pointer; - transition: left .2s ease-in-out, width .2s ease-in-out; + transform: translate3d(0, -50%, 0); + transition: all .36s cubic-bezier(.78, .14, .15, .86); } .k-switch-inner { color: #fff; margin-left: 25px; + margin-right: 8px; + display: block; + line-height: 22px; } &:active { - .k-switch-button { + &:after { width: 25px; } } } .k-switch-mini { - width: 28px; + min-width: 28px; height: 16px; - .k-switch-button { + &:after { width: 12px; height: 12px; border-radius: 12px; } &:active { - .k-switch-button { - width: 18px; + &:after { + width: 15px; } } } @@ -57,26 +71,14 @@ .k-switch-checked { background: @main; border-color: @main; - .k-switch-button { - left: 25px; - } - &:active { - .k-switch-button { - left: 20px; - } - } - &.k-switch-mini { - .k-switch-button { - left: 13px; - } - &:active { - .k-switch-button { - left: 7px; - } - } + &:after { + left: 100%; + transform: translate3d(-100%, -50%, 0); + margin-left: -1px; } .k-switch-inner { margin-left: 8px; + margin-right: 25px; } &.k-switch-success { background: #19be6b; diff --git a/components/switch/switch.jsx b/components/switch/switch.jsx new file mode 100755 index 0000000000000000000000000000000000000000..9292a34961cc7dd927765e9daec88699f257ff37 --- /dev/null +++ b/components/switch/switch.jsx @@ -0,0 +1,59 @@ +import { hasProp } from '../_tool/utils' +export default { + name: "kSwitch", + props: { + checked: [Boolean, Number], + type: String, + disabled: Boolean, + mini: Boolean, + trueText: String, + falseText: String, + checked: [Boolean, Number] + }, + model: { + prop: 'checked', + }, + data() { + const checked = hasProp(this, 'checked') ? this.checked : false + return { + isChecked: checked, + } + }, + methods: { + change(e) { + if (this.disabled) { + return false; + } + + let checked = !this.checked + if (!hasProp(this, 'checked')) { + this.isChecked = !this.isChecked; + } else { + this.isChecked = checked + } + this.$emit("input", checked); + this.$emit("change", this.isChecked); + } + }, + render() { + let { disabled, type, mini, change, falseText, trueText, checked, isChecked, $slots } = this + if (!hasProp(this, 'checked')) { + checked = isChecked + } + const classes = [ + "k-switch", + { + ["k-switch-checked"]: checked, + ["k-switch-disabled"]: disabled, + [`k-switch-${type}`]: !!type, + ["k-switch-mini"]: mini, + } + ]; + const textNode = ( + !mini ? {checked ? $slots.checked || trueText : $slots.unchecked || falseText} : null + ) + return ( + + ) + } +}; \ No newline at end of file diff --git a/components/table/demo/base.md b/components/table/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..164532577dc14a3b166d2f4ac6fc6cb7771cee2c --- /dev/null +++ b/components/table/demo/base.md @@ -0,0 +1,41 @@ ++
++
++
+
++ ++ + + ++ +
++ ++ + +#### 基本用法 +一个普通的表格 + + +```tpl + ++ +
+ + +``` diff --git a/components/table/demo/bordered.md b/components/table/demo/bordered.md new file mode 100644 index 0000000000000000000000000000000000000000..b36e8d169b67c8f2261201f12093362809b55640 --- /dev/null +++ b/components/table/demo/bordered.md @@ -0,0 +1,50 @@ +{{tag}} + ++ + Edit + Delete + + +#### 带边框 +添加表格边框线,页头和页脚。 + + +```tpl + ++ {{text}} + + ¥{{text}}/㎡ + + + Header + + + Footer + +
+ + + +``` \ No newline at end of file diff --git a/components/tabs/index.js b/components/tabs/index.js new file mode 100755 index 0000000000000000000000000000000000000000..d01d0f3b7d987ef8d4d822cd4452cdf201f39a9d --- /dev/null +++ b/components/tabs/index.js @@ -0,0 +1,3 @@ +import Tabs from './tabs.jsx' +import TabPane from './tabpane.jsx' +export { Tabs, TabPane } \ No newline at end of file diff --git a/components/tabs/index.md b/components/tabs/index.md new file mode 100644 index 0000000000000000000000000000000000000000..dffb15f1bd3babb284b0bb41d74abff6f3bfaab7 --- /dev/null +++ b/components/tabs/index.md @@ -0,0 +1,19 @@ +### Tabs API +| 属性 | 说明 | 类型 | 默认值 | +|-----------|---------------------------------------|---------------------|--------| +| value | 当前激活 tab 面板的 key | String | - | +| card | 页签样式是否为卡片样式 | Boolean | false | +| sample | 页签样式是否为简洁样式 | Boolean | false | +| animated | 是否使用动画切换 Tabs | Boolean | true | +| remove | tab关闭时的回调,返回关闭的tab的key值 | Function(activeKey) | - | +| change | 切换面板的回调 | Function(activeKey) | - | +| tab-click | tab点击时的回调 | Function(activeKey) | - | + +### Tabs.TabPane API +| 属性 | 说明 | 类型 | 默认值 | +|----------|---------------------|---------|--------| +| key | vue需要的key值 | String | - | +| title | 选项卡头显示文字 | String | - | +| icon | 选项卡头显示的图标 | String | - | +| disabled | tab是否被禁用 | Boolean | false | +| closable | tab是否显示关闭按钮 | Boolean | false | \ No newline at end of file diff --git a/src/components/tabs/tabs.less b/components/tabs/styles/index.less old mode 100644 new mode 100755 similarity index 54% rename from src/components/tabs/tabs.less rename to components/tabs/styles/index.less index b3d64d07069101d7ac09e65304d2e94779f6d2d5..3cbbb6d472d36a91ccede7d7c4c5e5bc45dd15e6 --- a/src/components/tabs/tabs.less +++ b/components/tabs/styles/index.less @@ -2,24 +2,31 @@ .k-tabs { overflow: hidden; .k-tabs-bar { - border-bottom: 1px solid #e8e8e8; + border-bottom: 1px solid @border-color; margin: 0 0 16px; - .k-tabs-tab-next, .k-tabs-tab-prev { + .k-tabs-tab-btn-next, .k-tabs-tab-btn-prev { position: absolute; line-height: 39px; cursor: pointer; left: 0; width: 32px; text-align: center; - display: none; font-size: 20px; + color: @icon-color; + bottom: 0; + } + .k-tabs-tab-btn-next-disabed, .k-tabs-tab-btn-prev-disabed { + color: @disable-color; + cursor:not-allowed; } - .k-tabs-tab-next { + .k-tabs-tab-btn-next { right: 2px; left: auto; } .k-tabs-extra { float: right; + line-height: 45px; + padding-left: 6px; } .k-tabs-nav-container { margin-bottom: -1px; @@ -28,17 +35,18 @@ overflow: hidden; font-size: 14px; line-height: 1.5; - } - .k-tabs-nav-wrap { - overflow: hidden; + .k-tabs-nav-wrap { + overflow: hidden; + } + .k-tabs-nav{ + display: inline-block; + transition: transform .3s; + } } .k-tabs-nav-container-scroll { padding: 0 32px; .k-tabs-nav-scroll { - transition: transform .3s ease-in-out; - } - .k-tabs-tab-next, .k-tabs-tab-prev { - display: block; + transition: transform .3s; } } .k-tabs-tab { @@ -46,48 +54,38 @@ height: 100%; margin: 0 32px 0 0; padding: 12px 16px; + font-size: 14px; cursor: pointer; user-select: none; - transition: all .3s ease-in-out; + transition: color .3s; border-top-left-radius: @radius; border-top-right-radius: @radius; - i { - margin-right: 8px; - font-size: 14px; - } - .k-ion-md-close { + color: @color; + .k-tabs-close { margin: 0 -5px 0 0; width: 16px; text-align: center; - color: #999; + color: @icon-color; &:hover { - color: @danger !important; + color: @danger; } } - } - .k-tabs-tab-active { - position: relative; - &::after { - position: absolute; - bottom: 0; - content: ''; - left: 0; - height: 2px; - background: @main; - width: 100%; + &:last-child{ + margin: 0 2px 0 0; + } + &:hover { + color: @main; } } - .k-tabs-tab-active, .k-tabs-tab:hover { + .k-tabs-tab-active { color: @main; - .k-ion-android-close { - color: #999; - } + font-weight: bold; } .k-tabs-tab-disabled { - color: @gray; - cursor: default; + color: @disable-color; + cursor: not-allowed; &:hover { - color: @gray; + color: @disable-color; } } .k-tabs-ink-bar { @@ -95,14 +93,19 @@ height: 2px; background: @main; bottom: 0; - transition: width .3s ease-in-out, left .3s ease-in-out; + transition: transform .3s ease-in-out, } } .k-tabs-content { width: 100%; - transition: transform .3s ease-in-out; + display: flex; + flex-direction: row; + transition: margin-left .3s cubic-bezier(.645, .045, .355, 1); + will-change: margin-left; .k-tabs-tabpane { - // float: left; + flex-shrink: 0; + width: 100%; + opacity: 1; } } } @@ -114,19 +117,20 @@ .k-tabs-content { .k-tabs-tabpane { float: left; + transition: opacity .45s; } } } .k-tabs-card { - .k-tabs-ink-bar { - display: none; - } .k-tabs-bar { + .k-tabs-extra { + line-height: 38px; + } .k-tabs-tab { margin-right: 2px; - border: 1px solid #e8e8e8; - background: #fafafa; + border: 1px solid @border-color; + background: @back-color; padding: 8px 16px; } .k-tabs-tab-active { @@ -137,6 +141,16 @@ } } } + .k-tabs-content { + display: block; + .k-tabs-tabpane:not(.k-tabs-tabpane-active) { + height: 0; + padding: 0; + overflow: hidden; + opacity: 0; + pointer-events: none; + } + } } .k-tabs-sample { @@ -154,13 +168,21 @@ display: none; } } - .k-tabs-ink-bar { - display: none; - } } - .k-tabs-tabpane { - padding: 16px; - background: #fff; - box-sizing: border-box; + .k-tabs-content { + display: block; + .k-tabs-tabpane { + padding: 16px; + background: #fff; + box-sizing: border-box; + } + .k-tabs-tabpane:not(.k-tabs-tabpane-active) { + height: 0; + padding: 0; + overflow: hidden; + opacity: 0; + pointer-events: none; + transition: none; + } } } \ No newline at end of file diff --git a/components/tabs/tabpane.jsx b/components/tabs/tabpane.jsx new file mode 100644 index 0000000000000000000000000000000000000000..4eea481cb61d8240832af1fe27ff0249eaa4395e --- /dev/null +++ b/components/tabs/tabpane.jsx @@ -0,0 +1,26 @@ +export default { + name: "Tabs", + props: { + title: String, + icon: String, + disabled: Boolean, + closable: Boolean + }, + inject: { + Tabs: { default: {} }, + collectTabPanes: { default: () => { } } + }, + created() { + this.collectTabPanes(this, 'add') + }, + beforeDestroy() { + this.collectTabPanes(this, 'delete') + }, + render() { + return ( ++ {this.$slots.default} ++ ) + } +} \ No newline at end of file diff --git a/components/tabs/tabs.jsx b/components/tabs/tabs.jsx new file mode 100644 index 0000000000000000000000000000000000000000..9440fbbce9c67fcb4e7ef1389136efdc169473ef --- /dev/null +++ b/components/tabs/tabs.jsx @@ -0,0 +1,231 @@ +import Icon from '../icon' +export default { + name: 'Tabs', + props: { + value: String, + card: Boolean, + sample: Boolean, + animated: { type: Boolean, default: true } + }, + data() { + return { + tabPanes: [], + activeKey: this.value, + currentIndex: -1, + scrollable: false, + navOffsetLeft: 0, + prevBtnDisabed: false, + nextBtnDisabed: false, + } + }, + watch: { + value(value) { + this.activeKey = value + this.updateIndex() + } + }, + provide() { + return { + Tabs: this, + collectTabPanes: (context, type) => { + const panes = this.tabPanes + type === 'delete' ? panes.splice(panes.indexOf(context), 1) : panes.push(context) + this.resetNavPosition() + this.updateNav() + } + } + }, + mounted() { + window.addEventListener('resize', this.resetNavPosition) + this.updateIndex() + }, + beforeDistory() { + window.removeEventListener('resize', this.resetNavPosition) + }, + methods: { + closeTab(key, e) { + this.$emit('remove', key) + e.stopPropagation() + // e.preventDefault(); + }, + resetActivePostion() { + const target = this.$refs.nav.children[this.currentIndex] + if (!target) return; + // show active tab in client + const pane = this.$refs.navscroll + // let totalWidth = pane.offsetWidth + let clientWidth = this.$refs.navbox.clientWidth + let { navOffsetLeft } = this + let { offsetLeft, offsetWidth } = target + + + + // min left + if (navOffsetLeft + offsetLeft < 0) { + navOffsetLeft = -offsetLeft + } + //max right + else if (clientWidth - navOffsetLeft < offsetLeft + offsetWidth) { //outside + + // let marginRight = window.getComputedStyle(target).marginRight + // marginRight = parseFloat(marginRight) + + navOffsetLeft -= offsetLeft + offsetWidth + navOffsetLeft - clientWidth + 2 //marginRight + } + this.navOffsetLeft = navOffsetLeft + pane.style.transform = `translate3d(${navOffsetLeft}px,0,0)` + }, + resetNavPosition() { + // when one tab removed or append + this.$nextTick(e => { + const pane = this.$refs.navscroll + if (!pane) return; + let totalWidth = pane.offsetWidth + let clientWidth = this.$refs.navbox.clientWidth + let { navOffsetLeft } = this + if (clientWidth + navOffsetLeft < clientWidth) { + navOffsetLeft = clientWidth - totalWidth + } + if (navOffsetLeft > 0) navOffsetLeft = 0 + this.navOffsetLeft = navOffsetLeft + + + this.nextBtnDisabed = navOffsetLeft == clientWidth - totalWidth + this.prevBtnDisabed = navOffsetLeft == 0 + + pane.style.transform = `translate3d(${navOffsetLeft}px,0,0)` + + + this.resetActivePostion() + + this.updateNav() + }) + + }, + scroll(direction) { + //control left or right + + const pane = this.$refs.navscroll + let totalWidth = pane.offsetWidth + let clientWidth = this.$refs.navbox.clientWidth + let { navOffsetLeft } = this + // console.log(totalWidth, clientWidth) + if (direction == 'right') { + const endWidth = totalWidth - clientWidth + navOffsetLeft + if (endWidth > clientWidth) { + navOffsetLeft -= clientWidth + } else if (endWidth > 0) { + navOffsetLeft -= endWidth + } + } else { + if (navOffsetLeft < -clientWidth) { + navOffsetLeft += clientWidth + } else if (navOffsetLeft < 0) { + navOffsetLeft = 0 + } + } + this.nextBtnDisabed = navOffsetLeft == clientWidth - totalWidth + this.prevBtnDisabed = navOffsetLeft == 0 + + this.navOffsetLeft = navOffsetLeft + pane.style.transform = `translate3d(${navOffsetLeft}px,0,0)` + }, + tabClick(pane, index) { + if (!pane.disabled) { + let key = pane.$vnode.key + this.$emit('input', key) + this.$emit('change', key) + this.$emit('tab-click', key) + this.activeKey = key + this.currentIndex = index + } + }, + updateIndex() { + this.$nextTick(e => { + const { tabPanes } = this + const currentTab = tabPanes.filter(tab => tab.$vnode.key == this.activeKey)[0] || {} + this.currentIndex = tabPanes.indexOf(currentTab) + setTimeout(e => { + this.resetActivePostion() + this.updateInkBarPosition() + }, 100) + }) + }, + updateInkBarPosition() { + if (!this.card && !this.sample && this.animated) { + const nav = this.$refs.nav.children[this.currentIndex] + if (nav) { + const inkbar = this.$refs.inkbar + inkbar.style.width = `${nav.offsetWidth}px` + inkbar.style.transform = `translate3d(${nav.offsetLeft}px, 0px, 0px)` + } + } + }, + updateNav() { + this.$nextTick(e => { + // update inkbar position + + // set pane has scroll arrow + const navbox = this.$refs.navbox + if (!navbox) return; + this.scrollable = navbox.scrollWidth > navbox.clientWidth + }) + }, + renderNav() { + return this.tabPanes.map((pane, index) => { + const prop = { + class: ['k-tabs-tab', { ['k-tabs-tab-active']: pane.$vnode.key == this.activeKey, ['k-tabs-tab-disabled']: pane.disabled }], + on: { + click: e => this.tabClick(pane, index) + } + } + return+ {pane.icon ?+ }) + }, + + }, + render() { + const { $slots, card, animated, sample, tabPanes } = this + const classes = [ + "k-tabs", + { + ["k-tabs-animated"]: animated && !card && !sample, + ["k-tabs-card"]: card && !sample, + ["k-tabs-sample"]: sample && !card + } + ]; + + let scrollStyle = {}, paneStyle = {}; + + + if (animated && !card && !sample) { + paneStyle.marginLeft = `-${100 * this.currentIndex}%` + } + + const navCls = ['k-tabs-nav-container', { ['k-tabs-nav-container-scroll']: this.scrollable }] + return ( +: null} + {pane.title} + {pane.closable && this.card ? this.closeTab(pane.$vnode.key, e)} /> : null} + ++ ) + } +} \ No newline at end of file diff --git a/components/tag/demo/base.md b/components/tag/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..33b6d757d1d8b59d8a6db12609acf0c68648f92a --- /dev/null +++ b/components/tag/demo/base.md @@ -0,0 +1,15 @@ + ++ {$slots.default} +++#### 基本用法 +通过 `closeable` 显示关闭按钮,点击隐藏标签,触发 `close` 回调 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/tag/demo/color.md b/components/tag/demo/color.md new file mode 100755 index 0000000000000000000000000000000000000000..c5794daca2714fb600bd64768be70326145d9b41 --- /dev/null +++ b/components/tag/demo/color.md @@ -0,0 +1,49 @@ +标签1 +标签2 +标签3 +标签4 ++#### 多彩标签 +多种预设色彩的标签样式,用作不同场景使用。如果预设值不能满足你的需求,可以设置为具体的色值。 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/tag/demo/dynamic.md b/components/tag/demo/dynamic.md new file mode 100755 index 0000000000000000000000000000000000000000..a4cba0d0676d5d84403a293778af07b650fb8819 --- /dev/null +++ b/components/tag/demo/dynamic.md @@ -0,0 +1,39 @@ ++ Presets: +
+++{{color}} ++ Custom: +
+++#c20 +#39f +#e3f +#6c0 ++#### 动态添加和删除 +通过 `closeable` 显示关闭按钮 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/components/tag/demo/index.vue b/components/tag/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..27a8596f52b5800b90fdb3596aee3949d7253d69 --- /dev/null +++ b/components/tag/demo/index.vue @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/components/tag/demo/info.md b/components/tag/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..9b7b1b8975186f24f1e17266f48b1fe6eef215a1 --- /dev/null +++ b/components/tag/demo/info.md @@ -0,0 +1,8 @@ +# 标签 Tag +进行标记和分类的小标签。 + +## 何时使用 +- 用于标记事物的属性和维度。 +- 进行分类。 + +## 代码演示 \ No newline at end of file diff --git a/components/tag/index.js b/components/tag/index.js new file mode 100755 index 0000000000000000000000000000000000000000..6826d94c6b232553520d81c53163f64c9a38e5a7 --- /dev/null +++ b/components/tag/index.js @@ -0,0 +1,2 @@ +import Tag from './tag.jsx' +export default Tag \ No newline at end of file diff --git a/components/tag/index.md b/components/tag/index.md new file mode 100755 index 0000000000000000000000000000000000000000..a467378d579c2a067679dcfba2605a111167566d --- /dev/null +++ b/components/tag/index.md @@ -0,0 +1,6 @@ +### Tag API +| 属性 | 说明 | 类型 | 默认值 | +|-----------|----------------|----------|-------| +| closeable | 是否显示关闭按钮 | Boolean | false | +| color | 标签的颜色,默认提供5组颜色 | String | - | +| close | 关闭标签的回调事件 | Function | - | \ No newline at end of file diff --git a/components/tag/styles/index.less b/components/tag/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..887dc68aed833ae20298120c1774c32650010b01 --- /dev/null +++ b/components/tag/styles/index.less @@ -0,0 +1,127 @@ +@import '../../styles/global.less'; +.k-tag { + display: inline-block; + line-height: 20px; + height: auto; + padding: 0 7px; + border: 1px solid @border-color; + background-color: @back-color; + font-size: 12px; + border-radius: @radius; + box-sizing: border-box; + white-space: nowrap; + margin-right: 8px; + vertical-align: middle; + cursor: pointer; + .k-tag-close { + font-size: 16px; + margin-left: 4px; + vertical-align: -4px; + &:hover { + color: @danger; + } + } + &-pink { + color: @pink; + border-color: @pink; + background-color: tint(@pink, 90); + } + &-red { + color: @red; + border-color: @red; + background-color: tint(@red, 90); + } + &-yellow { + color: saturate(@yellow, 30%); + border-color: @yellow; + background-color: tint(@yellow, 90); + } + &-orange { + color: @orange; + border-color: @orange; + background-color: tint(@orange, 90); + } + &-cyan { + color: @cyan; + border-color: @cyan; + background-color: tint(@cyan, 90); + } + &-green { + color: @green; + border-color: @green; + background-color: tint(@green, 90); + } + &-blue { + color: @blue; + border-color: @blue; + background-color: tint(@blue, 90); + } + &-purple { + color: @purple; + border-color: @purple; + background-color: tint(@purple, 90); + } + &-geekblue { + color: @geekblue; + border-color: @geekblue; + background-color: tint(@geekblue, 90); + } + &-magenta { + color: @magenta; + border-color: @magenta; + background-color: tint(@magenta, 90); + } + &-volcano { + color: @volcano; + border-color: @volcano; + background-color: tint(@volcano, 90); + } + &-gold { + color: @gold; + border-color: @gold; + background-color: tint(@gold, 90); + } + &-lime { + color: @lime; + border-color: @lime; + background-color: tint(@lime, 90); + } +} + +.k-tag-has-color { + color: #fff; + border-color: transparent; + .k-tag-close { + color: #fff; + } +} + +@keyframes zoomIn { + from { + opacity: 0; + transform: scale(0, 0); + } + to { + opacity: 1; + transform: scale(1, 1); + } +} + +@keyframes zoomOut { + from { + opacity: 1; + transform: scale(1, 1); + } + to { + opacity: 0; + transform: scale(0, 0); + } +} + +.k-tag-enter-active { + animation: zoomIn .2s ease-out; +} + +.k-tag-leave-active { + animation: zoomOut .2s ease-out; +} \ No newline at end of file diff --git a/components/tag/tag.jsx b/components/tag/tag.jsx new file mode 100755 index 0000000000000000000000000000000000000000..35dcaebd43b771ecca7f815cfa9360cfbad8341d --- /dev/null +++ b/components/tag/tag.jsx @@ -0,0 +1,45 @@ +import Icon from '../icon' +export default { + name: 'Tag', + props: { + closeable: Boolean, + color: String + }, + data() { + return { + visible: true, + } + }, + methods: { + handle(e) { + this.$emit('click', e) + }, + close(e) { + this.$emit('close', e) + this.visible = false + } + }, + render() { + const { visible, styles, handle, color, $slots, close, classes, closeable } = this + const props = { + on: { + click: handle + }, + class: ['k-tag', { + [`k-tag-${color}`]: color && !/^#/.test(color), + ['k-tag-has-color']: /^#/.test(color) + }], + style: { backgroundColor: /^#/.test(color) ? color : null } + } + return ( +{{t}} + + ++ + ) + } +} \ No newline at end of file diff --git a/components/timeline/demo/base.md b/components/timeline/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..c6d784c17109b4760eaa00da977998c504855844 --- /dev/null +++ b/components/timeline/demo/base.md @@ -0,0 +1,16 @@ ++ + {$slots.default} + + {closeable ?+: null} + +#### 基本用法 +`TimeLine` 内部必须包含 `TimeLineItem` + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/timeline/demo/icon.md b/components/timeline/demo/icon.md new file mode 100755 index 0000000000000000000000000000000000000000..9586243a5df92acdf646f00f771083b520e6f240 --- /dev/null +++ b/components/timeline/demo/icon.md @@ -0,0 +1,18 @@ ++ +2019 年 11月 发布3.0版本 +2019 年 1月27日 发布2.0版本 +2017 年 12月 发布1.0版本 ++#### 图标 +给 `TimeLineItem` 设置 `icon` 和 `color` 可以改变图标展示 + + +```tpl + +++ +``` \ No newline at end of file diff --git a/components/timeline/demo/index.vue b/components/timeline/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..03f3167abeaae05a6c50c24ff59482fe8b0bbbc6 --- /dev/null +++ b/components/timeline/demo/index.vue @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/components/timeline/demo/info.md b/components/timeline/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..bef6ca871c453edf553211a74e285575268b3f63 --- /dev/null +++ b/components/timeline/demo/info.md @@ -0,0 +1,10 @@ +# 时间轴 +垂直展示的时间流信息。 + +## 何时使用 +在操作需要较长时间才能完成时,为用户显示该操作的当前进度和状态。 + +- 当有一系列信息需按时间排列时,可正序和倒序。 +- 需要有一条时间轴进行视觉上的串联时。。 + +## 代码演示 \ No newline at end of file diff --git a/components/timeline/demo/mode.md b/components/timeline/demo/mode.md new file mode 100755 index 0000000000000000000000000000000000000000..03187703a90b46a4f39648b72540523731e39941 --- /dev/null +++ b/components/timeline/demo/mode.md @@ -0,0 +1,34 @@ ++ +优化成吨的改善和体验 +新增一些很友好的功能 +发布2.0版本 +修复bug +发布1.0版本 ++#### 呈现方向 +指定 `mode` 可以改变呈现方向 + + +```tpl + +++ + +``` \ No newline at end of file diff --git a/docs/src/code/timeline.js b/components/timeline/demo/timeline.js old mode 100644 new mode 100755 similarity index 100% rename from docs/src/code/timeline.js rename to components/timeline/demo/timeline.js diff --git a/docs/src/views/timeline.vue b/components/timeline/demo/timeline.vue old mode 100644 new mode 100755 similarity index 100% rename from docs/src/views/timeline.vue rename to components/timeline/demo/timeline.vue diff --git a/components/timeline/index.js b/components/timeline/index.js new file mode 100755 index 0000000000000000000000000000000000000000..c2785d1102ba1d6d675364de8fa59827cf7bb06f --- /dev/null +++ b/components/timeline/index.js @@ -0,0 +1,5 @@ +import TimeLine from './timeline.jsx'; +import TimeLineItem from './timelineitem.jsx'; + + +export { TimeLine, TimeLineItem } \ No newline at end of file diff --git a/components/timeline/index.md b/components/timeline/index.md new file mode 100755 index 0000000000000000000000000000000000000000..ec3261fde14550795114c7b06691a1a47b6aafd5 --- /dev/null +++ b/components/timeline/index.md @@ -0,0 +1,7 @@ +### API +| 属性 | 说明 | 类型 | 默认值 | +|-------|---------------|--------|-----| +| icon | 时间轴 `item` 图标 | String | - | +| color | 时间轴 `item` 图标颜色 | String | - | +| dot | 自定义时间轴点 | slot | - | +| mode| 通过设置 `mode` 可以改变时间轴和内容的相对位置 `left` \| `alternate` \| `right` |String|left| \ No newline at end of file diff --git a/components/timeline/styles/index.less b/components/timeline/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..d6c3c64d24133ab7546dc0a2d2d3c4879faec268 --- /dev/null +++ b/components/timeline/styles/index.less @@ -0,0 +1,96 @@ +@import '../../styles/global.less'; +.k-timeline { + background-color: #fff; + font-size: 12px; + overflow: hidden; + position: relative; + z-index: 1; + margin: 0; + padding: 0; + list-style: none; + .k-time-line-item { + position: relative; + &:before { + position: absolute; + width: 1px; + background: @border-color; + left: 7px; + content: ""; + height: 100%; + top: 8px; + } + &:last-child:before { + display: none; + } + } + .k-time-line-dot { + position: absolute; + background: #fff; + top: 4px; + left: -.5px; + font-size: 16px; + color: @main; + line-height: 1; + border-radius: 50%; + } + .k-time-line-icon-default { + font-size: 12px; + left: 1px; + top: 5.5px; + } + .k-time-line-item-content { + padding: 0 0 20px 18px; + font-size: 12px; + position: relative; + line-height: 22px; + top: 0; + box-sizing: border-box; + } +} + +.k-timeline-center { + width: 100%; + display: inline-block; + .k-time-line-item { + width: 50%; + &:nth-child(odd) { + left: 50%; + margin-left: -8px; + } + &:nth-child(even) { + text-align: right; + .k-time-line-dot { + left: 100%; + transform: translateX(-50%); + } + .k-time-line-item-content { + padding: 0 12px 20px 0; + } + &:before { + left: 100%; + margin-left: -1px; + z-index: 0; + } + } + } +} + +.k-timeline-right { + text-align: right; + .k-time-line-item { + &:before { + left: 100%; + margin-left: -7px; + } + } + .k-time-line-dot { + left: 100%; + margin-left: -14.5px; + } + .k-time-line-icon-default { + margin-left: -12.5px; + } + .k-time-line-item-content { + padding-right: 18px + } +} \ No newline at end of file diff --git a/components/timeline/timeline.jsx b/components/timeline/timeline.jsx new file mode 100755 index 0000000000000000000000000000000000000000..2bb7171914788d9d52feff84661b23e938864ed6 --- /dev/null +++ b/components/timeline/timeline.jsx @@ -0,0 +1,16 @@ + +export default { + name: "TimeLine", + props: { + mode: { type: String, default: 'left' } + }, + render() { + const classes = ['k-timeline', `k-timeline-${this.mode}`] + return ( ++ ++ + +
+
++ +优化成吨的改善和体验 +新增一些很友好的功能 +发布2.0版本 +修复bug +发布1.0版本 ++ {this.$slots.default} +
+ ) + } +}; + diff --git a/components/timeline/timelineitem.jsx b/components/timeline/timelineitem.jsx new file mode 100755 index 0000000000000000000000000000000000000000..6cbd577763f5e90ac56dd8e1915dd100498ae8b5 --- /dev/null +++ b/components/timeline/timelineitem.jsx @@ -0,0 +1,26 @@ +import Icon from '../icon' +export default { + name: "TimeLineItem", + props: { + color: String, + icon: String + }, + render() { + const styles = { color: this.color } + let { icon } = this + const type = icon ? icon : "ios-radio-button-off"; + const iconNode = this.$slots.dot ||+ const iconCls = ['k-time-line-dot', { 'k-time-line-icon-default': !icon }] + + return ( + + + ) + } +}; \ No newline at end of file diff --git a/components/tooltip/demo/base.md b/components/tooltip/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..608967b9f6ad79451d6c40b1002ba43c40d4f5b2 --- /dev/null +++ b/components/tooltip/demo/base.md @@ -0,0 +1,16 @@ ++ {iconNode} +++ {this.$slots.default} +++#### 基础用法 +最简单的用法,浮层的大小由内容区域决定。 + + +```tpl + ++ + + +``` \ No newline at end of file diff --git a/components/tooltip/demo/index.vue b/components/tooltip/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..9de4162f512f79aa9182ffc5b9373c38bccf59a9 --- /dev/null +++ b/components/tooltip/demo/index.vue @@ -0,0 +1,27 @@ + + \ No newline at end of file diff --git a/components/tooltip/demo/info.md b/components/tooltip/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..1f5ce3122dc9de88863aece3c2798c1da1692904 --- /dev/null +++ b/components/tooltip/demo/info.md @@ -0,0 +1,9 @@ +## Tooltip +简单的文字提示气泡框。 + +## 何时使用 +鼠标移入则显示提示,移出消失,气泡浮层不承载复杂文本和操作。 + +可用来代替系统默认的 `title` 提示,提供一个`按钮/文字/操作`的文案解释。 + +## 代码演示 \ No newline at end of file diff --git a/components/tooltip/demo/placement.md b/components/tooltip/demo/placement.md new file mode 100755 index 0000000000000000000000000000000000000000..a0c6e81b0eb9e218567d821a2c67cccc86fada6f --- /dev/null +++ b/components/tooltip/demo/placement.md @@ -0,0 +1,110 @@ +明月几时有,把酒问青天!
+不知天上宫阙,今夕是何年 ?
+ + 月几时有,把酒问青天 ++#### 位置 +通过 `placement`控制方向, 位置有十二个方向。 + + +```tpl + ++++ + + +{{title}}
+{{title}}
+ ++ + + +{{title}}
+{{title}}
+ ++ + + +{{title}}
+{{title}}
+ ++++ + + +{{title}}
+{{title}}
+ ++ + + +{{title}}
+{{title}}
+ ++ + + +{{title}}
+{{title}}
+ ++++ + + +{{title}}
+{{title}}
+ ++ + + +{{title}}
+{{title}}
+ ++ + + +{{title}}
+{{title}}
+ +++ + +``` \ No newline at end of file diff --git a/components/tooltip/index.js b/components/tooltip/index.js new file mode 100755 index 0000000000000000000000000000000000000000..b16c1031c7e791462757e4302e7dd69dab0dc426 --- /dev/null +++ b/components/tooltip/index.js @@ -0,0 +1,2 @@ +import Tooltip from './tooltip.jsx' +export default Tooltip \ No newline at end of file diff --git a/components/tooltip/index.md b/components/tooltip/index.md new file mode 100755 index 0000000000000000000000000000000000000000..64405752092e380593468023bbb65e929101ce0c --- /dev/null +++ b/components/tooltip/index.md @@ -0,0 +1,7 @@ +## API +| 属性 | 说明 | 类型 | 默认值 | +|-----------|----------------------------------------------------------------------------------------------------------------------------------------------------|--------------|------| +| title | 显示的标题 | String,Slots | - | +| placement | 提示框出现的位置,可选值为`top`,`top-left`,`top-right`,`bottom`,`bottom-left`,`bottom-right`,`left`,`left-top`,`left-bottom`,`right`,`right-top`,`right-bottom` | String | top | +| width | 展示的宽度,默认为内容区域的大小 | String | - | +| transfer | 是否将弹层放置于 `body` 内,在 `Tabs`、带有 `fixed` 的 `Table` 列内使用时,建议添加此属性,它将不受父级样式影响,从而达到更好的效果 | Boolean | true | \ No newline at end of file diff --git a/src/components/tooltip/tooltip.less b/components/tooltip/styles/index.less old mode 100644 new mode 100755 similarity index 31% rename from src/components/tooltip/tooltip.less rename to components/tooltip/styles/index.less index 20559f4897bb280b97ed5f97aebbeebbf8b13a97..9ff3a5734b833e8deae2ac8ed31c0654e41ee111 --- a/src/components/tooltip/tooltip.less +++ b/components/tooltip/styles/index.less @@ -2,165 +2,166 @@ .k-tooltip { display: inline-block; position: relative; - .k-tooltip-rel { - display: inline-block; - } } -.k-tooltip-dom { - z-index: 800; - padding: 10px; +.k-tooltip-content { + // min-width: 200px; + // max-width: 300px; + font-size: 12px; + line-height: 1.5; position: absolute; - .k-tooltip-content { + z-index: 1001; + .k-tooltip-inner { + background: @color; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + border-radius: @radius; + } + .k-tooltip-title { padding: 6px 8px; + color: #fff; font-size: 14px; - line-height: 1.5; - max-width: 250px; - color: #000; - box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 6px; - text-align: left; - text-decoration: none; - background-color: white; - border-radius: @radius; // -webkit-box-shadow: 0 2px 8px rgba(0,0,0,.15); - // box-shadow: 0 2px 8px rgba(0,0,0,.15); - min-height: 32px; - box-sizing: border-box; - white-space: nowrap; } - .k-tooltip-content-breaked { - word-break: break-all; - white-space: normal; - } - .k-poptip-arrow { + .k-tooltip-arrow { position: absolute; - width: 17px; - height: 17px; - bottom: 0; - overflow: hidden; - &::after { - content: ''; - position: absolute; - width: 12px; - height: 12px; - transform: rotate(-45deg); - background: #fff; - box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 3px; - } + width: 0; + height: 0; + border-style: solid; + border-color: transparent; + box-sizing: border-box; } &[k-placement^=top] { - .k-poptip-arrow { - height: 6px; - bottom: 4px; - &::after { - top: -10px; - left: 2px; - } + .k-tooltip-arrow { + bottom: 7px; + border-width: 5px 5px 0 5px; + border-top-color: @color; + } + .k-tooltip-inner { + margin-bottom: 12px; } } &[k-placement=top] { - .k-poptip-arrow { + .k-tooltip-arrow { left: 50%; - margin-left: -6px; + transform: translateX(-50%); } } &[k-placement=top-right] { - .k-poptip-arrow { - right: 15px; + .k-tooltip-arrow { + right: 10px; } } &[k-placement=top-left] { - .k-poptip-arrow { - left: 15px; + .k-tooltip-arrow { + left: 10px; } } &[k-placement^=bottom] { - .k-poptip-arrow { - top: 4px; - height: 6px; - &::after { - top: 4px; - } + .k-tooltip-arrow { + top: 7px; + border-width: 0px 5px 5px 5px; + border-bottom-color: @color; + } + .k-tooltip-inner { + margin-top: 12px; } } &[k-placement=bottom] { - .k-poptip-arrow { + .k-tooltip-arrow { left: 50%; - margin-left: -6px; } } &[k-placement=bottom-left] { - .k-poptip-arrow { - left: 15px; + .k-tooltip-arrow { + left: 10px; } } &[k-placement=bottom-right] { - .k-poptip-arrow { - right: 15px; + .k-tooltip-arrow { + right: 10px; } } &[k-placement^=left] { - .k-poptip-arrow { - right: 4px; - width: 6px; - &::after { - top: 0px; - left: -10px; - } + .k-tooltip-arrow { + right: 7px; + border-width: 5px 0px 5px 5px; + border-left-color: @color; + } + .k-tooltip-inner { + margin-right: 12px; } } &[k-placement=left] { - .k-poptip-arrow { + .k-tooltip-arrow { top: 50%; margin-top: -6px; } } &[k-placement=left-bottom] { - .k-poptip-arrow { - bottom: 15px; + .k-tooltip-arrow { + bottom: 10px; } } &[k-placement=left-top] { - .k-poptip-arrow { - top: 15px; + .k-tooltip-arrow { + top: 10px; } - } //ok + } &[k-placement^=right] { - .k-poptip-arrow { - left: 4px; - width: 6px; - &::after { - top: 0px; - left: 4px; - } + .k-tooltip-arrow { + left: 7px; + border-width: 5px 5px 5px 0px; + border-right-color: @color; + } + .k-tooltip-inner { + margin-left: 12px; } } &[k-placement=right] { - .k-poptip-arrow { + .k-tooltip-arrow { top: 50%; - margin-top: -6px; + transform: translateY(-50%); } } &[k-placement=right-top] { - .k-poptip-arrow { - top: 15px; + .k-tooltip-arrow { + top: 10px; } } &[k-placement=right-bottom] { - .k-poptip-arrow { - bottom: 15px; + .k-tooltip-arrow { + bottom: 10px; } } } -.k-tooltip-dark { - .k-tooltip-dom { - .k-tooltip-content { - background: @dark; - color: #fff; - box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 6px; - } - .k-poptip-arrow::after { - background: rgba(0, 0, 0, 0.75); - } +@keyframes pop-zoom-in { + from { + opacity: 0; + transform: scale(.8, .8); + } + to { + opacity: 1; + transform: scale(1, 1); + } +} + +@keyframes pop-zoom-out { + from { + opacity: 1; + transform: scale(1, 1); } + to { + opacity: 0; + transform: scale(.8, .8); + } +} + +.k-tooltip-fade-enter-active { + // transform-origin: center bottom; + animation: pop-zoom-in .3s; +} + +.k-tooltip-fade-leave-active { + // transform-origin: center bottom; + animation: pop-zoom-out .3s; } \ No newline at end of file diff --git a/components/tooltip/tooltip.jsx b/components/tooltip/tooltip.jsx new file mode 100755 index 0000000000000000000000000000000000000000..698d604cc82f4867096c165b72e781c213051580 --- /dev/null +++ b/components/tooltip/tooltip.jsx @@ -0,0 +1,30 @@ +import BasePop from '../base/pop' +export default { + name: 'Tooltip', + props: { + dark: Boolean, + transfer: { type: Boolean, default: true }, + title: String, + width: [Number, String], + placement: { + validator(value) { + return ( + ["top", "top-left", "top-right", "bottom", "bottom-left", "bottom-right", "left", "left-bottom", "left-top", "right", "right-top", "right-bottom"].indexOf(value) >= 0 + ); + }, + default: "top" + }, + }, + render() { + let props = { + props: { preCls: 'tooltip', ...this.$props }, + } + const title = this.$slots.title || this.title + return (title ? ++ + + +{{title}}
+{{title}}
+ ++ + + +{{title}}
+{{title}}
+ ++ + + +{{title}}
+{{title}}
+ ++ {this.$slots.default} + {title} + : this.$slots.default + ) + } +}; \ No newline at end of file diff --git a/components/tree/demo/base.md b/components/tree/demo/base.md new file mode 100755 index 0000000000000000000000000000000000000000..29e26e8e6d01fa5e3005e1e22ff3b3045d92a941 --- /dev/null +++ b/components/tree/demo/base.md @@ -0,0 +1,42 @@ ++#### 基础用法 +最简单的用法,展示可选中,默认展开功能。 + + +```tpl + ++ + +``` \ No newline at end of file diff --git a/components/tree/demo/checkable.md b/components/tree/demo/checkable.md new file mode 100755 index 0000000000000000000000000000000000000000..24bd2be45db4391e33577199b9f0f3f40d67977f --- /dev/null +++ b/components/tree/demo/checkable.md @@ -0,0 +1,47 @@ + +#### 可勾选 +设置属性 `checkable` 可以对节点进行勾选。 + + +```tpl + ++ + +``` \ No newline at end of file diff --git a/components/tree/demo/disabled.md b/components/tree/demo/disabled.md new file mode 100755 index 0000000000000000000000000000000000000000..87f0ed3811d3427993f4c4f0dd02038ade9e10d5 --- /dev/null +++ b/components/tree/demo/disabled.md @@ -0,0 +1,48 @@ + +#### 禁用节点 +设置属性 `disabled` 可以禁用节点。 + + +```tpl + ++ + +``` \ No newline at end of file diff --git a/components/tree/demo/icon.md b/components/tree/demo/icon.md new file mode 100755 index 0000000000000000000000000000000000000000..8afe1fc2ef6df61300826f4fd4aebd2f8861ad02 --- /dev/null +++ b/components/tree/demo/icon.md @@ -0,0 +1,59 @@ + +#### 自定义图标 +可以针对不同的节点定制图标。 + + +```tpl + ++ + +``` \ No newline at end of file diff --git a/components/tree/demo/index.vue b/components/tree/demo/index.vue new file mode 100755 index 0000000000000000000000000000000000000000..a23119e38a41e21db4af9baf4f81a5e8a87e1f45 --- /dev/null +++ b/components/tree/demo/index.vue @@ -0,0 +1,24 @@ + \ No newline at end of file diff --git a/components/tree/demo/info.md b/components/tree/demo/info.md new file mode 100755 index 0000000000000000000000000000000000000000..905e237dc081e0f6f6ee96bc6a876c6607012ce9 --- /dev/null +++ b/components/tree/demo/info.md @@ -0,0 +1,7 @@ +## Tree 树形控件 + +## 何时使用 +文件夹、组织架构、生物分类、国家地区等等,世间万物的大多数结构都是树形结构。使用`树控件` 可以完整展现其中的层级关系并具有展开收起选择等交互功能。 + + +## 代码演示 \ No newline at end of file diff --git a/components/tree/demo/sync.md b/components/tree/demo/sync.md new file mode 100755 index 0000000000000000000000000000000000000000..f0d79c775f6cd8e2de72e00cf8ba7e313b5939c6 --- /dev/null +++ b/components/tree/demo/sync.md @@ -0,0 +1,43 @@ + +#### 异步加载 +点击展开节点,动态加载数据。 + + +```tpl + ++ + +``` \ No newline at end of file diff --git a/src/components/tree/index.js b/components/tree/index.js old mode 100644 new mode 100755 similarity index 68% rename from src/components/tree/index.js rename to components/tree/index.js index f9455bf2a5f9f93ff601aa6c029484c96dfb3124..984ffbc0624a0822d686183af75a2cdc7a5f1eba --- a/src/components/tree/index.js +++ b/components/tree/index.js @@ -1,3 +1,2 @@ -import './tree.less' import Tree from './tree' export default Tree \ No newline at end of file diff --git a/components/tree/index.md b/components/tree/index.md new file mode 100755 index 0000000000000000000000000000000000000000..d97a268c1c8c6b57ed3fac4f9cc7135779ed1f1e --- /dev/null +++ b/components/tree/index.md @@ -0,0 +1,21 @@ +## Tree API + +| 属性 | 说明 | 类型 | 默认值 | +|-----------|---------------------------|----------|-------| +| data | 可嵌套的节点属性的数组,生成 `tree` 的数据 | Array | [] | +| checkable | 是否显示多选框 | Boolean | false | +| load-data | 异步加载数据的方法 | Function | - | +| select | 点击树节点时触发,返回当前已选中的节点数组 | Function | - | +| check | 点击复选框时触发,返回当前已勾选节点的数组 | Function | - | +| expand | 展开和收起子节点时触发,返回当前已勾选节点的数组 | Function | - | + +## TreeNode API + +| 属性 | 说明 | 类型 | 默认值 | +|----------|---------|---------|-------| +| title | 节点标题 | String | - | +| expand | 是否展开节点 | Boolean | false | +| disabled | 是否禁用节点 | Boolean | false | +| selected | 节点是否被选中 | Boolean | false | +| checked | 节点是否勾选 | Boolean | false | +| children | 子节点 | Array | - | diff --git a/components/tree/node.jsx b/components/tree/node.jsx new file mode 100755 index 0000000000000000000000000000000000000000..68048cdae35c5c3d6a503be92a4c2f1fdd3d09c6 --- /dev/null +++ b/components/tree/node.jsx @@ -0,0 +1,89 @@ +import Icon from '../icon' +import { Checkbox } from '../checkbox' +import TreeNode from './node.jsx' +import { getTranstionProp } from '../_tool/transition' + +export default { + name: 'TreeNode', + props: { + data: Object, + checkable: Boolean + }, + inject: { + Tree: { default: null } + }, + methods: { + setChildCheck(data) { + data.indeterminate = false + if (data.children && data.children.length) { + data.children.forEach(child => { + if (!child.disabled) { + child.indeterminate = false + this.$set(child, 'checked', this.data.checked) + this.setChildCheck(child) + } + }) + } + }, + handleCheck() { + this.setChildCheck(this.data) + if (this.Tree && !this.data.disabled) { + this.Tree.checked(this.data) + } + }, + handleSelect() { + if (this.Tree && !this.data.disabled) { + this.Tree.selected(this.data) + } + }, + handleExpand() { + let { loading, children } = this.data + let hasChilds = children && children.length > 0 + if (loading !== undefined && !hasChilds) { + this.data.loading = true + this.Tree && this.Tree.load(this.data) + } else if (hasChilds) { + this.data.expand = !this.data.expand + } + this.Tree && this.Tree.expand(this.data) + } + }, + render() { + let { expand = false, loading, checked = false, disabled, indeterminate, icon, selected, title, children } = this.data + let itemNode = [] + let hasChilds = children && children.length > 0 + if (hasChilds || loading !== undefined) { + let arrowCls = ['k-tree-arrow', { 'k-tree-arrow-open': expand }] + let arrowNode = + itemNode.push(arrowNode) + } else { + itemNode.push() + } + let { checkable } = this + if (checkable) { + let props = { + props: { checked, disabled, indeterminate }, + on: { change: this.handleCheck, input: e => { this.$set(this.data, 'checked', e) } } + } + itemNode.push( ) + } + + if (icon) { + itemNode.push( ) + } + + let titleCls = ['k-tree-title', { 'k-tree-title-selected': selected }] + itemNode.push({title}) + + let childs = null + if (expand && hasChilds) { + childs = children.map((t, i) => ) + } + let onProps = getTranstionProp('k-tree-slide') + return ( + +) + } +} \ No newline at end of file diff --git a/components/tree/styles/index.less b/components/tree/styles/index.less new file mode 100755 index 0000000000000000000000000000000000000000..c71437e3934e8c7621e03189497ea73cde2d42d8 --- /dev/null +++ b/components/tree/styles/index.less @@ -0,0 +1,78 @@ +@import '../../styles/global.less'; +.k-tree { + .k-tree-item { + padding: .2em 0; + margin: 0; + list-style: none; + white-space: nowrap; + outline: 0; + user-select: none; + } + .k-tree-children { + margin: 0; + .k-tree-children { + padding: 0 0 0 24px; + } + } + .k-tree-commes { + display: inline-block; + width: 12px; + } + .k-checkbox-wp { + margin: 0; + } + .k-tree-icon { + vertical-align: middle; + } + .k-tree-title { + display: inline-block; + margin: 0; + padding: 0 4px; + border-radius: 3px; + cursor: pointer; + color: @color; + // transition: all .2s ease-in-out; + &:hover, &:focus { + background: tint(@main, 90%); + outline: none; + } + } + .k-tree-item-disabled { + .k-tree-title, .k-tree-icon { + color: @disable-color; + cursor: not-allowed; + } + } + .k-tree-title-selected { + background: tint(@main, 70%); + &:hover, &:focus { + background: tint(@main, 70%); + } + } + .k-tree-arrow { + // font-size: 20px; + width: 24px; + height: 24px; + line-height: 24px; + display: inline-block; + vertical-align: middle; + position: relative; + text-align: center; + transform: rotate(0deg); + transition: transform .2s ease-in-out; + cursor: pointer; + } + .k-tree-arrow-open { + transform: rotate(90deg) + } + .k-tree-children { + overflow: hidden; + transition: all .2s ease-in-out; + } + .tree-nodata { + padding: 8px 10px; + display: block; + color: @disable-color; + font-size: 12px; + } +} \ No newline at end of file diff --git a/components/tree/tree.jsx b/components/tree/tree.jsx new file mode 100755 index 0000000000000000000000000000000000000000..8ba0321aa32b18fc1ae40515f56dcfae7b84f354 --- /dev/null +++ b/components/tree/tree.jsx @@ -0,0 +1,72 @@ +import TreeNode from './node.jsx' + +export default { + name: 'Tree', + props: { + data: Array, + checkable: Boolean, + dragable: Boolean + }, + provide() { + return { + Tree: this, + } + }, + methods: { + load(data) { + this.$emit('load-data', data, child => { + this.$set(data, 'loading', false) + if (child && child.length) { + data.children = child + this.$set(data, 'expand', !data.expand) + } + }) + }, + expand(data) { + this.$emit('expand', data) + }, + parentChecked(parents, item) { + parents.forEach(childs => { + let { children, disabled } = childs + if (!disabled) { + if (children && children.indexOf(item) >= 0) { + let checkLen = children.filter(child => child.checked).length + let halfLen = children.filter(child => child.indeterminate).length + let isCheckAll = children.length == checkLen + this.$set(childs, 'checked', isCheckAll) + this.$set(childs, 'indeterminate', (checkLen > 0 || halfLen > 0) && !isCheckAll) + this.parentChecked(this.data, childs) + } else { + if (children && children.length > 0) { + this.parentChecked(children, item) + } + } + } + }) + }, + checked(data) { + //set parent check + this.parentChecked(this.data, data) + this.$emit('check', data) + }, + + selected(data) { + let setSelected = (datas) => { + datas.forEach(item => { + let selected = item == data ? !item.selected : false + this.$set(item, 'selected', selected) + if (item.children && item.children.length > 0) { + setSelected(item.children) + } + }) + } + setSelected(this.data) + this.$emit('select', data.selected ? [data] : []) + } + }, + render() { + return ({itemNode}+{childs} ++ {this.data.map((t, i) =>) + } +} \ No newline at end of file diff --git a/docs/src/code/treeselect.js b/components/treeselect/demo/treeselect.js old mode 100644 new mode 100755 similarity index 100% rename from docs/src/code/treeselect.js rename to components/treeselect/demo/treeselect.js diff --git a/docs/src/views/treeselect.vue b/components/treeselect/demo/treeselect.vue old mode 100644 new mode 100755 similarity index 100% rename from docs/src/views/treeselect.vue rename to components/treeselect/demo/treeselect.vue diff --git a/src/components/treeselect/index.js b/components/treeselect/index.js old mode 100644 new mode 100755 similarity index 70% rename from src/components/treeselect/index.js rename to components/treeselect/index.js index 985a1eebe5e7dcdc8eed0d7ad2bc8f13a62e770c..79b70d6c446d32800755212eb1914c2532661d60 --- a/src/components/treeselect/index.js +++ b/components/treeselect/index.js @@ -1,3 +1,2 @@ -import './treeselect.less' import TreeSelect from './treeselect' export default TreeSelect \ No newline at end of file diff --git a/src/components/treeselect/treeselect.less b/components/treeselect/styles/index.less old mode 100644 new mode 100755 similarity index 100% rename from src/components/treeselect/treeselect.less rename to components/treeselect/styles/index.less diff --git a/src/components/treeselect/treeselect.vue b/components/treeselect/treeselect.vue old mode 100644 new mode 100755 similarity index 95% rename from src/components/treeselect/treeselect.vue rename to components/treeselect/treeselect.vue index cb24771f723fdf8cbd00feef09a70ab93e6aac1d..f8f872113ef6eb0b19869f8e798e27e985804abd --- a/src/components/treeselect/treeselect.vue +++ b/components/treeselect/treeselect.vue @@ -19,9 +19,9 @@ diff --git a/docs/src/views/angular-kui.vue b/docs/components/base.vue old mode 100644 new mode 100755 similarity index 39% rename from docs/src/views/angular-kui.vue rename to docs/components/base.vue index 6568dad036644e6ed2120e74499571f824bc0f70..32481eb22175496909e129c9e9809a160580d86a --- a/docs/src/views/angular-kui.vue +++ b/docs/components/base.vue @@ -1,5 +1,11 @@ +)} + +#### + + +```tpl-+``` \ No newline at end of file diff --git a/docs/src/components/code/atom-one-light.css b/docs/components/code/atom-one-light.css old mode 100644 new mode 100755 similarity index 100% rename from docs/src/components/code/atom-one-light.css rename to docs/components/code/atom-one-light.css diff --git a/docs/src/components/code/code.vue b/docs/components/code/code.vue old mode 100644 new mode 100755 similarity index 71% rename from docs/src/components/code/code.vue rename to docs/components/code/code.vue index d2bf9ccecd8121ad99160c4a46c62c2e6e5b3045..17991dcaa92629c72e5f71d5489f99e748b004d5 --- a/docs/src/components/code/code.vue +++ b/docs/components/code/code.vue @@ -4,20 +4,12 @@抱歉,For Angular部分文档还在完善中....
+- - - --- +- --
+
+
diff --git a/docs/layout.vue b/docs/layout.vue
new file mode 100755
index 0000000000000000000000000000000000000000..51c2aba71c2459003c196e06d074a8340a8151e7
--- /dev/null
+++ b/docs/layout.vue
@@ -0,0 +1,99 @@
+
+
';
+ return true;
+ }
+ return false;
+ }
+
+ function start() {
+ while (testDebuger()) {
+ testDebuger();
+ }
+ }
+
+ if (!testDebuger()) {
+ window.onblur = function () {
+ setTimeout(function () {
+ start();
+ }, 500)
+ }
+ } else {
+ start();
+ }
+}
+noDebuger() */
\ No newline at end of file
diff --git a/docs/menu.js b/docs/menu.js
new file mode 100755
index 0000000000000000000000000000000000000000..c9696bd58a05c2ca270b86147438243e7e4407b0
--- /dev/null
+++ b/docs/menu.js
@@ -0,0 +1,74 @@
+const Nav = [
+ {
+ title: "基础组件",
+ child: [
+ { title: "图标", sub: "Icon", name: "icon", icon: "ios-heart" },
+ { title: "按钮", sub: "Button", name: "button", icon: 'ios-square' },
+ { title: "颜色", sub: "ColorPicker", name: "colorpicker", icon: 'ios-color-palette' },
+ { title: "栅格", sub: "Grid", name: "grid", icon: 'ios-grid' },
+ { title: "布局", sub: "Layout", name: "layout", icon: 'ios-albums' },
+ ]
+ },
+ {
+ title: "表单",
+ child: [
+ { title: "输入框", sub: "Input", name: "input", icon: 'ios-create' },
+ { title: "多选框", sub: "Checkbox", name: "checkbox", icon: 'ios-checkbox' },
+ { title: "单选框", sub: "Radio", name: "radio", icon: 'ios-checkmark-circle' },
+ { title: "开关", sub: "Switch", name: "switch", icon: 'ios-switch' },
+ { title: "下拉框", sub: "Select", name: "select", icon: 'ios-arrow-down' },
+ { title: "日期选择框", sub: "DatePicker", name: "datepicker", icon: 'ios-calendar' },
+ { title: "表格", sub: "Table", name: "table", icon: 'ios-grid' },
+ // { title: "上传", sub: "Upload", name: "upload", icon: 'ios-cloud-upload' },
+ { title: "表单", sub: "Form", name: "form", icon: 'ios-list' },
+ ]
+ },
+ {
+ title: '视图',
+ child: [
+ { title: "警告提示", sub: "Alert", name: "alert", icon: 'ios-alert' },
+ { title: "徽标", sub: "Badge", name: "badge", icon: 'ios-mail-unread' },
+ { title: "卡片", sub: "Card", name: "card", icon: 'ios-card' },
+ { title: "走马灯", sub: "Carousel", name: "carousel", icon: 'ios-film' },
+ { title: "折叠面板", sub: "Collapse", name: "collapse", icon: 'ios-funnel' },
+ { title: "抽屉", sub: "Drawer", name: "drawer", icon: 'ios-map' },
+ // { title: "图片预览", sub: "ImagePreview", name: "imagepreview", icon: 'ios-images' },
+ { title: "全局提示", sub: "Message", name: "message", icon: 'ios-chatboxes' },
+ { title: "通知提醒", sub: "Notice", name: "notice", icon: 'ios-notifications' },
+ { title: "对话框", sub: "Modal", name: "modal", icon: 'ios-chatbubbles' },
+ { title: "标签", sub: "Tag", name: "tag", icon: 'ios-bookmark' },
+ { title: "时间轴", sub: "TimeLine", name: "timeline", icon: 'ios-time' },
+ { title: "气泡卡片", sub: "Poptip", name: "poptip", icon: 'ios-chatbubbles' },
+ { title: "气泡确认框", sub: "Popconfirm", name: "popconfirm", icon: 'ios-chatbubbles' },
+ { title: "加载中", sub: "Spin", name: "spin", icon: 'ios-radio' },
+ { title: "进度条", sub: "Progress", name: "progress", icon: 'ios-pulse' },
+ { title: "文字提示", sub: "Tooltip", name: "tooltip", icon: 'ios-text' },
+ { title: "树形控件", sub: "Tree", name: "tree", icon: 'ios-git-merge' },
+ // { title: "树选择", sub: "TreeSelect", name: "treeselect", icon: 'ios-git-pull-request' },
+ ]
+ },
+ {
+ title: '导航',
+ child: [
+ { title: "图钉", sub: "Affix", name: "affix", icon: 'ios-pin' },
+ { title: "面包屑", sub: "Breadcrumb", name: "breadcrumb", icon: 'ios-arrow-forward' },
+ { title: "回到顶部", sub: "BackTop", name: "backtop", icon: 'md-arrow-up' },
+ // { title: "下拉菜单", sub: "Dropdown", name: "dropdown", icon: 'ios-arrow-dropdown-circle' },
+ // { title: "加载进度", sub: "Loading", name: "loading", icon: 'ios-pulse' },
+ { title: "导航菜单", sub: "Menu", name: "menu", icon: 'ios-list' },
+ { title: "分页", sub: "Page", name: "page", icon: 'ios-fastforward' },
+ // { title: "步骤条", sub: "Steps", name: "steps", icon: 'ios-done-all' },
+ { title: "标签页", sub: "Tabs", name: "tabs", icon: 'ios-photos' },
+ ]
+ },
+]
+const baseNav = [
+ { title: "快速上手", name: "start", },
+ { title: "在 vue 中使用", name: "use-in-vue" },
+ { title: "SSR 支持", name: "ssr" },
+ { title: "更新日志", name: "log", log: 1, },
+ { title: "定制主题", name: "theme" },
+ { title: "kui-loader", name: "kui-loader" }
+]
+
+export { Nav, baseNav }
\ No newline at end of file
diff --git a/docs/src/router.js b/docs/router.js
old mode 100644
new mode 100755
similarity index 41%
rename from docs/src/router.js
rename to docs/router.js
index 4ca5ec67fd6c1f484f020bad8f6cc24955f932ec..eb4464ede80b2c3d6592f1dcbc1956497fffccb3
--- a/docs/src/router.js
+++ b/docs/router.js
@@ -1,103 +1,101 @@
import Vue from 'vue'
-import loading from '@/components/loading'
-//Vue.use(kui);
import Router from 'vue-router'
Vue.use(Router)
+// 解决 vue-router在3.0版本以上重复点菜单报错问题
+const originalPush = Router.prototype.push
+Router.prototype.push = function push(location) {
+ return originalPush.call(this, location).catch(err => err)
+}
let router = []
-//此种编译后,无法实现按需加载,会打包在一个文件
-/*let r=['','install','start','log','input','button','select','switch','form','colorpicker','loading',
-'icon','timeline','theme','react-kui','angular-kui','alert','message','notice','upload','poptip','menu','tabs','badge',
-'checkbox','radio','datepicker','table','layout','page','modal','kui-loader','sponsor','about'];
-r.map((x)=>{
-children.push({
-path:`/${x}`,
-component:resolve=>require([x==''?'./views/index':`./views/${x}`],resolve),
-//component:r=>require.ensure([],()=>r(require(x==''?'/views/index':`./views/${x}`),x)
-})
-})*/
-
-let children = [
- { path: 'about', component: () => import(/*webpackChunkName:'about'*/'./views/about'), },
- { path: 'alert', component: () => import(/*webpackChunkName:'alert'*/'./views/alert'), },
- { path: 'affix', component: () => import(/*webpackChunkName:'affix'*/'./views/affix'), },
- { path: 'angular-kui', component: () => import(/*webpackChunkName:'angular-kui'*/'./views/angular-kui'), },
- { path: 'card', component: () => import(/*webpackChunkName:'card'*/'./views/card'), },
- { path: 'carousel', component: () => import(/*webpackChunkName:'carousel'*/'./views/carousel'), },
- { path: 'collapse', component: () => import(/*webpackChunkName:'collapse'*/'./views/collapse'), },
- { path: 'colorpicker', component: () => import(/*webpackChunkName:'colorpicker'*/'./views/colorpicker'), },
- { path: 'color', component: () => import(/*webpackChunkName:'color'*/'./views/color'), },
- { path: 'checkbox', component: () => import(/*webpackChunkName:'checkbox'*/'./views/checkbox'), },
- { path: 'button', component: () => import(/*webpackChunkName:'button'*/'./views/button'), },
- { path: 'breadcrumb', component: () => import(/*webpackChunkName:'breadcrumb'*/'./views/breadcrumb'), },
- { path: 'backtop', component: () => import(/*webpackChunkName:'backtop'*/'./views/backtop'), },
- { path: 'badge', component: () => import(/*webpackChunkName:'badge'*/'./views/badge'), },
- { path: 'datepicker', component: () => import(/*webpackChunkName:'datepicker'*/'./views/datepicker'), },
- { path: 'dropdown', component: () => import(/*webpackChunkName:'dropdown'*/'./views/dropdown'), },
- { path: 'drawer', component: () => import(/*webpackChunkName:'drawer'*/'./views/drawer'), },
- { path: 'form', component: () => import(/*webpackChunkName:'form'*/'./views/form'), },
- { path: 'font', component: () => import(/*webpackChunkName:'font'*/'./views/font'), },
- { path: 'grid', component: () => import(/*webpackChunkName:'grid'*/'./views/grid'), },
- { path: 'imagepreview', component: () => import(/*webpackChunkName:'image-preview'*/'./views/image-preview'), },
- { path: 'install', component: () => import(/*webpackChunkName:'install'*/'./views/install'), },
- { path: 'input', component: () => import(/*webpackChunkName:'input'*/'./views/input'), },
- { path: 'icon', component: () => import(/*webpackChunkName:'icon'*/'./views/icon'), },
- { path: 'kui-loader', component: () => import(/*webpackChunkName:'kui-loader'*/'./views/kui-loader'), },
- { path: 'log', component: () => import(/*webpackChunkName:'log'*/'./views/log'), },
- { path: 'layout', component: () => import(/*webpackChunkName:'layout'*/'./views/layout'), },
- { path: 'loading', component: () => import(/*webpackChunkName:'loading'*/'./views/loading'), },
- { path: 'message', component: () => import(/*webpackChunkName:'message'*/'./views/message'), },
- { path: 'modal', component: () => import(/*webpackChunkName:'modal'*/'./views/modal'), },
- { path: 'menu', component: () => import(/*webpackChunkName:'menu'*/'./views/menu'), },
- { path: 'notice', component: () => import(/*webpackChunkName:'notice'*/'./views/notice'), },
- { path: 'radio', component: () => import(/*webpackChunkName:'radio'*/'./views/radio'), },
- { path: 'react-kui', component: () => import(/*webpackChunkName:'react-kui'*/'./views/react-kui'), },
- { path: 'select', component: () => import(/*webpackChunkName:'select'*/'./views/select'), },
- { path: 'ssr', component: () => import(/*webpackChunkName:'ssr'*/'./views/ssr'), },
- { path: 'switch', component: () => import(/*webpackChunkName:'switch'*/'./views/switch'), },
- { path: 'start', component: () => import(/*webpackChunkName:'start'*/'./views/start'), },
- { path: 'steps', component: () => import(/*webpackChunkName:'steps'*/'./views/steps'), },
- { path: 'sponsor', component: () => import(/*webpackChunkName:'sponsor'*/'./views/sponsor'), },
- { path: 'table', component: () => import(/*webpackChunkName:'table'*/'./views/table'), },
- { path: 'tag', component: () => import(/*webpackChunkName:'tag'*/'./views/tag'), },
- { path: 'tabs', component: () => import(/*webpackChunkName:'tabs'*/'./views/tabs'), },
- { path: 'timeline', component: () => import(/*webpackChunkName:'timeline'*/'./views/timeline'), },
- { path: 'tooltip', component: () => import(/*webpackChunkName:'tooltip'*/'./views/tooltip'), },
- { path: 'theme', component: () => import(/*webpackChunkName:'theme'*/'./views/theme'), },
- { path: 'tree', component: () => import(/*webpackChunkName:'tree'*/'./views/tree'), },
- { path: 'treeselect', component: () => import(/*webpackChunkName:'treeselect'*/'./views/treeselect'), },
- { path: 'test', component: () => import(/*webpackChunkName:'test'*/'./views/test'), },
- { path: 'poptip', component: () => import(/*webpackChunkName:'poptip'*/'./views/poptip'), },
- { path: 'page', component: () => import(/*webpackChunkName:'page'*/'./views/page'), },
- { path: 'upload', component: () => import(/*webpackChunkName:'upload'*/'./views/upload'), },
+let docs = [
+ { path: 'start', component: () => import(/*webpackChunkName:'start'*/'./views/start') },
+ { path: 'use-in-vue', component: () => import(/*webpackChunkName:'use-in-vue'*/'./views/use-in-vue') },
+ { path: 'log', component: () => import(/*webpackChunkName:'log'*/'./views/log') },
+ { path: 'ssr', component: () => import(/*webpackChunkName:'ssr'*/'./views/ssr') },
+ { path: 'theme', component: () => import(/*webpackChunkName:'theme'*/'./views/theme') },
+ { path: 'kui-loader', component: () => import(/*webpackChunkName:'kui-loader'*/'./views/kui-loader') },
+]
+let components = [
+ { path: 'alert', component: () => import(/*webpackChunkName:'alert'*/'../components/alert/demo'), },
+ { path: 'affix', component: () => import(/*webpackChunkName:'affix'*/'../components/affix/demo'), },
+ { path: 'card', component: () => import(/*webpackChunkName:'card'*/'../components/card/demo'), },
+ { path: 'carousel', component: () => import(/*webpackChunkName:'carousel'*/'../components/carousel/demo'), },
+ { path: 'collapse', component: () => import(/*webpackChunkName:'collapse'*/'../components/collapse/demo'), },
+ { path: 'colorpicker', component: () => import(/*webpackChunkName:'colorpicker'*/'../components/colorPicker/demo'), },
+ { path: 'checkbox', component: () => import(/*webpackChunkName:'checkbox'*/'../components/checkbox/demo'), },
+ { path: 'button', component: () => import(/*webpackChunkName:'button'*/'../components/button/demo'), },
+ { path: 'breadcrumb', component: () => import(/*webpackChunkName:'breadcrumb'*/'../components/breadcrumb/demo'), },
+ { path: 'backtop', component: () => import(/*webpackChunkName:'backtop'*/'../components/backtop/demo'), },
+ { path: 'badge', component: () => import(/*webpackChunkName:'badge'*/'../components/badge/demo'), },
+ { path: 'datepicker', component: () => import(/*webpackChunkName:'datepicker'*/'../components/datePicker/demo'), },
+ { path: 'dropdown', component: () => import(/*webpackChunkName:'dropdown'*/'../components/dropdown/demo'), },
+ { path: 'drawer', component: () => import(/*webpackChunkName:'drawer'*/'../components/drawer/demo'), },
+ { path: 'form', component: () => import(/*webpackChunkName:'form'*/'../components/form/demo'), },
+ { path: 'grid', component: () => import(/*webpackChunkName:'grid'*/'../components/grid/demo'), },
+ // { path: 'imagepreview', component: () => import(/*webpackChunkName:'image-preview'*/'../components/image-preview/demo'), },
+ { path: 'input', component: () => import(/*webpackChunkName:'input'*/'../components/input/demo'), },
+ { path: 'icon', component: () => import(/*webpackChunkName:'icon'*/'../components/icon/demo'), },
+ { path: 'layout', component: () => import(/*webpackChunkName:'layout'*/'../components/layout/demo'), },
+ { path: 'message', component: () => import(/*webpackChunkName:'message'*/'../components/message/demo'), },
+ { path: 'modal', component: () => import(/*webpackChunkName:'modal'*/'../components/modal/demo'), },
+ { path: 'menu', component: () => import(/*webpackChunkName:'menu'*/'../components/menu/demo'), },
+ { path: 'notice', component: () => import(/*webpackChunkName:'notice'*/'../components/notice/demo'), },
+ { path: 'radio', component: () => import(/*webpackChunkName:'radio'*/'../components/radio/demo'), },
+ { path: 'select', component: () => import(/*webpackChunkName:'select'*/'../components/select/demo'), },
+ { path: 'spin', component: () => import(/*webpackChunkName:'spin'*/'../components/spin/demo'), },
+ { path: 'switch', component: () => import(/*webpackChunkName:'switch'*/'../components/switch/demo'), },
+ // { path: 'steps', component: () => import(/*webpackChunkName:'steps'*/'../components/steps/demo'), },
+ { path: 'table', component: () => import(/*webpackChunkName:'table'*/'../components/table/demo'), },
+ { path: 'tag', component: () => import(/*webpackChunkName:'tag'*/'../components/tag/demo'), },
+ { path: 'tabs', component: () => import(/*webpackChunkName:'tabs'*/'../components/tabs/demo'), },
+ { path: 'timeline', component: () => import(/*webpackChunkName:'timeline'*/'../components/timeline/demo'), },
+ { path: 'tooltip', component: () => import(/*webpackChunkName:'tooltip'*/'../components/tooltip/demo'), },
+ { path: 'tree', component: () => import(/*webpackChunkName:'tree'*/'../components/tree/demo'), },
+ // { path: 'treeselect', component: () => import(/*webpackChunkName:'treeselect'*/'../components/treeselect'), },
+ { path: 'poptip', component: () => import(/*webpackChunkName:'poptip'*/'../components/poptip/demo'), },
+ { path: 'popconfirm', component: () => import(/*webpackChunkName:'popconfirm'*/'../components/popconfirm/demo'), },
+ { path: 'progress', component: () => import(/*webpackChunkName:'progress'*/'../components/progress/demo'), },
+ { path: 'page', component: () => import(/*webpackChunkName:'page'*/'../components/page/demo'), },
+ // { path: 'upload', component: () => import(/*webpackChunkName:'upload'*/'../components/upload/demo'), },
];
+import layout from './layout'
router.push(
- { path: '/', component: () => import(/*webpackChunkName:'home'*/'./views/index') },
+ { path: '/', component: () => import(/*webpackChunkName:'home'*/'./index') },
{ path: '/test', component: () => import(/*webpackChunkName:'test'*/'./test') },
+ // { path: '/wwocao', component: () => import(/*webpackChunkName:'test'*/'./views/start') },
{
- path: '/',
- component: () => import(/*webpackChunkName:'layout'*/'./layout'),
- children: children
- })
+ path: '/components',
+ component: layout,
+ children: components
+ },
+ {
+ path: '/docs',
+ component: layout,
+ children: docs
+ }
+)
let routers = new Router({
- routes: router, mode: 'hash', scrollBehavior(to, from, savedPosition) {
- //return期望滚动到哪个的位置
- //returnsavedPosition||{x:0,y:0}
- document.querySelector('.colMain') && (document.querySelector('.colMain').scrollTop = 0)
+ routes: router,
+ mode: 'history',
+ scrollBehavior(to, from, savedPosition) {
+ return savedPosition || { x: 0, y: 0 }
}
})
-routers.beforeEach(function (to, from, next) {
- typeof (_hmt) != 'undefined' && _hmt.push(['_trackPageview', to.path]);
- loading.start('line');
- next()
-})
-routers.afterEach((to, from, next) => {
- // (process.env.NODE_ENV == 'development') &&
- loading.finish();
-});
+
+
+// routers.beforeEach(function (to, from, next) {
+// // typeof (_hmt) != 'undefined' && _hmt.push(['_trackPageview', to.path]);
+// // loading.start('line');
+// next()
+// })
+// routers.afterEach((to, from, next) => {
+// // (process.env.NODE_ENV == 'development') &&
+// // loading.finish();
+// });
export default routers
\ No newline at end of file
diff --git a/docs/src/assets/ani.less b/docs/src/assets/ani.less
deleted file mode 100644
index 0b3ba5d948e6a9fc69988d37b8f894844c72e9cb..0000000000000000000000000000000000000000
--- a/docs/src/assets/ani.less
+++ /dev/null
@@ -1,3205 +0,0 @@
-@charset "UTF-8";
-
-/*!
- * animate.css -http://daneden.me/animate
- * Version - 3.7.0
- * Licensed under the MIT license - http://opensource.org/licenses/MIT
- *
- * Copyright (c) 2018 Daniel Eden
- */
-
-@-webkit-keyframes bounce {
- from, 20%, 53%, 80%, to {
- -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
- 40%, 43% {
- -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
- animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
- -webkit-transform: translate3d(0, -30px, 0);
- transform: translate3d(0, -30px, 0);
- }
- 70% {
- -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
- animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
- -webkit-transform: translate3d(0, -15px, 0);
- transform: translate3d(0, -15px, 0);
- }
- 90% {
- -webkit-transform: translate3d(0, -4px, 0);
- transform: translate3d(0, -4px, 0);
- }
-}
-
-@keyframes bounce {
- from, 20%, 53%, 80%, to {
- -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
- 40%, 43% {
- -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
- animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
- -webkit-transform: translate3d(0, -30px, 0);
- transform: translate3d(0, -30px, 0);
- }
- 70% {
- -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
- animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
- -webkit-transform: translate3d(0, -15px, 0);
- transform: translate3d(0, -15px, 0);
- }
- 90% {
- -webkit-transform: translate3d(0, -4px, 0);
- transform: translate3d(0, -4px, 0);
- }
-}
-
-.bounce {
- -webkit-animation-name: bounce;
- animation-name: bounce;
- -webkit-transform-origin: center bottom;
- transform-origin: center bottom;
-}
-
-@-webkit-keyframes flash {
- from, 50%, to {
- opacity: 1;
- }
- 25%, 75% {
- opacity: 0;
- }
-}
-
-@keyframes flash {
- from, 50%, to {
- opacity: 1;
- }
- 25%, 75% {
- opacity: 0;
- }
-}
-
-.flash {
- -webkit-animation-name: flash;
- animation-name: flash;
-}
-
-
-/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
-
-@-webkit-keyframes pulse {
- from {
- -webkit-transform: scale3d(1, 1, 1);
- transform: scale3d(1, 1, 1);
- }
- 50% {
- -webkit-transform: scale3d(1.05, 1.05, 1.05);
- transform: scale3d(1.05, 1.05, 1.05);
- }
- to {
- -webkit-transform: scale3d(1, 1, 1);
- transform: scale3d(1, 1, 1);
- }
-}
-
-@keyframes pulse {
- from {
- -webkit-transform: scale3d(1, 1, 1);
- transform: scale3d(1, 1, 1);
- }
- 50% {
- -webkit-transform: scale3d(1.05, 1.05, 1.05);
- transform: scale3d(1.05, 1.05, 1.05);
- }
- to {
- -webkit-transform: scale3d(1, 1, 1);
- transform: scale3d(1, 1, 1);
- }
-}
-
-.pulse {
- -webkit-animation-name: pulse;
- animation-name: pulse;
-}
-
-@-webkit-keyframes rubberBand {
- from {
- -webkit-transform: scale3d(1, 1, 1);
- transform: scale3d(1, 1, 1);
- }
- 30% {
- -webkit-transform: scale3d(1.25, 0.75, 1);
- transform: scale3d(1.25, 0.75, 1);
- }
- 40% {
- -webkit-transform: scale3d(0.75, 1.25, 1);
- transform: scale3d(0.75, 1.25, 1);
- }
- 50% {
- -webkit-transform: scale3d(1.15, 0.85, 1);
- transform: scale3d(1.15, 0.85, 1);
- }
- 65% {
- -webkit-transform: scale3d(0.95, 1.05, 1);
- transform: scale3d(0.95, 1.05, 1);
- }
- 75% {
- -webkit-transform: scale3d(1.05, 0.95, 1);
- transform: scale3d(1.05, 0.95, 1);
- }
- to {
- -webkit-transform: scale3d(1, 1, 1);
- transform: scale3d(1, 1, 1);
- }
-}
-
-@keyframes rubberBand {
- from {
- -webkit-transform: scale3d(1, 1, 1);
- transform: scale3d(1, 1, 1);
- }
- 30% {
- -webkit-transform: scale3d(1.25, 0.75, 1);
- transform: scale3d(1.25, 0.75, 1);
- }
- 40% {
- -webkit-transform: scale3d(0.75, 1.25, 1);
- transform: scale3d(0.75, 1.25, 1);
- }
- 50% {
- -webkit-transform: scale3d(1.15, 0.85, 1);
- transform: scale3d(1.15, 0.85, 1);
- }
- 65% {
- -webkit-transform: scale3d(0.95, 1.05, 1);
- transform: scale3d(0.95, 1.05, 1);
- }
- 75% {
- -webkit-transform: scale3d(1.05, 0.95, 1);
- transform: scale3d(1.05, 0.95, 1);
- }
- to {
- -webkit-transform: scale3d(1, 1, 1);
- transform: scale3d(1, 1, 1);
- }
-}
-
-.rubberBand {
- -webkit-animation-name: rubberBand;
- animation-name: rubberBand;
-}
-
-@-webkit-keyframes shake {
- from, to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
- 10%, 30%, 50%, 70%, 90% {
- -webkit-transform: translate3d(-10px, 0, 0);
- transform: translate3d(-10px, 0, 0);
- }
- 20%, 40%, 60%, 80% {
- -webkit-transform: translate3d(10px, 0, 0);
- transform: translate3d(10px, 0, 0);
- }
-}
-
-@keyframes shake {
- from, to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
- 10%, 30%, 50%, 70%, 90% {
- -webkit-transform: translate3d(-10px, 0, 0);
- transform: translate3d(-10px, 0, 0);
- }
- 20%, 40%, 60%, 80% {
- -webkit-transform: translate3d(10px, 0, 0);
- transform: translate3d(10px, 0, 0);
- }
-}
-
-.shake {
- -webkit-animation-name: shake;
- animation-name: shake;
-}
-
-@-webkit-keyframes headShake {
- 0% {
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
- 6.5% {
- -webkit-transform: translateX(-6px) rotateY(-9deg);
- transform: translateX(-6px) rotateY(-9deg);
- }
- 18.5% {
- -webkit-transform: translateX(5px) rotateY(7deg);
- transform: translateX(5px) rotateY(7deg);
- }
- 31.5% {
- -webkit-transform: translateX(-3px) rotateY(-5deg);
- transform: translateX(-3px) rotateY(-5deg);
- }
- 43.5% {
- -webkit-transform: translateX(2px) rotateY(3deg);
- transform: translateX(2px) rotateY(3deg);
- }
- 50% {
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
-}
-
-@keyframes headShake {
- 0% {
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
- 6.5% {
- -webkit-transform: translateX(-6px) rotateY(-9deg);
- transform: translateX(-6px) rotateY(-9deg);
- }
- 18.5% {
- -webkit-transform: translateX(5px) rotateY(7deg);
- transform: translateX(5px) rotateY(7deg);
- }
- 31.5% {
- -webkit-transform: translateX(-3px) rotateY(-5deg);
- transform: translateX(-3px) rotateY(-5deg);
- }
- 43.5% {
- -webkit-transform: translateX(2px) rotateY(3deg);
- transform: translateX(2px) rotateY(3deg);
- }
- 50% {
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
-}
-
-.headShake {
- -webkit-animation-timing-function: ease-in-out;
- animation-timing-function: ease-in-out;
- -webkit-animation-name: headShake;
- animation-name: headShake;
-}
-
-@-webkit-keyframes swing {
- 20% {
- -webkit-transform: rotate3d(0, 0, 1, 15deg);
- transform: rotate3d(0, 0, 1, 15deg);
- }
- 40% {
- -webkit-transform: rotate3d(0, 0, 1, -10deg);
- transform: rotate3d(0, 0, 1, -10deg);
- }
- 60% {
- -webkit-transform: rotate3d(0, 0, 1, 5deg);
- transform: rotate3d(0, 0, 1, 5deg);
- }
- 80% {
- -webkit-transform: rotate3d(0, 0, 1, -5deg);
- transform: rotate3d(0, 0, 1, -5deg);
- }
- to {
- -webkit-transform: rotate3d(0, 0, 1, 0deg);
- transform: rotate3d(0, 0, 1, 0deg);
- }
-}
-
-@keyframes swing {
- 20% {
- -webkit-transform: rotate3d(0, 0, 1, 15deg);
- transform: rotate3d(0, 0, 1, 15deg);
- }
- 40% {
- -webkit-transform: rotate3d(0, 0, 1, -10deg);
- transform: rotate3d(0, 0, 1, -10deg);
- }
- 60% {
- -webkit-transform: rotate3d(0, 0, 1, 5deg);
- transform: rotate3d(0, 0, 1, 5deg);
- }
- 80% {
- -webkit-transform: rotate3d(0, 0, 1, -5deg);
- transform: rotate3d(0, 0, 1, -5deg);
- }
- to {
- -webkit-transform: rotate3d(0, 0, 1, 0deg);
- transform: rotate3d(0, 0, 1, 0deg);
- }
-}
-
-.swing {
- -webkit-transform-origin: top center;
- transform-origin: top center;
- -webkit-animation-name: swing;
- animation-name: swing;
-}
-
-@-webkit-keyframes tada {
- from {
- -webkit-transform: scale3d(1, 1, 1);
- transform: scale3d(1, 1, 1);
- }
- 10%, 20% {
- -webkit-transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
- transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
- }
- 30%, 50%, 70%, 90% {
- -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
- transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
- }
- 40%, 60%, 80% {
- -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
- transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
- }
- to {
- -webkit-transform: scale3d(1, 1, 1);
- transform: scale3d(1, 1, 1);
- }
-}
-
-@keyframes tada {
- from {
- -webkit-transform: scale3d(1, 1, 1);
- transform: scale3d(1, 1, 1);
- }
- 10%, 20% {
- -webkit-transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
- transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
- }
- 30%, 50%, 70%, 90% {
- -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
- transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
- }
- 40%, 60%, 80% {
- -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
- transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
- }
- to {
- -webkit-transform: scale3d(1, 1, 1);
- transform: scale3d(1, 1, 1);
- }
-}
-
-.tada {
- -webkit-animation-name: tada;
- animation-name: tada;
-}
-
-
-/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
-
-@-webkit-keyframes wobble {
- from {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
- 15% {
- -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
- transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
- }
- 30% {
- -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
- transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
- }
- 45% {
- -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
- transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
- }
- 60% {
- -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
- transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
- }
- 75% {
- -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
- transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-@keyframes wobble {
- from {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
- 15% {
- -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
- transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
- }
- 30% {
- -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
- transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
- }
- 45% {
- -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
- transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
- }
- 60% {
- -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
- transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
- }
- 75% {
- -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
- transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-.wobble {
- -webkit-animation-name: wobble;
- animation-name: wobble;
-}
-
-@-webkit-keyframes jello {
- from, 11.1%, to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
- 22.2% {
- -webkit-transform: skewX(-12.5deg) skewY(-12.5deg);
- transform: skewX(-12.5deg) skewY(-12.5deg);
- }
- 33.3% {
- -webkit-transform: skewX(6.25deg) skewY(6.25deg);
- transform: skewX(6.25deg) skewY(6.25deg);
- }
- 44.4% {
- -webkit-transform: skewX(-3.125deg) skewY(-3.125deg);
- transform: skewX(-3.125deg) skewY(-3.125deg);
- }
- 55.5% {
- -webkit-transform: skewX(1.5625deg) skewY(1.5625deg);
- transform: skewX(1.5625deg) skewY(1.5625deg);
- }
- 66.6% {
- -webkit-transform: skewX(-0.78125deg) skewY(-0.78125deg);
- transform: skewX(-0.78125deg) skewY(-0.78125deg);
- }
- 77.7% {
- -webkit-transform: skewX(0.390625deg) skewY(0.390625deg);
- transform: skewX(0.390625deg) skewY(0.390625deg);
- }
- 88.8% {
- -webkit-transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
- transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
- }
-}
-
-@keyframes jello {
- from, 11.1%, to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
- 22.2% {
- -webkit-transform: skewX(-12.5deg) skewY(-12.5deg);
- transform: skewX(-12.5deg) skewY(-12.5deg);
- }
- 33.3% {
- -webkit-transform: skewX(6.25deg) skewY(6.25deg);
- transform: skewX(6.25deg) skewY(6.25deg);
- }
- 44.4% {
- -webkit-transform: skewX(-3.125deg) skewY(-3.125deg);
- transform: skewX(-3.125deg) skewY(-3.125deg);
- }
- 55.5% {
- -webkit-transform: skewX(1.5625deg) skewY(1.5625deg);
- transform: skewX(1.5625deg) skewY(1.5625deg);
- }
- 66.6% {
- -webkit-transform: skewX(-0.78125deg) skewY(-0.78125deg);
- transform: skewX(-0.78125deg) skewY(-0.78125deg);
- }
- 77.7% {
- -webkit-transform: skewX(0.390625deg) skewY(0.390625deg);
- transform: skewX(0.390625deg) skewY(0.390625deg);
- }
- 88.8% {
- -webkit-transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
- transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
- }
-}
-
-.jello {
- -webkit-animation-name: jello;
- animation-name: jello;
- -webkit-transform-origin: center;
- transform-origin: center;
-}
-
-@-webkit-keyframes heartBeat {
- 0% {
- -webkit-transform: scale(1);
- transform: scale(1);
- }
- 14% {
- -webkit-transform: scale(1.3);
- transform: scale(1.3);
- }
- 28% {
- -webkit-transform: scale(1);
- transform: scale(1);
- }
- 42% {
- -webkit-transform: scale(1.3);
- transform: scale(1.3);
- }
- 70% {
- -webkit-transform: scale(1);
- transform: scale(1);
- }
-}
-
-@keyframes heartBeat {
- 0% {
- -webkit-transform: scale(1);
- transform: scale(1);
- }
- 14% {
- -webkit-transform: scale(1.3);
- transform: scale(1.3);
- }
- 28% {
- -webkit-transform: scale(1);
- transform: scale(1);
- }
- 42% {
- -webkit-transform: scale(1.3);
- transform: scale(1.3);
- }
- 70% {
- -webkit-transform: scale(1);
- transform: scale(1);
- }
-}
-
-.heartBeat {
- -webkit-animation-name: heartBeat;
- animation-name: heartBeat;
- -webkit-animation-duration: 1.3s;
- animation-duration: 1.3s;
- -webkit-animation-timing-function: ease-in-out;
- animation-timing-function: ease-in-out;
-}
-
-@-webkit-keyframes bounceIn {
- from, 20%, 40%, 60%, 80%, to {
- -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- }
- 0% {
- opacity: 0;
- -webkit-transform: scale3d(0.3, 0.3, 0.3);
- transform: scale3d(0.3, 0.3, 0.3);
- }
- 20% {
- -webkit-transform: scale3d(1.1, 1.1, 1.1);
- transform: scale3d(1.1, 1.1, 1.1);
- }
- 40% {
- -webkit-transform: scale3d(0.9, 0.9, 0.9);
- transform: scale3d(0.9, 0.9, 0.9);
- }
- 60% {
- opacity: 1;
- -webkit-transform: scale3d(1.03, 1.03, 1.03);
- transform: scale3d(1.03, 1.03, 1.03);
- }
- 80% {
- -webkit-transform: scale3d(0.97, 0.97, 0.97);
- transform: scale3d(0.97, 0.97, 0.97);
- }
- to {
- opacity: 1;
- -webkit-transform: scale3d(1, 1, 1);
- transform: scale3d(1, 1, 1);
- }
-}
-
-@keyframes bounceIn {
- from, 20%, 40%, 60%, 80%, to {
- -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- }
- 0% {
- opacity: 0;
- -webkit-transform: scale3d(0.3, 0.3, 0.3);
- transform: scale3d(0.3, 0.3, 0.3);
- }
- 20% {
- -webkit-transform: scale3d(1.1, 1.1, 1.1);
- transform: scale3d(1.1, 1.1, 1.1);
- }
- 40% {
- -webkit-transform: scale3d(0.9, 0.9, 0.9);
- transform: scale3d(0.9, 0.9, 0.9);
- }
- 60% {
- opacity: 1;
- -webkit-transform: scale3d(1.03, 1.03, 1.03);
- transform: scale3d(1.03, 1.03, 1.03);
- }
- 80% {
- -webkit-transform: scale3d(0.97, 0.97, 0.97);
- transform: scale3d(0.97, 0.97, 0.97);
- }
- to {
- opacity: 1;
- -webkit-transform: scale3d(1, 1, 1);
- transform: scale3d(1, 1, 1);
- }
-}
-
-.bounceIn {
- -webkit-animation-duration: 0.75s;
- animation-duration: 0.75s;
- -webkit-animation-name: bounceIn;
- animation-name: bounceIn;
-}
-
-@-webkit-keyframes bounceInDown {
- from, 60%, 75%, 90%, to {
- -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- }
- 0% {
- opacity: 0;
- -webkit-transform: translate3d(0, -3000px, 0);
- transform: translate3d(0, -3000px, 0);
- }
- 60% {
- opacity: 1;
- -webkit-transform: translate3d(0, 25px, 0);
- transform: translate3d(0, 25px, 0);
- }
- 75% {
- -webkit-transform: translate3d(0, -10px, 0);
- transform: translate3d(0, -10px, 0);
- }
- 90% {
- -webkit-transform: translate3d(0, 5px, 0);
- transform: translate3d(0, 5px, 0);
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-@keyframes bounceInDown {
- from, 60%, 75%, 90%, to {
- -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- }
- 0% {
- opacity: 0;
- -webkit-transform: translate3d(0, -3000px, 0);
- transform: translate3d(0, -3000px, 0);
- }
- 60% {
- opacity: 1;
- -webkit-transform: translate3d(0, 25px, 0);
- transform: translate3d(0, 25px, 0);
- }
- 75% {
- -webkit-transform: translate3d(0, -10px, 0);
- transform: translate3d(0, -10px, 0);
- }
- 90% {
- -webkit-transform: translate3d(0, 5px, 0);
- transform: translate3d(0, 5px, 0);
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-.bounceInDown {
- -webkit-animation-name: bounceInDown;
- animation-name: bounceInDown;
-}
-
-@-webkit-keyframes bounceInLeft {
- from, 60%, 75%, 90%, to {
- -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- }
- 0% {
- opacity: 0;
- -webkit-transform: translate3d(-3000px, 0, 0);
- transform: translate3d(-3000px, 0, 0);
- }
- 60% {
- opacity: 1;
- -webkit-transform: translate3d(25px, 0, 0);
- transform: translate3d(25px, 0, 0);
- }
- 75% {
- -webkit-transform: translate3d(-10px, 0, 0);
- transform: translate3d(-10px, 0, 0);
- }
- 90% {
- -webkit-transform: translate3d(5px, 0, 0);
- transform: translate3d(5px, 0, 0);
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-@keyframes bounceInLeft {
- from, 60%, 75%, 90%, to {
- -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- }
- 0% {
- opacity: 0;
- -webkit-transform: translate3d(-3000px, 0, 0);
- transform: translate3d(-3000px, 0, 0);
- }
- 60% {
- opacity: 1;
- -webkit-transform: translate3d(25px, 0, 0);
- transform: translate3d(25px, 0, 0);
- }
- 75% {
- -webkit-transform: translate3d(-10px, 0, 0);
- transform: translate3d(-10px, 0, 0);
- }
- 90% {
- -webkit-transform: translate3d(5px, 0, 0);
- transform: translate3d(5px, 0, 0);
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-.bounceInLeft {
- -webkit-animation-name: bounceInLeft;
- animation-name: bounceInLeft;
-}
-
-@-webkit-keyframes bounceInRight {
- from, 60%, 75%, 90%, to {
- -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- }
- from {
- opacity: 0;
- -webkit-transform: translate3d(3000px, 0, 0);
- transform: translate3d(3000px, 0, 0);
- }
- 60% {
- opacity: 1;
- -webkit-transform: translate3d(-25px, 0, 0);
- transform: translate3d(-25px, 0, 0);
- }
- 75% {
- -webkit-transform: translate3d(10px, 0, 0);
- transform: translate3d(10px, 0, 0);
- }
- 90% {
- -webkit-transform: translate3d(-5px, 0, 0);
- transform: translate3d(-5px, 0, 0);
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-@keyframes bounceInRight {
- from, 60%, 75%, 90%, to {
- -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- }
- from {
- opacity: 0;
- -webkit-transform: translate3d(3000px, 0, 0);
- transform: translate3d(3000px, 0, 0);
- }
- 60% {
- opacity: 1;
- -webkit-transform: translate3d(-25px, 0, 0);
- transform: translate3d(-25px, 0, 0);
- }
- 75% {
- -webkit-transform: translate3d(10px, 0, 0);
- transform: translate3d(10px, 0, 0);
- }
- 90% {
- -webkit-transform: translate3d(-5px, 0, 0);
- transform: translate3d(-5px, 0, 0);
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-.bounceInRight {
- -webkit-animation-name: bounceInRight;
- animation-name: bounceInRight;
-}
-
-@-webkit-keyframes bounceInUp {
- from, 60%, 75%, 90%, to {
- -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- }
- from {
- opacity: 0;
- -webkit-transform: translate3d(0, 3000px, 0);
- transform: translate3d(0, 3000px, 0);
- }
- 60% {
- opacity: 1;
- -webkit-transform: translate3d(0, -20px, 0);
- transform: translate3d(0, -20px, 0);
- }
- 75% {
- -webkit-transform: translate3d(0, 10px, 0);
- transform: translate3d(0, 10px, 0);
- }
- 90% {
- -webkit-transform: translate3d(0, -5px, 0);
- transform: translate3d(0, -5px, 0);
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-@keyframes bounceInUp {
- from, 60%, 75%, 90%, to {
- -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- }
- from {
- opacity: 0;
- -webkit-transform: translate3d(0, 3000px, 0);
- transform: translate3d(0, 3000px, 0);
- }
- 60% {
- opacity: 1;
- -webkit-transform: translate3d(0, -20px, 0);
- transform: translate3d(0, -20px, 0);
- }
- 75% {
- -webkit-transform: translate3d(0, 10px, 0);
- transform: translate3d(0, 10px, 0);
- }
- 90% {
- -webkit-transform: translate3d(0, -5px, 0);
- transform: translate3d(0, -5px, 0);
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-.bounceInUp {
- -webkit-animation-name: bounceInUp;
- animation-name: bounceInUp;
-}
-
-@-webkit-keyframes bounceOut {
- 20% {
- -webkit-transform: scale3d(0.9, 0.9, 0.9);
- transform: scale3d(0.9, 0.9, 0.9);
- }
- 50%, 55% {
- opacity: 1;
- -webkit-transform: scale3d(1.1, 1.1, 1.1);
- transform: scale3d(1.1, 1.1, 1.1);
- }
- to {
- opacity: 0;
- -webkit-transform: scale3d(0.3, 0.3, 0.3);
- transform: scale3d(0.3, 0.3, 0.3);
- }
-}
-
-@keyframes bounceOut {
- 20% {
- -webkit-transform: scale3d(0.9, 0.9, 0.9);
- transform: scale3d(0.9, 0.9, 0.9);
- }
- 50%, 55% {
- opacity: 1;
- -webkit-transform: scale3d(1.1, 1.1, 1.1);
- transform: scale3d(1.1, 1.1, 1.1);
- }
- to {
- opacity: 0;
- -webkit-transform: scale3d(0.3, 0.3, 0.3);
- transform: scale3d(0.3, 0.3, 0.3);
- }
-}
-
-.bounceOut {
- -webkit-animation-duration: 0.75s;
- animation-duration: 0.75s;
- -webkit-animation-name: bounceOut;
- animation-name: bounceOut;
-}
-
-@-webkit-keyframes bounceOutDown {
- 20% {
- -webkit-transform: translate3d(0, 10px, 0);
- transform: translate3d(0, 10px, 0);
- }
- 40%, 45% {
- opacity: 1;
- -webkit-transform: translate3d(0, -20px, 0);
- transform: translate3d(0, -20px, 0);
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(0, 2000px, 0);
- transform: translate3d(0, 2000px, 0);
- }
-}
-
-@keyframes bounceOutDown {
- 20% {
- -webkit-transform: translate3d(0, 10px, 0);
- transform: translate3d(0, 10px, 0);
- }
- 40%, 45% {
- opacity: 1;
- -webkit-transform: translate3d(0, -20px, 0);
- transform: translate3d(0, -20px, 0);
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(0, 2000px, 0);
- transform: translate3d(0, 2000px, 0);
- }
-}
-
-.bounceOutDown {
- -webkit-animation-name: bounceOutDown;
- animation-name: bounceOutDown;
-}
-
-@-webkit-keyframes bounceOutLeft {
- 20% {
- opacity: 1;
- -webkit-transform: translate3d(20px, 0, 0);
- transform: translate3d(20px, 0, 0);
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(-2000px, 0, 0);
- transform: translate3d(-2000px, 0, 0);
- }
-}
-
-@keyframes bounceOutLeft {
- 20% {
- opacity: 1;
- -webkit-transform: translate3d(20px, 0, 0);
- transform: translate3d(20px, 0, 0);
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(-2000px, 0, 0);
- transform: translate3d(-2000px, 0, 0);
- }
-}
-
-.bounceOutLeft {
- -webkit-animation-name: bounceOutLeft;
- animation-name: bounceOutLeft;
-}
-
-@-webkit-keyframes bounceOutRight {
- 20% {
- opacity: 1;
- -webkit-transform: translate3d(-20px, 0, 0);
- transform: translate3d(-20px, 0, 0);
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(2000px, 0, 0);
- transform: translate3d(2000px, 0, 0);
- }
-}
-
-@keyframes bounceOutRight {
- 20% {
- opacity: 1;
- -webkit-transform: translate3d(-20px, 0, 0);
- transform: translate3d(-20px, 0, 0);
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(2000px, 0, 0);
- transform: translate3d(2000px, 0, 0);
- }
-}
-
-.bounceOutRight {
- -webkit-animation-name: bounceOutRight;
- animation-name: bounceOutRight;
-}
-
-@-webkit-keyframes bounceOutUp {
- 20% {
- -webkit-transform: translate3d(0, -10px, 0);
- transform: translate3d(0, -10px, 0);
- }
- 40%, 45% {
- opacity: 1;
- -webkit-transform: translate3d(0, 20px, 0);
- transform: translate3d(0, 20px, 0);
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(0, -2000px, 0);
- transform: translate3d(0, -2000px, 0);
- }
-}
-
-@keyframes bounceOutUp {
- 20% {
- -webkit-transform: translate3d(0, -10px, 0);
- transform: translate3d(0, -10px, 0);
- }
- 40%, 45% {
- opacity: 1;
- -webkit-transform: translate3d(0, 20px, 0);
- transform: translate3d(0, 20px, 0);
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(0, -2000px, 0);
- transform: translate3d(0, -2000px, 0);
- }
-}
-
-.bounceOutUp {
- -webkit-animation-name: bounceOutUp;
- animation-name: bounceOutUp;
-}
-
-@-webkit-keyframes fadeIn {
- from {
- opacity: 0;
- }
- to {
- opacity: 1;
- }
-}
-
-@keyframes fadeIn {
- from {
- opacity: 0;
- }
- to {
- opacity: 1;
- }
-}
-
-.fadeIn {
- -webkit-animation-name: fadeIn;
- animation-name: fadeIn;
-}
-
-@-webkit-keyframes fadeInDown {
- from {
- opacity: 0;
- -webkit-transform: translate3d(0, -100%, 0);
- transform: translate3d(0, -100%, 0);
- }
- to {
- opacity: 1;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-@keyframes fadeInDown {
- from {
- opacity: 0;
- -webkit-transform: translate3d(0, -100%, 0);
- transform: translate3d(0, -100%, 0);
- }
- to {
- opacity: 1;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-.fadeInDown {
- -webkit-animation-name: fadeInDown;
- animation-name: fadeInDown;
-}
-
-@-webkit-keyframes fadeInDownBig {
- from {
- opacity: 0;
- -webkit-transform: translate3d(0, -2000px, 0);
- transform: translate3d(0, -2000px, 0);
- }
- to {
- opacity: 1;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-@keyframes fadeInDownBig {
- from {
- opacity: 0;
- -webkit-transform: translate3d(0, -2000px, 0);
- transform: translate3d(0, -2000px, 0);
- }
- to {
- opacity: 1;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-.fadeInDownBig {
- -webkit-animation-name: fadeInDownBig;
- animation-name: fadeInDownBig;
-}
-
-@-webkit-keyframes fadeInLeft {
- from {
- opacity: 0;
- -webkit-transform: translate3d(-100%, 0, 0);
- transform: translate3d(-100%, 0, 0);
- }
- to {
- opacity: 1;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-@keyframes fadeInLeft {
- from {
- opacity: 0;
- -webkit-transform: translate3d(-100%, 0, 0);
- transform: translate3d(-100%, 0, 0);
- }
- to {
- opacity: 1;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-.fadeInLeft {
- -webkit-animation-name: fadeInLeft;
- animation-name: fadeInLeft;
-}
-
-@-webkit-keyframes fadeInLeftBig {
- from {
- opacity: 0;
- -webkit-transform: translate3d(-2000px, 0, 0);
- transform: translate3d(-2000px, 0, 0);
- }
- to {
- opacity: 1;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-@keyframes fadeInLeftBig {
- from {
- opacity: 0;
- -webkit-transform: translate3d(-2000px, 0, 0);
- transform: translate3d(-2000px, 0, 0);
- }
- to {
- opacity: 1;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-.fadeInLeftBig {
- -webkit-animation-name: fadeInLeftBig;
- animation-name: fadeInLeftBig;
-}
-
-@-webkit-keyframes fadeInRight {
- from {
- opacity: 0;
- -webkit-transform: translate3d(100%, 0, 0);
- transform: translate3d(100%, 0, 0);
- }
- to {
- opacity: 1;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-@keyframes fadeInRight {
- from {
- opacity: 0;
- -webkit-transform: translate3d(100%, 0, 0);
- transform: translate3d(100%, 0, 0);
- }
- to {
- opacity: 1;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-.fadeInRight {
- -webkit-animation-name: fadeInRight;
- animation-name: fadeInRight;
-}
-
-@-webkit-keyframes fadeInRightBig {
- from {
- opacity: 0;
- -webkit-transform: translate3d(2000px, 0, 0);
- transform: translate3d(2000px, 0, 0);
- }
- to {
- opacity: 1;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-@keyframes fadeInRightBig {
- from {
- opacity: 0;
- -webkit-transform: translate3d(2000px, 0, 0);
- transform: translate3d(2000px, 0, 0);
- }
- to {
- opacity: 1;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-.fadeInRightBig {
- -webkit-animation-name: fadeInRightBig;
- animation-name: fadeInRightBig;
-}
-
-@-webkit-keyframes fadeInUp {
- from {
- opacity: 0;
- -webkit-transform: translate3d(0, 100%, 0);
- transform: translate3d(0, 100%, 0);
- }
- to {
- opacity: 1;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-@keyframes fadeInUp {
- from {
- opacity: 0;
- -webkit-transform: translate3d(0, 100%, 0);
- transform: translate3d(0, 100%, 0);
- }
- to {
- opacity: 1;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-.fadeInUp {
- -webkit-animation-name: fadeInUp;
- animation-name: fadeInUp;
-}
-
-@-webkit-keyframes fadeInUpBig {
- from {
- opacity: 0;
- -webkit-transform: translate3d(0, 2000px, 0);
- transform: translate3d(0, 2000px, 0);
- }
- to {
- opacity: 1;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-@keyframes fadeInUpBig {
- from {
- opacity: 0;
- -webkit-transform: translate3d(0, 2000px, 0);
- transform: translate3d(0, 2000px, 0);
- }
- to {
- opacity: 1;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-.fadeInUpBig {
- -webkit-animation-name: fadeInUpBig;
- animation-name: fadeInUpBig;
-}
-
-@-webkit-keyframes fadeOut {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- }
-}
-
-@keyframes fadeOut {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- }
-}
-
-.fadeOut {
- -webkit-animation-name: fadeOut;
- animation-name: fadeOut;
-}
-
-@-webkit-keyframes fadeOutDown {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(0, 100%, 0);
- transform: translate3d(0, 100%, 0);
- }
-}
-
-@keyframes fadeOutDown {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(0, 100%, 0);
- transform: translate3d(0, 100%, 0);
- }
-}
-
-.fadeOutDown {
- -webkit-animation-name: fadeOutDown;
- animation-name: fadeOutDown;
-}
-
-@-webkit-keyframes fadeOutDownBig {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(0, 2000px, 0);
- transform: translate3d(0, 2000px, 0);
- }
-}
-
-@keyframes fadeOutDownBig {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(0, 2000px, 0);
- transform: translate3d(0, 2000px, 0);
- }
-}
-
-.fadeOutDownBig {
- -webkit-animation-name: fadeOutDownBig;
- animation-name: fadeOutDownBig;
-}
-
-@-webkit-keyframes fadeOutLeft {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(-100%, 0, 0);
- transform: translate3d(-100%, 0, 0);
- }
-}
-
-@keyframes fadeOutLeft {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(-100%, 0, 0);
- transform: translate3d(-100%, 0, 0);
- }
-}
-
-.fadeOutLeft {
- -webkit-animation-name: fadeOutLeft;
- animation-name: fadeOutLeft;
-}
-
-@-webkit-keyframes fadeOutLeftBig {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(-2000px, 0, 0);
- transform: translate3d(-2000px, 0, 0);
- }
-}
-
-@keyframes fadeOutLeftBig {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(-2000px, 0, 0);
- transform: translate3d(-2000px, 0, 0);
- }
-}
-
-.fadeOutLeftBig {
- -webkit-animation-name: fadeOutLeftBig;
- animation-name: fadeOutLeftBig;
-}
-
-@-webkit-keyframes fadeOutRight {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(100%, 0, 0);
- transform: translate3d(100%, 0, 0);
- }
-}
-
-@keyframes fadeOutRight {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(100%, 0, 0);
- transform: translate3d(100%, 0, 0);
- }
-}
-
-.fadeOutRight {
- -webkit-animation-name: fadeOutRight;
- animation-name: fadeOutRight;
-}
-
-@-webkit-keyframes fadeOutRightBig {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(2000px, 0, 0);
- transform: translate3d(2000px, 0, 0);
- }
-}
-
-@keyframes fadeOutRightBig {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(2000px, 0, 0);
- transform: translate3d(2000px, 0, 0);
- }
-}
-
-.fadeOutRightBig {
- -webkit-animation-name: fadeOutRightBig;
- animation-name: fadeOutRightBig;
-}
-
-@-webkit-keyframes fadeOutUp {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(0, -100%, 0);
- transform: translate3d(0, -100%, 0);
- }
-}
-
-@keyframes fadeOutUp {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(0, -100%, 0);
- transform: translate3d(0, -100%, 0);
- }
-}
-
-.fadeOutUp {
- -webkit-animation-name: fadeOutUp;
- animation-name: fadeOutUp;
-}
-
-@-webkit-keyframes fadeOutUpBig {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(0, -2000px, 0);
- transform: translate3d(0, -2000px, 0);
- }
-}
-
-@keyframes fadeOutUpBig {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(0, -2000px, 0);
- transform: translate3d(0, -2000px, 0);
- }
-}
-
-.fadeOutUpBig {
- -webkit-animation-name: fadeOutUpBig;
- animation-name: fadeOutUpBig;
-}
-
-@-webkit-keyframes flip {
- from {
- -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, -360deg);
- transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, -360deg);
- -webkit-animation-timing-function: ease-out;
- animation-timing-function: ease-out;
- }
- 40% {
- -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
- transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
- -webkit-animation-timing-function: ease-out;
- animation-timing-function: ease-out;
- }
- 50% {
- -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
- transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- }
- 80% {
- -webkit-transform: perspective(400px) scale3d(0.95, 0.95, 0.95) translate3d(0, 0, 0) rotate3d(0, 1, 0, 0deg);
- transform: perspective(400px) scale3d(0.95, 0.95, 0.95) translate3d(0, 0, 0) rotate3d(0, 1, 0, 0deg);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- }
- to {
- -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, 0deg);
- transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, 0deg);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- }
-}
-
-@keyframes flip {
- from {
- -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, -360deg);
- transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, -360deg);
- -webkit-animation-timing-function: ease-out;
- animation-timing-function: ease-out;
- }
- 40% {
- -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
- transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
- -webkit-animation-timing-function: ease-out;
- animation-timing-function: ease-out;
- }
- 50% {
- -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
- transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- }
- 80% {
- -webkit-transform: perspective(400px) scale3d(0.95, 0.95, 0.95) translate3d(0, 0, 0) rotate3d(0, 1, 0, 0deg);
- transform: perspective(400px) scale3d(0.95, 0.95, 0.95) translate3d(0, 0, 0) rotate3d(0, 1, 0, 0deg);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- }
- to {
- -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, 0deg);
- transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, 0deg);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- }
-}
-
-.animated.flip {
- -webkit-backface-visibility: visible;
- backface-visibility: visible;
- -webkit-animation-name: flip;
- animation-name: flip;
-}
-
-@-webkit-keyframes flipInX {
- from {
- -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
- transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- opacity: 0;
- }
- 40% {
- -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
- transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- }
- 60% {
- -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
- transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
- opacity: 1;
- }
- 80% {
- -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
- transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
- }
- to {
- -webkit-transform: perspective(400px);
- transform: perspective(400px);
- }
-}
-
-@keyframes flipInX {
- from {
- -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
- transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- opacity: 0;
- }
- 40% {
- -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
- transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- }
- 60% {
- -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
- transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
- opacity: 1;
- }
- 80% {
- -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
- transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
- }
- to {
- -webkit-transform: perspective(400px);
- transform: perspective(400px);
- }
-}
-
-.flipInX {
- -webkit-backface-visibility: visible !important;
- backface-visibility: visible !important;
- -webkit-animation-name: flipInX;
- animation-name: flipInX;
-}
-
-@-webkit-keyframes flipInY {
- from {
- -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
- transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- opacity: 0;
- }
- 40% {
- -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
- transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- }
- 60% {
- -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
- transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
- opacity: 1;
- }
- 80% {
- -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
- transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
- }
- to {
- -webkit-transform: perspective(400px);
- transform: perspective(400px);
- }
-}
-
-@keyframes flipInY {
- from {
- -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
- transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- opacity: 0;
- }
- 40% {
- -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
- transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- }
- 60% {
- -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
- transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
- opacity: 1;
- }
- 80% {
- -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
- transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
- }
- to {
- -webkit-transform: perspective(400px);
- transform: perspective(400px);
- }
-}
-
-.flipInY {
- -webkit-backface-visibility: visible !important;
- backface-visibility: visible !important;
- -webkit-animation-name: flipInY;
- animation-name: flipInY;
-}
-
-@-webkit-keyframes flipOutX {
- from {
- -webkit-transform: perspective(400px);
- transform: perspective(400px);
- }
- 30% {
- -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
- transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
- opacity: 1;
- }
- to {
- -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
- transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
- opacity: 0;
- }
-}
-
-@keyframes flipOutX {
- from {
- -webkit-transform: perspective(400px);
- transform: perspective(400px);
- }
- 30% {
- -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
- transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
- opacity: 1;
- }
- to {
- -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
- transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
- opacity: 0;
- }
-}
-
-.flipOutX {
- -webkit-animation-duration: 0.75s;
- animation-duration: 0.75s;
- -webkit-animation-name: flipOutX;
- animation-name: flipOutX;
- -webkit-backface-visibility: visible !important;
- backface-visibility: visible !important;
-}
-
-@-webkit-keyframes flipOutY {
- from {
- -webkit-transform: perspective(400px);
- transform: perspective(400px);
- }
- 30% {
- -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
- transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
- opacity: 1;
- }
- to {
- -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
- transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
- opacity: 0;
- }
-}
-
-@keyframes flipOutY {
- from {
- -webkit-transform: perspective(400px);
- transform: perspective(400px);
- }
- 30% {
- -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
- transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
- opacity: 1;
- }
- to {
- -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
- transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
- opacity: 0;
- }
-}
-
-.flipOutY {
- -webkit-animation-duration: 0.75s;
- animation-duration: 0.75s;
- -webkit-backface-visibility: visible !important;
- backface-visibility: visible !important;
- -webkit-animation-name: flipOutY;
- animation-name: flipOutY;
-}
-
-@-webkit-keyframes lightSpeedIn {
- from {
- -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg);
- transform: translate3d(100%, 0, 0) skewX(-30deg);
- opacity: 0;
- }
- 60% {
- -webkit-transform: skewX(20deg);
- transform: skewX(20deg);
- opacity: 1;
- }
- 80% {
- -webkit-transform: skewX(-5deg);
- transform: skewX(-5deg);
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-@keyframes lightSpeedIn {
- from {
- -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg);
- transform: translate3d(100%, 0, 0) skewX(-30deg);
- opacity: 0;
- }
- 60% {
- -webkit-transform: skewX(20deg);
- transform: skewX(20deg);
- opacity: 1;
- }
- 80% {
- -webkit-transform: skewX(-5deg);
- transform: skewX(-5deg);
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-.lightSpeedIn {
- -webkit-animation-name: lightSpeedIn;
- animation-name: lightSpeedIn;
- -webkit-animation-timing-function: ease-out;
- animation-timing-function: ease-out;
-}
-
-@-webkit-keyframes lightSpeedOut {
- from {
- opacity: 1;
- }
- to {
- -webkit-transform: translate3d(100%, 0, 0) skewX(30deg);
- transform: translate3d(100%, 0, 0) skewX(30deg);
- opacity: 0;
- }
-}
-
-@keyframes lightSpeedOut {
- from {
- opacity: 1;
- }
- to {
- -webkit-transform: translate3d(100%, 0, 0) skewX(30deg);
- transform: translate3d(100%, 0, 0) skewX(30deg);
- opacity: 0;
- }
-}
-
-.lightSpeedOut {
- -webkit-animation-name: lightSpeedOut;
- animation-name: lightSpeedOut;
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
-}
-
-@-webkit-keyframes rotateIn {
- from {
- -webkit-transform-origin: center;
- transform-origin: center;
- -webkit-transform: rotate3d(0, 0, 1, -200deg);
- transform: rotate3d(0, 0, 1, -200deg);
- opacity: 0;
- }
- to {
- -webkit-transform-origin: center;
- transform-origin: center;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- opacity: 1;
- }
-}
-
-@keyframes rotateIn {
- from {
- -webkit-transform-origin: center;
- transform-origin: center;
- -webkit-transform: rotate3d(0, 0, 1, -200deg);
- transform: rotate3d(0, 0, 1, -200deg);
- opacity: 0;
- }
- to {
- -webkit-transform-origin: center;
- transform-origin: center;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- opacity: 1;
- }
-}
-
-.rotateIn {
- -webkit-animation-name: rotateIn;
- animation-name: rotateIn;
-}
-
-@-webkit-keyframes rotateInDownLeft {
- from {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate3d(0, 0, 1, -45deg);
- transform: rotate3d(0, 0, 1, -45deg);
- opacity: 0;
- }
- to {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- opacity: 1;
- }
-}
-
-@keyframes rotateInDownLeft {
- from {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate3d(0, 0, 1, -45deg);
- transform: rotate3d(0, 0, 1, -45deg);
- opacity: 0;
- }
- to {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- opacity: 1;
- }
-}
-
-.rotateInDownLeft {
- -webkit-animation-name: rotateInDownLeft;
- animation-name: rotateInDownLeft;
-}
-
-@-webkit-keyframes rotateInDownRight {
- from {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate3d(0, 0, 1, 45deg);
- transform: rotate3d(0, 0, 1, 45deg);
- opacity: 0;
- }
- to {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- opacity: 1;
- }
-}
-
-@keyframes rotateInDownRight {
- from {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate3d(0, 0, 1, 45deg);
- transform: rotate3d(0, 0, 1, 45deg);
- opacity: 0;
- }
- to {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- opacity: 1;
- }
-}
-
-.rotateInDownRight {
- -webkit-animation-name: rotateInDownRight;
- animation-name: rotateInDownRight;
-}
-
-@-webkit-keyframes rotateInUpLeft {
- from {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate3d(0, 0, 1, 45deg);
- transform: rotate3d(0, 0, 1, 45deg);
- opacity: 0;
- }
- to {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- opacity: 1;
- }
-}
-
-@keyframes rotateInUpLeft {
- from {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate3d(0, 0, 1, 45deg);
- transform: rotate3d(0, 0, 1, 45deg);
- opacity: 0;
- }
- to {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- opacity: 1;
- }
-}
-
-.rotateInUpLeft {
- -webkit-animation-name: rotateInUpLeft;
- animation-name: rotateInUpLeft;
-}
-
-@-webkit-keyframes rotateInUpRight {
- from {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate3d(0, 0, 1, -90deg);
- transform: rotate3d(0, 0, 1, -90deg);
- opacity: 0;
- }
- to {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- opacity: 1;
- }
-}
-
-@keyframes rotateInUpRight {
- from {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate3d(0, 0, 1, -90deg);
- transform: rotate3d(0, 0, 1, -90deg);
- opacity: 0;
- }
- to {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- opacity: 1;
- }
-}
-
-.rotateInUpRight {
- -webkit-animation-name: rotateInUpRight;
- animation-name: rotateInUpRight;
-}
-
-@-webkit-keyframes rotateOut {
- from {
- -webkit-transform-origin: center;
- transform-origin: center;
- opacity: 1;
- }
- to {
- -webkit-transform-origin: center;
- transform-origin: center;
- -webkit-transform: rotate3d(0, 0, 1, 200deg);
- transform: rotate3d(0, 0, 1, 200deg);
- opacity: 0;
- }
-}
-
-@keyframes rotateOut {
- from {
- -webkit-transform-origin: center;
- transform-origin: center;
- opacity: 1;
- }
- to {
- -webkit-transform-origin: center;
- transform-origin: center;
- -webkit-transform: rotate3d(0, 0, 1, 200deg);
- transform: rotate3d(0, 0, 1, 200deg);
- opacity: 0;
- }
-}
-
-.rotateOut {
- -webkit-animation-name: rotateOut;
- animation-name: rotateOut;
-}
-
-@-webkit-keyframes rotateOutDownLeft {
- from {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- opacity: 1;
- }
- to {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate3d(0, 0, 1, 45deg);
- transform: rotate3d(0, 0, 1, 45deg);
- opacity: 0;
- }
-}
-
-@keyframes rotateOutDownLeft {
- from {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- opacity: 1;
- }
- to {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate3d(0, 0, 1, 45deg);
- transform: rotate3d(0, 0, 1, 45deg);
- opacity: 0;
- }
-}
-
-.rotateOutDownLeft {
- -webkit-animation-name: rotateOutDownLeft;
- animation-name: rotateOutDownLeft;
-}
-
-@-webkit-keyframes rotateOutDownRight {
- from {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- opacity: 1;
- }
- to {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate3d(0, 0, 1, -45deg);
- transform: rotate3d(0, 0, 1, -45deg);
- opacity: 0;
- }
-}
-
-@keyframes rotateOutDownRight {
- from {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- opacity: 1;
- }
- to {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate3d(0, 0, 1, -45deg);
- transform: rotate3d(0, 0, 1, -45deg);
- opacity: 0;
- }
-}
-
-.rotateOutDownRight {
- -webkit-animation-name: rotateOutDownRight;
- animation-name: rotateOutDownRight;
-}
-
-@-webkit-keyframes rotateOutUpLeft {
- from {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- opacity: 1;
- }
- to {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate3d(0, 0, 1, -45deg);
- transform: rotate3d(0, 0, 1, -45deg);
- opacity: 0;
- }
-}
-
-@keyframes rotateOutUpLeft {
- from {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- opacity: 1;
- }
- to {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate3d(0, 0, 1, -45deg);
- transform: rotate3d(0, 0, 1, -45deg);
- opacity: 0;
- }
-}
-
-.rotateOutUpLeft {
- -webkit-animation-name: rotateOutUpLeft;
- animation-name: rotateOutUpLeft;
-}
-
-@-webkit-keyframes rotateOutUpRight {
- from {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- opacity: 1;
- }
- to {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate3d(0, 0, 1, 90deg);
- transform: rotate3d(0, 0, 1, 90deg);
- opacity: 0;
- }
-}
-
-@keyframes rotateOutUpRight {
- from {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- opacity: 1;
- }
- to {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate3d(0, 0, 1, 90deg);
- transform: rotate3d(0, 0, 1, 90deg);
- opacity: 0;
- }
-}
-
-.rotateOutUpRight {
- -webkit-animation-name: rotateOutUpRight;
- animation-name: rotateOutUpRight;
-}
-
-@-webkit-keyframes hinge {
- 0% {
- -webkit-transform-origin: top left;
- transform-origin: top left;
- -webkit-animation-timing-function: ease-in-out;
- animation-timing-function: ease-in-out;
- }
- 20%, 60% {
- -webkit-transform: rotate3d(0, 0, 1, 80deg);
- transform: rotate3d(0, 0, 1, 80deg);
- -webkit-transform-origin: top left;
- transform-origin: top left;
- -webkit-animation-timing-function: ease-in-out;
- animation-timing-function: ease-in-out;
- }
- 40%, 80% {
- -webkit-transform: rotate3d(0, 0, 1, 60deg);
- transform: rotate3d(0, 0, 1, 60deg);
- -webkit-transform-origin: top left;
- transform-origin: top left;
- -webkit-animation-timing-function: ease-in-out;
- animation-timing-function: ease-in-out;
- opacity: 1;
- }
- to {
- -webkit-transform: translate3d(0, 700px, 0);
- transform: translate3d(0, 700px, 0);
- opacity: 0;
- }
-}
-
-@keyframes hinge {
- 0% {
- -webkit-transform-origin: top left;
- transform-origin: top left;
- -webkit-animation-timing-function: ease-in-out;
- animation-timing-function: ease-in-out;
- }
- 20%, 60% {
- -webkit-transform: rotate3d(0, 0, 1, 80deg);
- transform: rotate3d(0, 0, 1, 80deg);
- -webkit-transform-origin: top left;
- transform-origin: top left;
- -webkit-animation-timing-function: ease-in-out;
- animation-timing-function: ease-in-out;
- }
- 40%, 80% {
- -webkit-transform: rotate3d(0, 0, 1, 60deg);
- transform: rotate3d(0, 0, 1, 60deg);
- -webkit-transform-origin: top left;
- transform-origin: top left;
- -webkit-animation-timing-function: ease-in-out;
- animation-timing-function: ease-in-out;
- opacity: 1;
- }
- to {
- -webkit-transform: translate3d(0, 700px, 0);
- transform: translate3d(0, 700px, 0);
- opacity: 0;
- }
-}
-
-.hinge {
- -webkit-animation-duration: 2s;
- animation-duration: 2s;
- -webkit-animation-name: hinge;
- animation-name: hinge;
-}
-
-@-webkit-keyframes jackInTheBox {
- from {
- opacity: 0;
- -webkit-transform: scale(0.1) rotate(30deg);
- transform: scale(0.1) rotate(30deg);
- -webkit-transform-origin: center bottom;
- transform-origin: center bottom;
- }
- 50% {
- -webkit-transform: rotate(-10deg);
- transform: rotate(-10deg);
- }
- 70% {
- -webkit-transform: rotate(3deg);
- transform: rotate(3deg);
- }
- to {
- opacity: 1;
- -webkit-transform: scale(1);
- transform: scale(1);
- }
-}
-
-@keyframes jackInTheBox {
- from {
- opacity: 0;
- -webkit-transform: scale(0.1) rotate(30deg);
- transform: scale(0.1) rotate(30deg);
- -webkit-transform-origin: center bottom;
- transform-origin: center bottom;
- }
- 50% {
- -webkit-transform: rotate(-10deg);
- transform: rotate(-10deg);
- }
- 70% {
- -webkit-transform: rotate(3deg);
- transform: rotate(3deg);
- }
- to {
- opacity: 1;
- -webkit-transform: scale(1);
- transform: scale(1);
- }
-}
-
-.jackInTheBox {
- -webkit-animation-name: jackInTheBox;
- animation-name: jackInTheBox;
-}
-
-
-/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
-
-@-webkit-keyframes rollIn {
- from {
- opacity: 0;
- -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
- transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
- }
- to {
- opacity: 1;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-@keyframes rollIn {
- from {
- opacity: 0;
- -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
- transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
- }
- to {
- opacity: 1;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-.rollIn {
- -webkit-animation-name: rollIn;
- animation-name: rollIn;
-}
-
-
-/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
-
-@-webkit-keyframes rollOut {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
- transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
- }
-}
-
-@keyframes rollOut {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
- transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
- }
-}
-
-.rollOut {
- -webkit-animation-name: rollOut;
- animation-name: rollOut;
-}
-
-@-webkit-keyframes zoomIn {
- from {
- opacity: 0;
- -webkit-transform: scale3d(0.3, 0.3, 0.3);
- transform: scale3d(0.3, 0.3, 0.3);
- }
- 50% {
- opacity: 1;
- }
-}
-
-@keyframes zoomIn {
- from {
- opacity: 0;
- -webkit-transform: scale3d(0.3, 0.3, 0.3);
- transform: scale3d(0.3, 0.3, 0.3);
- }
- 50% {
- opacity: 1;
- }
-}
-
-.zoomIn {
- -webkit-animation-name: zoomIn;
- animation-name: zoomIn;
-}
-
-@-webkit-keyframes zoomInDown {
- from {
- opacity: 0;
- -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0);
- transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0);
- -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- }
- 60% {
- opacity: 1;
- -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
- transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
- -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- }
-}
-
-@keyframes zoomInDown {
- from {
- opacity: 0;
- -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0);
- transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0);
- -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- }
- 60% {
- opacity: 1;
- -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
- transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
- -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- }
-}
-
-.zoomInDown {
- -webkit-animation-name: zoomInDown;
- animation-name: zoomInDown;
-}
-
-@-webkit-keyframes zoomInLeft {
- from {
- opacity: 0;
- -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0);
- transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0);
- -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- }
- 60% {
- opacity: 1;
- -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0);
- transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0);
- -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- }
-}
-
-@keyframes zoomInLeft {
- from {
- opacity: 0;
- -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0);
- transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0);
- -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- }
- 60% {
- opacity: 1;
- -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0);
- transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0);
- -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- }
-}
-
-.zoomInLeft {
- -webkit-animation-name: zoomInLeft;
- animation-name: zoomInLeft;
-}
-
-@-webkit-keyframes zoomInRight {
- from {
- opacity: 0;
- -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0);
- transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0);
- -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- }
- 60% {
- opacity: 1;
- -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0);
- transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0);
- -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- }
-}
-
-@keyframes zoomInRight {
- from {
- opacity: 0;
- -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0);
- transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0);
- -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- }
- 60% {
- opacity: 1;
- -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0);
- transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0);
- -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- }
-}
-
-.zoomInRight {
- -webkit-animation-name: zoomInRight;
- animation-name: zoomInRight;
-}
-
-@-webkit-keyframes zoomInUp {
- from {
- opacity: 0;
- -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0);
- transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0);
- -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- }
- 60% {
- opacity: 1;
- -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
- transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
- -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- }
-}
-
-@keyframes zoomInUp {
- from {
- opacity: 0;
- -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0);
- transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0);
- -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- }
- 60% {
- opacity: 1;
- -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
- transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
- -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- }
-}
-
-.zoomInUp {
- -webkit-animation-name: zoomInUp;
- animation-name: zoomInUp;
-}
-
-@-webkit-keyframes zoomOut {
- from {
- opacity: 1;
- }
- 50% {
- opacity: 0;
- -webkit-transform: scale3d(0.3, 0.3, 0.3);
- transform: scale3d(0.3, 0.3, 0.3);
- }
- to {
- opacity: 0;
- }
-}
-
-@keyframes zoomOut {
- from {
- opacity: 1;
- }
- 50% {
- opacity: 0;
- -webkit-transform: scale3d(0.3, 0.3, 0.3);
- transform: scale3d(0.3, 0.3, 0.3);
- }
- to {
- opacity: 0;
- }
-}
-
-.zoomOut {
- -webkit-animation-name: zoomOut;
- animation-name: zoomOut;
-}
-
-@-webkit-keyframes zoomOutDown {
- 40% {
- opacity: 1;
- -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
- transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
- -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- }
- to {
- opacity: 0;
- -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0);
- transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0);
- -webkit-transform-origin: center bottom;
- transform-origin: center bottom;
- -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- }
-}
-
-@keyframes zoomOutDown {
- 40% {
- opacity: 1;
- -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
- transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
- -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- }
- to {
- opacity: 0;
- -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0);
- transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0);
- -webkit-transform-origin: center bottom;
- transform-origin: center bottom;
- -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- }
-}
-
-.zoomOutDown {
- -webkit-animation-name: zoomOutDown;
- animation-name: zoomOutDown;
-}
-
-@-webkit-keyframes zoomOutLeft {
- 40% {
- opacity: 1;
- -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0);
- transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0);
- }
- to {
- opacity: 0;
- -webkit-transform: scale(0.1) translate3d(-2000px, 0, 0);
- transform: scale(0.1) translate3d(-2000px, 0, 0);
- -webkit-transform-origin: left center;
- transform-origin: left center;
- }
-}
-
-@keyframes zoomOutLeft {
- 40% {
- opacity: 1;
- -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0);
- transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0);
- }
- to {
- opacity: 0;
- -webkit-transform: scale(0.1) translate3d(-2000px, 0, 0);
- transform: scale(0.1) translate3d(-2000px, 0, 0);
- -webkit-transform-origin: left center;
- transform-origin: left center;
- }
-}
-
-.zoomOutLeft {
- -webkit-animation-name: zoomOutLeft;
- animation-name: zoomOutLeft;
-}
-
-@-webkit-keyframes zoomOutRight {
- 40% {
- opacity: 1;
- -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0);
- transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0);
- }
- to {
- opacity: 0;
- -webkit-transform: scale(0.1) translate3d(2000px, 0, 0);
- transform: scale(0.1) translate3d(2000px, 0, 0);
- -webkit-transform-origin: right center;
- transform-origin: right center;
- }
-}
-
-@keyframes zoomOutRight {
- 40% {
- opacity: 1;
- -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0);
- transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0);
- }
- to {
- opacity: 0;
- -webkit-transform: scale(0.1) translate3d(2000px, 0, 0);
- transform: scale(0.1) translate3d(2000px, 0, 0);
- -webkit-transform-origin: right center;
- transform-origin: right center;
- }
-}
-
-.zoomOutRight {
- -webkit-animation-name: zoomOutRight;
- animation-name: zoomOutRight;
-}
-
-@-webkit-keyframes zoomOutUp {
- 40% {
- opacity: 1;
- -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
- transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
- -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- }
- to {
- opacity: 0;
- -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0);
- transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0);
- -webkit-transform-origin: center bottom;
- transform-origin: center bottom;
- -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- }
-}
-
-@keyframes zoomOutUp {
- 40% {
- opacity: 1;
- -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
- transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
- -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
- }
- to {
- opacity: 0;
- -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0);
- transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0);
- -webkit-transform-origin: center bottom;
- transform-origin: center bottom;
- -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
- }
-}
-
-.zoomOutUp {
- -webkit-animation-name: zoomOutUp;
- animation-name: zoomOutUp;
-}
-
-@-webkit-keyframes slideInDown {
- from {
- -webkit-transform: translate3d(0, -100%, 0);
- transform: translate3d(0, -100%, 0);
- visibility: visible;
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-@keyframes slideInDown {
- from {
- -webkit-transform: translate3d(0, -100%, 0);
- transform: translate3d(0, -100%, 0);
- visibility: visible;
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-.slideInDown {
- -webkit-animation-name: slideInDown;
- animation-name: slideInDown;
-}
-
-@-webkit-keyframes slideInLeft {
- from {
- -webkit-transform: translate3d(-100%, 0, 0);
- transform: translate3d(-100%, 0, 0);
- visibility: visible;
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-@keyframes slideInLeft {
- from {
- -webkit-transform: translate3d(-100%, 0, 0);
- transform: translate3d(-100%, 0, 0);
- visibility: visible;
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-.slideInLeft {
- -webkit-animation-name: slideInLeft;
- animation-name: slideInLeft;
-}
-
-@-webkit-keyframes slideInRight {
- from {
- -webkit-transform: translate3d(100%, 0, 0);
- transform: translate3d(100%, 0, 0);
- visibility: visible;
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-@keyframes slideInRight {
- from {
- -webkit-transform: translate3d(100%, 0, 0);
- transform: translate3d(100%, 0, 0);
- visibility: visible;
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-.slideInRight {
- -webkit-animation-name: slideInRight;
- animation-name: slideInRight;
-}
-
-@-webkit-keyframes slideInUp {
- from {
- -webkit-transform: translate3d(0, 100%, 0);
- transform: translate3d(0, 100%, 0);
- visibility: visible;
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-@keyframes slideInUp {
- from {
- -webkit-transform: translate3d(0, 100%, 0);
- transform: translate3d(0, 100%, 0);
- visibility: visible;
- }
- to {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
-}
-
-.slideInUp {
- -webkit-animation-name: slideInUp;
- animation-name: slideInUp;
-}
-
-@-webkit-keyframes slideOutDown {
- from {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
- to {
- visibility: hidden;
- -webkit-transform: translate3d(0, 100%, 0);
- transform: translate3d(0, 100%, 0);
- }
-}
-
-@keyframes slideOutDown {
- from {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
- to {
- visibility: hidden;
- -webkit-transform: translate3d(0, 100%, 0);
- transform: translate3d(0, 100%, 0);
- }
-}
-
-.slideOutDown {
- -webkit-animation-name: slideOutDown;
- animation-name: slideOutDown;
-}
-
-@-webkit-keyframes slideOutLeft {
- from {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
- to {
- visibility: hidden;
- -webkit-transform: translate3d(-100%, 0, 0);
- transform: translate3d(-100%, 0, 0);
- }
-}
-
-@keyframes slideOutLeft {
- from {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
- to {
- visibility: hidden;
- -webkit-transform: translate3d(-100%, 0, 0);
- transform: translate3d(-100%, 0, 0);
- }
-}
-
-.slideOutLeft {
- -webkit-animation-name: slideOutLeft;
- animation-name: slideOutLeft;
-}
-
-@-webkit-keyframes slideOutRight {
- from {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
- to {
- visibility: hidden;
- -webkit-transform: translate3d(100%, 0, 0);
- transform: translate3d(100%, 0, 0);
- }
-}
-
-@keyframes slideOutRight {
- from {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
- to {
- visibility: hidden;
- -webkit-transform: translate3d(100%, 0, 0);
- transform: translate3d(100%, 0, 0);
- }
-}
-
-.slideOutRight {
- -webkit-animation-name: slideOutRight;
- animation-name: slideOutRight;
-}
-
-@-webkit-keyframes slideOutUp {
- from {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
- to {
- visibility: hidden;
- -webkit-transform: translate3d(0, -100%, 0);
- transform: translate3d(0, -100%, 0);
- }
-}
-
-@keyframes slideOutUp {
- from {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- }
- to {
- visibility: hidden;
- -webkit-transform: translate3d(0, -100%, 0);
- transform: translate3d(0, -100%, 0);
- }
-}
-
-.slideOutUp {
- -webkit-animation-name: slideOutUp;
- animation-name: slideOutUp;
-}
-
-.animated {
- -webkit-animation-duration: 1s;
- animation-duration: 1s;
- -webkit-animation-fill-mode: both;
- animation-fill-mode: both;
-}
-
-.animated.infinite {
- -webkit-animation-iteration-count: infinite;
- animation-iteration-count: infinite;
-}
-
-.animated.delay-1s {
- -webkit-animation-delay: 1s;
- animation-delay: 1s;
-}
-
-.animated.delay-2s {
- -webkit-animation-delay: 2s;
- animation-delay: 2s;
-}
-
-.animated.delay-3s {
- -webkit-animation-delay: 3s;
- animation-delay: 3s;
-}
-
-.animated.delay-4s {
- -webkit-animation-delay: 4s;
- animation-delay: 4s;
-}
-
-.animated.delay-5s {
- -webkit-animation-delay: 5s;
- animation-delay: 5s;
-}
-
-.animated.fast {
- -webkit-animation-duration: 800ms;
- animation-duration: 800ms;
-}
-
-.animated.faster {
- -webkit-animation-duration: 500ms;
- animation-duration: 500ms;
-}
-
-.animated.slow {
- -webkit-animation-duration: 2s;
- animation-duration: 2s;
-}
-
-.animated.slower {
- -webkit-animation-duration: 3s;
- animation-duration: 3s;
-}
-
-@media (print), (prefers-reduced-motion) {
- .animated {
- -webkit-animation: unset !important;
- animation: unset !important;
- -webkit-transition: none !important;
- transition: none !important;
- }
-}
\ No newline at end of file
diff --git a/docs/src/assets/back.jpg b/docs/src/assets/back.jpg
deleted file mode 100644
index 50a8751d904131f8aafbc77e2d42a874e086abd0..0000000000000000000000000000000000000000
Binary files a/docs/src/assets/back.jpg and /dev/null differ
diff --git a/docs/src/assets/fonts/CenturyGothic.ttf b/docs/src/assets/fonts/CenturyGothic.ttf
deleted file mode 100755
index 879704e34a2d16d5ea8fb44bb0ebecdb13c2c430..0000000000000000000000000000000000000000
Binary files a/docs/src/assets/fonts/CenturyGothic.ttf and /dev/null differ
diff --git a/docs/src/assets/fonts/w-e-icon.woff b/docs/src/assets/fonts/w-e-icon.woff
deleted file mode 100755
index fa64c4d86cef0bd3aadc1906f25b2c0ce6bf96da..0000000000000000000000000000000000000000
Binary files a/docs/src/assets/fonts/w-e-icon.woff and /dev/null differ
diff --git a/docs/src/assets/react.svg b/docs/src/assets/react.svg
deleted file mode 100644
index 84b96a777810c4aff34d9582d4f34480f88cdbdf..0000000000000000000000000000000000000000
--- a/docs/src/assets/react.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/src/assets/theme.jpg b/docs/src/assets/theme.jpg
deleted file mode 100644
index 618f0cddc515286333d48724e4e8dfeaf5ca6e04..0000000000000000000000000000000000000000
Binary files a/docs/src/assets/theme.jpg and /dev/null differ
diff --git a/docs/src/assets/wx.jpg b/docs/src/assets/wx.jpg
deleted file mode 100644
index 5cadf0998912cd12f2be366912a1f72885682e1c..0000000000000000000000000000000000000000
Binary files a/docs/src/assets/wx.jpg and /dev/null differ
diff --git a/docs/src/assets/zfb.jpg b/docs/src/assets/zfb.jpg
deleted file mode 100644
index c50d62897b2705696db1fcfbd4d5c99b6c54f27b..0000000000000000000000000000000000000000
Binary files a/docs/src/assets/zfb.jpg and /dev/null differ
diff --git a/docs/src/code/affix.js b/docs/src/code/affix.js
deleted file mode 100644
index f9a97c6b079532c350f4544f42c6cd1241bce022..0000000000000000000000000000000000000000
--- a/docs/src/code/affix.js
+++ /dev/null
@@ -1,38 +0,0 @@
-let code = {}
-
-code.base = ` 内容随便写, 欢迎使用 内容随便写, 欢迎使用 内容随便写, 欢迎使用 内容随便写, 欢迎使用 内容随便写, 欢迎使用 内容随便写, 欢迎使用 内容随便写, 欢迎使用 内容随便写, 欢迎使用 内容随便写, 欢迎使用 内容随便写, 欢迎使用 内容随便写, 欢迎使用 内容随便写, 欢迎使用
{{checked}}
- 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是内容,要写很多文字 我是自定义内容年
- 月
- 时间
- 范围
- 范围符号
- 局部禁用
- 禁用
-
-
-`
-
-export default code
\ No newline at end of file
diff --git a/docs/src/code/grid.js b/docs/src/code/grid.js
deleted file mode 100644
index 425480a8a82babed8bfe1b3b50fa9960c150a89f..0000000000000000000000000000000000000000
--- a/docs/src/code/grid.js
+++ /dev/null
@@ -1,47 +0,0 @@
-let code = {}
-
-code.base = `
-
-`
-
-
-code.textArea = `
-`
-
-
-export default code
\ No newline at end of file
diff --git a/docs/src/code/install.js b/docs/src/code/install.js
deleted file mode 100644
index 05a5ab34f35c1ede31bad8fe732b416d2123c8be..0000000000000000000000000000000000000000
--- a/docs/src/code/install.js
+++ /dev/null
@@ -1,42 +0,0 @@
-let code = {}
-
-code.install = `$ npm install kui-vue --save`
-
-code.import = `
-`
-
-code.size=`
-
-`
-
-code.clearable =`
-
-`
-
-code.search=`
-`
-
-code.disabled=`
-
-`
-
-
-export default code
\ No newline at end of file
diff --git a/docs/src/code/start.js b/docs/src/code/start.js
deleted file mode 100644
index 89e4d5dde1476168a145134ba66e94886d47b979..0000000000000000000000000000000000000000
--- a/docs/src/code/start.js
+++ /dev/null
@@ -1,25 +0,0 @@
-let code = {}
-
-code.webpack = `import Vue from 'vue';
-import VueRouter from 'vue-router';
-import App from 'components/app.vue';
-import Routers from './router.js';
-import kui from 'kui-vue';
-import 'kui-vue/dist/k-ui.css';
-
-Vue.use(VueRouter);
-Vue.use(kui);
-
-// The routing configuration
-const RouterConfig = {
- routes: Routers
-};
-const router = new VueRouter(RouterConfig);
-
-new Vue({
- el: '#app',
- router: router,
- render: h => h(App)
-});`
-
-export default code
\ No newline at end of file
diff --git a/docs/src/code/switch.js b/docs/src/code/switch.js
deleted file mode 100644
index b665ad8794c4d91f068559cf43f4b60788378e12..0000000000000000000000000000000000000000
--- a/docs/src/code/switch.js
+++ /dev/null
@@ -1,17 +0,0 @@
-let code = {}
-
-code.base = `
{{checked}}
- 我是内容1.... 我是内容1.... 我是内容1.... 我是内容2.... 我是内容2.... 我是内容2.... 我是内容2.... 我是内容2.... 我是内容2....
-
-
-
`
-
-code.slot = `
- 我独占一行,然后....
-
-
-
- -
- - - - - -
- - -