Modify the directory structure

Modify the directory structure
This commit is contained in:
梁灏 2016-10-28 10:09:07 +08:00
parent 31fbef10e4
commit 4b05d84ea2
175 changed files with 48 additions and 46 deletions

View file

@ -0,0 +1,126 @@
<template>
<div>
<div :class="classes" :style="styles">
<slot></slot>
</div>
</div>
</template>
<script>
const prefixCls = 'ivu-affix';
function getScroll(target, top) {
const prop = top ? 'pageYOffset' : 'pageXOffset';
const method = top ? 'scrollTop' : 'scrollLeft';
let ret = target[prop];
if (typeof ret !== 'number') {
ret = window.document.documentElement[method];
}
return ret;
}
function getOffset(element) {
const rect = element.getBoundingClientRect();
const scrollTop = getScroll(window, true);
const scrollLeft = getScroll(window);
const docEl = window.document.body;
const clientTop = docEl.clientTop || 0;
const clientLeft = docEl.clientLeft || 0;
return {
top: rect.top + scrollTop - clientTop,
left: rect.left + scrollLeft - clientLeft
}
}
export default {
props: {
offsetTop: {
type: Number,
default: 0
},
offsetBottom: {
type: Number
}
},
data () {
return {
affix: false,
styles: {}
}
},
computed: {
offsetType () {
let type = 'top';
if (this.offsetBottom >= 0) {
type = 'bottom';
}
return type;
},
classes () {
return [
{
[`${prefixCls}`]: this.affix
}
]
}
},
ready () {
window.addEventListener('scroll', this.handleScroll, false);
window.addEventListener('resize', this.handleScroll, false);
},
beforeDestroy () {
window.removeEventListener('scroll', this.handleScroll, false);
window.removeEventListener('resize', this.handleScroll, false);
},
methods: {
handleScroll () {
const affix = this.affix;
const scrollTop = getScroll(window, true);
const elOffset = getOffset(this.$el);
const windowHeight = window.innerHeight;
const elHeight = this.$el.getElementsByTagName('div')[0].offsetHeight;
// Fixed Top
if ((elOffset.top - this.offsetTop) < scrollTop && this.offsetType == 'top' && !affix) {
this.affix = true;
this.styles = {
top: `${this.offsetTop}px`,
left: `${elOffset.left}px`,
width: `${this.$el.offsetWidth}px`
};
this.$emit('on-change', true);
} else if ((elOffset.top - this.offsetTop) > scrollTop && this.offsetType == 'top' && affix) {
this.affix = false;
this.styles = null;
this.$emit('on-change', false);
}
// Fixed Bottom
if ((elOffset.top + this.offsetBottom + elHeight) > (scrollTop + windowHeight) && this.offsetType == 'bottom' && !affix) {
this.affix = true;
this.styles = {
bottom: `${this.offsetBottom}px`,
left: `${elOffset.left}px`,
width: `${this.$el.offsetWidth}px`
};
this.$emit('on-change', true);
} else if ((elOffset.top + this.offsetBottom + elHeight) < (scrollTop + windowHeight) && this.offsetType == 'bottom' && affix) {
this.affix = false;
this.styles = null;
this.$emit('on-change', false);
}
}
}
}
</script>

View file

@ -0,0 +1,2 @@
import Affix from './affix.vue';
export default Affix;

View file

@ -0,0 +1,101 @@
<template>
<div v-if="!closed" :class="wrapClasses" transition="fade">
<span :class="iconClasses" v-if="showIcon">
<slot name="icon">
<Icon :type="iconType"></Icon>
</slot>
</span>
<span :class="messageClasses"><slot></slot></span>
<span :class="descClasses" v-el:desc><slot name="desc"></slot></span>
<a :class="closeClasses" v-if="closable" @click="close">
<slot name="close">
<Icon type="ios-close-empty"></Icon>
</slot>
</a>
</div>
</template>
<script>
import Icon from '../icon';
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-alert';
export default {
components: { Icon },
props: {
type: {
validator (value) {
return oneOf(value, ['success', 'info', 'warning', 'error']);
},
default: 'info'
},
closable: {
type: Boolean,
default: false
},
showIcon: {
type: Boolean,
default: false
}
},
data () {
return {
closed: false,
desc: false
}
},
computed: {
wrapClasses () {
return [
`${prefixCls}`,
`${prefixCls}-${this.type}`,
{
[`${prefixCls}-with-icon`]: this.showIcon,
[`${prefixCls}-with-desc`]: this.desc
}
]
},
messageClasses () {
return `${prefixCls}-message`;
},
descClasses () {
return `${prefixCls}-desc`;
},
closeClasses () {
return `${prefixCls}-close`;
},
iconClasses () {
return `${prefixCls}-icon`;
},
iconType () {
let type = '';
switch (this.type) {
case 'success':
type = 'checkmark-circled';
break;
case 'info':
type = 'information-circled';
break;
case 'warning':
type = 'android-alert';
break;
case 'error':
type = 'close-circled';
break;
}
return type;
}
},
methods: {
close (e) {
this.closed = true;
this.$emit('on-close', e);
}
},
compiled () {
this.desc = this.$els.desc.innerHTML != '';
}
}
</script>

View file

@ -0,0 +1,2 @@
import Alert from './alert.vue';
export default Alert;

View file

@ -0,0 +1,90 @@
<template>
<div :class="classes" :style="styles" @click="back">
<slot>
<div :class="innerClasses">
<i class="ivu-icon ivu-icon-chevron-up"></i>
</div>
</slot>
</div>
</template>
<script>
const prefixCls = 'ivu-back-top';
function getScroll(target, top) {
const prop = top ? 'pageYOffset' : 'pageXOffset';
const method = top ? 'scrollTop' : 'scrollLeft';
let ret = target[prop];
if (typeof ret !== 'number') {
ret = window.document.documentElement[method];
}
return ret;
}
export default {
props: {
height: {
type: Number,
default: 400
},
bottom: {
type: Number,
default: 30
},
right: {
type: Number,
default: 30
}
},
data () {
return {
backTop: false
}
},
ready () {
window.addEventListener('scroll', this.handleScroll, false);
window.addEventListener('resize', this.handleScroll, false);
},
beforeDestroy () {
window.removeEventListener('scroll', this.handleScroll, false);
window.removeEventListener('resize', this.handleScroll, false);
},
computed: {
classes () {
return [
`${prefixCls}`,
{
[`${prefixCls}-show`]: this.backTop
}
]
},
styles () {
return {
bottom: `${this.bottom}px`,
right: `${this.right}px`
}
},
innerClasses () {
return `${prefixCls}-inner`;
}
},
methods: {
handleScroll () {
const backTop = this.backTop;
const scrollTop = getScroll(window, true);
if (this.height <= scrollTop && !backTop) {
this.backTop = true;
} else if (this.height > scrollTop && backTop) {
this.backTop = false;
}
},
back () {
window.scrollTo(0, 0);
this.$emit('on-click');
}
}
}
</script>

View file

@ -0,0 +1,2 @@
import BackTop from './back-top.vue';
export default BackTop;

View file

@ -0,0 +1,77 @@
<template>
<span v-if="dot" :class="classes" v-el:badge>
<slot></slot>
<sup :class="dotClasses" v-show="badge"></sup>
</span>
<span v-else :class="classes" v-el:badge>
<slot></slot>
<sup v-if="count" :class="countClasses" v-show="badge">{{ finalCount }}</sup>
</span>
</template>
<script>
const prefixCls = 'ivu-badge';
export default {
props: {
count: [Number, String],
dot: {
type: Boolean,
default: false
},
overflowCount: {
type: [Number, String],
default: 99
},
class: String
},
computed: {
classes () {
return `${prefixCls}`;
},
dotClasses () {
return `${prefixCls}-dot`;
},
countClasses () {
return [
`${prefixCls}-count`,
{
[`${this.class}`]: !!this.class,
[`${prefixCls}-count-alone`]: this.alone
}
]
},
finalCount () {
return parseInt(this.count) >= parseInt(this.overflowCount) ? `${this.overflowCount}+` : this.count;
},
badge () {
let status = false;
if (this.count) {
status = !(parseInt(this.count) === 0);
}
if (this.dot) {
status = true;
if (this.count) {
if (parseInt(this.count) === 0) {
status = false;
}
}
}
return status;
}
},
data () {
return {
alone: false
}
},
compiled () {
const child_length = this.$els.badge.children.length;
if (child_length === 1) {
this.alone = true;
}
}
}
</script>

View file

@ -0,0 +1,2 @@
import Badge from './badge.vue';
export default Badge;

View file

@ -0,0 +1,37 @@
import Notification from './notification.vue';
import Vue from 'vue';
import { camelcaseToHyphen } from '../../../utils/assist';
Notification.newInstance = properties => {
const _props = properties || {};
let props = '';
Object.keys(_props).forEach(prop => {
props += ' :' + camelcaseToHyphen(prop) + '=' + prop;
});
const div = document.createElement('div');
div.innerHTML = `<notification${props}></notification>`;
document.body.appendChild(div);
const notification = new Vue({
el: div,
data: _props,
components: { Notification }
}).$children[0];
return {
notice (noticeProps) {
notification.add(noticeProps);
},
remove (key) {
notification.close(key);
},
component: notification,
destroy () {
document.body.removeChild(div);
}
}
};
export default Notification;

View file

@ -0,0 +1,93 @@
<template>
<div :class="classes" :style="style" :transition="transitionName">
<div :class="[`${baseClass}-content`]" v-el:content>{{{ content }}}</div>
<a :class="[`${baseClass}-close`]" @click="close" v-if="closable">
<i class="ivu-icon ivu-icon-ios-close-empty"></i>
</a>
</div>
</template>
<script>
export default {
props: {
prefixCls: {
type: String,
default: ''
},
duration: {
type: Number,
default: 1.5
},
content: {
type: String,
default: ''
},
style: {
type: Object,
default: function() {
return {
right: '50%'
}
}
},
closable: {
type: Boolean,
default: false
},
className: {
type: String
},
key: {
type: String,
required: true
},
onClose: {
type: Function
},
transitionName: {
type: String
}
},
computed: {
baseClass () {
return `${this.prefixCls}-notice`;
},
classes () {
return [
this.baseClass,
{
[`${this.className}`]: !!this.className,
[`${this.baseClass}-closable`]: this.closable
}
]
},
contentClasses () {
return `${this.baseClass}-content`;
}
},
methods: {
clearCloseTimer () {
if (this.closeTimer) {
clearTimeout(this.closeTimer);
this.closeTimer = null;
}
},
close () {
this.clearCloseTimer();
this.onClose();
this.$parent.close(this.key);
}
},
compiled () {
this.clearCloseTimer();
if (this.duration !== 0) {
this.closeTimer = setTimeout(() => {
this.close();
}, this.duration * 1000)
}
},
beforeDestroy () {
this.clearCloseTimer();
}
}
</script>

View file

@ -0,0 +1,92 @@
<template>
<div :class="classes" :style="style">
<Notice v-for="notice in notices"
:prefix-cls="prefixCls"
:style="notice.style"
:content="notice.content"
:duration="notice.duration"
:closable="notice.closable"
:key="notice.key"
:transition-name="notice.transitionName"
:on-close="notice.onClose">
</Notice>
</div>
</template>
<script>
import Notice from './notice.vue';
const prefixCls = 'ivu-notification';
let seed = 0;
const now = Date.now();
function getUuid () {
return 'ivuNotification_' + now + '_' + (seed++);
}
export default {
components: { Notice },
props: {
prefixCls: {
type: String,
default: prefixCls
},
style: {
type: Object,
default: function () {
return {
top: '65px',
left: '50%'
}
}
},
content: {
type: String
},
className: {
type: String
}
},
data () {
return {
notices: []
}
},
computed: {
classes () {
return [
`${this.prefixCls}`,
{
[`${this.className}`]: !!this.className
}
]
}
},
methods: {
add (notice) {
const key = notice.key || getUuid();
let _notice = Object.assign({
style: {
right: '50%'
},
content: '',
duration: 1.5,
closable: false,
key: key
}, notice);
this.notices.push(_notice);
},
close (key) {
const notices = this.notices;
for (let i = 0; i < notices.length; i++) {
if (notices[i].key === key) {
this.notices.splice(i, 1);
break;
}
}
}
}
}
</script>

View file

@ -0,0 +1,101 @@
/**
* https://github.com/freeze-component/vue-popper
* */
import Popper from 'popper.js';
export default {
props: {
placement: {
type: String,
default: 'bottom'
},
boundariesPadding: {
type: Number,
default: 5
},
reference: Object,
popper: Object,
offset: {
default: 0
},
value: Boolean,
transition: String,
options: {
type: Object,
default () {
return {
gpuAcceleration: false,
boundariesElement: 'body'
}
}
},
visible: {
type: Boolean,
default: false
}
},
watch: {
value: {
immediate: true,
handler(val) {
this.visible = val;
this.$emit('input', val);
}
},
visible(val) {
val ? this.updatePopper() : this.destroyPopper();
this.$emit('input', val);
}
},
methods: {
createPopper() {
if (!/^(top|bottom|left|right)(-start|-end)?$/g.test(this.placement)) {
return;
}
const options = this.options;
const popper = this.popper || this.$els.popper;
const reference = this.reference || this.$els.reference;
if (!popper || !reference) return;
if (this.popperJS && this.popperJS.hasOwnProperty('destroy')) {
this.popperJS.destroy();
}
options.placement = this.placement;
options.offset = this.offset;
this.popperJS = new Popper(reference, popper, options);
this.popperJS.onCreate(popper => {
this.resetTransformOrigin(popper);
this.$nextTick(this.updatePopper);
this.$emit('created', this);
});
},
updatePopper() {
this.popperJS ? this.popperJS.update() : this.createPopper();
},
doDestroy() {
if (this.visible) return;
this.popperJS.destroy();
this.popperJS = null;
},
destroyPopper() {
if (this.popperJS) {
this.resetTransformOrigin(this.popperJS);
}
},
resetTransformOrigin(popper) {
let placementMap = {top: 'bottom', bottom: 'top', left: 'right', right: 'left'};
let placement = popper._popper.getAttribute('x-placement').split('-')[0];
let origin = placementMap[placement];
popper._popper.style.transformOrigin = ['top', 'bottom'].indexOf(placement) > -1 ? `center ${ origin }` : `${ origin } center`;
}
},
beforeDestroy() {
if (this.popperJS) {
this.popperJS.destroy();
}
}
};

View file

@ -0,0 +1,36 @@
<template>
<span>
<a v-if="href" :href="href" :class="linkClasses">
<slot></slot>
</a>
<span v-else :class="linkClasses">
<slot></slot>
</span>
<span :class="separatorClasses">
<slot name="separator">{{{ separator }}}</slot>
</span>
</span>
</template>
<script>
const prefixCls = 'ivu-breadcrumb-item';
export default {
props: {
href: {
type: String
},
separator: {
type: String,
default: '/'
}
},
computed: {
linkClasses () {
return `${prefixCls}-link`;
},
separatorClasses () {
return `${prefixCls}-separator`;
}
}
}
</script>

View file

@ -0,0 +1,37 @@
<template>
<div :class="classes">
<slot></slot>
</div>
</template>
<script>
const prefixCls = 'ivu-breadcrumb';
export default {
props: {
separator: {
type: String,
default: '/'
}
},
computed: {
classes () {
return `${prefixCls}`;
}
},
compiled () {
this.updateChildren();
},
methods: {
updateChildren () {
this.$children.forEach((child) => {
child.separator = this.separator;
});
}
},
watch: {
separator () {
this.updateChildren();
}
}
}
</script>

View file

@ -0,0 +1,5 @@
import Breadcrumb from './breadcrumb.vue';
import BreadcrumbItem from './breadcrumb-item.vue';
Breadcrumb.Item = BreadcrumbItem;
export default Breadcrumb;

View file

@ -0,0 +1,30 @@
<template>
<div :class="classes">
<slot></slot>
</div>
</template>
<script>
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-btn-group';
export default {
props: {
size: {
validator (value) {
return oneOf(value, ['small', 'large']);
}
},
},
computed: {
classes () {
return [
`${prefixCls}`,
{
[`${prefixCls}-${this.size}`]: !!this.size
}
]
}
}
}
</script>

View file

@ -0,0 +1,68 @@
<template>
<button :type="htmlType" :class="classes" :disabled="disabled">
<i :class="loadingIconClasses" v-if="loading"></i>
<i :class="typeIconClasses" v-if="icon && !loading"></i>
<slot></slot>
</button>
</template>
<script>
import Icon from '../icon';
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-btn';
const iconPrefixCls = 'ivu-icon';
export default {
components: { Icon },
props: {
type: {
validator (value) {
return oneOf(value, ['primary', 'ghost']);
}
},
shape: {
validator (value) {
return oneOf(value, ['circle', 'circle-outline']);
}
},
size: {
validator (value) {
return oneOf(value, ['small', 'large']);
}
},
loading: Boolean,
disabled: Boolean,
htmlType: {
default: 'button',
validator (value) {
return oneOf(value, ['button', 'submit', 'reset']);
}
},
icon: String
},
computed: {
classes () {
return [
`${prefixCls}`,
{
[`${prefixCls}-${this.type}`]: !!this.type,
[`${prefixCls}-${this.shape}`]: !!this.shape,
[`${prefixCls}-${this.size}`]: !!this.size,
[`${prefixCls}-loading`]: this.loading != null && this.loading
}
]
},
loadingIconClasses () {
return `${iconPrefixCls} ivu-load-loop ${iconPrefixCls}-load-c`;
},
typeIconClasses () {
return [
`${iconPrefixCls}`,
{
[`${iconPrefixCls}-${this.icon}`]: !!this.icon
}
]
}
}
}
</script>

View file

@ -0,0 +1,5 @@
import Button from './button.vue';
import ButtonGroup from './button-group.vue';
Button.Group = ButtonGroup;
export default Button;

View file

@ -0,0 +1,58 @@
<template>
<div :class="classes">
<div :class="headClasses" v-if="showHead" v-el:head><slot name="title"></slot></div>
<div :class="extraClasses" v-if="showExtra" v-el:extra><slot name="extra"></slot></div>
<div :class="bodyClasses"><slot></slot></div>
</div>
</template>
<script>
const prefixCls = 'ivu-card';
export default {
props: {
bordered: {
type: Boolean,
default: true
},
disHover: {
type: Boolean,
default: false
},
shadow: {
type: Boolean,
default: false
}
},
data () {
return {
showHead: true,
showExtra: true
}
},
computed: {
classes () {
return [
`${prefixCls}`,
{
[`${prefixCls}-bordered`]: this.bordered && !this.shadow,
[`${prefixCls}-dis-hover`]: this.disHover || this.shadow,
[`${prefixCls}-shadow`]: this.shadow
}
]
},
headClasses () {
return `${prefixCls}-head`;
},
extraClasses () {
return `${prefixCls}-extra`;
},
bodyClasses () {
return `${prefixCls}-body`;
}
},
compiled () {
this.showHead = this.$els.head.innerHTML != '';
this.showExtra = this.$els.extra.innerHTML != '';
}
}
</script>

View file

@ -0,0 +1,2 @@
import Card from './card.vue';
export default Card;

View file

@ -0,0 +1,52 @@
<template>
<div :class="classes">
<slot></slot>
</div>
</template>
<script>
const prefixCls = 'ivu-checkbox-group';
export default {
props: {
model: {
type: Array,
default: []
}
},
computed: {
classes () {
return `${prefixCls}`;
}
},
compiled () {
this.updateModel(true);
},
methods: {
updateModel (update) {
const model = this.model;
this.$children.forEach((child) => {
child.model = model;
if (update) {
child.selected = model.indexOf(child.value) >= 0;
child.group = true;
}
});
},
change (data) {
this.model = data;
this.$emit('on-change', data);
}
},
watch: {
model (val, oldVal) {
if (val == oldVal) {
this.updateModel();
} else {
this.updateModel(true);
}
}
}
}
</script>

View file

@ -0,0 +1,104 @@
<template>
<label :class="wrapClasses">
<span :class="checkboxClasses">
<span :class="innerClasses"></span>
<input
v-if="group"
type="checkbox"
:class="inputClasses"
:disabled="disabled"
:value="value"
v-model="model"
@change="change">
<input
v-if="!group"
type="checkbox"
:class="inputClasses"
:disabled="disabled"
v-model="checked"
@change="change">
</span>
<slot><span>{{ value }}</span></slot>
</label>
</template>
<script>
const prefixCls = 'ivu-checkbox';
export default {
props: {
disabled: {
type: Boolean,
default: false
},
value: {
type: [String, Number, Boolean]
},
checked: {
type: Boolean,
default: false
}
},
data () {
return {
model: [],
selected: false,
group: false
}
},
computed: {
wrapClasses () {
return [
`${prefixCls}-wrapper`,
{
[`${prefixCls}-group-item`]: this.group,
[`${prefixCls}-wrapper-checked`]: this.selected,
[`${prefixCls}-wrapper-disabled`]: this.disabled
}
]
},
checkboxClasses () {
return [
`${prefixCls}`,
{
[`${prefixCls}-checked`]: this.selected,
[`${prefixCls}-disabled`]: this.disabled
}
]
},
innerClasses () {
return `${prefixCls}-inner`;
},
inputClasses () {
return `${prefixCls}-input`;
}
},
ready () {
if (!this.group) {
this.updateModel();
}
},
methods: {
change (event) {
if (this.disabled) {
return false;
}
this.selected = event.target.checked;
if (this.group) {
this.$parent.change(this.model);
} else {
this.$emit('on-change', this.checked);
}
},
updateModel () {
this.selected = this.checked;
}
},
watch: {
checked () {
this.updateModel();
}
}
}
</script>

View file

@ -0,0 +1,5 @@
import Checkbox from './checkbox.vue';
import CheckboxGroup from './checkbox-group.vue';
Checkbox.Group = CheckboxGroup;
export default Checkbox;

View file

@ -0,0 +1,83 @@
<template>
<div :style="circleSize" :class="wrapClasses">
<svg viewBox="0 0 100 100">
<path :d="pathString" :stroke="trailColor" :stroke-width="trailWidth" :fill-opacity="0"/>
<path :d="pathString" :stroke-linecap="strokeLinecap" :stroke="strokeColor" :stroke-width="strokeWidth" fill-opacity="0" :style="pathStyle"/>
</svg>
<div :class="innerClasses">
<slot></slot>
</div>
</div>
</template>
<script>
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-chart-circle';
export default {
props: {
percent: {
type: Number,
default: 0
},
size: {
type: Number,
default: 120
},
strokeWidth: {
type: Number,
default: 6
},
strokeColor: {
type: String,
default: '#2db7f5'
},
strokeLinecap: {
validator (value) {
return oneOf(value, ['square', 'round']);
},
default: 'round'
},
trailWidth: {
type: Number,
default: 5
},
trailColor: {
type: String,
default: '#eaeef2'
}
},
computed: {
circleSize () {
return {
width: `${this.size}px`,
height: `${this.size}px`
};
},
radius () {
return 50 - this.strokeWidth / 2;
},
pathString () {
return `M 50,50 m 0,-${this.radius}
a ${this.radius},${this.radius} 0 1 1 0,${2 * this.radius}
a ${this.radius},${this.radius} 0 1 1 0,-${2 * this.radius}`;
},
len () {
return Math.PI * 2 * this.radius;
},
pathStyle () {
return {
'stroke-dasharray': `${this.len}px ${this.len}px`,
'stroke-dashoffset': `${((100 - this.percent) / 100 * this.len)}px`,
'transition': 'stroke-dashoffset 0.6s ease 0s, stroke 0.6s ease'
}
},
wrapClasses () {
return `${prefixCls}`;
},
innerClasses () {
return `${prefixCls}-inner`;
}
}
}
</script>

View file

@ -0,0 +1,2 @@
import Circle from './circle.vue';
export default Circle;

View file

@ -0,0 +1,98 @@
<template>
<div :class="classes">
<slot></slot>
</div>
</template>
<script>
const prefixCls = 'ivu-collapse';
export default {
props: {
accordion: {
type: Boolean,
default: false
},
activeKey: {
type: [Array, String]
}
},
computed: {
classes () {
return `${prefixCls}`;
}
},
compiled () {
this.setActive();
},
methods: {
setActive () {
const activeKey = this.getActiveKey();
this.$children.forEach((child, index) => {
const key = child.key || index.toString();
let isActive = false;
if (self.accordion) {
isActive = activeKey === key;
} else {
isActive = activeKey.indexOf(key) > -1;
}
child.isActive = isActive;
child.index = index;
})
},
getActiveKey () {
let activeKey = this.activeKey || [];
const accordion = this.accordion;
if (!Array.isArray(activeKey)) {
activeKey = [activeKey];
}
if (accordion && activeKey.length > 1) {
activeKey = [activeKey[0]];
}
for (let i = 0; i < activeKey.length; i++) {
activeKey[i] = activeKey[i].toString();
}
return activeKey;
},
toggle (data) {
const key = data.key.toString();
let newActiveKey = [];
if (this.accordion) {
if (!data.isActive) {
newActiveKey.push(key);
}
} else {
let activeKey = this.getActiveKey();
const keyIndex = activeKey.indexOf(key);
if (data.isActive) {
if (keyIndex > -1) {
activeKey.splice(keyIndex, 1);
}
} else {
if (keyIndex < 0) {
activeKey.push(key);
}
}
newActiveKey = activeKey;
}
this.activeKey = newActiveKey;
this.$emit('on-change', newActiveKey);
}
},
watch: {
activeKey () {
this.setActive();
}
}
}
</script>

View file

@ -0,0 +1,5 @@
import Collapse from './collapse.vue';
import Panel from './panel.vue';
Collapse.Panel = Panel;
export default Collapse;

View file

@ -0,0 +1,57 @@
<template>
<div :class="itemClasses">
<div :class="headerClasses" @click="toggle">
<Icon type="arrow-right-b"></Icon>
<slot></slot>
</div>
<div :class="concentClasses" v-show="isActive">
<div :class="boxClasses"><slot name="content"></slot></div>
</div>
</div>
</template>
<script>
import Icon from '../icon';
const prefixCls = 'ivu-collapse';
export default {
components: { Icon },
props: {
key: {
type: String
}
},
data () {
return {
index: 0, // use index for default when key is null
isActive: false
}
},
computed: {
itemClasses () {
return [
`${prefixCls}-item`,
{
[`${prefixCls}-item-active`]: this.isActive
}
]
},
headerClasses () {
return `${prefixCls}-header`;
},
concentClasses () {
return `${prefixCls}-content`;
},
boxClasses () {
return `${prefixCls}-content-box`;
}
},
methods: {
toggle () {
this.$parent.toggle({
key: this.key || this.index,
isActive: this.isActive
});
}
}
}
</script>

View file

@ -0,0 +1,27 @@
<template>
<i :class="classes" :style="styles"></i>
</template>
<script>
const prefixCls = 'ivu-icon';
export default {
props: {
type: String,
size: [Number, String]
},
computed: {
classes () {
return `${prefixCls} ${prefixCls}-${this.type}`
},
styles () {
if (!!this.size) {
return {
'font-size': `${this.size}px`
}
} else {
return {}
}
}
}
}
</script>

View file

@ -0,0 +1,2 @@
import Icon from './icon.vue';
export default Icon;

View file

@ -0,0 +1,2 @@
import InputNumber from './input-number.vue';
export default InputNumber;

View file

@ -0,0 +1,242 @@
<template>
<div :class="wrapClasses">
<div :class="handlerClasses">
<a
@click="up"
@mouse.down="preventDefault"
:class="upClasses">
<span :class="innerUpClasses" @click="preventDefault"></span>
</a>
<a
@click="down"
@mouse.down="preventDefault"
:class="downClasses">
<span :class="innerDownClasses" @click="preventDefault"></span>
</a>
</div>
<div :class="inputWrapClasses">
<input
:class="inputClasses"
:disabled="disabled"
autoComplete="off"
@focus="focus"
@blur="blur"
@keydown.stop="keyDown"
@change="change"
:value="value">
</div>
</div>
</template>
<script>
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-input-number';
const iconPrefixCls = 'ivu-icon';
function isValueNumber (value) {
return (/(^-?[0-9]+\.{1}\d+$)|(^-?[1-9][0-9]*$)/).test(value + '');
}
function addNum (num1, num2) {
var sq1, sq2, m;
try {
sq1 = num1.toString().split(".")[1].length;
}
catch (e) {
sq1 = 0;
}
try {
sq2 = num2.toString().split(".")[1].length;
}
catch (e) {
sq2 = 0;
}
// if (sq1 === 0 || sq2 === 0) {
// return num1 + num2;
// } else {
// m = Math.pow(10, Math.max(sq1, sq2));
// return (num1 * m + num2 * m) / m;
// }
m = Math.pow(10, Math.max(sq1, sq2));
return (num1 * m + num2 * m) / m;
}
export default {
props: {
max: {
type: Number,
default: Infinity
},
min: {
type: Number,
default: -Infinity
},
step: {
type: Number,
default: 1
},
value: {
type: Number,
default: 1
},
size: {
validator (value) {
return oneOf(value, ['small', 'large']);
}
},
disabled: {
type: Boolean,
default: false
}
},
data () {
return {
focused: false,
upDisabled: false,
downDisabled: false
}
},
computed: {
wrapClasses () {
return [
`${prefixCls}`,
{
[`${prefixCls}-${this.size}`]: !!this.size,
[`${prefixCls}-disabled`]: this.disabled,
[`${prefixCls}-focused`]: this.focused
}
]
},
handlerClasses () {
return `${prefixCls}-handler-wrap`;
},
upClasses () {
return [
`${prefixCls}-handler`,
`${prefixCls}-handler-up`,
{
[`${prefixCls}-handler-up-disabled`]: this.upDisabled
}
]
},
innerUpClasses () {
return `${prefixCls}-handler-up-inner ${iconPrefixCls} ${iconPrefixCls}-ios-arrow-up`;
},
downClasses () {
return [
`${prefixCls}-handler`,
`${prefixCls}-handler-down`,
{
[`${prefixCls}-handler-down-disabled`]: this.downDisabled
}
]
},
innerDownClasses () {
return `${prefixCls}-handler-down-inner ${iconPrefixCls} ${iconPrefixCls}-ios-arrow-down`;
},
inputWrapClasses () {
return `${prefixCls}-input-wrap`;
},
inputClasses () {
return `${prefixCls}-input`;
}
},
methods: {
preventDefault (e) {
e.preventDefault();
},
up () {
if (this.upDisabled) {
return false;
}
this.changeStep('up');
},
down () {
if (this.downDisabled) {
return false;
}
this.changeStep('down');
},
changeStep (type) {
if (this.disabled) {
return false;
}
let val = Number(this.value);
const step = Number(this.step);
if (isNaN(val)) {
return false;
}
if (type == 'up') {
val = addNum(val, step);
} else if (type == 'down') {
val = addNum(val, -step);
}
this.setValue(val);
},
setValue (val) {
this.$nextTick(() => {
this.value = val;
});
this.$emit('on-change', val);
},
focus () {
this.focused = true;
},
blur () {
this.focused = false;
},
keyDown (e) {
if (e.keyCode === 38) {
e.preventDefault();
this.up()
} else if (e.keyCode === 40) {
e.preventDefault();
this.down()
}
},
change (event) {
let val = event.target.value.trim();
const max = this.max;
const min = this.min;
if (isValueNumber(val)) {
val = Number(val);
this.value = val;
if (val > max) {
this.setValue(max);
} else if (val < min) {
this.setValue(min);
} else {
this.setValue(val);
}
} else {
event.target.value = this.value;
}
},
changeVal (val) {
if (isValueNumber(val) || val === 0) {
val = Number(val);
const step = this.step;
this.upDisabled = val + step > this.max;
this.downDisabled = val - step < this.min;
} else {
this.upDisabled = true;
this.downDisabled = true;
}
}
},
ready () {
this.changeVal(this.value);
},
watch: {
value (val) {
this.changeVal(val);
}
}
}
</script>

View file

@ -0,0 +1,2 @@
import Input from './input.vue';
export default Input;

View file

@ -0,0 +1,49 @@
<template>
<input
:class="classes"
:type="type"
:placeholder="placeholder"
:name="name"
v-model="value">
</template>
<script>
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-input';
export default {
props: {
type: {
type: String,
default: 'text'
},
value: {
type: [String, Number],
default: '',
twoWay: true
},
placeholder: String,
name: String,
size: {
validator (value) {
return oneOf(value, ['small', 'large']);
}
}
},
data () {
return {
}
},
computed: {
classes () {
return [
`${prefixCls}`,
{
[`${prefixCls}-${this.size}`]: !!this.size
}
]
}
}
}
</script>

View file

@ -0,0 +1,36 @@
<template>
<div :class="classes">
<slot></slot>
</div>
</template>
<script>
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-col';
export default {
props: {
span: [Number, String],
order: [Number, String],
offset: [Number, String],
push: [Number, String],
pull: [Number, String],
className: String
},
computed: {
classes () {
return [
`${prefixCls}`,
{
[`${prefixCls}-span-${this.span}`]: this.span,
[`${prefixCls}-order-${this.order}`]: this.order,
[`${prefixCls}-offset-${this.offset}`]: this.offset,
[`${prefixCls}-push-${this.push}`]: this.push,
[`${prefixCls}-pull-${this.pull}`]: this.pull,
[`${this.className}`]: !!this.className
}
]
}
}
}
</script>

View file

@ -0,0 +1,4 @@
import Row from './row.vue';
import Col from './col.vue';
export { Row, Col };

View file

@ -0,0 +1,44 @@
<template>
<div :class="classes">
<slot></slot>
</div>
</template>
<script>
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-row';
export default {
props: {
type: {
validator (value) {
return oneOf(value, ['flex']);
}
},
align: {
validator (value) {
return oneOf(value, ['top', 'middle', 'bottom']);
}
},
justify: {
validator (value) {
return oneOf(value, ['start', 'end', 'center', 'space-around', 'space-between']);
}
},
className: String
},
computed: {
classes () {
return [
`${prefixCls}`,
{
[`${prefixCls}-${this.type}`]: !!this.type,
[`${prefixCls}-${this.type}-${this.align}`]: !!this.align,
[`${prefixCls}-${this.type}-${this.justify}`]: !!this.justify,
[`${this.className}`]: !!this.className
}
]
}
}
}
</script>

View file

@ -0,0 +1,110 @@
import LoadingBar from './loading-bar';
let loadingBarInstance;
let color = 'primary';
let failedColor = 'error';
let height = 2;
let timer;
function getLoadingBarInstance () {
loadingBarInstance = loadingBarInstance || LoadingBar.newInstance({
color: color,
failedColor: failedColor,
height: height
});
return loadingBarInstance;
}
function update(options) {
let instance = getLoadingBarInstance();
instance.update(options);
}
function hide() {
setTimeout(() => {
update({
show: false
});
setTimeout(() => {
update({
percent: 0
});
}, 200)
}, 800);
}
function clearTimer() {
if (timer) {
clearInterval(timer);
timer = null;
}
}
export default {
start () {
let percent = 0;
update({
percent: percent,
status: 'success',
show: true
});
timer = setInterval(() => {
percent += Math.floor(Math.random () * 3 + 5);
if (percent > 95) {
clearTimer();
}
update({
percent: percent,
status: 'success',
show: true
});
}, 200);
},
update (percent) {
clearTimer();
update({
percent: percent,
status: 'success',
show: true
});
},
finish () {
clearTimer();
update({
percent: 100,
status: 'success',
show: true
});
hide();
},
error () {
clearTimer();
update({
percent: 100,
status: 'error',
show: true
});
hide();
},
config (options) {
if (options.color) {
color = options.color;
}
if (options.failedColor) {
failedColor = options.failedColor;
}
if (options.height) {
height = options.height;
}
},
destroy () {
clearTimer();
let instance = getLoadingBarInstance();
loadingBarInstance = null;
instance.destroy();
}
}

View file

@ -0,0 +1,42 @@
import LoadingBar from './loading-bar.vue';
import Vue from 'vue';
import { camelcaseToHyphen } from '../../utils/assist';
LoadingBar.newInstance = properties => {
const _props = properties || {};
let props = '';
Object.keys(_props).forEach(prop => {
props += ' :' + camelcaseToHyphen(prop) + '=' + prop;
});
const div = document.createElement('div');
div.innerHTML = `<loading-bar${props}></loading-bar>`;
document.body.appendChild(div);
const loading_bar = new Vue({
el: div,
data: _props,
components: { LoadingBar }
}).$children[0];
return {
update (options) {
if ('percent' in options) {
loading_bar.percent = options.percent;
}
if (options.status) {
loading_bar.status = options.status;
}
if ('show' in options) {
loading_bar.show = options.show;
}
},
component: loading_bar,
destroy () {
document.body.removeChild(div);
}
}
};
export default LoadingBar;

View file

@ -0,0 +1,77 @@
<template>
<div :class="classes" :style="outerStyles" v-show="show" transition="fade">
<div :class="innerClasses" :style="styles"></div>
</div>
</template>
<script>
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-loading-bar';
export default {
props: {
percent: {
type: Number,
default: 0
},
color: {
type: String,
default: 'primary'
},
failedColor: {
type: String,
default: 'error'
},
height: {
type: Number,
default: 2
},
status: {
type: String,
validator (value) {
return oneOf(value, ['success', 'error']);
},
default: 'success'
},
show: {
type: Boolean,
default: false
}
},
computed: {
classes () {
return `${prefixCls}`;
},
innerClasses () {
return [
`${prefixCls}-inner`,
{
[`${prefixCls}-inner-color-primary`]: this.color === 'primary' && this.status === 'success',
[`${prefixCls}-inner-failed-color-error`]: this.failedColor === 'error' && this.status === 'error'
}
]
},
outerStyles () {
return {
height: `${this.height}px`
}
},
styles () {
let style = {
width: `${this.percent}%`,
height: `${this.height}px`
};
if (this.color !== 'primary' && this.status === 'success') {
style.backgroundColor = this.color;
}
if (this.failedColor !== 'error' && this.status === 'error') {
style.backgroundColor = this.failedColor;
}
return style;
}
}
}
</script>

View file

@ -0,0 +1,97 @@
import Notification from '../base/notification';
const prefixCls = 'ivu-message';
const iconPrefixCls = 'ivu-icon';
const prefixKey = 'ivu_message_key_';
let defaultDuration = 1.5;
let top;
let messageInstance;
let key = 1;
const iconTypes = {
'info': 'information-circled',
'success': 'checkmark-circled',
'warning': 'android-alert',
'error': 'close-circled',
'loading': 'load-c'
};
function getMessageInstance () {
messageInstance = messageInstance || Notification.newInstance({
prefixCls: prefixCls,
style: {
top: `${top}px`
}
});
return messageInstance;
}
function notice (content, duration = defaultDuration, type, onClose) {
if (!onClose) {
onClose = function () {
}
}
const iconType = iconTypes[type];
// if loading
const loadCls = type === 'loading' ? ' ivu-load-loop' : '';
let instance = getMessageInstance();
instance.notice({
key: `${prefixKey}${key}`,
duration: duration,
style: {},
transitionName: 'move-up',
content: `
<div class="${prefixCls}-custom-content ${prefixCls}-${type}">
<i class="${iconPrefixCls} ${iconPrefixCls}-${iconType}${loadCls}"></i>
<span>${content}</span>
</div>
`,
onClose: onClose
});
// 用于手动消除
return (function () {
let target = key++;
return function () {
instance.remove(`${prefixKey}${target}`);
}
})();
}
export default {
info (content, duration, onClose) {
return notice(content, duration, 'info', onClose);
},
success (content, duration, onClose) {
return notice(content, duration, 'success', onClose);
},
warning (content, duration, onClose) {
return notice(content, duration, 'warning', onClose);
},
error (content, duration, onClose) {
return notice(content, duration, 'error', onClose);
},
loading (content, duration, onClose) {
return notice(content, duration, 'loading', onClose);
},
config (options) {
if (options.top) {
top = options.top;
}
if (options.duration) {
defaultDuration = options.duration;
}
},
destroy () {
let instance = getMessageInstance();
messageInstance = null;
instance.destroy();
}
}

View file

@ -0,0 +1,169 @@
import Vue from 'vue';
import Modal from './modal.vue';
import Icon from '../icon/icon.vue';
import Button from '../button/button.vue';
import { camelcaseToHyphen } from '../../utils/assist';
const prefixCls = 'ivu-modal-confirm';
Modal.newInstance = properties => {
const _props = properties || {};
let props = '';
Object.keys(_props).forEach(prop => {
props += ' :' + camelcaseToHyphen(prop) + '=' + prop;
});
const div = document.createElement('div');
div.innerHTML = `
<Modal${props} :visible.sync="visible" :width="width">
<div class="${prefixCls}">
<div class="${prefixCls}-head">
<div :class="iconTypeCls"><i :class="iconNameCls"></i></div>
<div class="${prefixCls}-head-title">{{{ title }}}</div>
</div>
<div class="${prefixCls}-body">
{{{ body }}}
</div>
<div class="${prefixCls}-footer">
<Button type="ghost" size="large" v-if="showCancel" @click="cancel">{{ cancelText }}</Button>
<Button type="primary" size="large" :loading="buttonLoading" @click="ok">{{ okText }}</Button>
</div>
</div>
</Modal>
`;
document.body.appendChild(div);
const modal = new Vue({
el: div,
components: { Modal, Button, Icon },
data: Object.assign(_props, {
visible: false,
width: 416,
title: '',
body: '',
iconType: '',
iconName: '',
okText: '确定',
cancelText: '取消',
showCancel: false,
loading: false,
buttonLoading: false
}),
computed: {
iconTypeCls () {
return [
`${prefixCls}-head-icon`,
`${prefixCls}-head-icon-${this.iconType}`
]
},
iconNameCls () {
return [
'ivu-icon',
`ivu-icon-${this.iconName}`
]
}
},
methods: {
cancel () {
this.visible = false;
this.buttonLoading = false;
this.onCancel();
this.remove();
},
ok () {
if (this.loading) {
this.buttonLoading = true;
} else {
this.visible = false;
this.remove();
}
this.onOk();
},
remove () {
setTimeout(() => {
this.destroy();
}, 300);
},
destroy () {
this.$destroy();
document.body.removeChild(div);
this.onRemove();
},
onOk () {},
onCancel () {},
onRemove () {}
}
}).$children[0];
return {
show (props) {
modal.$parent.showCancel = props.showCancel;
modal.$parent.iconType = props.icon;
switch (props.icon) {
case 'info':
modal.$parent.iconName = 'information-circled';
break;
case 'success':
modal.$parent.iconName = 'checkmark-circled';
break;
case 'warning':
modal.$parent.iconName = 'android-alert';
break;
case 'error':
modal.$parent.iconName = 'close-circled';
break;
case 'confirm':
modal.$parent.iconName = 'help-circled';
break;
}
if ('width' in props) {
modal.$parent.width = props.width;
}
if ('title' in props) {
modal.$parent.title = props.title;
}
if ('content' in props) {
modal.$parent.body = props.content;
}
if ('okText' in props) {
modal.$parent.okText = props.okText;
}
if ('cancelText' in props) {
modal.$parent.cancelText = props.cancelText;
}
if ('onCancel' in props) {
modal.$parent.onCancel = props.onCancel;
}
if ('onOk' in props) {
modal.$parent.onOk = props.onOk;
}
// async for ok
if ('loading' in props) {
modal.$parent.loading = props.loading;
}
// notice when component destroy
modal.$parent.onRemove = props.onRemove;
modal.visible = true;
},
remove () {
modal.visible = false;
modal.$parent.buttonLoading = false;
modal.$parent.remove();
},
component: modal
}
};
export default Modal;

View file

@ -0,0 +1,65 @@
import Modal from './confirm';
let modalInstance;
function getModalInstance () {
modalInstance = modalInstance || Modal.newInstance({
closable: false,
maskClosable: false,
footerHide: true
});
return modalInstance;
}
function confirm (options) {
let instance = getModalInstance();
options.onRemove = function () {
modalInstance = null;
};
instance.show(options);
}
Modal.info = function (props = {}) {
props.icon = 'info';
props.showCancel = false;
return confirm(props);
};
Modal.success = function (props = {}) {
props.icon = 'success';
props.showCancel = false;
return confirm(props);
};
Modal.warning = function (props = {}) {
props.icon = 'warning';
props.showCancel = false;
return confirm(props);
};
Modal.error = function (props = {}) {
props.icon = 'error';
props.showCancel = false;
return confirm(props);
};
Modal.confirm = function (props = {}) {
props.icon = 'confirm';
props.showCancel = true;
return confirm(props);
};
Modal.remove = function () {
if (!modalInstance) { // at loading status, remove after Cancel
return false;
}
const instance = getModalInstance();
instance.remove();
};
export default Modal;

View file

@ -0,0 +1,205 @@
<template>
<div :class="wrapClasses">
<div :class="maskClasses" v-show="visible" @click="mask" transition="fade"></div>
<div :class="classes" :style="styles" v-show="visible" transition="ease">
<div :class="[`${prefixCls}-content`]">
<a :class="[`${prefixCls}-close`]" v-if="closable" @click="close">
<slot name="close">
<Icon type="ios-close-empty"></Icon>
</slot>
</a>
<div :class="[`${prefixCls}-header`]" v-if="showHead" v-el:head><slot name="header"><p>{{ title }}</p></slot></div>
<div :class="[`${prefixCls}-body`]"><slot></slot></div>
<div :class="[`${prefixCls}-footer`]" v-if="!footerHide">
<slot name="footer">
<Button type="ghost" size="large" @click="cancel">{{ cancelText }}</Button>
<Button type="primary" size="large" :loading="buttonLoading" @click="ok">{{ okText }}</Button>
</slot>
</div>
</div>
</div>
</div>
</template>
<script>
import Icon from '../icon';
import Button from '../button';
import { getScrollBarSize } from '../../utils/assist';
const prefixCls = 'ivu-modal';
export default {
components: { Icon, Button },
props: {
visible: {
type: Boolean,
default: false
},
closable: {
type: Boolean,
default: true
},
maskClosable: {
type: Boolean,
default: true
},
title: {
type: String
},
width: {
type: [Number, String],
default: 520
},
okText: {
type: String,
default: '确定'
},
cancelText: {
type: String,
default: '取消'
},
loading: {
type: Boolean,
default: false
},
style: {
type: Object
},
className: {
type: String
},
// for instance
footerHide: {
type: Boolean,
default: false
}
},
data () {
return {
prefixCls: prefixCls,
wrapShow: false,
showHead: true,
buttonLoading: false
}
},
computed: {
wrapClasses () {
return [
`${prefixCls}-wrap`,
{
[`${prefixCls}-hidden`]: !this.wrapShow,
[`${this.className}`]: !!this.className
}
]
},
maskClasses () {
return `${prefixCls}-mask`;
},
classes () {
return `${prefixCls}`;
},
styles () {
let style = {};
const styleWidth = {
width: `${this.width}px`
};
const customStyle = !!this.style ? this.style : {};
Object.assign(style, styleWidth, customStyle);
return style;
}
},
methods: {
close () {
this.visible = false;
this.$emit('on-cancel');
},
mask () {
if (this.maskClosable) {
this.close();
}
},
cancel () {
this.close();
},
ok () {
if (this.loading) {
this.buttonLoading = true;
} else {
this.visible = false;
}
this.$emit('on-ok');
},
EscClose (e) {
if (this.visible && this.closable) {
if (e.keyCode === 27) {
this.close()
}
}
},
checkScrollBar () {
let fullWindowWidth = window.innerWidth;
if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
const documentElementRect = document.documentElement.getBoundingClientRect();
fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left);
}
this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth;
if (this.bodyIsOverflowing) {
this.scrollBarWidth = getScrollBarSize();
}
},
setScrollBar () {
if (this.bodyIsOverflowing && this.scrollBarWidth !== undefined) {
document.body.style.paddingRight = `${this.scrollBarWidth}px`;
}
},
resetScrollBar () {
document.body.style.paddingRight = '';
},
addScrollEffect () {
this.checkScrollBar();
this.setScrollBar();
document.body.style.overflow = 'hidden';
},
removeScrollEffect() {
document.body.style.overflow = '';
this.resetScrollBar();
}
},
ready () {
if (this.visible) {
this.wrapShow = true;
}
let showHead = true;
if (this.$els.head.innerHTML == '<p></p>' && !this.title) {
showHead = false;
}
this.showHead = showHead;
// ESC close
document.addEventListener('keydown', this.EscClose);
},
beforeDestroy () {
document.removeEventListener('keydown', this.EscClose);
},
watch: {
visible (val) {
if (val === false) {
this.buttonLoading = false;
setTimeout(() => {
this.wrapShow = false;
}, 300);
this.removeScrollEffect();
} else {
this.wrapShow = true;
this.addScrollEffect();
}
}
}
}
</script>

View file

@ -0,0 +1,115 @@
import Notification from '../base/notification';
const prefixCls = 'ivu-notice';
const iconPrefixCls = 'ivu-icon';
const prefixKey = 'ivu_notice_key_';
let top = 24;
let defaultDuration = 4.5;
let noticeInstance;
let key = 1;
const iconTypes = {
'info': 'information-circled',
'success': 'checkmark-circled',
'warning': 'android-alert',
'error': 'close-circled'
};
function getNoticeInstance () {
noticeInstance = noticeInstance || Notification.newInstance({
prefixCls: prefixCls,
style: {
top: `${top}px`,
right: 0
}
});
return noticeInstance;
}
function notice (type, options) {
const title = options.title || '';
const desc = options.desc || '';
const noticeKey = options.key || `${prefixKey}${key}`;
const onClose = options.onClose || function () {};
// todo const btn = options.btn || null;
const duration = (options.duration === 0) ? 0 : options.duration || defaultDuration;
key++;
let instance = getNoticeInstance();
let content;
if (type == 'normal') {
content = `
<div class="${prefixCls}-custom-content">
<div class="${prefixCls}-title">${title}</div>
<div class="${prefixCls}-desc">${desc}</div>
</div>
`;
} else {
const iconType = iconTypes[type];
content = `
<div class="${prefixCls}-custom-content ${prefixCls}-with-icon">
<span class="${prefixCls}-icon ${prefixCls}-icon-${type}">
<i class="${iconPrefixCls} ${iconPrefixCls}-${iconType}"></i>
</span>
<div class="${prefixCls}-title">${title}</div>
<div class="${prefixCls}-desc">${desc}</div>
</div>
`;
}
instance.notice({
key: noticeKey.toString(),
duration: duration,
style: {},
transitionName: 'move-right',
content: content,
onClose: onClose,
closable: true
});
}
export default {
open (options) {
return notice('normal', options);
},
info (options) {
return notice('info', options);
},
success (options) {
return notice('success', options);
},
warning (options) {
return notice('warning', options);
},
error (options) {
return notice('error', options);
},
config (options) {
if (options.top) {
top = options.top;
}
if (options.duration || options.duration === 0) {
defaultDuration = options.duration;
}
},
close (key) {
if (key) {
key = key.toString();
if (noticeInstance) {
noticeInstance.remove(key);
}
} else {
return false;
}
},
destroy () {
let instance = getNoticeInstance();
noticeInstance = null;
instance.destroy();
}
}

View file

@ -0,0 +1,2 @@
import Page from './page.vue';
export default Page;

View file

@ -0,0 +1,87 @@
<template>
<div v-if="showSizer || showElevator" :class="optsClasses">
<div v-if="showSizer" :class="sizerClasses">
<i-select :model.sync="pageSize" :size="size" @on-change="changeSize">
<i-option v-for="item in pageSizeOpts" :value="item" style="text-align:center;">{{ item }} /</i-option>
</i-select>
</div>
<div v-if="showElevator" :class="ElevatorClasses">
跳至
<input type="text" :value="_current" @keyup.enter="changePage">
</div>
</div>
</template>
<script>
import iSelect from '../../components/select/select.vue';
import iOption from '../../components/select/option.vue';
const prefixCls = 'ivu-page';
function isValueNumber (value) {
return (/^[1-9][0-9]*$/).test(value + '');
}
export default {
components: { iSelect, iOption },
props: {
pageSizeOpts: Array,
showSizer: Boolean,
showElevator: Boolean,
current: Number,
_current: Number,
pageSize: Number,
allPages: Number,
isSmall: Boolean
},
computed: {
size () {
return this.isSmall ? 'small' : 'default';
},
optsClasses () {
return [
`${prefixCls}-options`
]
},
sizerClasses () {
return [
`${prefixCls}-options-sizer`
]
},
ElevatorClasses () {
return [
`${prefixCls}-options-elevator`
]
}
},
methods: {
changeSize () {
this.$emit('on-size', this.pageSize);
},
changePage (event) {
let val = event.target.value.trim();
let page = 0;
if (isValueNumber(val)) {
val = Number(val);
if (val != this.current) {
const allPages = this.allPages;
if (val > allPages) {
page = allPages;
} else {
page = val;
}
}
} else {
page = 1;
}
if (page) {
this.$emit('on-page', page);
event.target.value = page;
}
}
}
}
</script>

View file

@ -0,0 +1,238 @@
<template>
<ul :class="simpleWrapClasses" v-if="simple">
<li
title="上一页"
:class="prevClasses"
@click="prev">
<a><i class="ivu-icon ivu-icon-ios-arrow-left"></i></a>
</li>
<div :class="simplePagerClasses" :title="current + '/' + allPages">
<input
type="text"
:value="current"
@keydown="keyDown"
@keyup="keyUp"
@change="keyUp">
<span>/</span>
{{ allPages }}
</div>
<li
title="下一页"
:class="nextClasses"
@click="next">
<a><i class="ivu-icon ivu-icon-ios-arrow-right"></i></a>
</li>
</ul>
<ul :class="wrapClasses" v-else>
<span :class="[`${prefixCls}-total`]" v-if="showTotal">
<slot> {{ total }} </slot>
</span>
<li
title="上一页"
:class="prevClasses"
@click="prev">
<a><i class="ivu-icon ivu-icon-ios-arrow-left"></i></a>
</li>
<li title="第一页" :class="[`${prefixCls}-item`,{[`${prefixCls}-item-active`]: current == 1}]" @click="changePage(1)"><a>1</a></li>
<li title="向前 5 页" v-if="current - 3 > 1" :class="[`${prefixCls}-item-jump-prev`]" @click="fastPrev"><a><i class="ivu-icon ivu-icon-ios-arrow-left"></i></a></li>
<li :title="current - 2" v-if="current - 2 > 1" :class="[`${prefixCls}-item`]" @click="changePage(current - 2)"><a>{{ current - 2 }}</a></li>
<li :title="current - 1" v-if="current - 1 > 1" :class="[`${prefixCls}-item`]" @click="changePage(current - 1)"><a>{{ current - 1 }}</a></li>
<li :title="current" v-if="current != 1 && current != allPages" :class="[`${prefixCls}-item`,`${prefixCls}-item-active`]"><a>{{ current }}</a></li>
<li :title="current + 1" v-if="current + 1 < allPages" :class="[`${prefixCls}-item`]" @click="changePage(current + 1)"><a>{{ current + 1 }}</a></li>
<li :title="current + 2" v-if="current + 2 < allPages" :class="[`${prefixCls}-item`]" @click="changePage(current + 2)"><a>{{ current + 2 }}</a></li>
<li title="向后 5 页" v-if="current + 3 < allPages" :class="[`${prefixCls}-item-jump-next`]" @click="fastNext"><a><i class="ivu-icon ivu-icon-ios-arrow-right"></i></a></li>
<li :title="'最后一页:' + allPages" v-if="allPages > 1" :class="[`${prefixCls}-item`, {[`${prefixCls}-item-active`]: current == allPages}]" @click="changePage(allPages)"><a>{{ allPages }}</a></li>
<li
title="下一页"
:class="nextClasses"
@click="next">
<a><i class="ivu-icon ivu-icon-ios-arrow-right"></i></a>
</li>
<Options
:show-sizer="showSizer"
:page-size="pageSize"
:page-size-opts="pageSizeOpts"
:show-elevator="showElevator"
:_current.once="current"
:current.sync="current"
:all-pages="allPages"
:is-small="isSmall"
@on-size="onSize"
@on-page="onPage">
</Options>
</ul>
</template>
<script>
import { oneOf } from '../../utils/assist';
import Options from './options.vue';
const prefixCls = 'ivu-page';
export default {
components: { Options },
props: {
current: {
type: Number,
default: 1
},
total: {
type: Number,
default: 0
},
pageSize: {
type: Number,
default: 10
},
pageSizeOpts: {
type: Array,
default () {
return [10, 20, 30, 40]
}
},
size: {
validator (value) {
return oneOf(value, ['small']);
}
},
simple: {
type: Boolean,
default: false
},
showTotal: {
type: Boolean,
default: false
},
showElevator: {
type: Boolean,
default: false
},
showSizer: {
type: Boolean,
default: false
}
},
data () {
return {
prefixCls: prefixCls
}
},
computed: {
isSmall () {
return !!this.size;
},
allPages () {
const allPage = Math.ceil(this.total / this.pageSize);
return (allPage === 0) ? 1 : allPage;
},
simpleWrapClasses () {
return [
`${prefixCls}`,
`${prefixCls}-simple`
]
},
simplePagerClasses () {
return `${prefixCls}-simple-pager`;
},
wrapClasses () {
return [
`${prefixCls}`,
{
'mini': !!this.size
}
]
},
prevClasses () {
return [
`${prefixCls}-prev`,
{
[`${prefixCls}-disabled`]: this.current == 1
}
]
},
nextClasses () {
return [
`${prefixCls}-next`,
{
[`${prefixCls}-disabled`]: this.current == this.allPages
}
]
}
},
methods: {
changePage (page) {
if (this.current != page) {
this.current = page;
this.$emit('on-change', page);
}
},
prev () {
const current = this.current;
if (current <= 1) {
return false;
}
this.changePage(current - 1);
},
next () {
const current = this.current;
if (current >= this.allPages) {
return false;
}
this.changePage(current + 1);
},
fastPrev () {
const page = this.current - 5;
if (page > 0) {
this.changePage(page);
} else {
this.changePage(1);
}
},
fastNext () {
const page = this.current + 5;
if (page > this.allPages) {
this.changePage(this.allPages);
} else {
this.changePage(page);
}
},
onSize (pageSize) {
this.pageSize = pageSize;
this.changePage(1);
},
onPage (page) {
this.changePage(page);
},
keyDown (e) {
const key = e.keyCode;
const condition = (key >= 48 && key <= 57) || key == 8 || key == 37 || key == 39;
if (!condition) {
e.preventDefault();
}
},
keyUp (e) {
const key = e.keyCode;
const val = parseInt(e.target.value);
if (key === 38) {
this.prev()
} else if (key === 40) {
this.next()
} else if (key == 13) {
let page = 1;
if (val > this.allPages) {
page = this.allPages;
} else if (val <= 0) {
page = 1;
} else {
page = val;
}
e.target.value = page;
this.changePage(page);
}
}
}
}
</script>

View file

@ -0,0 +1,3 @@
import Poptip from './poptip.vue';
export default Poptip;

View file

@ -0,0 +1,170 @@
<template>
<div
:class="classes"
@mouseenter="handleMouseenter"
@mouseleave="handleMouseleave"
v-clickoutside="handleClose">
<div
:class="[`${prefixCls}-rel`]"
v-el:reference
@click="handleClick"
@mousedown="handleFocus"
@mouseup="handleBlur">
<slot></slot>
</div>
<div :class="[`${prefixCls}-popper`]" :style="styles" transition="fade" v-el:popper v-show="visible">
<div :class="[`${prefixCls}-content`]">
<div :class="[`${prefixCls}-arrow`]"></div>
<div :class="[`${prefixCls}-inner`]" v-if="confirm">
<div :class="[`${prefixCls}-body`]">
<i class="ivu-icon ivu-icon-help-circled"></i>
<div :class="[`${prefixCls}-body-message`]"><slot name="title">{{ title }}</slot></div>
</div>
<div :class="[`${prefixCls}-footer`]">
<Button type="ghost" size="small" @click="cancel">{{ cancelText }}</Button>
<Button type="primary" size="small" @click="ok">{{ okText }}</Button>
</div>
</div>
<div :class="[`${prefixCls}-inner`]" v-if="!confirm">
<div :class="[`${prefixCls}-title`]" v-if="showTitle" v-el:title><slot name="title">{{ title }}</slot></div>
<div :class="[`${prefixCls}-body`]">
<div :class="[`${prefixCls}-body-content`]"><slot name="content">{{ content }}</slot></div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Popper from '../base/popper';
import Button from '../button/button.vue';
import clickoutside from '../../directives/clickoutside';
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-poptip';
export default {
mixins: [Popper],
directives: { clickoutside },
components: { Button },
props: {
trigger: {
validator (value) {
return oneOf(value, ['click', 'focus', 'hover']);
},
default: 'click'
},
placement: {
validator (value) {
return oneOf(value, ['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end', 'right', 'right-start', 'right-end']);
},
default: 'top'
},
title: {
type: [String, Number]
},
content: {
type: [String, Number],
default: ''
},
width: {
type: [String, Number]
},
confirm: {
type: Boolean,
default: false
},
okText: {
type: String,
default: '确定'
},
cancelText: {
type: String,
default: '取消'
}
},
data () {
return {
prefixCls: prefixCls,
showTitle: true
}
},
computed: {
classes () {
return [
`${prefixCls}`,
{
[`${prefixCls}-confirm`]: this.confirm
}
]
},
styles () {
let style = {};
if (!!this.width) {
style.width = `${this.width}px`;
}
return style;
}
},
methods: {
handleClick () {
if (this.confirm) {
this.visible = !this.visible;
return true;
}
if (this.trigger !== 'click') {
return false;
}
this.visible = !this.visible;
},
handleClose () {
if (this.confirm) {
this.visible = false;
return true;
}
if (this.trigger !== 'click') {
return false;
}
this.visible = false;
},
handleFocus () {
if (this.trigger !== 'focus' || this.confirm) {
return false;
}
this.visible = true;
},
handleBlur () {
if (this.trigger !== 'focus' || this.confirm) {
return false;
}
this.visible = false;
},
handleMouseenter () {
if (this.trigger !== 'hover' || this.confirm) {
return false;
}
this.visible = true;
},
handleMouseleave () {
if (this.trigger !== 'hover' || this.confirm) {
return false;
}
this.visible = false;
},
cancel () {
this.visible = false;
this.$emit('on-cancel');
},
ok () {
this.visible = false;
this.$emit('on-ok');
}
},
ready () {
if (!this.confirm) {
this.showTitle = this.$els.title.innerHTML != '';
}
}
}
</script>

View file

@ -0,0 +1,2 @@
import Progress from './progress.vue';
export default Progress;

View file

@ -0,0 +1,121 @@
<template>
<div :class="wrapClasses">
<div :class="outerClasses">
<div :class="innerClasses">
<div :class="bgClasses" :style="bgStyle"></div>
</div>
</div>
<span v-if="!hideInfo" :class="textClasses">
<slot>
<span v-if="isStatus" :class="textInnerClasses">
<Icon :type="statusIcon"></Icon>
</span>
<span v-else :class="textInnerClasses">
{{ percent }}%
</span>
</slot>
</span>
</div>
</template>
<script>
import Icon from '../icon';
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-progress';
export default {
components: { Icon },
props: {
percent: {
type: Number,
default: 0
},
status: {
validator (value) {
return oneOf(value, ['normal', 'active', 'wrong', 'success']);
},
default: 'normal'
},
hideInfo: {
type: Boolean,
default: false
},
strokeWidth: {
type: Number,
default: 10
}
},
computed: {
isStatus () {
return this.status == 'wrong' || this.status == 'success';
},
statusIcon () {
let type = '';
switch (this.status) {
case 'wrong':
type = 'ios-close';
break;
case 'success':
type = 'ios-checkmark';
break;
}
return type;
},
bgStyle () {
return {
width: `${this.percent}%`,
height: `${this.strokeWidth}px`
}
},
wrapClasses () {
return [
`${prefixCls}`,
`${prefixCls}-${this.status}`,
{
[`${prefixCls}-show-info`]: !this.hideInfo,
}
]
},
textClasses () {
return `${prefixCls}-text`;
},
textInnerClasses () {
return `${prefixCls}-text-inner`;
},
outerClasses () {
return `${prefixCls}-outer`;
},
innerClasses () {
return `${prefixCls}-inner`;
},
bgClasses () {
return `${prefixCls}-bg`;
}
},
compiled () {
this.handleStatus();
},
methods: {
handleStatus (isDown) {
if (isDown) {
this.status = 'normal';
} else {
if (parseInt(this.percent, 10) == 100) {
this.status = 'success';
}
}
}
},
watch: {
percent (val, oldVal) {
if (val < oldVal) {
this.handleStatus(true);
} else {
this.handleStatus();
}
}
}
}
</script>

View file

@ -0,0 +1,5 @@
import Radio from './radio.vue';
import RadioGroup from './radio-group.vue';
Radio.Group = RadioGroup;
export default Radio;

View file

@ -0,0 +1,62 @@
<template>
<div :class="classes">
<slot></slot>
</div>
</template>
<script>
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-radio-group';
export default {
props: {
model: {
type: [String, Number],
default: ''
},
size: {
validator (value) {
return oneOf(value, ['small', 'large']);
}
},
type: {
validator (value) {
return oneOf(value, ['button']);
}
}
},
computed: {
classes () {
return [
`${prefixCls}`,
{
[`${prefixCls}-${this.size}`]: !!this.size,
[`${prefixCls}-${this.type}`]: !!this.type
}
]
}
},
compiled () {
this.updateModel();
},
methods: {
updateModel () {
const model = this.model;
this.$children.forEach((child) => {
child.selected = model == child.value;
child.group = true;
});
},
change (data) {
this.model = data.value;
this.updateModel();
this.$emit('on-change', data.value);
}
},
watch: {
model () {
this.updateModel()
}
}
}
</script>

View file

@ -0,0 +1,96 @@
<template>
<label :class="wrapClasses">
<span :class="radioClasses">
<span :class="innerClasses"></span>
<input
type="radio"
:class="inputClasses"
:disabled="disabled"
:checked="selected"
@change="change">
</span>
<slot>{{ value }}</slot>
</label>
</template>
<script>
const prefixCls = 'ivu-radio';
export default {
props: {
checked: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
value: {
type: [String, Number]
}
},
data () {
return {
selected: false,
group: false
}
},
computed: {
wrapClasses () {
return [
`${prefixCls}-wrapper`,
{
[`${prefixCls}-group-item`]: this.group,
[`${prefixCls}-wrapper-checked`]: this.selected,
[`${prefixCls}-wrapper-disabled`]: this.disabled
}
]
},
radioClasses () {
return [
`${prefixCls}`,
{
[`${prefixCls}-checked`]: this.selected,
[`${prefixCls}-disabled`]: this.disabled
}
]
},
innerClasses () {
return `${prefixCls}-inner`;
},
inputClasses () {
return `${prefixCls}-input`;
}
},
ready () {
if (!this.group) {
this.updateModel();
}
},
methods: {
change (event) {
if (this.disabled) {
return false;
}
this.selected = event.target.checked;
this.checked = this.selected;
if (this.group && this.checked) {
this.$parent.change({
value: this.value,
checked: this.checked
});
}
},
updateModel () {
this.selected = this.checked;
}
},
watch: {
checked () {
this.updateModel();
}
}
}
</script>

View file

@ -0,0 +1,59 @@
<template>
<div class="ivu-select-dropdown"><slot></slot></div>
</template>
<script>
import Popper from 'popper.js';
export default {
data () {
return {
popper: null
}
},
methods: {
update () {
if (this.popper) {
this.$nextTick(() => {
this.popper.update();
});
} else {
this.$nextTick(() => {
this.popper = new Popper(this.$parent.$els.reference, this.$el, {
gpuAcceleration: false,
placement: 'bottom-start',
boundariesPadding: 0,
forceAbsolute: true
});
this.popper.onCreate(popper => {
this.resetTransformOrigin(popper);
});
});
}
},
destroy () {
if (this.popper) {
this.resetTransformOrigin(this.popper);
setTimeout(() => {
this.popper.destroy();
this.popper = null;
}, 300);
}
},
resetTransformOrigin(popper) {
let placementMap = {top: 'bottom', bottom: 'top'};
let placement = popper._popper.getAttribute('x-placement').split('-')[0];
let origin = placementMap[placement];
popper._popper.style.transformOrigin = `center ${ origin }`;
}
},
ready () {
this.$on('on-update-popper', this.update);
this.$on('on-destroy-popper', this.destroy);
},
beforeDestroy () {
if (this.popper) {
this.popper.destroy();
}
}
}
</script>

View file

@ -0,0 +1,5 @@
import Select from './select.vue';
import Option from './option.vue';
import OptionGroup from './option-group.vue';
export { Select, Option, OptionGroup };

View file

@ -0,0 +1,25 @@
<template>
<li :class="[`${prefixCls}-wrap`]">
<div :class="[`${prefixCls}-title`]">{{ label }}</div>
<ul>
<li :class="[`${prefixCls}`]"><slot></slot></li>
</ul>
</li>
</template>
<script>
const prefixCls = 'ivu-select-group';
export default {
props: {
label: {
type: String,
default: ''
}
},
data () {
return {
prefixCls: prefixCls
}
}
}
</script>

View file

@ -0,0 +1,73 @@
<template>
<li :class="classes" @click.stop="select" @mouseout.stop="blur" v-show="!hidden"><slot>{{ showLabel }}</slot></li>
</template>
<script>
const prefixCls = 'ivu-select-item';
export default {
props: {
value: {
type: [String, Number],
required: true
},
label: {
type: [String, Number]
},
disabled: {
type: Boolean,
default: false
}
},
componentName: 'select-item',
data () {
return {
selected: false,
index: 0, // for up and down to focus
isFocus: false,
hidden: false, // for search
searchLabel: '' // the value is slot,only for search
}
},
computed: {
classes () {
return [
`${prefixCls}`,
{
[`${prefixCls}-disabled`]: this.disabled,
[`${prefixCls}-selected`]: this.selected,
[`${prefixCls}-focus`]: this.isFocus
}
]
},
showLabel () {
return (!!this.label) ? this.label : this.value;
}
},
methods: {
select () {
if (this.disabled) {
return false;
}
this.$dispatch('on-select-selected', this.value);
},
blur () {
this.isFocus = false;
},
queryChange (val) {
this.hidden = !new RegExp(val, 'i').test(this.searchLabel);
}
},
ready () {
this.searchLabel = this.$el.innerHTML;
},
events: {
'on-select-close' () {
this.isFocus = false;
},
'on-query-change' (val) {
this.queryChange(val);
}
}
}
</script>

View file

@ -0,0 +1,511 @@
<template>
<div :class="classes" v-clickoutside="handleClose">
<div
:class="[`${prefixCls}-selection`]"
v-el:reference
@click="toggleMenu">
<div class="ivu-tag" v-for="item in selectedMultiple">
<span class="ivu-tag-text">{{ item.label }}</span>
<Icon type="ios-close-empty" @click.stop="removeTag($index)"></Icon>
</div>
<span :class="[`${prefixCls}-placeholder`]" v-show="showPlaceholder && !filterable">{{ placeholder }}</span>
<span :class="[`${prefixCls}-selected-value`]" v-show="!showPlaceholder && !multiple && !filterable">{{ selectedSingle }}</span>
<input
type="text"
v-if="filterable"
v-model="query"
:class="[`${prefixCls}-input`]"
:placeholder="showPlaceholder ? placeholder : ''"
:style="inputStyle"
@blur="handleBlur"
@keydown="resetInputState"
@keydown.delete="handleInputDelete"
v-el:input>
<Icon type="ios-close" :class="[`${prefixCls}-arrow`]" v-show="showCloseIcon" @click.stop="clearSingleSelect"></Icon>
<Icon type="arrow-down-b" :class="[`${prefixCls}-arrow`]"></Icon>
</div>
<Dropdown v-show="visible" transition="slide-up" v-ref:dropdown>
<ul v-show="notFound" :class="[`${prefixCls}-not-found`]"><li>{{ notFoundText }}</li></ul>
<ul v-else :class="[`${prefixCls}-dropdown-list`]"><slot></slot></ul>
</Dropdown>
</div>
</template>
<script>
import Icon from '../icon';
import Dropdown from './dropdown.vue';
import clickoutside from '../../directives/clickoutside';
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-select';
export default {
components: { Icon, Dropdown },
directives: { clickoutside },
props: {
model: {
type: [String, Number, Array],
default: ''
},
multiple: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
clearable: {
type: Boolean,
default: false
},
placeholder: {
type: String,
default: '请选择'
},
filterable: {
type: Boolean,
default: false
},
filterMethod: {
type: Function
},
size: {
validator (value) {
return oneOf(value, ['small', 'large', 'default']);
}
},
labelInValue: {
type: Boolean,
default: false
},
notFoundText: {
type: String,
default: '无匹配数据'
}
},
data () {
return {
prefixCls: prefixCls,
visible: false,
options: [],
optionInstances: [],
selectedSingle: '', // label
selectedMultiple: [],
focusIndex: 0,
query: '',
inputLength: 20,
notFound: false
}
},
computed: {
classes () {
return [
`${prefixCls}`,
{
[`${prefixCls}-visible`]: this.visible,
[`${prefixCls}-disabled`]: this.disabled,
[`${prefixCls}-multiple`]: this.multiple,
[`${prefixCls}-single`]: !this.multiple,
[`${prefixCls}-show-clear`]: this.showCloseIcon,
[`${prefixCls}-${this.size}`]: !!this.size
}
]
},
showPlaceholder () {
let status = false;
if ((typeof this.model) === 'string') {
if (this.model === '') {
status = true;
}
} else if (Array.isArray(this.model)) {
if (!this.model.length) {
status = true;
}
}
return status;
},
showCloseIcon () {
return !this.multiple && this.clearable && !this.showPlaceholder;
},
inputStyle () {
let style = {};
if (this.multiple) {
if (this.showPlaceholder) {
style.width = '100%';
} else {
style.width = `${this.inputLength}px`;
}
}
return style;
}
},
methods: {
toggleMenu () {
if (this.disabled) {
return false;
}
this.visible = !this.visible;
},
hideMenu () {
this.visible = false;
this.focusIndex = 0;
this.$broadcast('on-select-close');
},
// find option component
findChild (cb) {
const find = function (child) {
const name = child.$options.componentName;
if (name) {
cb(child);
} else if (child.$children.length) {
child.$children.forEach((innerChild) => {
find(innerChild, cb);
});
}
};
if (this.optionInstances.length) {
this.optionInstances.forEach((child) => {
find(child);
})
} else {
this.$children.forEach((child) => {
find(child);
});
}
},
updateOptions (init) {
let options = [];
let index = 1;
this.findChild((child) => {
options.push({
value: child.value,
label: (child.label === undefined) ? child.$el.innerHTML : child.label
});
child.index = index++;
if (init) {
this.optionInstances.push(child);
}
});
this.options = options;
if (init) {
this.updateSingleSelected(true);
this.updateMultipleSelected(true);
}
},
updateSingleSelected (init = false) {
const type = typeof this.model;
if (type === 'string' || type === 'number') {
for (let i = 0; i < this.options.length; i++) {
if (this.model === this.options[i].value) {
this.selectedSingle = this.options[i].label;
break;
}
}
}
this.toggleSingleSelected(this.model, init);
},
clearSingleSelect () {
if (this.showCloseIcon) {
this.findChild((child) => {
child.selected = false;
});
this.model = '';
if (this.filterable) {
this.query = '';
}
}
},
updateMultipleSelected (init = false) {
if (this.multiple && Array.isArray(this.model)) {
let selected = [];
for (let i = 0; i < this.model.length; i++) {
const model = this.model[i];
for (let j = 0; j < this.options.length; j++) {
const option = this.options[j];
if (model === option.value) {
selected.push({
value: option.value,
label: option.label
})
}
}
}
this.selectedMultiple = selected;
}
this.toggleMultipleSelected(this.model, init);
},
removeTag (index) {
if (this.disabled) {
return false;
}
this.model.splice(index, 1);
if (this.filterable && this.visible) {
this.$els.input.focus();
}
this.$broadcast('on-update-popper');
},
// to select option for single
toggleSingleSelected (value, init = false) {
if (!this.multiple) {
let label = '';
this.findChild((child) => {
if (child.value === value) {
child.selected = true;
label = (child.label === undefined) ? child.$el.innerHTML : child.label;
} else {
child.selected = false;
}
});
this.hideMenu();
if (!init) {
if (this.labelInValue) {
this.$emit('on-change', {
value: value,
label: label
});
} else {
this.$emit('on-change', value);
}
}
}
},
// to select option for multiple
toggleMultipleSelected (value, init = false) {
if (this.multiple) {
let hybridValue = [];
for (let i = 0; i < value.length; i++) {
hybridValue.push({
value: value[i]
});
}
this.findChild((child) => {
const index = value.indexOf(child.value);
if (index >= 0) {
child.selected = true;
hybridValue[index].label = (child.label === undefined) ? child.$el.innerHTML : child.label;
} else {
child.selected = false;
}
});
if (!init) {
if (this.labelInValue) {
this.$emit('on-change', hybridValue);
} else {
this.$emit('on-change', value);
}
}
}
},
handleClose () {
this.hideMenu();
},
handleKeydown (e) {
if (this.visible) {
const keyCode = e.keyCode;
// Esc slide-up
if (keyCode === 27) {
e.preventDefault();
this.hideMenu();
}
// next
if (keyCode === 40) {
e.preventDefault();
this.navigateOptions('next');
}
// prev
if (keyCode === 38) {
e.preventDefault();
this.navigateOptions('prev');
}
// enter
if (keyCode === 13) {
e.preventDefault();
this.findChild((child) => {
if (child.isFocus) {
child.select();
}
});
}
}
},
navigateOptions (direction) {
if (direction === 'next') {
const next = this.focusIndex + 1;
this.focusIndex = (this.focusIndex === this.options.length) ? 1 : next;
} else if (direction === 'prev') {
const prev = this.focusIndex - 1;
this.focusIndex = (this.focusIndex <= 1) ? this.options.length : prev;
}
let child_status = {
disabled: false,
hidden: false
};
let find_deep = false; // can next find allowed
this.findChild((child) => {
if (child.index === this.focusIndex) {
child_status.disabled = child.disabled;
child_status.hidden = child.hidden;
if (!child.disabled && !child.hidden) {
child.isFocus = true;
}
} else {
child.isFocus = false;
}
if (!child.hidden && !child.disabled) {
find_deep = true;
}
});
this.resetScrollTop();
if ((child_status.disabled || child_status.hidden) && find_deep) {
this.navigateOptions(direction);
}
},
resetScrollTop () {
const index = this.focusIndex - 1;
let bottomOverflowDistance = this.optionInstances[index].$el.getBoundingClientRect().bottom - this.$refs.dropdown.$el.getBoundingClientRect().bottom;
let topOverflowDistance = this.optionInstances[index].$el.getBoundingClientRect().top - this.$refs.dropdown.$el.getBoundingClientRect().top;
if (bottomOverflowDistance > 0) {
this.$refs.dropdown.$el.scrollTop += bottomOverflowDistance;
}
if (topOverflowDistance < 0) {
this.$refs.dropdown.$el.scrollTop += topOverflowDistance;
}
},
handleBlur () {
setTimeout(() => {
const model = this.model;
if (this.multiple) {
} else {
if (model !== '') {
this.findChild((child) => {
if (child.value === model) {
this.query = child.searchLabel;
}
});
}
}
}, 300);
},
resetInputState () {
this.inputLength = this.$els.input.value.length * 12 + 20;
},
handleInputDelete () {
if (this.multiple && this.model.length && this.query === '') {
this.removeTag(this.model.length - 1);
}
}
},
ready () {
this.updateOptions(true);
document.addEventListener('keydown', this.handleKeydown);
},
beforeDestroy () {
document.removeEventListener('keydown', this.handleKeydown);
},
watch: {
model () {
if (this.multiple) {
this.updateMultipleSelected();
} else {
this.updateSingleSelected();
}
},
visible (val) {
if (val) {
if (this.multiple && this.filterable) {
this.$els.input.focus();
}
this.$broadcast('on-update-popper');
} else {
if (this.filterable) {
this.$els.input.blur();
}
this.$broadcast('on-destroy-popper');
}
},
query (val) {
this.$broadcast('on-query-change', val);
let is_hidden = true;
this.$nextTick(() => {
this.findChild((child) => {
if (!child.hidden) {
is_hidden = false;
}
});
this.notFound = is_hidden;
});
}
},
events: {
'on-select-selected' (value) {
if (this.model === value) {
this.hideMenu();
} else {
if (this.multiple) {
const index = this.model.indexOf(value);
if (index >= 0) {
this.removeTag(index);
} else {
this.model.push(value);
this.$broadcast('on-update-popper');
}
if (this.filterable) {
this.query = '';
this.$els.input.focus();
}
} else {
this.model = value;
if (this.filterable) {
this.findChild((child) => {
if (child.value === value) {
this.query = child.searchLabel;
}
});
}
}
}
}
}
}
</script>

View file

@ -0,0 +1,2 @@
import Spin from './spin.vue';
export default Spin;

View file

@ -0,0 +1,60 @@
<template>
<div :class="classes" transition="fade">
<div :class="mainClasses">
<span :class="dotClasses"></span>
<div :class="textClasses" v-el:text><slot></slot></div>
</div>
</div>
</template>
<script>
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-spin';
export default {
props: {
size: {
validator (value) {
return oneOf(value, ['small', 'large']);
}
},
fix: {
type: Boolean,
default: false
}
},
data () {
return {
showText: false
}
},
computed: {
classes () {
return [
`${prefixCls}`,
{
[`${prefixCls}-${this.size}`]: !!this.size,
[`${prefixCls}-fix`]: this.fix,
[`${prefixCls}-show-text`]: this.showText,
}
]
},
mainClasses () {
return `${prefixCls}-main`;
},
dotClasses () {
return `${prefixCls}-dot`;
},
textClasses () {
return `${prefixCls}-text`;
}
},
compiled () {
const text = this.$els.text.innerHTML;
if (text != '') {
this.showText = true;
}
}
}
</script>

View file

@ -0,0 +1,5 @@
import Steps from './steps.vue';
import Step from './step.vue';
Steps.Step = Step;
export default Steps;

View file

@ -0,0 +1,94 @@
<template>
<div :class="wrapClasses" :style="styles">
<div :class="[`${prefixCls}-tail`]"><i></i></div>
<div :class="[`${prefixCls}-head`]">
<div :class="[`${prefixCls}-head-inner`]">
<span v-if="!icon && status != 'finish' && status != 'error'">{{ stepNumber }}</span>
<span v-else :class="iconClasses"></span>
</div>
</div>
<div :class="[`${prefixCls}-main`]">
<div :class="[`${prefixCls}-title`]">{{ title }}</div>
<div v-if="content" :class="[`${prefixCls}-content`]">{{ content }}</div>
</div>
</div>
</template>
<script>
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-steps';
const iconPrefixCls = 'ivu-icon';
export default {
props: {
status: {
validator (value) {
return oneOf(value, ['wait', 'process', 'finish', 'error']);
}
},
title: {
type: String,
default: ''
},
content: {
type: String
},
icon: {
type: String
}
},
data () {
return {
prefixCls: prefixCls,
stepNumber: '',
nextError: false,
total: 1
}
},
computed: {
wrapClasses () {
return [
`${prefixCls}-item`,
`${prefixCls}-status-${this.status}`,
{
[`${prefixCls}-custom`]: !!this.icon,
[`${prefixCls}-next-error`]: this.nextError
}
]
},
iconClasses () {
let icon = '';
if (!!this.icon) {
icon = this.icon;
} else {
if (this.status == 'finish') {
icon = 'ios-checkmark-empty';
} else if (this.status == 'error') {
icon = 'ios-close-empty';
}
}
return [
`${prefixCls}-icon`,
`${iconPrefixCls}`,
{
[`${iconPrefixCls}-${icon}`]: icon != ''
}
]
},
styles () {
return {
width: `${1/this.total*100}%`
}
}
},
watch: {
status () {
if (this.status == 'error') {
this.$parent.setNextError();
}
}
}
}
</script>

View file

@ -0,0 +1,107 @@
<template>
<div :class="classes">
<slot></slot>
</div>
</template>
<script>
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-steps';
export default {
props: {
current: {
type: Number,
default: 0
},
status: {
validator (value) {
return oneOf(value, ['wait', 'process', 'finish', 'error']);
},
default: 'process'
},
size: {
validator (value) {
return oneOf(value, ['small']);
}
},
direction: {
validator (value) {
return oneOf(value, ['horizontal', 'vertical']);
},
default: 'horizontal'
}
},
computed: {
classes () {
return [
`${prefixCls}`,
`${prefixCls}-${this.direction}`,
{
[`${prefixCls}-${this.size}`]: !!this.size
}
]
}
},
ready () {
this.updateChildProps(true);
this.setNextError();
this.updateCurrent(true);
},
methods: {
updateChildProps (isInit) {
const total = this.$children.length;
this.$children.forEach((child, index) => {
child.stepNumber = index + 1;
if (this.direction === 'horizontal') {
child.total = total;
}
// status,,
// todo error,current
if (!(isInit && child.status)) {
if (index == this.current) {
if (this.status != 'error') {
child.status = 'process';
}
} else if (index < this.current) {
child.status = 'finish';
} else {
child.status = 'wait';
}
}
if (child.status != 'error' && index != 0) {
this.$children[index - 1].nextError = false;
}
});
},
setNextError () {
this.$children.forEach((child, index) => {
if (child.status == 'error' && index != 0) {
this.$children[index - 1].nextError = true;
}
});
},
updateCurrent (isInit) {
if (isInit) {
const current_status = this.$children[this.current].status;
if (!current_status) {
this.$children[this.current].status = this.status;
}
} else {
this.$children[this.current].status = this.status;
}
}
},
watch: {
current () {
this.updateChildProps();
},
status () {
this.updateCurrent();
}
}
}
</script>

View file

@ -0,0 +1,2 @@
import Switch from './switch.vue';
export default Switch;

View file

@ -0,0 +1,56 @@
<template>
<span :class="wrapClasses" @click="toggle">
<span :class="innerClasses">
<slot name="open" v-if="checked"></slot>
<slot name="close" v-if="!checked"></slot>
</span>
</span>
</template>
<script>
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-switch';
export default {
props: {
checked: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
size: {
validator (value) {
return oneOf(value, ['small']);
}
}
},
computed: {
wrapClasses () {
return [
`${prefixCls}`,
{
[`${prefixCls}-checked`]: this.checked,
[`${prefixCls}-disabled`]: this.disabled,
[`${prefixCls}-${this.size}`]: !!this.size
}
]
},
innerClasses () {
return `${prefixCls}-inner`;
}
},
methods: {
toggle () {
if (this.disabled) {
return false;
}
this.checked = !this.checked;
this.$emit('on-change', this.checked);
}
}
}
</script>

View file

@ -0,0 +1,2 @@
import Tag from './tag.vue';
export default Tag;

View file

@ -0,0 +1,51 @@
<template>
<div v-if="!closed" :class="classes" transition="fade">
<span :class="textClasses"><slot></slot></span>
<Icon v-if="closable" type="ios-close-empty" @click="close"></Icon>
</div>
</template>
<script>
import Icon from '../icon';
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-tag';
export default {
components: { Icon },
props: {
closable: {
type: Boolean,
default: false
},
color: {
validator (value) {
return oneOf(value, ['blue', 'green', 'red', 'yellow']);
}
}
},
data () {
return {
closed: false
}
},
computed: {
classes () {
return [
`${prefixCls}`,
{
[`${prefixCls}-${this.color}`]: !!this.color
}
]
},
textClasses () {
return `${prefixCls}-text`;
}
},
methods: {
close (e) {
this.closed = true;
this.$emit('on-close', e);
}
}
}
</script>

View file

@ -0,0 +1,5 @@
import Timeline from './timeline.vue';
import TimelineItem from './timeline-item.vue';
Timeline.Item = TimelineItem;
export default Timeline;

View file

@ -0,0 +1,65 @@
<template>
<li :class="itemClasses">
<div :class="tailClasses"></div>
<div :class="headClasses" :style="customColor" v-el:dot><slot name="dot"></slot></div>
<div :class="contentClasses">
<slot></slot>
</div>
</li>
</template>
<script>
const prefixCls = 'ivu-timeline';
export default {
props: {
color: {
type: String,
default: 'blue'
}
},
data () {
return {
dot: false
}
},
ready () {
this.dot = this.$els.dot.innerHTML.length ? true : false;
},
computed: {
itemClasses () {
return `${prefixCls}-item`;
},
tailClasses () {
return `${prefixCls}-item-tail`;
},
headClasses () {
return [
`${prefixCls}-item-head`,
{
[`${prefixCls}-item-head-custom`]: this.dot,
[`${prefixCls}-item-head-${this.color}`]: this.headColorShow
}
]
},
headColorShow () {
return this.color == 'blue' || this.color == 'red' || this.color == 'green';
},
customColor () {
let style = {};
if (this.color) {
if (!this.headColorShow) {
style = {
'color': this.color,
'border-color': this.color
}
}
}
return style;
},
contentClasses () {
return `${prefixCls}-item-content`;
}
}
}
</script>

View file

@ -0,0 +1,27 @@
<template>
<ul :class="classes">
<slot></slot>
</ul>
</template>
<script>
const prefixCls = 'ivu-timeline';
export default {
props: {
pending: {
type: Boolean,
default: false
}
},
computed: {
classes () {
return [
`${prefixCls}`,
{
[`${prefixCls}-pending`]: this.pending
}
]
}
}
}
</script>

View file

@ -0,0 +1,3 @@
import Tooltip from './tooltip.vue';
export default Tooltip;

View file

@ -0,0 +1,59 @@
<template>
<div :class="[`${prefixCls}`]" @mouseenter="handleShowPopper" @mouseleave="handleClosePopper">
<div :class="[`${prefixCls}-rel`]" v-el:reference>
<slot></slot>
</div>
<div :class="[`${prefixCls}-popper`]" transition="fade" v-el:popper v-show="!disabled && visible">
<div :class="[`${prefixCls}-content`]">
<div :class="[`${prefixCls}-arrow`]"></div>
<div :class="[`${prefixCls}-inner`]"><slot name="content">{{ content }}</slot></div>
</div>
</div>
</div>
</template>
<script>
import Popper from '../base/popper';
import { oneOf } from '../../utils/assist';
const prefixCls = 'ivu-tooltip';
export default {
mixins: [Popper],
props: {
placement: {
validator (value) {
return oneOf(value, ['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end', 'right', 'right-start', 'right-end']);
},
default: 'bottom'
},
content: {
type: [String, Number],
default: ''
},
delay: {
type: Number,
default: 0
},
disabled: {
type: Boolean,
default: false
}
},
data () {
return {
prefixCls: prefixCls
}
},
methods: {
handleShowPopper() {
this.timeout = setTimeout(() => {
this.visible = true;
}, this.delay);
},
handleClosePopper() {
clearTimeout(this.timeout);
this.visible = false;
}
}
}
</script>

View file

@ -0,0 +1,19 @@
export default {
bind () {
this.documentHandler = (e) => {
if (this.el.contains(e.target)) {
return false;
}
if (this.expression) {
this.vm[this.expression]();
}
};
document.addEventListener('click', this.documentHandler);
},
update () {
},
unbind () {
document.removeEventListener('click', this.documentHandler);
}
}

73
src/index.js Normal file
View file

@ -0,0 +1,73 @@
import Button from './components/button';
import Icon from './components/icon';
import Input from './components/input';
import Switch from './components/switch';
import Radio from './components/radio';
import Checkbox from './components/checkbox';
import InputNumber from './components/input-number';
import { Row, Col } from './components/layout';
import Page from './components/page';
import Badge from './components/badge';
import Tag from './components/tag';
import Progress from './components/progress';
import Circle from './components/circle';
import Timeline from './components/timeline';
import Affix from './components/affix';
import BackTop from './components/back-top';
import Spin from './components/spin';
import Steps from './components/steps';
import Breadcrumb from './components/breadcrumb';
import Alert from './components/alert';
import Collapse from './components/collapse';
import Card from './components/card';
import Message from './components/message';
import Notice from './components/notice';
import LoadingBar from './components/loading-bar';
import Modal from './components/modal';
import { Select, Option, OptionGroup } from './components/select';
import Tooltip from './components/tooltip';
import Poptip from './components/poptip';
const iview = {
Button,
ButtonGroup: Button.Group,
Icon,
Input,
Switch,
Radio,
RadioGroup: Radio.Group,
Checkbox,
CheckboxGroup: Checkbox.Group,
InputNumber,
Row,
iCol: Col,
Page,
Badge,
Tag,
Progress,
Circle,
Timeline,
TimelineItem: Timeline.Item,
Affix,
BackTop,
Spin,
Steps,
Step: Steps.Step,
Breadcrumb,
BreadcrumbItem: Breadcrumb.Item,
Alert,
Collapse,
Panel: Collapse.Panel,
Card,
Message,
Notice,
LoadingBar,
Modal,
iSelect: Select,
iOption: Option,
iOptionGroup: OptionGroup,
Tooltip,
Poptip
};
module.exports = iview;

11
src/styles/README.md Normal file
View file

@ -0,0 +1,11 @@
# 样式库说明
## 目录
|-- components (组件样式)
|-- common (全局样式)
|-- packages (套装)
|-- themes (皮肤)

View file

@ -0,0 +1,36 @@
.ease-motion(@className, @keyframeName) {
.make-motion(@className, @keyframeName);
.@{className}-enter, .@{className}-appear {
opacity: 0;
animation-timing-function: linear;
animation-duration: @transition-time;
}
.@{className}-leave {
animation-timing-function: linear;
animation-duration: @transition-time;
}
}
.ease-motion(ease, ivuEase);
@keyframes ivuEaseIn {
0% {
opacity: 0;
transform: scale(0.9);
}
100% {
opacity: 1;
transform: scale(1);
}
}
@keyframes ivuEaseOut {
0% {
opacity: 1;
transform: scale(1);
}
100% {
opacity: 0;
transform: scale(0.9);
}
}

View file

@ -0,0 +1,30 @@
.fade-motion(@className, @keyframeName) {
.make-motion(@className, @keyframeName);
.@{className}-enter, .@{className}-appear {
opacity: 0;
animation-timing-function: linear;
}
.@{className}-leave {
animation-timing-function: linear;
}
}
.fade-motion(fade, ivuFade);
@keyframes ivuFadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes ivuFadeOut {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}

View file

@ -0,0 +1,28 @@
.motion-common() {
animation-duration: @animation-time;
animation-fill-mode: both;
}
.make-motion(@className, @keyframeName) {
.@{className}-enter, .@{className}-appear {
.motion-common();
animation-play-state: paused;
}
.@{className}-leave {
.motion-common();
animation-play-state: paused;
}
.@{className}-enter, .@{className}-appear {
animation-name: ~"@{keyframeName}In";
animation-play-state: running;
}
.@{className}-leave {
animation-name: ~"@{keyframeName}Out";
animation-play-state: running;
}
}
@import "fade";
@import "move";
@import "ease";
@import "slide";

View file

@ -0,0 +1,119 @@
.move-motion(@className, @keyframeName) {
.make-motion(@className, @keyframeName);
.@{className}-enter, .@{className}-appear {
opacity: 0;
animation-timing-function: @ease-in-out;
}
.@{className}-leave {
animation-timing-function: @ease-in-out;
}
}
.move-motion(move-up, ivuMoveUp);
.move-motion(move-down, ivuMoveDown);
.move-motion(move-left, ivuMoveLeft);
.move-motion(move-right, ivuMoveRight);
@keyframes ivuMoveDownIn {
0% {
transform-origin: 0 0;
transform: translateY(100%);
opacity: 0;
}
100% {
transform-origin: 0 0;
transform: translateY(0%);
opacity: 1;
}
}
@keyframes ivuMoveDownOut {
0% {
transform-origin: 0 0;
transform: translateY(0%);
opacity: 1;
}
100% {
transform-origin: 0 0;
transform: translateY(100%);
opacity: 0;
}
}
@keyframes ivuMoveLeftIn {
0% {
transform-origin: 0 0;
transform: translateX(-100%);
opacity: 0;
}
100% {
transform-origin: 0 0;
transform: translateX(0%);
opacity: 1;
}
}
@keyframes ivuMoveLeftOut {
0% {
transform-origin: 0 0;
transform: translateX(0%);
opacity: 1;
}
100% {
transform-origin: 0 0;
transform: translateX(-100%);
opacity: 0;
}
}
@keyframes ivuMoveRightIn {
0% {
opacity: 0;
transform-origin: 0 0;
transform: translateX(100%);
}
100% {
opacity: 1;
transform-origin: 0 0;
transform: translateX(0%);
}
}
@keyframes ivuMoveRightOut {
0% {
transform-origin: 0 0;
transform: translateX(0%);
opacity: 1;
}
100% {
transform-origin: 0 0;
transform: translateX(100%);
opacity: 0;
}
}
@keyframes ivuMoveUpIn {
0% {
transform-origin: 0 0;
transform: translateY(-100%);
opacity: 0;
}
100% {
transform-origin: 0 0;
transform: translateY(0%);
opacity: 1;
}
}
@keyframes ivuMoveUpOut {
0% {
transform-origin: 0 0;
transform: translateY(0%);
opacity: 1;
}
100% {
transform-origin: 0 0;
transform: translateY(-100%);
opacity: 0;
}
}

View file

@ -0,0 +1,119 @@
.slide-motion(@className, @keyframeName) {
.make-motion(@className, @keyframeName);
.@{className}-enter, .@{className}-appear {
opacity: 0;
animation-timing-function: @ease-in-out;
}
.@{className}-leave {
animation-timing-function: @ease-in-out;
}
}
.slide-motion(slide-up, ivuSlideUp);
.slide-motion(slide-down, ivuSlideDown);
.slide-motion(slide-left, ivuSlideLeft);
.slide-motion(slide-right, ivuSlideRight);
@keyframes ivuSlideUpIn {
0% {
opacity: 0;
transform-origin: 0% 0%;
transform: scaleY(.8);
}
100% {
opacity: 1;
transform-origin: 0% 0%;
transform: scaleY(1);
}
}
@keyframes ivuSlideUpOut {
0% {
opacity: 1;
transform-origin: 0% 0%;
transform: scaleY(1);
}
100% {
opacity: 0;
transform-origin: 0% 0%;
transform: scaleY(.8);
}
}
@keyframes ivuSlideDownIn {
0% {
opacity: 0;
transform-origin: 100% 100%;
transform: scaleY(.8);
}
100% {
opacity: 1;
transform-origin: 100% 100%;
transform: scaleY(1);
}
}
@keyframes ivuSlideDownOut {
0% {
opacity: 1;
transform-origin: 100% 100%;
transform: scaleY(1);
}
100% {
opacity: 0;
transform-origin: 100% 100%;
transform: scaleY(.8);
}
}
@keyframes ivuSlideLeftIn {
0% {
opacity: 0;
transform-origin: 0% 0%;
transform: scaleX(.8);
}
100% {
opacity: 1;
transform-origin: 0% 0%;
transform: scaleX(1);
}
}
@keyframes ivuSlideLeftOut {
0% {
opacity: 1;
transform-origin: 0% 0%;
transform: scaleX(1);
}
100% {
opacity: 0;
transform-origin: 0% 0%;
transform: scaleX(.8);
}
}
@keyframes ivuSlideRightIn {
0% {
opacity: 0;
transform-origin: 100% 0%;
transform: scaleX(.8);
}
100% {
opacity: 1;
transform-origin: 100% 0%;
transform: scaleX(1);
}
}
@keyframes ivuSlideRightOut {
0% {
opacity: 1;
transform-origin: 100% 0%;
transform: scaleX(1);
}
100% {
opacity: 0;
transform-origin: 100% 0%;
transform: scaleX(.8);
}
}

View file

@ -0,0 +1,44 @@
.ivu-article {
h1{
font-size: 28px;
}
h2{
font-size: 22px;
}
h3{
font-size: 18px;
}
h4{
font-size: 14px;
}
h5{
font-size: 12px;
}
h6{
font-size: 12px;
}
blockquote{
padding: 5px 5px 3px 10px;
line-height: 1.5;
border-left: 4px solid #ddd;
margin-bottom: 20px;
color: #666;
font-size: 14px;
}
ul{
padding-left: 40px;
list-style-type: disc;
}
li{
margin-bottom: 5px;
}
ul ul, ol ul{
list-style-type: circle;
}
p{
margin: 5px;
}
}

View file

@ -0,0 +1,77 @@
@import "normalize";
* {
box-sizing: border-box;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
*:before,
*:after {
box-sizing: border-box;
}
body {
font-family: @font-family;
font-size: @font-size-base;
line-height: @line-height-base;
color: @text-color;
background-color: @body-background;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, form, fieldset, legend, input, textarea, p, blockquote, th, td, hr, button, article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
margin: 0;
padding: 0;
}
button, input, select, textarea {
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
ul,
ol {
list-style: none;
}
input::-ms-clear, input::-ms-reveal {
display: none;
}
a {
color: @link-color;
background: transparent;
text-decoration: none;
outline: none;
cursor: pointer;
.transition(color @transition-time ease);
&:hover {
color: @link-hover-color;
}
&:active {
color: @link-active-color;
}
&:active,
&:hover {
outline: 0;
text-decoration: none;
}
&[disabled] {
color: #ccc;
cursor: not-allowed;
pointer-events: none;
}
}
code,
kbd,
pre,
samp {
font-family: @code-family;
}

View file

@ -0,0 +1,31 @@
// Ionicons Font Path
// --------------------------
@font-face {
font-family: @ionicons-font-family;
src:url("@{ionicons-font-path}/ionicons.eot?v=@{ionicons-version}");
src:url("@{ionicons-font-path}/ionicons.eot?v=@{ionicons-version}#iefix") format("embedded-opentype"),
url("@{ionicons-font-path}/ionicons.ttf?v=@{ionicons-version}") format("truetype"),
url("@{ionicons-font-path}/ionicons.woff?v=@{ionicons-version}") format("woff"),
url("@{ionicons-font-path}/ionicons.svg?v=@{ionicons-version}#Ionicons") format("svg");
font-weight: normal;
font-style: normal;
}
.ivu-icon() {
display: inline-block;
font-family: @ionicons-font-family;
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
text-rendering: auto;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.ivu-icon {
.ivu-icon();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,747 @@
/*
Ionicons, v2.0.0
Created by Ben Sperry for the Ionic Framework, http://ionicons.com/
https://twitter.com/benjsperry https://twitter.com/ionicframework
MIT License: https://github.com/driftyco/ionicons
*/
// Ionicons Variables
// --------------------------
@ionicons-font-path: "./fonts";
@ionicons-font-family: "Ionicons";
@ionicons-version: "2.0.0";
@ionicons-prefix: ivu-icon-;
@ionicon-var-alert: "\f101";
@ionicon-var-alert-circled: "\f100";
@ionicon-var-android-add: "\f2c7";
@ionicon-var-android-add-circle: "\f359";
@ionicon-var-android-alarm-clock: "\f35a";
@ionicon-var-android-alert: "\f35b";
@ionicon-var-android-apps: "\f35c";
@ionicon-var-android-archive: "\f2c9";
@ionicon-var-android-arrow-back: "\f2ca";
@ionicon-var-android-arrow-down: "\f35d";
@ionicon-var-android-arrow-dropdown: "\f35f";
@ionicon-var-android-arrow-dropdown-circle: "\f35e";
@ionicon-var-android-arrow-dropleft: "\f361";
@ionicon-var-android-arrow-dropleft-circle: "\f360";
@ionicon-var-android-arrow-dropright: "\f363";
@ionicon-var-android-arrow-dropright-circle: "\f362";
@ionicon-var-android-arrow-dropup: "\f365";
@ionicon-var-android-arrow-dropup-circle: "\f364";
@ionicon-var-android-arrow-forward: "\f30f";
@ionicon-var-android-arrow-up: "\f366";
@ionicon-var-android-attach: "\f367";
@ionicon-var-android-bar: "\f368";
@ionicon-var-android-bicycle: "\f369";
@ionicon-var-android-boat: "\f36a";
@ionicon-var-android-bookmark: "\f36b";
@ionicon-var-android-bulb: "\f36c";
@ionicon-var-android-bus: "\f36d";
@ionicon-var-android-calendar: "\f2d1";
@ionicon-var-android-call: "\f2d2";
@ionicon-var-android-camera: "\f2d3";
@ionicon-var-android-cancel: "\f36e";
@ionicon-var-android-car: "\f36f";
@ionicon-var-android-cart: "\f370";
@ionicon-var-android-chat: "\f2d4";
@ionicon-var-android-checkbox: "\f374";
@ionicon-var-android-checkbox-blank: "\f371";
@ionicon-var-android-checkbox-outline: "\f373";
@ionicon-var-android-checkbox-outline-blank: "\f372";
@ionicon-var-android-checkmark-circle: "\f375";
@ionicon-var-android-clipboard: "\f376";
@ionicon-var-android-close: "\f2d7";
@ionicon-var-android-cloud: "\f37a";
@ionicon-var-android-cloud-circle: "\f377";
@ionicon-var-android-cloud-done: "\f378";
@ionicon-var-android-cloud-outline: "\f379";
@ionicon-var-android-color-palette: "\f37b";
@ionicon-var-android-compass: "\f37c";
@ionicon-var-android-contact: "\f2d8";
@ionicon-var-android-contacts: "\f2d9";
@ionicon-var-android-contract: "\f37d";
@ionicon-var-android-create: "\f37e";
@ionicon-var-android-delete: "\f37f";
@ionicon-var-android-desktop: "\f380";
@ionicon-var-android-document: "\f381";
@ionicon-var-android-done: "\f383";
@ionicon-var-android-done-all: "\f382";
@ionicon-var-android-download: "\f2dd";
@ionicon-var-android-drafts: "\f384";
@ionicon-var-android-exit: "\f385";
@ionicon-var-android-expand: "\f386";
@ionicon-var-android-favorite: "\f388";
@ionicon-var-android-favorite-outline: "\f387";
@ionicon-var-android-film: "\f389";
@ionicon-var-android-folder: "\f2e0";
@ionicon-var-android-folder-open: "\f38a";
@ionicon-var-android-funnel: "\f38b";
@ionicon-var-android-globe: "\f38c";
@ionicon-var-android-hand: "\f2e3";
@ionicon-var-android-hangout: "\f38d";
@ionicon-var-android-happy: "\f38e";
@ionicon-var-android-home: "\f38f";
@ionicon-var-android-image: "\f2e4";
@ionicon-var-android-laptop: "\f390";
@ionicon-var-android-list: "\f391";
@ionicon-var-android-locate: "\f2e9";
@ionicon-var-android-lock: "\f392";
@ionicon-var-android-mail: "\f2eb";
@ionicon-var-android-map: "\f393";
@ionicon-var-android-menu: "\f394";
@ionicon-var-android-microphone: "\f2ec";
@ionicon-var-android-microphone-off: "\f395";
@ionicon-var-android-more-horizontal: "\f396";
@ionicon-var-android-more-vertical: "\f397";
@ionicon-var-android-navigate: "\f398";
@ionicon-var-android-notifications: "\f39b";
@ionicon-var-android-notifications-none: "\f399";
@ionicon-var-android-notifications-off: "\f39a";
@ionicon-var-android-open: "\f39c";
@ionicon-var-android-options: "\f39d";
@ionicon-var-android-people: "\f39e";
@ionicon-var-android-person: "\f3a0";
@ionicon-var-android-person-add: "\f39f";
@ionicon-var-android-phone-landscape: "\f3a1";
@ionicon-var-android-phone-portrait: "\f3a2";
@ionicon-var-android-pin: "\f3a3";
@ionicon-var-android-plane: "\f3a4";
@ionicon-var-android-playstore: "\f2f0";
@ionicon-var-android-print: "\f3a5";
@ionicon-var-android-radio-button-off: "\f3a6";
@ionicon-var-android-radio-button-on: "\f3a7";
@ionicon-var-android-refresh: "\f3a8";
@ionicon-var-android-remove: "\f2f4";
@ionicon-var-android-remove-circle: "\f3a9";
@ionicon-var-android-restaurant: "\f3aa";
@ionicon-var-android-sad: "\f3ab";
@ionicon-var-android-search: "\f2f5";
@ionicon-var-android-send: "\f2f6";
@ionicon-var-android-settings: "\f2f7";
@ionicon-var-android-share: "\f2f8";
@ionicon-var-android-share-alt: "\f3ac";
@ionicon-var-android-star: "\f2fc";
@ionicon-var-android-star-half: "\f3ad";
@ionicon-var-android-star-outline: "\f3ae";
@ionicon-var-android-stopwatch: "\f2fd";
@ionicon-var-android-subway: "\f3af";
@ionicon-var-android-sunny: "\f3b0";
@ionicon-var-android-sync: "\f3b1";
@ionicon-var-android-textsms: "\f3b2";
@ionicon-var-android-time: "\f3b3";
@ionicon-var-android-train: "\f3b4";
@ionicon-var-android-unlock: "\f3b5";
@ionicon-var-android-upload: "\f3b6";
@ionicon-var-android-volume-down: "\f3b7";
@ionicon-var-android-volume-mute: "\f3b8";
@ionicon-var-android-volume-off: "\f3b9";
@ionicon-var-android-volume-up: "\f3ba";
@ionicon-var-android-walk: "\f3bb";
@ionicon-var-android-warning: "\f3bc";
@ionicon-var-android-watch: "\f3bd";
@ionicon-var-android-wifi: "\f305";
@ionicon-var-aperture: "\f313";
@ionicon-var-archive: "\f102";
@ionicon-var-arrow-down-a: "\f103";
@ionicon-var-arrow-down-b: "\f104";
@ionicon-var-arrow-down-c: "\f105";
@ionicon-var-arrow-expand: "\f25e";
@ionicon-var-arrow-graph-down-left: "\f25f";
@ionicon-var-arrow-graph-down-right: "\f260";
@ionicon-var-arrow-graph-up-left: "\f261";
@ionicon-var-arrow-graph-up-right: "\f262";
@ionicon-var-arrow-left-a: "\f106";
@ionicon-var-arrow-left-b: "\f107";
@ionicon-var-arrow-left-c: "\f108";
@ionicon-var-arrow-move: "\f263";
@ionicon-var-arrow-resize: "\f264";
@ionicon-var-arrow-return-left: "\f265";
@ionicon-var-arrow-return-right: "\f266";
@ionicon-var-arrow-right-a: "\f109";
@ionicon-var-arrow-right-b: "\f10a";
@ionicon-var-arrow-right-c: "\f10b";
@ionicon-var-arrow-shrink: "\f267";
@ionicon-var-arrow-swap: "\f268";
@ionicon-var-arrow-up-a: "\f10c";
@ionicon-var-arrow-up-b: "\f10d";
@ionicon-var-arrow-up-c: "\f10e";
@ionicon-var-asterisk: "\f314";
@ionicon-var-at: "\f10f";
@ionicon-var-backspace: "\f3bf";
@ionicon-var-backspace-outline: "\f3be";
@ionicon-var-bag: "\f110";
@ionicon-var-battery-charging: "\f111";
@ionicon-var-battery-empty: "\f112";
@ionicon-var-battery-full: "\f113";
@ionicon-var-battery-half: "\f114";
@ionicon-var-battery-low: "\f115";
@ionicon-var-beaker: "\f269";
@ionicon-var-beer: "\f26a";
@ionicon-var-bluetooth: "\f116";
@ionicon-var-bonfire: "\f315";
@ionicon-var-bookmark: "\f26b";
@ionicon-var-bowtie: "\f3c0";
@ionicon-var-briefcase: "\f26c";
@ionicon-var-bug: "\f2be";
@ionicon-var-calculator: "\f26d";
@ionicon-var-calendar: "\f117";
@ionicon-var-camera: "\f118";
@ionicon-var-card: "\f119";
@ionicon-var-cash: "\f316";
@ionicon-var-chatbox: "\f11b";
@ionicon-var-chatbox-working: "\f11a";
@ionicon-var-chatboxes: "\f11c";
@ionicon-var-chatbubble: "\f11e";
@ionicon-var-chatbubble-working: "\f11d";
@ionicon-var-chatbubbles: "\f11f";
@ionicon-var-checkmark: "\f122";
@ionicon-var-checkmark-circled: "\f120";
@ionicon-var-checkmark-round: "\f121";
@ionicon-var-chevron-down: "\f123";
@ionicon-var-chevron-left: "\f124";
@ionicon-var-chevron-right: "\f125";
@ionicon-var-chevron-up: "\f126";
@ionicon-var-clipboard: "\f127";
@ionicon-var-clock: "\f26e";
@ionicon-var-close: "\f12a";
@ionicon-var-close-circled: "\f128";
@ionicon-var-close-round: "\f129";
@ionicon-var-closed-captioning: "\f317";
@ionicon-var-cloud: "\f12b";
@ionicon-var-code: "\f271";
@ionicon-var-code-download: "\f26f";
@ionicon-var-code-working: "\f270";
@ionicon-var-coffee: "\f272";
@ionicon-var-compass: "\f273";
@ionicon-var-compose: "\f12c";
@ionicon-var-connection-bars: "\f274";
@ionicon-var-contrast: "\f275";
@ionicon-var-crop: "\f3c1";
@ionicon-var-cube: "\f318";
@ionicon-var-disc: "\f12d";
@ionicon-var-document: "\f12f";
@ionicon-var-document-text: "\f12e";
@ionicon-var-drag: "\f130";
@ionicon-var-earth: "\f276";
@ionicon-var-easel: "\f3c2";
@ionicon-var-edit: "\f2bf";
@ionicon-var-egg: "\f277";
@ionicon-var-eject: "\f131";
@ionicon-var-email: "\f132";
@ionicon-var-email-unread: "\f3c3";
@ionicon-var-erlenmeyer-flask: "\f3c5";
@ionicon-var-erlenmeyer-flask-bubbles: "\f3c4";
@ionicon-var-eye: "\f133";
@ionicon-var-eye-disabled: "\f306";
@ionicon-var-female: "\f278";
@ionicon-var-filing: "\f134";
@ionicon-var-film-marker: "\f135";
@ionicon-var-fireball: "\f319";
@ionicon-var-flag: "\f279";
@ionicon-var-flame: "\f31a";
@ionicon-var-flash: "\f137";
@ionicon-var-flash-off: "\f136";
@ionicon-var-folder: "\f139";
@ionicon-var-fork: "\f27a";
@ionicon-var-fork-repo: "\f2c0";
@ionicon-var-forward: "\f13a";
@ionicon-var-funnel: "\f31b";
@ionicon-var-gear-a: "\f13d";
@ionicon-var-gear-b: "\f13e";
@ionicon-var-grid: "\f13f";
@ionicon-var-hammer: "\f27b";
@ionicon-var-happy: "\f31c";
@ionicon-var-happy-outline: "\f3c6";
@ionicon-var-headphone: "\f140";
@ionicon-var-heart: "\f141";
@ionicon-var-heart-broken: "\f31d";
@ionicon-var-help: "\f143";
@ionicon-var-help-buoy: "\f27c";
@ionicon-var-help-circled: "\f142";
@ionicon-var-home: "\f144";
@ionicon-var-icecream: "\f27d";
@ionicon-var-image: "\f147";
@ionicon-var-images: "\f148";
@ionicon-var-information: "\f14a";
@ionicon-var-information-circled: "\f149";
@ionicon-var-ionic: "\f14b";
@ionicon-var-ios-alarm: "\f3c8";
@ionicon-var-ios-alarm-outline: "\f3c7";
@ionicon-var-ios-albums: "\f3ca";
@ionicon-var-ios-albums-outline: "\f3c9";
@ionicon-var-ios-americanfootball: "\f3cc";
@ionicon-var-ios-americanfootball-outline: "\f3cb";
@ionicon-var-ios-analytics: "\f3ce";
@ionicon-var-ios-analytics-outline: "\f3cd";
@ionicon-var-ios-arrow-back: "\f3cf";
@ionicon-var-ios-arrow-down: "\f3d0";
@ionicon-var-ios-arrow-forward: "\f3d1";
@ionicon-var-ios-arrow-left: "\f3d2";
@ionicon-var-ios-arrow-right: "\f3d3";
@ionicon-var-ios-arrow-thin-down: "\f3d4";
@ionicon-var-ios-arrow-thin-left: "\f3d5";
@ionicon-var-ios-arrow-thin-right: "\f3d6";
@ionicon-var-ios-arrow-thin-up: "\f3d7";
@ionicon-var-ios-arrow-up: "\f3d8";
@ionicon-var-ios-at: "\f3da";
@ionicon-var-ios-at-outline: "\f3d9";
@ionicon-var-ios-barcode: "\f3dc";
@ionicon-var-ios-barcode-outline: "\f3db";
@ionicon-var-ios-baseball: "\f3de";
@ionicon-var-ios-baseball-outline: "\f3dd";
@ionicon-var-ios-basketball: "\f3e0";
@ionicon-var-ios-basketball-outline: "\f3df";
@ionicon-var-ios-bell: "\f3e2";
@ionicon-var-ios-bell-outline: "\f3e1";
@ionicon-var-ios-body: "\f3e4";
@ionicon-var-ios-body-outline: "\f3e3";
@ionicon-var-ios-bolt: "\f3e6";
@ionicon-var-ios-bolt-outline: "\f3e5";
@ionicon-var-ios-book: "\f3e8";
@ionicon-var-ios-book-outline: "\f3e7";
@ionicon-var-ios-bookmarks: "\f3ea";
@ionicon-var-ios-bookmarks-outline: "\f3e9";
@ionicon-var-ios-box: "\f3ec";
@ionicon-var-ios-box-outline: "\f3eb";
@ionicon-var-ios-briefcase: "\f3ee";
@ionicon-var-ios-briefcase-outline: "\f3ed";
@ionicon-var-ios-browsers: "\f3f0";
@ionicon-var-ios-browsers-outline: "\f3ef";
@ionicon-var-ios-calculator: "\f3f2";
@ionicon-var-ios-calculator-outline: "\f3f1";
@ionicon-var-ios-calendar: "\f3f4";
@ionicon-var-ios-calendar-outline: "\f3f3";
@ionicon-var-ios-camera: "\f3f6";
@ionicon-var-ios-camera-outline: "\f3f5";
@ionicon-var-ios-cart: "\f3f8";
@ionicon-var-ios-cart-outline: "\f3f7";
@ionicon-var-ios-chatboxes: "\f3fa";
@ionicon-var-ios-chatboxes-outline: "\f3f9";
@ionicon-var-ios-chatbubble: "\f3fc";
@ionicon-var-ios-chatbubble-outline: "\f3fb";
@ionicon-var-ios-checkmark: "\f3ff";
@ionicon-var-ios-checkmark-empty: "\f3fd";
@ionicon-var-ios-checkmark-outline: "\f3fe";
@ionicon-var-ios-circle-filled: "\f400";
@ionicon-var-ios-circle-outline: "\f401";
@ionicon-var-ios-clock: "\f403";
@ionicon-var-ios-clock-outline: "\f402";
@ionicon-var-ios-close: "\f406";
@ionicon-var-ios-close-empty: "\f404";
@ionicon-var-ios-close-outline: "\f405";
@ionicon-var-ios-cloud: "\f40c";
@ionicon-var-ios-cloud-download: "\f408";
@ionicon-var-ios-cloud-download-outline: "\f407";
@ionicon-var-ios-cloud-outline: "\f409";
@ionicon-var-ios-cloud-upload: "\f40b";
@ionicon-var-ios-cloud-upload-outline: "\f40a";
@ionicon-var-ios-cloudy: "\f410";
@ionicon-var-ios-cloudy-night: "\f40e";
@ionicon-var-ios-cloudy-night-outline: "\f40d";
@ionicon-var-ios-cloudy-outline: "\f40f";
@ionicon-var-ios-cog: "\f412";
@ionicon-var-ios-cog-outline: "\f411";
@ionicon-var-ios-color-filter: "\f414";
@ionicon-var-ios-color-filter-outline: "\f413";
@ionicon-var-ios-color-wand: "\f416";
@ionicon-var-ios-color-wand-outline: "\f415";
@ionicon-var-ios-compose: "\f418";
@ionicon-var-ios-compose-outline: "\f417";
@ionicon-var-ios-contact: "\f41a";
@ionicon-var-ios-contact-outline: "\f419";
@ionicon-var-ios-copy: "\f41c";
@ionicon-var-ios-copy-outline: "\f41b";
@ionicon-var-ios-crop: "\f41e";
@ionicon-var-ios-crop-strong: "\f41d";
@ionicon-var-ios-download: "\f420";
@ionicon-var-ios-download-outline: "\f41f";
@ionicon-var-ios-drag: "\f421";
@ionicon-var-ios-email: "\f423";
@ionicon-var-ios-email-outline: "\f422";
@ionicon-var-ios-eye: "\f425";
@ionicon-var-ios-eye-outline: "\f424";
@ionicon-var-ios-fastforward: "\f427";
@ionicon-var-ios-fastforward-outline: "\f426";
@ionicon-var-ios-filing: "\f429";
@ionicon-var-ios-filing-outline: "\f428";
@ionicon-var-ios-film: "\f42b";
@ionicon-var-ios-film-outline: "\f42a";
@ionicon-var-ios-flag: "\f42d";
@ionicon-var-ios-flag-outline: "\f42c";
@ionicon-var-ios-flame: "\f42f";
@ionicon-var-ios-flame-outline: "\f42e";
@ionicon-var-ios-flask: "\f431";
@ionicon-var-ios-flask-outline: "\f430";
@ionicon-var-ios-flower: "\f433";
@ionicon-var-ios-flower-outline: "\f432";
@ionicon-var-ios-folder: "\f435";
@ionicon-var-ios-folder-outline: "\f434";
@ionicon-var-ios-football: "\f437";
@ionicon-var-ios-football-outline: "\f436";
@ionicon-var-ios-game-controller-a: "\f439";
@ionicon-var-ios-game-controller-a-outline: "\f438";
@ionicon-var-ios-game-controller-b: "\f43b";
@ionicon-var-ios-game-controller-b-outline: "\f43a";
@ionicon-var-ios-gear: "\f43d";
@ionicon-var-ios-gear-outline: "\f43c";
@ionicon-var-ios-glasses: "\f43f";
@ionicon-var-ios-glasses-outline: "\f43e";
@ionicon-var-ios-grid-view: "\f441";
@ionicon-var-ios-grid-view-outline: "\f440";
@ionicon-var-ios-heart: "\f443";
@ionicon-var-ios-heart-outline: "\f442";
@ionicon-var-ios-help: "\f446";
@ionicon-var-ios-help-empty: "\f444";
@ionicon-var-ios-help-outline: "\f445";
@ionicon-var-ios-home: "\f448";
@ionicon-var-ios-home-outline: "\f447";
@ionicon-var-ios-infinite: "\f44a";
@ionicon-var-ios-infinite-outline: "\f449";
@ionicon-var-ios-information: "\f44d";
@ionicon-var-ios-information-empty: "\f44b";
@ionicon-var-ios-information-outline: "\f44c";
@ionicon-var-ios-ionic-outline: "\f44e";
@ionicon-var-ios-keypad: "\f450";
@ionicon-var-ios-keypad-outline: "\f44f";
@ionicon-var-ios-lightbulb: "\f452";
@ionicon-var-ios-lightbulb-outline: "\f451";
@ionicon-var-ios-list: "\f454";
@ionicon-var-ios-list-outline: "\f453";
@ionicon-var-ios-location: "\f456";
@ionicon-var-ios-location-outline: "\f455";
@ionicon-var-ios-locked: "\f458";
@ionicon-var-ios-locked-outline: "\f457";
@ionicon-var-ios-loop: "\f45a";
@ionicon-var-ios-loop-strong: "\f459";
@ionicon-var-ios-medical: "\f45c";
@ionicon-var-ios-medical-outline: "\f45b";
@ionicon-var-ios-medkit: "\f45e";
@ionicon-var-ios-medkit-outline: "\f45d";
@ionicon-var-ios-mic: "\f461";
@ionicon-var-ios-mic-off: "\f45f";
@ionicon-var-ios-mic-outline: "\f460";
@ionicon-var-ios-minus: "\f464";
@ionicon-var-ios-minus-empty: "\f462";
@ionicon-var-ios-minus-outline: "\f463";
@ionicon-var-ios-monitor: "\f466";
@ionicon-var-ios-monitor-outline: "\f465";
@ionicon-var-ios-moon: "\f468";
@ionicon-var-ios-moon-outline: "\f467";
@ionicon-var-ios-more: "\f46a";
@ionicon-var-ios-more-outline: "\f469";
@ionicon-var-ios-musical-note: "\f46b";
@ionicon-var-ios-musical-notes: "\f46c";
@ionicon-var-ios-navigate: "\f46e";
@ionicon-var-ios-navigate-outline: "\f46d";
@ionicon-var-ios-nutrition: "\f470";
@ionicon-var-ios-nutrition-outline: "\f46f";
@ionicon-var-ios-paper: "\f472";
@ionicon-var-ios-paper-outline: "\f471";
@ionicon-var-ios-paperplane: "\f474";
@ionicon-var-ios-paperplane-outline: "\f473";
@ionicon-var-ios-partlysunny: "\f476";
@ionicon-var-ios-partlysunny-outline: "\f475";
@ionicon-var-ios-pause: "\f478";
@ionicon-var-ios-pause-outline: "\f477";
@ionicon-var-ios-paw: "\f47a";
@ionicon-var-ios-paw-outline: "\f479";
@ionicon-var-ios-people: "\f47c";
@ionicon-var-ios-people-outline: "\f47b";
@ionicon-var-ios-person: "\f47e";
@ionicon-var-ios-person-outline: "\f47d";
@ionicon-var-ios-personadd: "\f480";
@ionicon-var-ios-personadd-outline: "\f47f";
@ionicon-var-ios-photos: "\f482";
@ionicon-var-ios-photos-outline: "\f481";
@ionicon-var-ios-pie: "\f484";
@ionicon-var-ios-pie-outline: "\f483";
@ionicon-var-ios-pint: "\f486";
@ionicon-var-ios-pint-outline: "\f485";
@ionicon-var-ios-play: "\f488";
@ionicon-var-ios-play-outline: "\f487";
@ionicon-var-ios-plus: "\f48b";
@ionicon-var-ios-plus-empty: "\f489";
@ionicon-var-ios-plus-outline: "\f48a";
@ionicon-var-ios-pricetag: "\f48d";
@ionicon-var-ios-pricetag-outline: "\f48c";
@ionicon-var-ios-pricetags: "\f48f";
@ionicon-var-ios-pricetags-outline: "\f48e";
@ionicon-var-ios-printer: "\f491";
@ionicon-var-ios-printer-outline: "\f490";
@ionicon-var-ios-pulse: "\f493";
@ionicon-var-ios-pulse-strong: "\f492";
@ionicon-var-ios-rainy: "\f495";
@ionicon-var-ios-rainy-outline: "\f494";
@ionicon-var-ios-recording: "\f497";
@ionicon-var-ios-recording-outline: "\f496";
@ionicon-var-ios-redo: "\f499";
@ionicon-var-ios-redo-outline: "\f498";
@ionicon-var-ios-refresh: "\f49c";
@ionicon-var-ios-refresh-empty: "\f49a";
@ionicon-var-ios-refresh-outline: "\f49b";
@ionicon-var-ios-reload: "\f49d";
@ionicon-var-ios-reverse-camera: "\f49f";
@ionicon-var-ios-reverse-camera-outline: "\f49e";
@ionicon-var-ios-rewind: "\f4a1";
@ionicon-var-ios-rewind-outline: "\f4a0";
@ionicon-var-ios-rose: "\f4a3";
@ionicon-var-ios-rose-outline: "\f4a2";
@ionicon-var-ios-search: "\f4a5";
@ionicon-var-ios-search-strong: "\f4a4";
@ionicon-var-ios-settings: "\f4a7";
@ionicon-var-ios-settings-strong: "\f4a6";
@ionicon-var-ios-shuffle: "\f4a9";
@ionicon-var-ios-shuffle-strong: "\f4a8";
@ionicon-var-ios-skipbackward: "\f4ab";
@ionicon-var-ios-skipbackward-outline: "\f4aa";
@ionicon-var-ios-skipforward: "\f4ad";
@ionicon-var-ios-skipforward-outline: "\f4ac";
@ionicon-var-ios-snowy: "\f4ae";
@ionicon-var-ios-speedometer: "\f4b0";
@ionicon-var-ios-speedometer-outline: "\f4af";
@ionicon-var-ios-star: "\f4b3";
@ionicon-var-ios-star-half: "\f4b1";
@ionicon-var-ios-star-outline: "\f4b2";
@ionicon-var-ios-stopwatch: "\f4b5";
@ionicon-var-ios-stopwatch-outline: "\f4b4";
@ionicon-var-ios-sunny: "\f4b7";
@ionicon-var-ios-sunny-outline: "\f4b6";
@ionicon-var-ios-telephone: "\f4b9";
@ionicon-var-ios-telephone-outline: "\f4b8";
@ionicon-var-ios-tennisball: "\f4bb";
@ionicon-var-ios-tennisball-outline: "\f4ba";
@ionicon-var-ios-thunderstorm: "\f4bd";
@ionicon-var-ios-thunderstorm-outline: "\f4bc";
@ionicon-var-ios-time: "\f4bf";
@ionicon-var-ios-time-outline: "\f4be";
@ionicon-var-ios-timer: "\f4c1";
@ionicon-var-ios-timer-outline: "\f4c0";
@ionicon-var-ios-toggle: "\f4c3";
@ionicon-var-ios-toggle-outline: "\f4c2";
@ionicon-var-ios-trash: "\f4c5";
@ionicon-var-ios-trash-outline: "\f4c4";
@ionicon-var-ios-undo: "\f4c7";
@ionicon-var-ios-undo-outline: "\f4c6";
@ionicon-var-ios-unlocked: "\f4c9";
@ionicon-var-ios-unlocked-outline: "\f4c8";
@ionicon-var-ios-upload: "\f4cb";
@ionicon-var-ios-upload-outline: "\f4ca";
@ionicon-var-ios-videocam: "\f4cd";
@ionicon-var-ios-videocam-outline: "\f4cc";
@ionicon-var-ios-volume-high: "\f4ce";
@ionicon-var-ios-volume-low: "\f4cf";
@ionicon-var-ios-wineglass: "\f4d1";
@ionicon-var-ios-wineglass-outline: "\f4d0";
@ionicon-var-ios-world: "\f4d3";
@ionicon-var-ios-world-outline: "\f4d2";
@ionicon-var-ipad: "\f1f9";
@ionicon-var-iphone: "\f1fa";
@ionicon-var-ipod: "\f1fb";
@ionicon-var-jet: "\f295";
@ionicon-var-key: "\f296";
@ionicon-var-knife: "\f297";
@ionicon-var-laptop: "\f1fc";
@ionicon-var-leaf: "\f1fd";
@ionicon-var-levels: "\f298";
@ionicon-var-lightbulb: "\f299";
@ionicon-var-link: "\f1fe";
@ionicon-var-load-a: "\f29a";
@ionicon-var-load-b: "\f29b";
@ionicon-var-load-c: "\f29c";
@ionicon-var-load-d: "\f29d";
@ionicon-var-location: "\f1ff";
@ionicon-var-lock-combination: "\f4d4";
@ionicon-var-locked: "\f200";
@ionicon-var-log-in: "\f29e";
@ionicon-var-log-out: "\f29f";
@ionicon-var-loop: "\f201";
@ionicon-var-magnet: "\f2a0";
@ionicon-var-male: "\f2a1";
@ionicon-var-man: "\f202";
@ionicon-var-map: "\f203";
@ionicon-var-medkit: "\f2a2";
@ionicon-var-merge: "\f33f";
@ionicon-var-mic-a: "\f204";
@ionicon-var-mic-b: "\f205";
@ionicon-var-mic-c: "\f206";
@ionicon-var-minus: "\f209";
@ionicon-var-minus-circled: "\f207";
@ionicon-var-minus-round: "\f208";
@ionicon-var-model-s: "\f2c1";
@ionicon-var-monitor: "\f20a";
@ionicon-var-more: "\f20b";
@ionicon-var-mouse: "\f340";
@ionicon-var-music-note: "\f20c";
@ionicon-var-navicon: "\f20e";
@ionicon-var-navicon-round: "\f20d";
@ionicon-var-navigate: "\f2a3";
@ionicon-var-network: "\f341";
@ionicon-var-no-smoking: "\f2c2";
@ionicon-var-nuclear: "\f2a4";
@ionicon-var-outlet: "\f342";
@ionicon-var-paintbrush: "\f4d5";
@ionicon-var-paintbucket: "\f4d6";
@ionicon-var-paper-airplane: "\f2c3";
@ionicon-var-paperclip: "\f20f";
@ionicon-var-pause: "\f210";
@ionicon-var-person: "\f213";
@ionicon-var-person-add: "\f211";
@ionicon-var-person-stalker: "\f212";
@ionicon-var-pie-graph: "\f2a5";
@ionicon-var-pin: "\f2a6";
@ionicon-var-pinpoint: "\f2a7";
@ionicon-var-pizza: "\f2a8";
@ionicon-var-plane: "\f214";
@ionicon-var-planet: "\f343";
@ionicon-var-play: "\f215";
@ionicon-var-playstation: "\f30a";
@ionicon-var-plus: "\f218";
@ionicon-var-plus-circled: "\f216";
@ionicon-var-plus-round: "\f217";
@ionicon-var-podium: "\f344";
@ionicon-var-pound: "\f219";
@ionicon-var-power: "\f2a9";
@ionicon-var-pricetag: "\f2aa";
@ionicon-var-pricetags: "\f2ab";
@ionicon-var-printer: "\f21a";
@ionicon-var-pull-request: "\f345";
@ionicon-var-qr-scanner: "\f346";
@ionicon-var-quote: "\f347";
@ionicon-var-radio-waves: "\f2ac";
@ionicon-var-record: "\f21b";
@ionicon-var-refresh: "\f21c";
@ionicon-var-reply: "\f21e";
@ionicon-var-reply-all: "\f21d";
@ionicon-var-ribbon-a: "\f348";
@ionicon-var-ribbon-b: "\f349";
@ionicon-var-sad: "\f34a";
@ionicon-var-sad-outline: "\f4d7";
@ionicon-var-scissors: "\f34b";
@ionicon-var-search: "\f21f";
@ionicon-var-settings: "\f2ad";
@ionicon-var-share: "\f220";
@ionicon-var-shuffle: "\f221";
@ionicon-var-skip-backward: "\f222";
@ionicon-var-skip-forward: "\f223";
@ionicon-var-social-android: "\f225";
@ionicon-var-social-android-outline: "\f224";
@ionicon-var-social-angular: "\f4d9";
@ionicon-var-social-angular-outline: "\f4d8";
@ionicon-var-social-apple: "\f227";
@ionicon-var-social-apple-outline: "\f226";
@ionicon-var-social-bitcoin: "\f2af";
@ionicon-var-social-bitcoin-outline: "\f2ae";
@ionicon-var-social-buffer: "\f229";
@ionicon-var-social-buffer-outline: "\f228";
@ionicon-var-social-chrome: "\f4db";
@ionicon-var-social-chrome-outline: "\f4da";
@ionicon-var-social-codepen: "\f4dd";
@ionicon-var-social-codepen-outline: "\f4dc";
@ionicon-var-social-css3: "\f4df";
@ionicon-var-social-css3-outline: "\f4de";
@ionicon-var-social-designernews: "\f22b";
@ionicon-var-social-designernews-outline: "\f22a";
@ionicon-var-social-dribbble: "\f22d";
@ionicon-var-social-dribbble-outline: "\f22c";
@ionicon-var-social-dropbox: "\f22f";
@ionicon-var-social-dropbox-outline: "\f22e";
@ionicon-var-social-euro: "\f4e1";
@ionicon-var-social-euro-outline: "\f4e0";
@ionicon-var-social-facebook: "\f231";
@ionicon-var-social-facebook-outline: "\f230";
@ionicon-var-social-foursquare: "\f34d";
@ionicon-var-social-foursquare-outline: "\f34c";
@ionicon-var-social-freebsd-devil: "\f2c4";
@ionicon-var-social-github: "\f233";
@ionicon-var-social-github-outline: "\f232";
@ionicon-var-social-google: "\f34f";
@ionicon-var-social-google-outline: "\f34e";
@ionicon-var-social-googleplus: "\f235";
@ionicon-var-social-googleplus-outline: "\f234";
@ionicon-var-social-hackernews: "\f237";
@ionicon-var-social-hackernews-outline: "\f236";
@ionicon-var-social-html5: "\f4e3";
@ionicon-var-social-html5-outline: "\f4e2";
@ionicon-var-social-instagram: "\f351";
@ionicon-var-social-instagram-outline: "\f350";
@ionicon-var-social-javascript: "\f4e5";
@ionicon-var-social-javascript-outline: "\f4e4";
@ionicon-var-social-linkedin: "\f239";
@ionicon-var-social-linkedin-outline: "\f238";
@ionicon-var-social-markdown: "\f4e6";
@ionicon-var-social-nodejs: "\f4e7";
@ionicon-var-social-octocat: "\f4e8";
@ionicon-var-social-pinterest: "\f2b1";
@ionicon-var-social-pinterest-outline: "\f2b0";
@ionicon-var-social-python: "\f4e9";
@ionicon-var-social-reddit: "\f23b";
@ionicon-var-social-reddit-outline: "\f23a";
@ionicon-var-social-rss: "\f23d";
@ionicon-var-social-rss-outline: "\f23c";
@ionicon-var-social-sass: "\f4ea";
@ionicon-var-social-skype: "\f23f";
@ionicon-var-social-skype-outline: "\f23e";
@ionicon-var-social-snapchat: "\f4ec";
@ionicon-var-social-snapchat-outline: "\f4eb";
@ionicon-var-social-tumblr: "\f241";
@ionicon-var-social-tumblr-outline: "\f240";
@ionicon-var-social-tux: "\f2c5";
@ionicon-var-social-twitch: "\f4ee";
@ionicon-var-social-twitch-outline: "\f4ed";
@ionicon-var-social-twitter: "\f243";
@ionicon-var-social-twitter-outline: "\f242";
@ionicon-var-social-usd: "\f353";
@ionicon-var-social-usd-outline: "\f352";
@ionicon-var-social-vimeo: "\f245";
@ionicon-var-social-vimeo-outline: "\f244";
@ionicon-var-social-whatsapp: "\f4f0";
@ionicon-var-social-whatsapp-outline: "\f4ef";
@ionicon-var-social-windows: "\f247";
@ionicon-var-social-windows-outline: "\f246";
@ionicon-var-social-wordpress: "\f249";
@ionicon-var-social-wordpress-outline: "\f248";
@ionicon-var-social-yahoo: "\f24b";
@ionicon-var-social-yahoo-outline: "\f24a";
@ionicon-var-social-yen: "\f4f2";
@ionicon-var-social-yen-outline: "\f4f1";
@ionicon-var-social-youtube: "\f24d";
@ionicon-var-social-youtube-outline: "\f24c";
@ionicon-var-soup-can: "\f4f4";
@ionicon-var-soup-can-outline: "\f4f3";
@ionicon-var-speakerphone: "\f2b2";
@ionicon-var-speedometer: "\f2b3";
@ionicon-var-spoon: "\f2b4";
@ionicon-var-star: "\f24e";
@ionicon-var-stats-bars: "\f2b5";
@ionicon-var-steam: "\f30b";
@ionicon-var-stop: "\f24f";
@ionicon-var-thermometer: "\f2b6";
@ionicon-var-thumbsdown: "\f250";
@ionicon-var-thumbsup: "\f251";
@ionicon-var-toggle: "\f355";
@ionicon-var-toggle-filled: "\f354";
@ionicon-var-transgender: "\f4f5";
@ionicon-var-trash-a: "\f252";
@ionicon-var-trash-b: "\f253";
@ionicon-var-trophy: "\f356";
@ionicon-var-tshirt: "\f4f7";
@ionicon-var-tshirt-outline: "\f4f6";
@ionicon-var-umbrella: "\f2b7";
@ionicon-var-university: "\f357";
@ionicon-var-unlocked: "\f254";
@ionicon-var-upload: "\f255";
@ionicon-var-usb: "\f2b8";
@ionicon-var-videocamera: "\f256";
@ionicon-var-volume-high: "\f257";
@ionicon-var-volume-low: "\f258";
@ionicon-var-volume-medium: "\f259";
@ionicon-var-volume-mute: "\f25a";
@ionicon-var-wand: "\f358";
@ionicon-var-waterdrop: "\f25b";
@ionicon-var-wifi: "\f25c";
@ionicon-var-wineglass: "\f2b9";
@ionicon-var-woman: "\f25d";
@ionicon-var-wrench: "\f2ba";
@ionicon-var-xbox: "\f30c";

Binary file not shown.

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 326 KiB

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,3 @@
@import "_ionicons-variables";
@import "_ionicons-font";
@import "_ionicons-icons";

View file

@ -0,0 +1,3 @@
@import "base";
@import "iconfont/ionicons";
@import "layout";

View file

@ -0,0 +1,54 @@
.@{row-prefix-cls} {
.make-row();
display: block;
&-flex {
display: flex;
flex-direction: row;
flex-wrap: wrap;
&:before,
&:after {
display: flex;
}
// x轴原点
&-start {
justify-content: flex-start;
}
// x轴居中
&-center {
justify-content: center;
}
// x轴反方向
&-end {
justify-content: flex-end;
}
// x轴平分
&-space-between {
justify-content: space-between;
}
// x轴有间隔地平分
&-space-around {
justify-content: space-around;
}
// 顶部对齐
&-top {
align-items: flex-start;
}
// 居中对齐
&-middle {
align-items: center;
}
// 底部对齐
&-bottom {
align-items: flex-end;
}
};
}
.@{col-prefix-cls} {
position: relative;
display: block;
}
.make-grid();

421
src/styles/common/normalize.less vendored Normal file
View file

@ -0,0 +1,421 @@
/* normalize.css v4.2.0 | MIT License | github.com/necolas/normalize.css */
/**
* 1. Change the default font family in all browsers (opinionated).
* 2. Correct the line height in all browsers.
* 3. Prevent adjustments of font size after orientation changes in IE and iOS.
*/
html {
font-family: sans-serif; /* 1 */
-ms-text-size-adjust: 100%; /* 3 */
-webkit-text-size-adjust: 100%; /* 3 */
}
/**
* Remove the margin in all browsers (opinionated).
*/
body {
margin: 0;
}
/* HTML5 display definitions
========================================================================== */
/**
* Add the correct display in IE 9-.
* 1. Add the correct display in Edge, IE, and Firefox.
* 2. Add the correct display in IE.
*/
article,
aside,
details, /* 1 */
figcaption,
figure,
footer,
header,
main, /* 2 */
menu,
nav,
section,
summary { /* 1 */
display: block;
}
/**
* Add the correct display in IE 9-.
*/
audio,
canvas,
progress,
video {
display: inline-block;
}
/**
* Add the correct display in iOS 4-7.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Add the correct display in IE 10-.
* 1. Add the correct display in IE.
*/
template, /* 1 */
[hidden] {
display: none;
}
/* Links
========================================================================== */
/**
* 1. Remove the gray background on active links in IE 10.
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
*/
a {
background-color: transparent; /* 1 */
-webkit-text-decoration-skip: objects; /* 2 */
}
/**
* Remove the outline on focused links when they are also active or hovered
* in all browsers (opinionated).
*/
a:active,
a:hover {
outline-width: 0;
}
/* Text-level semantics
========================================================================== */
/**
* 1. Remove the bottom border in Firefox 39-.
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Prevent the duplicate application of `bolder` by the next rule in Safari 6.
*/
b,
strong {
font-weight: inherit;
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* Add the correct font style in Android 4.3-.
*/
dfn {
font-style: italic;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/**
* Add the correct background and color in IE 9-.
*/
mark {
background-color: #ff0;
color: #000;
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10-.
*/
img {
border-style: none;
}
/**
* Hide the overflow in IE.
*/
svg:not(:root) {
overflow: hidden;
}
/* Grouping content
========================================================================== */
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
pre,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct margin in IE 8.
*/
figure {
margin: 1em 40px;
}
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/* Forms
========================================================================== */
/**
* 1. Change font properties to `inherit` in all browsers (opinionated).
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font: inherit; /* 1 */
margin: 0; /* 2 */
}
/**
* Restore the font weight unset by the previous rule.
*/
optgroup {
font-weight: bold;
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
* controls in Android 4.
* 2. Correct the inability to style clickable types in iOS and Safari.
*/
button,
html [type="button"], /* 1 */
[type="reset"],
[type="submit"] {
-webkit-appearance: button; /* 2 */
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Change the border, margin, and padding in all browsers (opinionated).
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* Remove the default vertical scrollbar in IE.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10-.
* 2. Remove the padding in IE 10-.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding and cancel buttons in Chrome and Safari on OS X.
*/
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* Correct the text style of placeholders in Chrome, Edge, and Safari.
*/
::-webkit-input-placeholder {
color: inherit;
opacity: 0.54;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}

View file

@ -0,0 +1,4 @@
.ivu-affix {
position: fixed;
z-index: @zindex-affix;
}

View file

@ -0,0 +1,97 @@
@alert-prefix-cls: ~"@{css-prefix}alert";
@icon-prefix-cls: ~"@{css-prefix}icon";
.@{alert-prefix-cls}{
position: relative;
padding: 8px 48px 8px 16px;
border-radius: @border-radius-base;
color: @text-color;
font-size: 12px;
line-height: 16px;
margin-bottom: 10px;
&&-with-icon{
padding: 8px 48px 8px 38px;
}
&-icon {
font-size: 14px;
top: 8px;
left: 16px;
position: absolute;
}
&-desc {
font-size: 12px;
color: @legend-color;
line-height: 21px;
display: none;
text-align: justify;
}
&-success {
border: 1px solid tint(@success-color, 80%);
background-color: tint(@success-color, 90%);
.@{alert-prefix-cls}-icon {
color: @success-color;
}
}
&-info {
border: 1px solid tint(@primary-color, 80%);
background-color: tint(@primary-color, 90%);
.@{alert-prefix-cls}-icon {
color: @primary-color;
}
}
&-warning {
border: 1px solid tint(@warning-color, 80%);
background-color: tint(@warning-color, 90%);
.@{alert-prefix-cls}-icon {
color: @warning-color;
}
}
&-error {
border: 1px solid tint(@error-color, 80%);
background-color: tint(@error-color, 90%);
.@{alert-prefix-cls}-icon {
color: @error-color;
}
}
&-close {
.content-close(-3px);
}
&-with-desc {
padding: 16px;
position: relative;
border-radius: @border-radius-base;
margin-bottom: 10px;
color: @text-color;
line-height: 1.5;
}
&-with-desc&-with-icon{
padding: 16px 16px 16px 69px;
}
&-with-desc &-desc{
display: block;
}
&-with-desc &-message {
font-size: 14px;
color: @text-color;
display: block;
}
&-with-desc &-icon {
top: 50%;
left: 24px;
margin-top: -21px;
font-size: 28px;
}
}

View file

@ -0,0 +1,29 @@
@backtop-prefix-cls: ~"@{css-prefix}back-top";
.@{backtop-prefix-cls} {
z-index: @zindex-back-top;
position: fixed;
cursor: pointer;
display: none;
&.@{backtop-prefix-cls}-show {
display: block;
}
&-inner {
background-color: rgba(0,0,0,.6);
border-radius: 2px;
.box-shadow(0 1px 3px rgba(0,0,0,.2));
.transition(all @transition-time @ease-in-out);
&:hover {
background-color: rgba(0,0,0,.7);
}
}
i{
color: #fff;
font-size: 24px;
padding: 8px 12px;
}
}

View file

@ -0,0 +1,55 @@
@badge-prefix-cls: ~"@{css-prefix}badge";
.@{badge-prefix-cls} {
position: relative;
display: inline-block;
line-height: 1;
vertical-align: middle;
&-count {
position: absolute;
.transform(translateX(50%));
top: -10px;
right: 0;
height: 20px;
border-radius: 10px;
min-width: 20px;
background: @error-color;
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);
a,
a:hover {
color: #fff;
}
&-alone {
top: auto;
display: block;
position: relative;
.transform(translateX(0));
}
}
&-dot {
position: absolute;
.transform(translateX(-50%));
.transform-origin(0 center);
top: -4px;
right: -8px;
height: 8px;
width: 8px;
border-radius: 100%;
background: @error-color;
z-index: 10;
.box-shadow(0 0 0 1px #fff);
}
}

View file

@ -0,0 +1,74 @@
@btn-prefix-cls: ~"@{css-prefix}btn";
.@{btn-prefix-cls} {
.btn;
.btn-default;
&-primary {
.btn-primary;
.@{btn-prefix-cls}-group &:not(:first-child):not(:last-child) {
border-right-color: @btn-group-border;
border-left-color: @btn-group-border;
}
.@{btn-prefix-cls}-group &:first-child {
&:not(:last-child) {
border-right-color: @btn-group-border;
&[disabled] {
border-right-color: @btn-default-border;
}
}
}
.@{btn-prefix-cls}-group &:last-child:not(:first-child),
.@{btn-prefix-cls}-group & + .@{btn-prefix-cls} {
border-left-color: @btn-group-border;
&[disabled] {
border-left-color: @btn-default-border;
}
}
}
&-ghost {
.btn-ghost;
}
//&-dashed {
// .btn-dashed;
//}
&-circle,
&-circle-outline {
.btn-circle(@btn-prefix-cls);
}
&:before {
position: absolute;
top: -1px;
left: -1px;
bottom: -1px;
right: -1px;
background: #fff;
opacity: 0.35;
content: '';
border-radius: inherit;
z-index: 1;
.transition(opacity @transition-time);
pointer-events: none;
display: none;
}
&&-loading {
pointer-events: none;
position: relative;
&:before {
display: block;
}
}
&-group {
.btn-group(@btn-prefix-cls);
}
}

Some files were not shown because too many files have changed in this diff Show more