From c7fecd1c6ef05efc608f18c0c623c078ef8d1221 Mon Sep 17 00:00:00 2001 From: tangjinzhou <415800467@qq.com> Date: Thu, 26 Oct 2017 15:18:08 +0800 Subject: [PATCH 01/47] button checkbox --- .babelrc | 4 + .editorconfig | 9 + .eslintignore | 1 + .eslintrc | 7 + .stylelintrc | 21 + .vscode/settings.json | 21 + components/button/button-group.vue | 42 + components/button/button.vue | 98 ++ components/button/index.en-US.md | 38 + components/button/index.js | 6 + components/button/index.zh-CN.md | 41 + components/button/style/index.js | 2 + components/button/style/index.less | 175 +++ components/button/style/mixin.less | 294 +++++ components/checkbox/checkbox-group.vue | 89 ++ components/checkbox/checkbox.vue | 88 ++ components/checkbox/index.js | 6 + components/checkbox/style/index.js | 2 + components/checkbox/style/index.less | 4 + components/checkbox/style/mixin.less | 206 ++++ components/dialog/dialog.vue | 37 + components/dialog/dialogWrap.vue | 57 + components/dialog/index.js | 6 + components/icon/icon.vue | 49 + components/icon/index.js | 3 + components/icon/style/index.js | 1 + components/index.js | 9 + components/style/color/bezierEasing.less | 108 ++ components/style/color/colorPalette.less | 46 + components/style/color/colors.less | 90 ++ components/style/color/tinyColor.less | 1184 ++++++++++++++++++++ components/style/core/base.less | 122 ++ components/style/core/iconfont.less | 301 +++++ components/style/core/index.less | 4 + components/style/core/motion.less | 15 + components/style/core/motion/fade.less | 31 + components/style/core/motion/move.less | 120 ++ components/style/core/motion/other.less | 10 + components/style/core/motion/slide.less | 120 ++ components/style/core/motion/swing.less | 33 + components/style/core/motion/zoom.less | 160 +++ components/style/core/normalize.less | 447 ++++++++ components/style/index.js | 1 + components/style/index.less | 2 + components/style/mixins/clearfix.less | 16 + components/style/mixins/compatibility.less | 45 + components/style/mixins/iconfont.less | 38 + components/style/mixins/index.less | 8 + components/style/mixins/motion.less | 33 + components/style/mixins/opacity.less | 8 + components/style/mixins/size.less | 10 + components/style/themes/default.less | 362 ++++++ examples/button.vue | 95 ++ examples/checkbox.vue | 58 + examples/dialog.vue | 29 + examples/index.html | 11 + examples/index.js | 19 + examples/index.less | 0 package.json | 56 + webpack.config.js | 87 ++ 60 files changed, 4985 insertions(+) create mode 100644 .babelrc create mode 100644 .editorconfig create mode 100644 .eslintignore create mode 100644 .eslintrc create mode 100644 .stylelintrc create mode 100644 .vscode/settings.json create mode 100644 components/button/button-group.vue create mode 100644 components/button/button.vue create mode 100644 components/button/index.en-US.md create mode 100644 components/button/index.js create mode 100644 components/button/index.zh-CN.md create mode 100644 components/button/style/index.js create mode 100644 components/button/style/index.less create mode 100644 components/button/style/mixin.less create mode 100644 components/checkbox/checkbox-group.vue create mode 100644 components/checkbox/checkbox.vue create mode 100644 components/checkbox/index.js create mode 100644 components/checkbox/style/index.js create mode 100644 components/checkbox/style/index.less create mode 100644 components/checkbox/style/mixin.less create mode 100644 components/dialog/dialog.vue create mode 100644 components/dialog/dialogWrap.vue create mode 100644 components/dialog/index.js create mode 100644 components/icon/icon.vue create mode 100644 components/icon/index.js create mode 100644 components/icon/style/index.js create mode 100644 components/index.js create mode 100644 components/style/color/bezierEasing.less create mode 100644 components/style/color/colorPalette.less create mode 100644 components/style/color/colors.less create mode 100644 components/style/color/tinyColor.less create mode 100644 components/style/core/base.less create mode 100644 components/style/core/iconfont.less create mode 100644 components/style/core/index.less create mode 100644 components/style/core/motion.less create mode 100644 components/style/core/motion/fade.less create mode 100644 components/style/core/motion/move.less create mode 100644 components/style/core/motion/other.less create mode 100644 components/style/core/motion/slide.less create mode 100644 components/style/core/motion/swing.less create mode 100644 components/style/core/motion/zoom.less create mode 100644 components/style/core/normalize.less create mode 100644 components/style/index.js create mode 100644 components/style/index.less create mode 100644 components/style/mixins/clearfix.less create mode 100644 components/style/mixins/compatibility.less create mode 100644 components/style/mixins/iconfont.less create mode 100644 components/style/mixins/index.less create mode 100644 components/style/mixins/motion.less create mode 100644 components/style/mixins/opacity.less create mode 100644 components/style/mixins/size.less create mode 100644 components/style/themes/default.less create mode 100644 examples/button.vue create mode 100644 examples/checkbox.vue create mode 100644 examples/dialog.vue create mode 100644 examples/index.html create mode 100644 examples/index.js create mode 100644 examples/index.less create mode 100644 package.json create mode 100644 webpack.config.js diff --git a/.babelrc b/.babelrc new file mode 100644 index 000000000..3bde2e0da --- /dev/null +++ b/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["env"], + "plugins": ["transform-vue-jsx"] +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..3dce4145f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true \ No newline at end of file diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..c2658d7d1 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +node_modules/ diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 000000000..acd24c6e4 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,7 @@ +{ + "extends": ["plugin:vue-libs/recommended"], // ,"plugin:vue-libs/recommended" + "rules": { + "comma-dangle": [2, "always-multiline"], + "no-var": "error" + } +} diff --git a/.stylelintrc b/.stylelintrc new file mode 100644 index 000000000..3ae31aec8 --- /dev/null +++ b/.stylelintrc @@ -0,0 +1,21 @@ +{ + "extends": "stylelint-config-standard", + "rules": { + "comment-empty-line-before": null, + "declaration-empty-line-before": null, + "function-comma-newline-after": null, + "function-name-case": null, + "function-parentheses-newline-inside": null, + "function-max-empty-lines": null, + "function-whitespace-after": null, + "indentation": null, + "number-leading-zero": null, + "number-no-trailing-zeros": null, + "rule-empty-line-before": null, + "selector-combinator-space-after": null, + "selector-list-comma-newline-after": null, + "selector-pseudo-element-colon-notation": null, + "unit-no-unknown": null, + "value-list-max-empty-lines": null + } +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..2915911e1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,21 @@ +// 将设置放入此文件中以覆盖默认值和用户设置。 +{ + "eslint.enable": true, + "eslint.options": { + "extensions": [".js", ".vue"], + "configFile": ".eslintrc" + }, + "eslint.validate": [ + "javascript", + "javascriptreact", + { "language": "vue", "autoFix": true } + ], + "emmet.syntaxProfiles": { + "vue-html": "html", + "vue": "html" + }, + "eslint.autoFixOnSave": true, + "vetur.validation.template": true, + "vetur.format.html.wrap_line_length": 60, + "vetur.format.js.InsertSpaceBeforeFunctionParenthesis": true +} diff --git a/components/button/button-group.vue b/components/button/button-group.vue new file mode 100644 index 000000000..080a5c6b9 --- /dev/null +++ b/components/button/button-group.vue @@ -0,0 +1,42 @@ + + diff --git a/components/button/button.vue b/components/button/button.vue new file mode 100644 index 000000000..ee249d272 --- /dev/null +++ b/components/button/button.vue @@ -0,0 +1,98 @@ + + diff --git a/components/button/index.en-US.md b/components/button/index.en-US.md new file mode 100644 index 000000000..ca62dfeed --- /dev/null +++ b/components/button/index.en-US.md @@ -0,0 +1,38 @@ +--- +category: Components +type: General +title: Button +--- + +To trigger an operation. + +## When To Use + +A button means an operation (or a series of operations). Clicking a button will trigger corresponding business logic. + +## API + +To get a customized button, just set `type`/`shape`/`size`/`loading`/`disabled`. + +| Property | Description | Type | Default | +| -------- | ----------- | ---- | ------- | +| ghost | make background transparent and invert text and border colors, added in 2.7 | boolean | false | +| htmlType | set the original html `type` of `button`, see: [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-type) | string | `button` | +| icon | set the icon of button, see: Icon component | string | - | +| loading | set the loading status of button | boolean \| { delay: number } | false | +| shape | can be set to `circle` or omitted | string | - | +| size | can be set to `small` `large` or omitted | string | `default` | +| type | can be set to `primary` `ghost` `dashed` `danger`(added in 2.7) or omitted (meaning `default`) | string | `default` | +| onClick | set the handler to handle `click` event | function | - | + +`` will be rendered into ``, and all the properties which are not listed above will be transferred to the `` 最终会被渲染为 ``,并且除了上表中的属性,其它属性都会直接传到 ``。 + + diff --git a/components/button/style/index.js b/components/button/style/index.js new file mode 100644 index 000000000..cf31ed80f --- /dev/null +++ b/components/button/style/index.js @@ -0,0 +1,2 @@ +import '../../style/index.less' +import './index.less' diff --git a/components/button/style/index.less b/components/button/style/index.less new file mode 100644 index 000000000..e9b930802 --- /dev/null +++ b/components/button/style/index.less @@ -0,0 +1,175 @@ +@import "../../style/themes/default"; +@import "../../style/mixins/index"; +@import "./mixin"; + +@btn-prefix-cls: ~"@{ant-prefix}-btn"; + +// for compatibile +@btn-ghost-color: @text-color; +@btn-ghost-bg: transparent; +@btn-ghost-border: @border-color-base; + +// Button styles +// ----------------------------- +.@{btn-prefix-cls} { + .btn; + .btn-default; + + // Make sure that the target of Button's click event always be `button` + // Ref: https://github.com/ant-design/ant-design/issues/7034 + > i, + > span { + pointer-events: none; + } + + &-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; + + &:disabled { + border-color: @btn-default-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 & + & { + border-left-color: @btn-group-border; + &[disabled] { + border-left-color: @btn-default-border; + } + } + } + + &-ghost { + .btn-ghost; + } + + &-dashed { + .btn-dashed; + } + + &-danger { + .btn-danger; + } + + &-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 .2s; + pointer-events: none; + display: none; + } + + .@{iconfont-css-prefix} { + transition: margin-left .3s @ease-in-out; + } + + &&-loading:before { + display: block; + } + + &&-loading:not(&-circle):not(&-circle-outline):not(&-icon-only) { + padding-left: 29px; + pointer-events: none; + position: relative; + .@{iconfont-css-prefix} { + margin-left: -14px; + } + } + + &-sm&-loading:not(&-circle):not(&-circle-outline):not(&-icon-only) { + padding-left: 24px; + .@{iconfont-css-prefix} { + margin-left: -17px; + } + } + + &-group { + .btn-group(@btn-prefix-cls); + } + + &:not(&-circle):not(&-circle-outline)&-icon-only { + padding-left: 8px; + padding-right: 8px; + } + + // http://stackoverflow.com/a/21281554/3040605 + &:focus > span, + &:active > span { + position: relative; + } + + // To ensure that a space will be placed between character and `Icon`. + > .@{iconfont-css-prefix} + span, + > span + .@{iconfont-css-prefix} { + margin-left: 0.5em; + } + + &-clicked:after { + content: ''; + position: absolute; + top: -1px; + left: -1px; + bottom: -1px; + right: -1px; + border-radius: inherit; + border: 0 solid @primary-color; + opacity: 0.4; + animation: buttonEffect .4s; + display: block; + } + + &-danger&-clicked:after { + border-color: @btn-danger-color; + } + + &-background-ghost { + background: transparent !important; + border-color: #fff; + color: #fff; + } + + &-background-ghost&-primary { + .button-variant-ghost(@primary-color); + } + + &-background-ghost&-danger { + .button-variant-ghost(@btn-danger-color); + } +} + +@keyframes buttonEffect { + to { + opacity: 0; + top: -6px; + left: -6px; + bottom: -6px; + right: -6px; + border-width: 6px; + } +} diff --git a/components/button/style/mixin.less b/components/button/style/mixin.less new file mode 100644 index 000000000..c8cfb0910 --- /dev/null +++ b/components/button/style/mixin.less @@ -0,0 +1,294 @@ +// mixins for button +// ------------------------ +.button-size(@height; @padding; @font-size; @border-radius) { + padding: @padding; + font-size: @font-size; + border-radius: @border-radius; + height: @height; +} + +.button-disabled() { + &.disabled, + &[disabled] { + &, + &:hover, + &:focus, + &:active, + &.active { + .button-color(@btn-disable-color; @btn-disable-bg; @btn-disable-border); + } + } +} + +.button-variant-primary(@color; @background) { + .button-color(@color; @background; @background); + &:hover, + &:focus { + .button-color(@color; ~`colorPalette("@{background}", 5)`; ~`colorPalette("@{background}", 5)`); + } + + &:active, + &.active { + .button-color(@color; ~`colorPalette("@{background}", 7)`; ~`colorPalette("@{background}", 7)`); + } + + .button-disabled(); +} + +.button-variant-other(@color; @background; @border) { + .button-color(@color; @background; @border); + + &:hover, + &:focus { + .button-color(@primary-color; @background; @primary-color); + } + + &:active, + &.active { + .button-color(@primary-7; @background; @primary-7); + } + + .button-disabled(); +} + +.button-variant-danger(@color; @background; @border) { + .button-color(@color; @background; @border); + + &:hover, + &:focus { + .button-color(@btn-primary-color; @color; @color;); + } + + &:active, + &.active { + .button-color(@btn-primary-color; ~`colorPalette("@{color}", 7)`; ~`colorPalette("@{color}", 7)`;); + } + + .button-disabled(); +} + +.button-variant-ghost(@color) { + .button-color(@color; transparent; @color); + + &:hover, + &:focus { + .button-color(~`colorPalette("@{color}", 5)`; transparent; ~`colorPalette("@{color}", 5)`); + } + + &:active, + &.active { + .button-color(~`colorPalette("@{color}", 7)`; transparent; ~`colorPalette("@{color}", 7)`); + } + + .button-disabled(); +} + +.button-color(@color; @background; @border) { + color: @color; + background-color: @background; + border-color: @border; + // a inside Button which only work in Chrome + // http://stackoverflow.com/a/17253457 + > a:only-child { + color: currentColor; + &:after { + content: ''; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + background: transparent; + } + } +} + +.button-group-base(@btnClassName) { + position: relative; + display: inline-block; + > .@{btnClassName} { + position: relative; + z-index: 1; + float: left; + &:hover, + &:focus, + &:active, + &.active { + z-index: 2; + } + + &:disabled { + z-index: 0; + } + } + + // size + &-lg > .@{btnClassName} { + .button-size(@btn-height-lg; @btn-padding-lg; @btn-font-size-lg; @btn-border-radius-base); + } + + &-sm > .@{btnClassName} { + .button-size(@btn-height-sm; @btn-padding-sm; @font-size-base; @btn-border-radius-sm); + > .@{iconfont-css-prefix} { + font-size: @font-size-base; + } + } +} + +// Base styles of buttons +// -------------------------------------------------- +.btn() { + display: inline-block; + margin-bottom: 0; + font-weight: @btn-font-weight; + text-align: center; + touch-action: manipulation; + cursor: pointer; + background-image: none; + border: @border-width-base @border-style-base transparent; + white-space: nowrap; + line-height: 1.15; // https://github.com/ant-design/ant-design/issues/7070 + .button-size(@btn-height-base; @btn-padding-base; @font-size-base; @btn-border-radius-base); + user-select: none; + transition: all .3s @ease-in-out; + position: relative; + + > .@{iconfont-css-prefix} { + line-height: 1; + } + + &, + &:active, + &:focus { + outline: 0; + } + + &:not([disabled]):hover { + text-decoration: none; + } + + &:not([disabled]):active { + outline: 0; + transition: none; + } + + &.disabled, + &[disabled] { + cursor: not-allowed; + > * { + pointer-events: none; + } + } + + &-lg { + .button-size(@btn-height-lg; @btn-padding-lg; @btn-font-size-lg; @btn-border-radius-base); + } + + &-sm { + .button-size(@btn-height-sm; @btn-padding-sm; @font-size-base; @btn-border-radius-sm); + } +} + +// primary button style +.btn-primary() { + .button-variant-primary(@btn-primary-color; @btn-primary-bg); +} + +// default button style +.btn-default() { + .button-variant-other(@btn-default-color; @btn-default-bg; @btn-default-border); + &:hover, + &:focus, + &:active, + &.active { + background: #fff; + } +} + +// ghost button style +.btn-ghost() { + .button-variant-other(@btn-ghost-color, @btn-ghost-bg, @btn-ghost-border); +} + +// dashed button style +.btn-dashed() { + .button-variant-other(@btn-default-color, @btn-default-bg, @btn-default-border); + border-style: dashed; +} + +// danger button style +.btn-danger() { + .button-variant-danger(@btn-danger-color, @btn-danger-bg, @btn-danger-border); +} + +// circle button: the content only contains icon +.btn-circle(@btnClassName: btn) { + .square(@btn-circle-size); + .button-size(@btn-circle-size; 0; @font-size-base + 2px; 50%); + + &.@{btnClassName}-lg { + .square(@btn-circle-size-lg); + .button-size(@btn-circle-size-lg; 0; @btn-font-size-lg + 2px; 50%); + } + + &.@{btnClassName}-sm { + .square(@btn-circle-size-sm); + .button-size(@btn-circle-size-sm; 0; @font-size-base; 50%); + } +} + +// Horizontal button groups styl +// -------------------------------------------------- +.btn-group(@btnClassName: btn) { + .button-group-base(@btnClassName); + + .@{btnClassName} + .@{btnClassName}, + .@{btnClassName} + &, + & + .@{btnClassName}, + & + & { + margin-left: -1px; + } + + .@{btnClassName}:not(:first-child):not(:last-child) { + border-radius: 0; + padding-left: 8px; + padding-right: 8px; + } + + > .@{btnClassName}:first-child { + margin-left: 0; + &:not(:last-child) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + padding-right: 8px; + } + } + + > .@{btnClassName}:last-child:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + padding-left: 8px; + } + + & > & { + float: left; + } + + & > &:not(:first-child):not(:last-child) > .@{btnClassName} { + border-radius: 0; + } + + & > &:first-child:not(:last-child) { + > .@{btnClassName}:last-child { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + padding-right: 8px; + } + } + + & > &:last-child:not(:first-child) > .@{btnClassName}:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + padding-left: 8px; + } +} diff --git a/components/checkbox/checkbox-group.vue b/components/checkbox/checkbox-group.vue new file mode 100644 index 000000000..684d939a9 --- /dev/null +++ b/components/checkbox/checkbox-group.vue @@ -0,0 +1,89 @@ + + diff --git a/components/checkbox/checkbox.vue b/components/checkbox/checkbox.vue new file mode 100644 index 000000000..e802c96d4 --- /dev/null +++ b/components/checkbox/checkbox.vue @@ -0,0 +1,88 @@ + + diff --git a/components/checkbox/index.js b/components/checkbox/index.js new file mode 100644 index 000000000..1c1109dec --- /dev/null +++ b/components/checkbox/index.js @@ -0,0 +1,6 @@ +import Checkbox from './checkbox.vue' +import CheckboxGroup from './checkbox-group.vue' + +Checkbox.Group = CheckboxGroup +export default Checkbox + diff --git a/components/checkbox/style/index.js b/components/checkbox/style/index.js new file mode 100644 index 000000000..cf31ed80f --- /dev/null +++ b/components/checkbox/style/index.js @@ -0,0 +1,2 @@ +import '../../style/index.less' +import './index.less' diff --git a/components/checkbox/style/index.less b/components/checkbox/style/index.less new file mode 100644 index 000000000..fa88d365a --- /dev/null +++ b/components/checkbox/style/index.less @@ -0,0 +1,4 @@ +@import "../../style/themes/default"; +@import "./mixin"; + +.antCheckboxFn(); diff --git a/components/checkbox/style/mixin.less b/components/checkbox/style/mixin.less new file mode 100644 index 000000000..7a940f36e --- /dev/null +++ b/components/checkbox/style/mixin.less @@ -0,0 +1,206 @@ +@import "../../style/mixins/index"; + +.antCheckboxFn(@checkbox-prefix-cls: ~"@{ant-prefix}-checkbox") { + @checkbox-inner-prefix-cls: ~"@{checkbox-prefix-cls}-inner"; + // 一般状态 + .@{checkbox-prefix-cls} { + white-space: nowrap; + cursor: pointer; + outline: none; + display: inline-block; + line-height: 1; + position: relative; + vertical-align: text-bottom; + + .@{checkbox-prefix-cls}-wrapper:hover &-inner, + &:hover &-inner, + &-input:focus + &-inner { + border-color: @primary-color; + } + + &-checked:after { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border-radius: @border-radius-sm; + border: 1px solid @primary-color; + content: ''; + animation: antCheckboxEffect 0.36s ease-in-out; + animation-fill-mode: both; + visibility: hidden; + } + + &:hover:after, + .@{checkbox-prefix-cls}-wrapper:hover &:after { + visibility: visible; + } + + &-inner { + position: relative; + top: 0; + left: 0; + display: block; + width: @checkbox-size; + height: @checkbox-size; + border: @border-width-base @border-style-base @border-color-base; + border-radius: @border-radius-sm; + background-color: #fff; + transition: all .3s; + + &:after { + @check-width: (@checkbox-size / 14) * 5px; + @check-height: (@checkbox-size / 14) * 8px; + transform: rotate(45deg) scale(0); + position: absolute; + left: (@checkbox-size - @check-width) / 2 - 0.5px * (@checkbox-size / 14); + top: (@checkbox-size - @check-height) / 2 - 2px * (@checkbox-size / 14); + display: table; + width: @check-width; + height: @check-height; + border: 2px solid #fff; + border-top: 0; + border-left: 0; + content: ' '; + transition: all .1s @ease-in-back; + } + } + + &-input { + position: absolute; + left: 0; + z-index: 1; + cursor: pointer; + .opacity(0); + top: 0; + bottom: 0; + right: 0; + width: 100%; + height: 100%; + } + } + + // 半选状态 + .@{checkbox-prefix-cls}-indeterminate .@{checkbox-inner-prefix-cls}:after { + @indeterminate-width: (@checkbox-size / 14) * 8px; + @indeterminate-height: (@checkbox-size / 14) * 1px; + content: ' '; + transform: scale(1); + position: absolute; + left: (@checkbox-size - 2 - @indeterminate-width) / 2; + top: (@checkbox-size - 3 - @indeterminate-height) / 2; + width: @indeterminate-width; + height: @indeterminate-height; + } + + .@{checkbox-prefix-cls}-indeterminate.@{checkbox-prefix-cls}-disabled .@{checkbox-inner-prefix-cls}:after { + border-color: @disabled-color; + } + + // 选中状态 + .@{checkbox-prefix-cls}-checked .@{checkbox-inner-prefix-cls}:after { + transform: rotate(45deg) scale(1); + position: absolute; + display: table; + border: 2px solid #fff; + border-top: 0; + border-left: 0; + content: ' '; + transition: all .2s @ease-out-back .1s; + } + + .@{checkbox-prefix-cls}-checked, + .@{checkbox-prefix-cls}-indeterminate { + .@{checkbox-inner-prefix-cls} { + background-color: @primary-color; + border-color: @primary-color; + } + } + + .@{checkbox-prefix-cls}-disabled { + cursor: not-allowed; + + &.@{checkbox-prefix-cls}-checked { + .@{checkbox-inner-prefix-cls}:after { + animation-name: none; + border-color: @disabled-color; + } + } + + .@{checkbox-prefix-cls}-input { + cursor: not-allowed; + } + + .@{checkbox-inner-prefix-cls} { + border-color: @border-color-base !important; + background-color: @input-disabled-bg; + &:after { + animation-name: none; + border-color: @input-disabled-bg; + } + } + + & + span { + color: @disabled-color; + cursor: not-allowed; + } + } + + .@{checkbox-prefix-cls}-wrapper { + cursor: pointer; + font-size: @font-size-base; + display: inline-block; + & + & { + margin-left: 8px; + } + } + + .@{checkbox-prefix-cls}-wrapper + span, + .@{checkbox-prefix-cls} + span { + padding-left: 8px; + padding-right: 8px; + } + + .@{checkbox-prefix-cls}-group { + font-size: @font-size-base; + &-item { + display: inline-block; + margin-right: 8px; + &:last-child { + margin-right: 0; + } + } + &-item + &-item { + margin-left: 0; + } + } + + @ie8: \0screen; + + // IE8 hack for https://github.com/ant-design/ant-design/issues/2148 + @media @ie8 { + .@{checkbox-prefix-cls}-checked .@{checkbox-prefix-cls}-inner:before, + .@{checkbox-prefix-cls}-checked .@{checkbox-prefix-cls}-inner:after { + .iconfont-font("\e632"); + font-weight: bold; + font-size: 8px; + border: 0; + color: #fff; + left: 2px; + top: 3px; + position: absolute; + } + } +} + +@keyframes antCheckboxEffect { + 0% { + transform: scale(1); + opacity: 0.5; + } + 100% { + transform: scale(1.6); + opacity: 0; + } +} diff --git a/components/dialog/dialog.vue b/components/dialog/dialog.vue new file mode 100644 index 000000000..9827a6f2c --- /dev/null +++ b/components/dialog/dialog.vue @@ -0,0 +1,37 @@ + + diff --git a/components/dialog/dialogWrap.vue b/components/dialog/dialogWrap.vue new file mode 100644 index 000000000..4b0992e08 --- /dev/null +++ b/components/dialog/dialogWrap.vue @@ -0,0 +1,57 @@ + + diff --git a/components/dialog/index.js b/components/dialog/index.js new file mode 100644 index 000000000..5d10a6377 --- /dev/null +++ b/components/dialog/index.js @@ -0,0 +1,6 @@ +// import Vue from 'vue' +// import * as VueTransferDom from 'vue-transfer-dom' +// Vue.use(VueTransferDom /*, {name: 'transferDom'}*/) +import Dialog from './DialogWrap.vue' +export default Dialog + diff --git a/components/icon/icon.vue b/components/icon/icon.vue new file mode 100644 index 000000000..f10e02b4e --- /dev/null +++ b/components/icon/icon.vue @@ -0,0 +1,49 @@ + + diff --git a/components/icon/index.js b/components/icon/index.js new file mode 100644 index 000000000..36ce4b22c --- /dev/null +++ b/components/icon/index.js @@ -0,0 +1,3 @@ +import Icon from './icon.vue' +export default Icon + diff --git a/components/icon/style/index.js b/components/icon/style/index.js new file mode 100644 index 000000000..40aaf01c1 --- /dev/null +++ b/components/icon/style/index.js @@ -0,0 +1 @@ +import '../../style/index.less' diff --git a/components/index.js b/components/index.js new file mode 100644 index 000000000..8a85844b2 --- /dev/null +++ b/components/index.js @@ -0,0 +1,9 @@ +import './button/style' +import './checkbox/style' +import './icon/style' + +export { default as Button } from './button' + +export { default as Checkbox } from './checkbox' + +export { default as Icon } from './icon' diff --git a/components/style/color/bezierEasing.less b/components/style/color/bezierEasing.less new file mode 100644 index 000000000..bcad6c1dc --- /dev/null +++ b/components/style/color/bezierEasing.less @@ -0,0 +1,108 @@ +/* stylelint-disable declaration-bang-space-before */ +.bezierEasingMixin() { +@functions: ~`(function() { + var NEWTON_ITERATIONS = 4; + var NEWTON_MIN_SLOPE = 0.001; + var SUBDIVISION_PRECISION = 0.0000001; + var SUBDIVISION_MAX_ITERATIONS = 10; + + var kSplineTableSize = 11; + var kSampleStepSize = 1.0 / (kSplineTableSize - 1.0); + + var float32ArraySupported = typeof Float32Array === 'function'; + + function A (aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; } + function B (aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; } + function C (aA1) { return 3.0 * aA1; } + + // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2. + function calcBezier (aT, aA1, aA2) { return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT; } + + // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2. + function getSlope (aT, aA1, aA2) { return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1); } + + function binarySubdivide (aX, aA, aB, mX1, mX2) { + var currentX, currentT, i = 0; + do { + currentT = aA + (aB - aA) / 2.0; + currentX = calcBezier(currentT, mX1, mX2) - aX; + if (currentX > 0.0) { + aB = currentT; + } else { + aA = currentT; + } + } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS); + return currentT; + } + + function newtonRaphsonIterate (aX, aGuessT, mX1, mX2) { + for (var i = 0; i < NEWTON_ITERATIONS; ++i) { + var currentSlope = getSlope(aGuessT, mX1, mX2); + if (currentSlope === 0.0) { + return aGuessT; + } + var currentX = calcBezier(aGuessT, mX1, mX2) - aX; + aGuessT -= currentX / currentSlope; + } + return aGuessT; + } + + var BezierEasing = function (mX1, mY1, mX2, mY2) { + if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) { + throw new Error('bezier x values must be in [0, 1] range'); + } + + // Precompute samples table + var sampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize); + if (mX1 !== mY1 || mX2 !== mY2) { + for (var i = 0; i < kSplineTableSize; ++i) { + sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2); + } + } + + function getTForX (aX) { + var intervalStart = 0.0; + var currentSample = 1; + var lastSample = kSplineTableSize - 1; + + for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) { + intervalStart += kSampleStepSize; + } + --currentSample; + + // Interpolate to provide an initial guess for t + var dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]); + var guessForT = intervalStart + dist * kSampleStepSize; + + var initialSlope = getSlope(guessForT, mX1, mX2); + if (initialSlope >= NEWTON_MIN_SLOPE) { + return newtonRaphsonIterate(aX, guessForT, mX1, mX2); + } else if (initialSlope === 0.0) { + return guessForT; + } else { + return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2); + } + } + + return function BezierEasing (x) { + if (mX1 === mY1 && mX2 === mY2) { + return x; // linear + } + // Because JavaScript number are imprecise, we should guarantee the extremes are right. + if (x === 0) { + return 0; + } + if (x === 1) { + return 1; + } + return calcBezier(getTForX(x), mY1, mY2); + }; + }; + + this.colorEasing = BezierEasing(0.26, 0.09, 0.37, 0.18); +})()`; +} +// It is hacky way to make this function will be compiled preferentially by less +// resolve error: `ReferenceError: colorPalette is not defined` +// https://github.com/ant-design/ant-motion/issues/44 +.bezierEasingMixin(); diff --git a/components/style/color/colorPalette.less b/components/style/color/colorPalette.less new file mode 100644 index 000000000..7c84cef7e --- /dev/null +++ b/components/style/color/colorPalette.less @@ -0,0 +1,46 @@ +@import "bezierEasing"; +@import "tinyColor"; + +// We create a very complex algorithm which take the place of original tint/shade color system +// to make sure no one can understand it 👻 +// and create an entire color palette magicly by inputing just a single primary color. +// We are using bezier-curve easing function and some color manipulations like tint/shade/darken/spin +.colorPaletteMixin() { +@functions: ~`(function() { + var warmDark = 0.5; // warm color darken radio + var warmRotate = -26; // warm color rotate degree + var coldDark = 0.55; // cold color darken radio + var coldRotate = 10; // cold color rotate degree + var getShadeColor = function(c) { + var shadeColor = tinycolor(c); + // warm and cold color will darken in different radio, and rotate in different degree + // warmer color + if (shadeColor.toRgb().r > shadeColor.toRgb().b) { + return shadeColor.darken(shadeColor.toHsl().l * warmDark * 100).spin(warmRotate).toHexString(); + } + // colder color + return shadeColor.darken(shadeColor.toHsl().l * coldDark * 100).spin(coldRotate).toHexString(); + } + var primaryEasing = colorEasing(0.6); + this.colorPalette = function(color, index) { + var currentEasing = colorEasing(index * 0.1); + // return light colors after tint + if (index <= 6) { + return tinycolor.mix( + '#ffffff', + color, + currentEasing * 100 / primaryEasing + ).toHexString(); + } + return tinycolor.mix( + getShadeColor(color), + color, + (1 - (currentEasing - primaryEasing) / (1 - primaryEasing)) * 100 + ).toHexString(); + }; +})()`; +} +// It is hacky way to make this function will be compiled preferentially by less +// resolve error: `ReferenceError: colorPalette is not defined` +// https://github.com/ant-design/ant-motion/issues/44 +.colorPaletteMixin(); diff --git a/components/style/color/colors.less b/components/style/color/colors.less new file mode 100644 index 000000000..53f16229e --- /dev/null +++ b/components/style/color/colors.less @@ -0,0 +1,90 @@ +@import 'colorPalette'; + +// color palettes +@blue-1: color(~`colorPalette("@{blue-6}", 1)`); +@blue-2: color(~`colorPalette("@{blue-6}", 2)`); +@blue-3: color(~`colorPalette("@{blue-6}", 3)`); +@blue-4: color(~`colorPalette("@{blue-6}", 4)`); +@blue-5: color(~`colorPalette("@{blue-6}", 5)`); +@blue-6: #108ee9; +@blue-7: color(~`colorPalette("@{blue-6}", 7)`); +@blue-8: color(~`colorPalette("@{blue-6}", 8)`); +@blue-9: color(~`colorPalette("@{blue-6}", 9)`); +@blue-10: color(~`colorPalette("@{blue-6}", 10)`); + +@purple-1: color(~`colorPalette("@{purple-6}", 1)`); +@purple-2: color(~`colorPalette("@{purple-6}", 2)`); +@purple-3: color(~`colorPalette("@{purple-6}", 3)`); +@purple-4: color(~`colorPalette("@{purple-6}", 4)`); +@purple-5: color(~`colorPalette("@{purple-6}", 5)`); +@purple-6: #7265e6; +@purple-7: color(~`colorPalette("@{purple-6}", 7)`); +@purple-8: color(~`colorPalette("@{purple-6}", 8)`); +@purple-9: color(~`colorPalette("@{purple-6}", 9)`); +@purple-10: color(~`colorPalette("@{purple-6}", 10)`); + +@cyan-1: color(~`colorPalette("@{cyan-6}", 1)`); +@cyan-2: color(~`colorPalette("@{cyan-6}", 2)`); +@cyan-3: color(~`colorPalette("@{cyan-6}", 3)`); +@cyan-4: color(~`colorPalette("@{cyan-6}", 4)`); +@cyan-5: color(~`colorPalette("@{cyan-6}", 5)`); +@cyan-6: #00a2ae; +@cyan-7: color(~`colorPalette("@{cyan-6}", 7)`); +@cyan-8: color(~`colorPalette("@{cyan-6}", 8)`); +@cyan-9: color(~`colorPalette("@{cyan-6}", 9)`); +@cyan-10: color(~`colorPalette("@{cyan-6}", 10)`); + +@green-1: color(~`colorPalette("@{green-6}", 1)`); +@green-2: color(~`colorPalette("@{green-6}", 2)`); +@green-3: color(~`colorPalette("@{green-6}", 3)`); +@green-4: color(~`colorPalette("@{green-6}", 4)`); +@green-5: color(~`colorPalette("@{green-6}", 5)`); +@green-6: #00a854; +@green-7: color(~`colorPalette("@{green-6}", 7)`); +@green-8: color(~`colorPalette("@{green-6}", 8)`); +@green-9: color(~`colorPalette("@{green-6}", 9)`); +@green-10: color(~`colorPalette("@{green-6}", 10)`); + +@pink-1: color(~`colorPalette("@{pink-6}", 1)`); +@pink-2: color(~`colorPalette("@{pink-6}", 2)`); +@pink-3: color(~`colorPalette("@{pink-6}", 3)`); +@pink-4: color(~`colorPalette("@{pink-6}", 4)`); +@pink-5: color(~`colorPalette("@{pink-6}", 5)`); +@pink-6: #f5317f; +@pink-7: color(~`colorPalette("@{pink-6}", 7)`); +@pink-8: color(~`colorPalette("@{pink-6}", 8)`); +@pink-9: color(~`colorPalette("@{pink-6}", 9)`); +@pink-10: color(~`colorPalette("@{pink-6}", 10)`); + +@red-1: color(~`colorPalette("@{red-6}", 1)`); +@red-2: color(~`colorPalette("@{red-6}", 2)`); +@red-3: color(~`colorPalette("@{red-6}", 3)`); +@red-4: color(~`colorPalette("@{red-6}", 4)`); +@red-5: color(~`colorPalette("@{red-6}", 5)`); +@red-6: #f04134; +@red-7: color(~`colorPalette("@{red-6}", 7)`); +@red-8: color(~`colorPalette("@{red-6}", 8)`); +@red-9: color(~`colorPalette("@{red-6}", 9)`); +@red-10: color(~`colorPalette("@{red-6}", 10)`); + +@orange-1: color(~`colorPalette("@{orange-6}", 1)`); +@orange-2: color(~`colorPalette("@{orange-6}", 2)`); +@orange-3: color(~`colorPalette("@{orange-6}", 3)`); +@orange-4: color(~`colorPalette("@{orange-6}", 4)`); +@orange-5: color(~`colorPalette("@{orange-6}", 5)`); +@orange-6: #f56a00; +@orange-7: color(~`colorPalette("@{orange-6}", 7)`); +@orange-8: color(~`colorPalette("@{orange-6}", 8)`); +@orange-9: color(~`colorPalette("@{orange-6}", 9)`); +@orange-10: color(~`colorPalette("@{orange-6}", 10)`); + +@yellow-1: color(~`colorPalette("@{yellow-6}", 1)`); +@yellow-2: color(~`colorPalette("@{yellow-6}", 2)`); +@yellow-3: color(~`colorPalette("@{yellow-6}", 3)`); +@yellow-4: color(~`colorPalette("@{yellow-6}", 4)`); +@yellow-5: color(~`colorPalette("@{yellow-6}", 5)`); +@yellow-6: #ffbf00; +@yellow-7: color(~`colorPalette("@{yellow-6}", 7)`); +@yellow-8: color(~`colorPalette("@{yellow-6}", 8)`); +@yellow-9: color(~`colorPalette("@{yellow-6}", 9)`); +@yellow-10: color(~`colorPalette("@{yellow-6}", 10)`); diff --git a/components/style/color/tinyColor.less b/components/style/color/tinyColor.less new file mode 100644 index 000000000..00aad3931 --- /dev/null +++ b/components/style/color/tinyColor.less @@ -0,0 +1,1184 @@ +/* stylelint-disable declaration-bang-space-before */ +.tinyColorMixin() { +@functions: ~`(function() { +// TinyColor v1.4.1 +// https://github.com/bgrins/TinyColor +// 2016-07-07, Brian Grinstead, MIT License +var trimLeft = /^\s+/, + trimRight = /\s+$/, + tinyCounter = 0, + mathRound = Math.round, + mathMin = Math.min, + mathMax = Math.max, + mathRandom = Math.random; + +function tinycolor (color, opts) { + + color = (color) ? color : ''; + opts = opts || { }; + + // If input is already a tinycolor, return itself + if (color instanceof tinycolor) { + return color; + } + // If we are called as a function, call using new instead + if (!(this instanceof tinycolor)) { + return new tinycolor(color, opts); + } + + var rgb = inputToRGB(color); + this._originalInput = color, + this._r = rgb.r, + this._g = rgb.g, + this._b = rgb.b, + this._a = rgb.a, + this._roundA = mathRound(100*this._a) / 100, + this._format = opts.format || rgb.format; + this._gradientType = opts.gradientType; + + // Don't let the range of [0,255] come back in [0,1]. + // Potentially lose a little bit of precision here, but will fix issues where + // .5 gets interpreted as half of the total, instead of half of 1 + // If it was supposed to be 128, this was already taken care of by inputToRgb + if (this._r < 1) { this._r = mathRound(this._r); } + if (this._g < 1) { this._g = mathRound(this._g); } + if (this._b < 1) { this._b = mathRound(this._b); } + + this._ok = rgb.ok; + this._tc_id = tinyCounter++; +} + +tinycolor.prototype = { + isDark: function() { + return this.getBrightness() < 128; + }, + isLight: function() { + return !this.isDark(); + }, + isValid: function() { + return this._ok; + }, + getOriginalInput: function() { + return this._originalInput; + }, + getFormat: function() { + return this._format; + }, + getAlpha: function() { + return this._a; + }, + getBrightness: function() { + //http://www.w3.org/TR/AERT#color-contrast + var rgb = this.toRgb(); + return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000; + }, + getLuminance: function() { + //http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef + var rgb = this.toRgb(); + var RsRGB, GsRGB, BsRGB, R, G, B; + RsRGB = rgb.r/255; + GsRGB = rgb.g/255; + BsRGB = rgb.b/255; + + if (RsRGB <= 0.03928) {R = RsRGB / 12.92;} else {R = Math.pow(((RsRGB + 0.055) / 1.055), 2.4);} + if (GsRGB <= 0.03928) {G = GsRGB / 12.92;} else {G = Math.pow(((GsRGB + 0.055) / 1.055), 2.4);} + if (BsRGB <= 0.03928) {B = BsRGB / 12.92;} else {B = Math.pow(((BsRGB + 0.055) / 1.055), 2.4);} + return (0.2126 * R) + (0.7152 * G) + (0.0722 * B); + }, + setAlpha: function(value) { + this._a = boundAlpha(value); + this._roundA = mathRound(100*this._a) / 100; + return this; + }, + toHsv: function() { + var hsv = rgbToHsv(this._r, this._g, this._b); + return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a }; + }, + toHsvString: function() { + var hsv = rgbToHsv(this._r, this._g, this._b); + var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100); + return (this._a == 1) ? + "hsv(" + h + ", " + s + "%, " + v + "%)" : + "hsva(" + h + ", " + s + "%, " + v + "%, "+ this._roundA + ")"; + }, + toHsl: function() { + var hsl = rgbToHsl(this._r, this._g, this._b); + return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a }; + }, + toHslString: function() { + var hsl = rgbToHsl(this._r, this._g, this._b); + var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100); + return (this._a == 1) ? + "hsl(" + h + ", " + s + "%, " + l + "%)" : + "hsla(" + h + ", " + s + "%, " + l + "%, "+ this._roundA + ")"; + }, + toHex: function(allow3Char) { + return rgbToHex(this._r, this._g, this._b, allow3Char); + }, + toHexString: function(allow3Char) { + return '#' + this.toHex(allow3Char); + }, + toHex8: function(allow4Char) { + return rgbaToHex(this._r, this._g, this._b, this._a, allow4Char); + }, + toHex8String: function(allow4Char) { + return '#' + this.toHex8(allow4Char); + }, + toRgb: function() { + return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a }; + }, + toRgbString: function() { + return (this._a == 1) ? + "rgb(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ")" : + "rgba(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ", " + this._roundA + ")"; + }, + toPercentageRgb: function() { + return { r: mathRound(bound01(this._r, 255) * 100) + "%", g: mathRound(bound01(this._g, 255) * 100) + "%", b: mathRound(bound01(this._b, 255) * 100) + "%", a: this._a }; + }, + toPercentageRgbString: function() { + return (this._a == 1) ? + "rgb(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%)" : + "rgba(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")"; + }, + toName: function() { + if (this._a === 0) { + return "transparent"; + } + + if (this._a < 1) { + return false; + } + + return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false; + }, + toFilter: function(secondColor) { + var hex8String = '#' + rgbaToArgbHex(this._r, this._g, this._b, this._a); + var secondHex8String = hex8String; + var gradientType = this._gradientType ? "GradientType = 1, " : ""; + + if (secondColor) { + var s = tinycolor(secondColor); + secondHex8String = '#' + rgbaToArgbHex(s._r, s._g, s._b, s._a); + } + + return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")"; + }, + toString: function(format) { + var formatSet = !!format; + format = format || this._format; + + var formattedString = false; + var hasAlpha = this._a < 1 && this._a >= 0; + var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "hex4" || format === "hex8" || format === "name"); + + if (needsAlphaFormat) { + // Special case for "transparent", all other non-alpha formats + // will return rgba when there is transparency. + if (format === "name" && this._a === 0) { + return this.toName(); + } + return this.toRgbString(); + } + if (format === "rgb") { + formattedString = this.toRgbString(); + } + if (format === "prgb") { + formattedString = this.toPercentageRgbString(); + } + if (format === "hex" || format === "hex6") { + formattedString = this.toHexString(); + } + if (format === "hex3") { + formattedString = this.toHexString(true); + } + if (format === "hex4") { + formattedString = this.toHex8String(true); + } + if (format === "hex8") { + formattedString = this.toHex8String(); + } + if (format === "name") { + formattedString = this.toName(); + } + if (format === "hsl") { + formattedString = this.toHslString(); + } + if (format === "hsv") { + formattedString = this.toHsvString(); + } + + return formattedString || this.toHexString(); + }, + clone: function() { + return tinycolor(this.toString()); + }, + + _applyModification: function(fn, args) { + var color = fn.apply(null, [this].concat([].slice.call(args))); + this._r = color._r; + this._g = color._g; + this._b = color._b; + this.setAlpha(color._a); + return this; + }, + lighten: function() { + return this._applyModification(lighten, arguments); + }, + brighten: function() { + return this._applyModification(brighten, arguments); + }, + darken: function() { + return this._applyModification(darken, arguments); + }, + desaturate: function() { + return this._applyModification(desaturate, arguments); + }, + saturate: function() { + return this._applyModification(saturate, arguments); + }, + greyscale: function() { + return this._applyModification(greyscale, arguments); + }, + spin: function() { + return this._applyModification(spin, arguments); + }, + + _applyCombination: function(fn, args) { + return fn.apply(null, [this].concat([].slice.call(args))); + }, + analogous: function() { + return this._applyCombination(analogous, arguments); + }, + complement: function() { + return this._applyCombination(complement, arguments); + }, + monochromatic: function() { + return this._applyCombination(monochromatic, arguments); + }, + splitcomplement: function() { + return this._applyCombination(splitcomplement, arguments); + }, + triad: function() { + return this._applyCombination(triad, arguments); + }, + tetrad: function() { + return this._applyCombination(tetrad, arguments); + } +}; + +// If input is an object, force 1 into "1.0" to handle ratios properly +// String input requires "1.0" as input, so 1 will be treated as 1 +tinycolor.fromRatio = function(color, opts) { + if (typeof color == "object") { + var newColor = {}; + for (var i in color) { + if (color.hasOwnProperty(i)) { + if (i === "a") { + newColor[i] = color[i]; + } + else { + newColor[i] = convertToPercentage(color[i]); + } + } + } + color = newColor; + } + + return tinycolor(color, opts); +}; + +// Given a string or object, convert that input to RGB +// Possible string inputs: +// +// "red" +// "#f00" or "f00" +// "#ff0000" or "ff0000" +// "#ff000000" or "ff000000" +// "rgb 255 0 0" or "rgb (255, 0, 0)" +// "rgb 1.0 0 0" or "rgb (1, 0, 0)" +// "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1" +// "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1" +// "hsl(0, 100%, 50%)" or "hsl 0 100% 50%" +// "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1" +// "hsv(0, 100%, 100%)" or "hsv 0 100% 100%" +// +function inputToRGB(color) { + + var rgb = { r: 0, g: 0, b: 0 }; + var a = 1; + var s = null; + var v = null; + var l = null; + var ok = false; + var format = false; + + if (typeof color == "string") { + color = stringInputToObject(color); + } + + if (typeof color == "object") { + if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) { + rgb = rgbToRgb(color.r, color.g, color.b); + ok = true; + format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb"; + } + else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) { + s = convertToPercentage(color.s); + v = convertToPercentage(color.v); + rgb = hsvToRgb(color.h, s, v); + ok = true; + format = "hsv"; + } + else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) { + s = convertToPercentage(color.s); + l = convertToPercentage(color.l); + rgb = hslToRgb(color.h, s, l); + ok = true; + format = "hsl"; + } + + if (color.hasOwnProperty("a")) { + a = color.a; + } + } + + a = boundAlpha(a); + + return { + ok: ok, + format: color.format || format, + r: mathMin(255, mathMax(rgb.r, 0)), + g: mathMin(255, mathMax(rgb.g, 0)), + b: mathMin(255, mathMax(rgb.b, 0)), + a: a + }; +} + +// Conversion Functions +// -------------------- + +// rgbToHsl, rgbToHsv, hslToRgb, hsvToRgb modified from: +// + +// rgbToRgb +// Handle bounds / percentage checking to conform to CSS color spec +// +// *Assumes:* r, g, b in [0, 255] or [0, 1] +// *Returns:* { r, g, b } in [0, 255] +function rgbToRgb(r, g, b){ + return { + r: bound01(r, 255) * 255, + g: bound01(g, 255) * 255, + b: bound01(b, 255) * 255 + }; +} + +// rgbToHsl +// Converts an RGB color value to HSL. +// *Assumes:* r, g, and b are contained in [0, 255] or [0, 1] +// *Returns:* { h, s, l } in [0,1] +function rgbToHsl(r, g, b) { + + r = bound01(r, 255); + g = bound01(g, 255); + b = bound01(b, 255); + + var max = mathMax(r, g, b), min = mathMin(r, g, b); + var h, s, l = (max + min) / 2; + + if(max == min) { + h = s = 0; // achromatic + } + else { + var d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch(max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + + h /= 6; + } + + return { h: h, s: s, l: l }; +} + +// hslToRgb +// Converts an HSL color value to RGB. +// *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100] +// *Returns:* { r, g, b } in the set [0, 255] +function hslToRgb(h, s, l) { + var r, g, b; + + h = bound01(h, 360); + s = bound01(s, 100); + l = bound01(l, 100); + + function hue2rgb(p, q, t) { + if(t < 0) t += 1; + if(t > 1) t -= 1; + if(t < 1/6) return p + (q - p) * 6 * t; + if(t < 1/2) return q; + if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; + return p; + } + + if(s === 0) { + r = g = b = l; // achromatic + } + else { + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1/3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1/3); + } + + return { r: r * 255, g: g * 255, b: b * 255 }; +} + +// rgbToHsv +// Converts an RGB color value to HSV +// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1] +// *Returns:* { h, s, v } in [0,1] +function rgbToHsv(r, g, b) { + + r = bound01(r, 255); + g = bound01(g, 255); + b = bound01(b, 255); + + var max = mathMax(r, g, b), min = mathMin(r, g, b); + var h, s, v = max; + + var d = max - min; + s = max === 0 ? 0 : d / max; + + if(max == min) { + h = 0; // achromatic + } + else { + switch(max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h, s: s, v: v }; +} + +// hsvToRgb +// Converts an HSV color value to RGB. +// *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100] +// *Returns:* { r, g, b } in the set [0, 255] + function hsvToRgb(h, s, v) { + + h = bound01(h, 360) * 6; + s = bound01(s, 100); + v = bound01(v, 100); + + var i = Math.floor(h), + f = h - i, + p = v * (1 - s), + q = v * (1 - f * s), + t = v * (1 - (1 - f) * s), + mod = i % 6, + r = [v, q, p, p, t, v][mod], + g = [t, v, v, q, p, p][mod], + b = [p, p, t, v, v, q][mod]; + + return { r: r * 255, g: g * 255, b: b * 255 }; +} + +// rgbToHex +// Converts an RGB color to hex +// Assumes r, g, and b are contained in the set [0, 255] +// Returns a 3 or 6 character hex +function rgbToHex(r, g, b, allow3Char) { + + var hex = [ + pad2(mathRound(r).toString(16)), + pad2(mathRound(g).toString(16)), + pad2(mathRound(b).toString(16)) + ]; + + // Return a 3 character hex if possible + if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) { + return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0); + } + + return hex.join(""); +} + +// rgbaToHex +// Converts an RGBA color plus alpha transparency to hex +// Assumes r, g, b are contained in the set [0, 255] and +// a in [0, 1]. Returns a 4 or 8 character rgba hex +function rgbaToHex(r, g, b, a, allow4Char) { + + var hex = [ + pad2(mathRound(r).toString(16)), + pad2(mathRound(g).toString(16)), + pad2(mathRound(b).toString(16)), + pad2(convertDecimalToHex(a)) + ]; + + // Return a 4 character hex if possible + if (allow4Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1) && hex[3].charAt(0) == hex[3].charAt(1)) { + return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0); + } + + return hex.join(""); +} + +// rgbaToArgbHex +// Converts an RGBA color to an ARGB Hex8 string +// Rarely used, but required for "toFilter()" +function rgbaToArgbHex(r, g, b, a) { + + var hex = [ + pad2(convertDecimalToHex(a)), + pad2(mathRound(r).toString(16)), + pad2(mathRound(g).toString(16)), + pad2(mathRound(b).toString(16)) + ]; + + return hex.join(""); +} + +// equals +// Can be called with any tinycolor input +tinycolor.equals = function (color1, color2) { + if (!color1 || !color2) { return false; } + return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString(); +}; + +tinycolor.random = function() { + return tinycolor.fromRatio({ + r: mathRandom(), + g: mathRandom(), + b: mathRandom() + }); +}; + +// Modification Functions +// ---------------------- +// Thanks to less.js for some of the basics here +// + +function desaturate(color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.s -= amount / 100; + hsl.s = clamp01(hsl.s); + return tinycolor(hsl); +} + +function saturate(color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.s += amount / 100; + hsl.s = clamp01(hsl.s); + return tinycolor(hsl); +} + +function greyscale(color) { + return tinycolor(color).desaturate(100); +} + +function lighten (color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.l += amount / 100; + hsl.l = clamp01(hsl.l); + return tinycolor(hsl); +} + +function brighten(color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var rgb = tinycolor(color).toRgb(); + rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100)))); + rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100)))); + rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100)))); + return tinycolor(rgb); +} + +function darken (color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.l -= amount / 100; + hsl.l = clamp01(hsl.l); + return tinycolor(hsl); +} + +// Spin takes a positive or negative amount within [-360, 360] indicating the change of hue. +// Values outside of this range will be wrapped into this range. +function spin(color, amount) { + var hsl = tinycolor(color).toHsl(); + var hue = (hsl.h + amount) % 360; + hsl.h = hue < 0 ? 360 + hue : hue; + return tinycolor(hsl); +} + +// Combination Functions +// --------------------- +// Thanks to jQuery xColor for some of the ideas behind these +// + +function complement(color) { + var hsl = tinycolor(color).toHsl(); + hsl.h = (hsl.h + 180) % 360; + return tinycolor(hsl); +} + +function triad(color) { + var hsl = tinycolor(color).toHsl(); + var h = hsl.h; + return [ + tinycolor(color), + tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }), + tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l }) + ]; +} + +function tetrad(color) { + var hsl = tinycolor(color).toHsl(); + var h = hsl.h; + return [ + tinycolor(color), + tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }), + tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }), + tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l }) + ]; +} + +function splitcomplement(color) { + var hsl = tinycolor(color).toHsl(); + var h = hsl.h; + return [ + tinycolor(color), + tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}), + tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l}) + ]; +} + +function analogous(color, results, slices) { + results = results || 6; + slices = slices || 30; + + var hsl = tinycolor(color).toHsl(); + var part = 360 / slices; + var ret = [tinycolor(color)]; + + for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) { + hsl.h = (hsl.h + part) % 360; + ret.push(tinycolor(hsl)); + } + return ret; +} + +function monochromatic(color, results) { + results = results || 6; + var hsv = tinycolor(color).toHsv(); + var h = hsv.h, s = hsv.s, v = hsv.v; + var ret = []; + var modification = 1 / results; + + while (results--) { + ret.push(tinycolor({ h: h, s: s, v: v})); + v = (v + modification) % 1; + } + + return ret; +} + +// Utility Functions +// --------------------- + +tinycolor.mix = function(color1, color2, amount) { + amount = (amount === 0) ? 0 : (amount || 50); + + var rgb1 = tinycolor(color1).toRgb(); + var rgb2 = tinycolor(color2).toRgb(); + + var p = amount / 100; + + var rgba = { + r: ((rgb2.r - rgb1.r) * p) + rgb1.r, + g: ((rgb2.g - rgb1.g) * p) + rgb1.g, + b: ((rgb2.b - rgb1.b) * p) + rgb1.b, + a: ((rgb2.a - rgb1.a) * p) + rgb1.a + }; + + return tinycolor(rgba); +}; + +// Readability Functions +// --------------------- +// false +// tinycolor.isReadable("#000", "#111",{level:"AA",size:"large"}) => false +tinycolor.isReadable = function(color1, color2, wcag2) { + var readability = tinycolor.readability(color1, color2); + var wcag2Parms, out; + + out = false; + + wcag2Parms = validateWCAG2Parms(wcag2); + switch (wcag2Parms.level + wcag2Parms.size) { + case "AAsmall": + case "AAAlarge": + out = readability >= 4.5; + break; + case "AAlarge": + out = readability >= 3; + break; + case "AAAsmall": + out = readability >= 7; + break; + } + return out; + +}; + +// mostReadable +// Given a base color and a list of possible foreground or background +// colors for that base, returns the most readable color. +// Optionally returns Black or White if the most readable color is unreadable. +// *Example* +// tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:false}).toHexString(); // "#112255" +// tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:true}).toHexString(); // "#ffffff" +// tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"large"}).toHexString(); // "#faf3f3" +// tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"small"}).toHexString(); // "#ffffff" +tinycolor.mostReadable = function(baseColor, colorList, args) { + var bestColor = null; + var bestScore = 0; + var readability; + var includeFallbackColors, level, size ; + args = args || {}; + includeFallbackColors = args.includeFallbackColors ; + level = args.level; + size = args.size; + + for (var i= 0; i < colorList.length ; i++) { + readability = tinycolor.readability(baseColor, colorList[i]); + if (readability > bestScore) { + bestScore = readability; + bestColor = tinycolor(colorList[i]); + } + } + + if (tinycolor.isReadable(baseColor, bestColor, {"level":level,"size":size}) || !includeFallbackColors) { + return bestColor; + } + else { + args.includeFallbackColors=false; + return tinycolor.mostReadable(baseColor,["#fff", "#000"],args); + } +}; + +// Big List of Colors +// ------------------ +// +var names = tinycolor.names = { + aliceblue: "f0f8ff", + antiquewhite: "faebd7", + aqua: "0ff", + aquamarine: "7fffd4", + azure: "f0ffff", + beige: "f5f5dc", + bisque: "ffe4c4", + black: "000", + blanchedalmond: "ffebcd", + blue: "00f", + blueviolet: "8a2be2", + brown: "a52a2a", + burlywood: "deb887", + burntsienna: "ea7e5d", + cadetblue: "5f9ea0", + chartreuse: "7fff00", + chocolate: "d2691e", + coral: "ff7f50", + cornflowerblue: "6495ed", + cornsilk: "fff8dc", + crimson: "dc143c", + cyan: "0ff", + darkblue: "00008b", + darkcyan: "008b8b", + darkgoldenrod: "b8860b", + darkgray: "a9a9a9", + darkgreen: "006400", + darkgrey: "a9a9a9", + darkkhaki: "bdb76b", + darkmagenta: "8b008b", + darkolivegreen: "556b2f", + darkorange: "ff8c00", + darkorchid: "9932cc", + darkred: "8b0000", + darksalmon: "e9967a", + darkseagreen: "8fbc8f", + darkslateblue: "483d8b", + darkslategray: "2f4f4f", + darkslategrey: "2f4f4f", + darkturquoise: "00ced1", + darkviolet: "9400d3", + deeppink: "ff1493", + deepskyblue: "00bfff", + dimgray: "696969", + dimgrey: "696969", + dodgerblue: "1e90ff", + firebrick: "b22222", + floralwhite: "fffaf0", + forestgreen: "228b22", + fuchsia: "f0f", + gainsboro: "dcdcdc", + ghostwhite: "f8f8ff", + gold: "ffd700", + goldenrod: "daa520", + gray: "808080", + green: "008000", + greenyellow: "adff2f", + grey: "808080", + honeydew: "f0fff0", + hotpink: "ff69b4", + indianred: "cd5c5c", + indigo: "4b0082", + ivory: "fffff0", + khaki: "f0e68c", + lavender: "e6e6fa", + lavenderblush: "fff0f5", + lawngreen: "7cfc00", + lemonchiffon: "fffacd", + lightblue: "add8e6", + lightcoral: "f08080", + lightcyan: "e0ffff", + lightgoldenrodyellow: "fafad2", + lightgray: "d3d3d3", + lightgreen: "90ee90", + lightgrey: "d3d3d3", + lightpink: "ffb6c1", + lightsalmon: "ffa07a", + lightseagreen: "20b2aa", + lightskyblue: "87cefa", + lightslategray: "789", + lightslategrey: "789", + lightsteelblue: "b0c4de", + lightyellow: "ffffe0", + lime: "0f0", + limegreen: "32cd32", + linen: "faf0e6", + magenta: "f0f", + maroon: "800000", + mediumaquamarine: "66cdaa", + mediumblue: "0000cd", + mediumorchid: "ba55d3", + mediumpurple: "9370db", + mediumseagreen: "3cb371", + mediumslateblue: "7b68ee", + mediumspringgreen: "00fa9a", + mediumturquoise: "48d1cc", + mediumvioletred: "c71585", + midnightblue: "191970", + mintcream: "f5fffa", + mistyrose: "ffe4e1", + moccasin: "ffe4b5", + navajowhite: "ffdead", + navy: "000080", + oldlace: "fdf5e6", + olive: "808000", + olivedrab: "6b8e23", + orange: "ffa500", + orangered: "ff4500", + orchid: "da70d6", + palegoldenrod: "eee8aa", + palegreen: "98fb98", + paleturquoise: "afeeee", + palevioletred: "db7093", + papayawhip: "ffefd5", + peachpuff: "ffdab9", + peru: "cd853f", + pink: "ffc0cb", + plum: "dda0dd", + powderblue: "b0e0e6", + purple: "800080", + rebeccapurple: "663399", + red: "f00", + rosybrown: "bc8f8f", + royalblue: "4169e1", + saddlebrown: "8b4513", + salmon: "fa8072", + sandybrown: "f4a460", + seagreen: "2e8b57", + seashell: "fff5ee", + sienna: "a0522d", + silver: "c0c0c0", + skyblue: "87ceeb", + slateblue: "6a5acd", + slategray: "708090", + slategrey: "708090", + snow: "fffafa", + springgreen: "00ff7f", + steelblue: "4682b4", + tan: "d2b48c", + teal: "008080", + thistle: "d8bfd8", + tomato: "ff6347", + turquoise: "40e0d0", + violet: "ee82ee", + wheat: "f5deb3", + white: "fff", + whitesmoke: "f5f5f5", + yellow: "ff0", + yellowgreen: "9acd32" +}; + +// Make it easy to access colors via hexNames[hex] +var hexNames = tinycolor.hexNames = flip(names); + +// Utilities +// --------- + +// { 'name1': 'val1' } becomes { 'val1': 'name1' } +function flip(o) { + var flipped = { }; + for (var i in o) { + if (o.hasOwnProperty(i)) { + flipped[o[i]] = i; + } + } + return flipped; +} + +// Return a valid alpha value [0,1] with all invalid values being set to 1 +function boundAlpha(a) { + a = parseFloat(a); + + if (isNaN(a) || a < 0 || a > 1) { + a = 1; + } + + return a; +} + +// Take input from [0, n] and return it as [0, 1] +function bound01(n, max) { + if (isOnePointZero(n)) { n = "100%"; } + + var processPercent = isPercentage(n); + n = mathMin(max, mathMax(0, parseFloat(n))); + + // Automatically convert percentage into number + if (processPercent) { + n = parseInt(n * max, 10) / 100; + } + + // Handle floating point rounding errors + if ((Math.abs(n - max) < 0.000001)) { + return 1; + } + + // Convert into [0, 1] range if it isn't already + return (n % max) / parseFloat(max); +} + +// Force a number between 0 and 1 +function clamp01(val) { + return mathMin(1, mathMax(0, val)); +} + +// Parse a base-16 hex value into a base-10 integer +function parseIntFromHex(val) { + return parseInt(val, 16); +} + +// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1 +// +function isOnePointZero(n) { + return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1; +} + +// Check to see if string passed in is a percentage +function isPercentage(n) { + return typeof n === "string" && n.indexOf('%') != -1; +} + +// Force a hex value to have 2 characters +function pad2(c) { + return c.length == 1 ? '0' + c : '' + c; +} + +// Replace a decimal with it's percentage value +function convertToPercentage(n) { + if (n <= 1) { + n = (n * 100) + "%"; + } + + return n; +} + +// Converts a decimal to a hex value +function convertDecimalToHex(d) { + return Math.round(parseFloat(d) * 255).toString(16); +} +// Converts a hex value to a decimal +function convertHexToDecimal(h) { + return (parseIntFromHex(h) / 255); +} + +var matchers = (function() { + + // + var CSS_INTEGER = "[-\\+]?\\d+%?"; + + // + var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?"; + + // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome. + var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")"; + + // Actual matching. + // Parentheses and commas are optional, but not required. + // Whitespace can take the place of commas or opening paren + var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; + var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; + + return { + CSS_UNIT: new RegExp(CSS_UNIT), + rgb: new RegExp("rgb" + PERMISSIVE_MATCH3), + rgba: new RegExp("rgba" + PERMISSIVE_MATCH4), + hsl: new RegExp("hsl" + PERMISSIVE_MATCH3), + hsla: new RegExp("hsla" + PERMISSIVE_MATCH4), + hsv: new RegExp("hsv" + PERMISSIVE_MATCH3), + hsva: new RegExp("hsva" + PERMISSIVE_MATCH4), + hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, + hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/, + hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, + hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/ + }; +})(); + +// isValidCSSUnit +// Take in a single string / number and check to see if it looks like a CSS unit +// (see matchers above for definition). +function isValidCSSUnit(color) { + return !!matchers.CSS_UNIT.exec(color); +} + +// stringInputToObject +// Permissive string parsing. Take in a number of formats, and output an object +// based on detected format. Returns { r, g, b } or { h, s, l } or { h, s, v} +function stringInputToObject(color) { + + color = color.replace(trimLeft, '').replace(trimRight, '').toLowerCase(); + var named = false; + if (names[color]) { + color = names[color]; + named = true; + } + else if (color == 'transparent') { + return { r: 0, g: 0, b: 0, a: 0, format: "name" }; + } + + // Try to match string input using regular expressions. + // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360] + // Just return an object and let the conversion functions handle that. + // This way the result will be the same whether the tinycolor is initialized with string or object. + var match; + if ((match = matchers.rgb.exec(color))) { + return { r: match[1], g: match[2], b: match[3] }; + } + if ((match = matchers.rgba.exec(color))) { + return { r: match[1], g: match[2], b: match[3], a: match[4] }; + } + if ((match = matchers.hsl.exec(color))) { + return { h: match[1], s: match[2], l: match[3] }; + } + if ((match = matchers.hsla.exec(color))) { + return { h: match[1], s: match[2], l: match[3], a: match[4] }; + } + if ((match = matchers.hsv.exec(color))) { + return { h: match[1], s: match[2], v: match[3] }; + } + if ((match = matchers.hsva.exec(color))) { + return { h: match[1], s: match[2], v: match[3], a: match[4] }; + } + if ((match = matchers.hex8.exec(color))) { + return { + r: parseIntFromHex(match[1]), + g: parseIntFromHex(match[2]), + b: parseIntFromHex(match[3]), + a: convertHexToDecimal(match[4]), + format: named ? "name" : "hex8" + }; + } + if ((match = matchers.hex6.exec(color))) { + return { + r: parseIntFromHex(match[1]), + g: parseIntFromHex(match[2]), + b: parseIntFromHex(match[3]), + format: named ? "name" : "hex" + }; + } + if ((match = matchers.hex4.exec(color))) { + return { + r: parseIntFromHex(match[1] + '' + match[1]), + g: parseIntFromHex(match[2] + '' + match[2]), + b: parseIntFromHex(match[3] + '' + match[3]), + a: convertHexToDecimal(match[4] + '' + match[4]), + format: named ? "name" : "hex8" + }; + } + if ((match = matchers.hex3.exec(color))) { + return { + r: parseIntFromHex(match[1] + '' + match[1]), + g: parseIntFromHex(match[2] + '' + match[2]), + b: parseIntFromHex(match[3] + '' + match[3]), + format: named ? "name" : "hex" + }; + } + + return false; +} + +function validateWCAG2Parms(parms) { + // return valid WCAG2 parms for isReadable. + // If input parms are invalid, return {"level":"AA", "size":"small"} + var level, size; + parms = parms || {"level":"AA", "size":"small"}; + level = (parms.level || "AA").toUpperCase(); + size = (parms.size || "small").toLowerCase(); + if (level !== "AA" && level !== "AAA") { + level = "AA"; + } + if (size !== "small" && size !== "large") { + size = "small"; + } + return {"level":level, "size":size}; +} + +this.tinycolor = tinycolor; + +})()`; +} +// It is hacky way to make this function will be compiled preferentially by less +// resolve error: `ReferenceError: colorPalette is not defined` +// https://github.com/ant-design/ant-motion/issues/44 +.tinyColorMixin(); diff --git a/components/style/core/base.less b/components/style/core/base.less new file mode 100644 index 000000000..d3d2149f1 --- /dev/null +++ b/components/style/core/base.less @@ -0,0 +1,122 @@ +@import "./normalize.less"; + +// http://stackoverflow.com/a/13611748/3040605 +@font-face { + font-family: "Helvetica Neue For Number"; + src: local("Helvetica Neue"); + unicode-range: U+30-39; +} + +* { + box-sizing: border-box; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); // remove tap highlight color for mobile safari +} + +*:before, +*:after { + box-sizing: border-box; +} + +// HTML & Body reset +html, body { + .square(100%); +} + +body { + font-family: @font-family; + font-size: @font-size-base; + line-height: @line-height-base; + color: @text-color; + background-color: @body-background; +} + +// unify the setting of elements's margin and padding for browsers +body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,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; +} + +// Reset fonts for relevant elements +button,input,select,textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; + color: inherit; + -webkit-appearance: none; +} + +ul, +ol { + list-style: none; +} + +// Remove the clear button of a text input control in IE10+ +input::-ms-clear, input::-ms-reveal { + display: none; +} + +::selection { + background: @primary-color; + color: #fff; +} + +// Headers +h1, h2, h3, h4, h5, h6 { + color: @heading-color; + font-weight: 500; +} + +// Links +a { + color: @link-color; + background: transparent; + text-decoration: @link-decoration; + outline: none; + cursor: pointer; + transition: color .3s ease; + + &:focus { + text-decoration: underline; + text-decoration-skip: ink; + } + + &:hover { + color: @link-hover-color; + } + + &:active { + color: @link-active-color; + } + + &:active, + &:hover { + outline: 0; + text-decoration: @link-hover-decoration; + } + + &[disabled] { + color: @disabled-color; + cursor: not-allowed; + pointer-events: none; + } +} + +.@{ant-prefix}-divider { + margin: 0 6px; + display: inline-block; + height: 8px; + width: 1px; + background: #ccc; +} + +code, +kbd, +pre, +samp { + font-family: @code-family; +} + +// Utility classes +.clearfix { + .clearfix(); +} diff --git a/components/style/core/iconfont.less b/components/style/core/iconfont.less new file mode 100644 index 000000000..a62853fcd --- /dev/null +++ b/components/style/core/iconfont.less @@ -0,0 +1,301 @@ +@import '../themes/default'; +@import "../mixins/iconfont"; + +// font-face +@font-face { + font-family: 'anticon'; + src: url('@{icon-url}.eot'); /* IE9*/ + src: + /* IE6-IE8 */ + url('@{icon-url}.eot?#iefix') format('embedded-opentype'), + /* chrome、firefox */ + url('@{icon-url}.woff') format('woff'), + /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/ + url('@{icon-url}.ttf') format('truetype'), + /* iOS 4.1- */ + url('@{icon-url}.svg#iconfont') format('svg'); +} + +.@{iconfont-css-prefix} { + .iconfont-mixin(); +} + +.@{iconfont-css-prefix}-step-forward:before { content: "\e600"; } +.@{iconfont-css-prefix}-step-backward:before { content: "\e601"; } +.@{iconfont-css-prefix}-forward:before { content: "\e602"; } +.@{iconfont-css-prefix}-backward:before { content: "\e603"; } +.@{iconfont-css-prefix}-caret-right:before { content: "\e604"; } +.@{iconfont-css-prefix}-caret-left:before { content: "\e605"; } +.@{iconfont-css-prefix}-caret-down:before { content: "\e606"; } +.@{iconfont-css-prefix}-caret-up:before { content: "\e607"; } +.@{iconfont-css-prefix}-right-circle:before { content: "\e608"; } +.@{iconfont-css-prefix}-circle-right:before { content: "\e608"; } // antd@1.x compatibility alias: right-circle +.@{iconfont-css-prefix}-caret-circle-right:before { content: "\e608"; } // antd@1.x compatibility alias: right-circle +.@{iconfont-css-prefix}-left-circle:before { content: "\e609"; } +.@{iconfont-css-prefix}-circle-left:before { content: "\e609"; } // antd@1.x compatibility alias: left-circle +.@{iconfont-css-prefix}-caret-circle-left:before { content: "\e609"; } // antd@1.x compatibility alias: left-circle +.@{iconfont-css-prefix}-up-circle:before { content: "\e60a"; } +.@{iconfont-css-prefix}-circle-up:before { content: "\e60a"; } // antd@1.x compatibility alias: up-circle +.@{iconfont-css-prefix}-caret-circle-up:before { content: "\e60a"; } // antd@1.x compatibility alias: up-circle +.@{iconfont-css-prefix}-down-circle:before { content: "\e60b"; } +.@{iconfont-css-prefix}-circle-down:before { content: "\e60b"; } // antd@1.x compatibility alias: down-circle +.@{iconfont-css-prefix}-caret-circle-down:before { content: "\e60b"; } // antd@1.x compatibility alias: down-circle +.@{iconfont-css-prefix}-right-circle-o:before { content: "\e60c"; } +.@{iconfont-css-prefix}-circle-o-right:before { content: "\e60c"; } // antd@1.x compatibility alias: right-circle-o +.@{iconfont-css-prefix}-caret-circle-o-right:before { content: "\e60c"; } // antd@1.x compatibility alias: right-circle-o +.@{iconfont-css-prefix}-left-circle-o:before { content: "\e60d"; } +.@{iconfont-css-prefix}-circle-o-left:before { content: "\e60d"; } // antd@1.x compatibility alias: left-circle-o +.@{iconfont-css-prefix}-caret-circle-o-left:before { content: "\e60d"; } // antd@1.x compatibility alias: left-circle-o +.@{iconfont-css-prefix}-up-circle-o:before { content: "\e60e"; } +.@{iconfont-css-prefix}-circle-o-up:before { content: "\e60e"; } // antd@1.x compatibility alias: up-circle-o +.@{iconfont-css-prefix}-caret-circle-o-up:before { content: "\e60e"; } // antd@1.x compatibility alias: up-circle-o +.@{iconfont-css-prefix}-down-circle-o:before { content: "\e60f"; } +.@{iconfont-css-prefix}-circle-o-down:before { content: "\e60f"; } // antd@1.x compatibility alias: down-circle-o +.@{iconfont-css-prefix}-caret-circle-o-down:before { content: "\e60f"; } // antd@1.x compatibility alias: down-circle-o +.@{iconfont-css-prefix}-verticle-left:before { content: "\e610"; } +.@{iconfont-css-prefix}-verticle-right:before { content: "\e611"; } +.@{iconfont-css-prefix}-rollback:before { content: "\e612"; } +.@{iconfont-css-prefix}-retweet:before { content: "\e613"; } +.@{iconfont-css-prefix}-shrink:before { content: "\e614"; } +.@{iconfont-css-prefix}-arrows-alt:before { content: "\e615"; } +.@{iconfont-css-prefix}-arrow-salt:before { content: "\e615"; } // antd@1.x compatibility alias: arrows-alt +.@{iconfont-css-prefix}-reload:before { content: "\e616"; } +.@{iconfont-css-prefix}-double-right:before { content: "\e617"; } +.@{iconfont-css-prefix}-double-left:before { content: "\e618"; } +.@{iconfont-css-prefix}-arrow-down:before { content: "\e619"; } +.@{iconfont-css-prefix}-arrow-up:before { content: "\e61a"; } +.@{iconfont-css-prefix}-arrow-right:before { content: "\e61b"; } +.@{iconfont-css-prefix}-arrow-left:before { content: "\e61c"; } +.@{iconfont-css-prefix}-down:before { content: "\e61d"; } +.@{iconfont-css-prefix}-up:before { content: "\e61e"; } +.@{iconfont-css-prefix}-right:before { content: "\e61f"; } +.@{iconfont-css-prefix}-left:before { content: "\e620"; } +.@{iconfont-css-prefix}-minus-square-o:before { content: "\e621"; } +.@{iconfont-css-prefix}-minus-circle:before { content: "\e622"; } +.@{iconfont-css-prefix}-minus-circle-o:before { content: "\e623"; } +.@{iconfont-css-prefix}-minus:before { content: "\e624"; } +.@{iconfont-css-prefix}-plus-circle-o:before { content: "\e625"; } +.@{iconfont-css-prefix}-plus-circle:before { content: "\e626"; } +.@{iconfont-css-prefix}-plus:before { content: "\e627"; } +.@{iconfont-css-prefix}-info-circle:before { content: "\e628"; } +.@{iconfont-css-prefix}-info-circle-o:before { content: "\e629"; } +.@{iconfont-css-prefix}-info:before { content: "\e62a"; } +.@{iconfont-css-prefix}-exclamation:before { content: "\e62b"; } +.@{iconfont-css-prefix}-exclamation-circle:before { content: "\e62c"; } +.@{iconfont-css-prefix}-exclamation-circle-o:before { content: "\e62d"; } +.@{iconfont-css-prefix}-close-circle:before { content: "\e62e"; } +.@{iconfont-css-prefix}-cross-circle:before { content: "\e62e"; } // antd@1.x compatibility alias: close-circle +.@{iconfont-css-prefix}-close-circle-o:before { content: "\e62f"; } +.@{iconfont-css-prefix}-cross-circle-o:before { content: "\e62f"; } // antd@1.x compatibility alias: close-circle-o +.@{iconfont-css-prefix}-check-circle:before { content: "\e630"; } +.@{iconfont-css-prefix}-check-circle-o:before { content: "\e631"; } +.@{iconfont-css-prefix}-check:before { content: "\e632"; } +.@{iconfont-css-prefix}-close:before { content: "\e633"; } +.@{iconfont-css-prefix}-cross:before { content: "\e633"; } // antd@1.x compatibility alias: close +.@{iconfont-css-prefix}-customer-service:before { content: "\e634"; } +.@{iconfont-css-prefix}-customerservice:before { content: "\e634"; } // antd@1.x compatibility alias: customer-service +.@{iconfont-css-prefix}-credit-card:before { content: "\e635"; } +.@{iconfont-css-prefix}-code-o:before { content: "\e636"; } +.@{iconfont-css-prefix}-book:before { content: "\e637"; } +.@{iconfont-css-prefix}-bar-chart:before { content: "\e638"; } +.@{iconfont-css-prefix}-bars:before { content: "\e639"; } +.@{iconfont-css-prefix}-question:before { content: "\e63a"; } +.@{iconfont-css-prefix}-question-circle:before { content: "\e63b"; } +.@{iconfont-css-prefix}-question-circle-o:before { content: "\e63c"; } +.@{iconfont-css-prefix}-pause:before { content: "\e63d"; } +.@{iconfont-css-prefix}-pause-circle:before { content: "\e63e"; } +.@{iconfont-css-prefix}-pause-circle-o:before { content: "\e63f"; } +.@{iconfont-css-prefix}-clock-circle:before { content: "\e640"; } +.@{iconfont-css-prefix}-clock-circle-o:before { content: "\e641"; } +.@{iconfont-css-prefix}-swap:before { content: "\e642"; } +.@{iconfont-css-prefix}-swap-left:before { content: "\e643"; } +.@{iconfont-css-prefix}-swap-right:before { content: "\e644"; } +.@{iconfont-css-prefix}-plus-square-o:before { content: "\e645"; } +.@{iconfont-css-prefix}-frown:before { content: "\e646"; } +.@{iconfont-css-prefix}-frown-circle:before { content: "\e646"; } // antd@1.x compatibility alias: frown +.@{iconfont-css-prefix}-ellipsis:before { content: "\e647"; } +.@{iconfont-css-prefix}-copy:before { content: "\e648"; } +.@{iconfont-css-prefix}-menu-fold:before { content: "\e658"; } +.@{iconfont-css-prefix}-mail:before { content: "\e659"; } +.@{iconfont-css-prefix}-logout:before { content: "\e65a"; } +.@{iconfont-css-prefix}-link:before { content: "\e65b"; } +.@{iconfont-css-prefix}-area-chart:before { content: "\e65c"; } +.@{iconfont-css-prefix}-line-chart:before { content: "\e65d"; } +.@{iconfont-css-prefix}-home:before { content: "\e65e"; } +.@{iconfont-css-prefix}-laptop:before { content: "\e65f"; } +.@{iconfont-css-prefix}-star:before { content: "\e660"; } +.@{iconfont-css-prefix}-star-o:before { content: "\e661"; } +.@{iconfont-css-prefix}-folder:before { content: "\e662"; } +.@{iconfont-css-prefix}-filter:before { content: "\e663"; } +.@{iconfont-css-prefix}-file:before { content: "\e664"; } +.@{iconfont-css-prefix}-exception:before { content: "\e665"; } +.@{iconfont-css-prefix}-meh:before { content: "\e666"; } +.@{iconfont-css-prefix}-meh-circle:before { content: "\e666"; } // antd@1.x compatibility alias: meh +.@{iconfont-css-prefix}-meh-o:before { content: "\e667"; } +.@{iconfont-css-prefix}-shopping-cart:before { content: "\e668"; } +.@{iconfont-css-prefix}-save:before { content: "\e669"; } +.@{iconfont-css-prefix}-user:before { content: "\e66a"; } +.@{iconfont-css-prefix}-video-camera:before { content: "\e66b"; } +.@{iconfont-css-prefix}-to-top:before { content: "\e66c"; } +.@{iconfont-css-prefix}-team:before { content: "\e66d"; } +.@{iconfont-css-prefix}-tablet:before { content: "\e66e"; } +.@{iconfont-css-prefix}-solution:before { content: "\e66f"; } +.@{iconfont-css-prefix}-search:before { content: "\e670"; } +.@{iconfont-css-prefix}-share-alt:before { content: "\e671"; } +.@{iconfont-css-prefix}-setting:before { content: "\e672"; } +.@{iconfont-css-prefix}-poweroff:before { content: "\e6d5"; } +.@{iconfont-css-prefix}-picture:before { content: "\e674"; } +.@{iconfont-css-prefix}-phone:before { content: "\e675"; } +.@{iconfont-css-prefix}-paper-clip:before { content: "\e676"; } +.@{iconfont-css-prefix}-notification:before { content: "\e677"; } +.@{iconfont-css-prefix}-mobile:before { content: "\e678"; } +.@{iconfont-css-prefix}-menu-unfold:before { content: "\e679"; } +.@{iconfont-css-prefix}-inbox:before { content: "\e67a"; } +.@{iconfont-css-prefix}-lock:before { content: "\e67b"; } +.@{iconfont-css-prefix}-qrcode:before { content: "\e67c"; } +.@{iconfont-css-prefix}-play-circle:before { content: "\e6d0"; } +.@{iconfont-css-prefix}-play-circle-o:before { content: "\e6d1"; } +.@{iconfont-css-prefix}-tag:before { content: "\e6d2"; } +.@{iconfont-css-prefix}-tag-o:before { content: "\e6d3"; } +.@{iconfont-css-prefix}-tags:before { content: "\e67d"; } +.@{iconfont-css-prefix}-tags-o:before { content: "\e67e"; } +.@{iconfont-css-prefix}-cloud-o:before { content: "\e67f"; } +.@{iconfont-css-prefix}-cloud:before { content: "\e680"; } +.@{iconfont-css-prefix}-cloud-upload:before { content: "\e681"; } +.@{iconfont-css-prefix}-cloud-download:before { content: "\e682"; } +.@{iconfont-css-prefix}-cloud-download-o:before { content: "\e683"; } +.@{iconfont-css-prefix}-cloud-upload-o:before { content: "\e684"; } +.@{iconfont-css-prefix}-environment:before { content: "\e685"; } +.@{iconfont-css-prefix}-environment-o:before { content: "\e686"; } +.@{iconfont-css-prefix}-eye:before { content: "\e687"; } +.@{iconfont-css-prefix}-eye-o:before { content: "\e688"; } +.@{iconfont-css-prefix}-camera:before { content: "\e689"; } +.@{iconfont-css-prefix}-camera-o:before { content: "\e68a"; } +.@{iconfont-css-prefix}-windows:before { content: "\e68b"; } +.@{iconfont-css-prefix}-apple:before { content: "\e68c"; } +.@{iconfont-css-prefix}-apple-o:before { content: "\e6d4"; } +.@{iconfont-css-prefix}-android:before { content: "\e938"; } +.@{iconfont-css-prefix}-android-o:before { content: "\e68d"; } +.@{iconfont-css-prefix}-aliwangwang:before { content: "\e68e"; } +.@{iconfont-css-prefix}-aliwangwang-o:before { content: "\e68f"; } +.@{iconfont-css-prefix}-export:before { content: "\e691"; } +.@{iconfont-css-prefix}-edit:before { content: "\e692"; } +.@{iconfont-css-prefix}-circle-down-o:before { content: "\e693"; } +.@{iconfont-css-prefix}-circle-down-:before { content: "\e694"; } +.@{iconfont-css-prefix}-appstore-o:before { content: "\e695"; } +.@{iconfont-css-prefix}-appstore:before { content: "\e696"; } +.@{iconfont-css-prefix}-scan:before { content: "\e697"; } +.@{iconfont-css-prefix}-file-text:before { content: "\e698"; } +.@{iconfont-css-prefix}-folder-open:before { content: "\e699"; } +.@{iconfont-css-prefix}-hdd:before { content: "\e69a"; } +.@{iconfont-css-prefix}-ie:before { content: "\e69b"; } +.@{iconfont-css-prefix}-file-jpg:before { content: "\e69c"; } +.@{iconfont-css-prefix}-like:before { content: "\e64c"; } +.@{iconfont-css-prefix}-like-o:before { content: "\e69d"; } +.@{iconfont-css-prefix}-dislike:before { content: "\e64b"; } +.@{iconfont-css-prefix}-dislike-o:before { content: "\e69e"; } +.@{iconfont-css-prefix}-delete:before { content: "\e69f"; } +.@{iconfont-css-prefix}-enter:before { content: "\e6a0"; } +.@{iconfont-css-prefix}-pushpin-o:before { content: "\e6a1"; } +.@{iconfont-css-prefix}-pushpin:before { content: "\e6a2"; } +.@{iconfont-css-prefix}-heart:before { content: "\e6a3"; } +.@{iconfont-css-prefix}-heart-o:before { content: "\e6a4"; } +.@{iconfont-css-prefix}-pay-circle:before { content: "\e6a5"; } +.@{iconfont-css-prefix}-pay-circle-o:before { content: "\e6a6"; } +.@{iconfont-css-prefix}-smile:before { content: "\e6a7"; } +.@{iconfont-css-prefix}-smile-circle:before { content: "\e6a7"; } // antd@1.x compatibility alias: smile +.@{iconfont-css-prefix}-smile-o:before { content: "\e6a8"; } +.@{iconfont-css-prefix}-frown-o:before { content: "\e6a9"; } +.@{iconfont-css-prefix}-calculator:before { content: "\e6aa"; } +.@{iconfont-css-prefix}-message:before { content: "\e6ab"; } +.@{iconfont-css-prefix}-chrome:before { content: "\e6ac"; } +.@{iconfont-css-prefix}-github:before { content: "\e6ad"; } +.@{iconfont-css-prefix}-file-unknown:before { content: "\e6af"; } +.@{iconfont-css-prefix}-file-excel:before { content: "\e6b0"; } +.@{iconfont-css-prefix}-file-ppt:before { content: "\e6b1"; } +.@{iconfont-css-prefix}-file-word:before { content: "\e6b2"; } +.@{iconfont-css-prefix}-file-pdf:before { content: "\e6b3"; } +.@{iconfont-css-prefix}-desktop:before { content: "\e6b4"; } +.@{iconfont-css-prefix}-upload:before { content: "\e6b6"; } +.@{iconfont-css-prefix}-download:before { content: "\e6b7"; } +.@{iconfont-css-prefix}-pie-chart:before { content: "\e6b8"; } +.@{iconfont-css-prefix}-unlock:before { content: "\e6ba"; } +.@{iconfont-css-prefix}-calendar:before { content: "\e6bb"; } +.@{iconfont-css-prefix}-windows-o:before { content: "\e6bc"; } +.@{iconfont-css-prefix}-dot-chart:before { content: "\e6bd"; } +.@{iconfont-css-prefix}-bar-chart:before { content: "\e6be"; } +.@{iconfont-css-prefix}-code:before { content: "\e6bf"; } +.@{iconfont-css-prefix}-api:before { content: "\e951"; } +.@{iconfont-css-prefix}-plus-square:before { content: "\e6c0"; } +.@{iconfont-css-prefix}-minus-square:before { content: "\e6c1"; } +.@{iconfont-css-prefix}-close-square:before { content: "\e6c2"; } +.@{iconfont-css-prefix}-close-square-o:before { content: "\e6c3"; } +.@{iconfont-css-prefix}-check-square:before { content: "\e6c4"; } +.@{iconfont-css-prefix}-check-square-o:before { content: "\e6c5"; } +.@{iconfont-css-prefix}-fast-backward:before { content: "\e6c6"; } +.@{iconfont-css-prefix}-fast-forward:before { content: "\e6c7"; } +.@{iconfont-css-prefix}-up-square:before { content: "\e6c8"; } +.@{iconfont-css-prefix}-down-square:before { content: "\e6c9"; } +.@{iconfont-css-prefix}-left-square:before { content: "\e6ca"; } +.@{iconfont-css-prefix}-right-square:before { content: "\e6cb"; } +.@{iconfont-css-prefix}-right-square-o:before { content: "\e6cc"; } +.@{iconfont-css-prefix}-left-square-o:before { content: "\e6cd"; } +.@{iconfont-css-prefix}-down-square-o:before { content: "\e6ce"; } +.@{iconfont-css-prefix}-up-square-o:before { content: "\e6cf"; } +.@{iconfont-css-prefix}-loading:before { content: "\e64d"; } +.@{iconfont-css-prefix}-loading-3-quarters:before { content: "\e6ae"; } +.@{iconfont-css-prefix}-bulb:before { content: "\e649"; } +.@{iconfont-css-prefix}-select:before { content: "\e64a"; } +.@{iconfont-css-prefix}-addfile:before, +.@{iconfont-css-prefix}-file-add:before { content: "\e910"; } +.@{iconfont-css-prefix}-addfolder:before, +.@{iconfont-css-prefix}-folder-add:before { content: "\e914"; } +.@{iconfont-css-prefix}-switcher:before { content: "\e913"; } +.@{iconfont-css-prefix}-rocket:before { content: "\e90f"; } +.@{iconfont-css-prefix}-dingding:before { content: "\e923"; } +.@{iconfont-css-prefix}-dingding-o:before { content: "\e925"; } +.@{iconfont-css-prefix}-bell:before { content: "\e64e"; } +.@{iconfont-css-prefix}-disconnect:before { content: "\e64f"; } +.@{iconfont-css-prefix}-database:before { content: "\e650"; } +.@{iconfont-css-prefix}-compass:before { content: "\e6db"; } +.@{iconfont-css-prefix}-barcode:before { content: "\e652"; } +.@{iconfont-css-prefix}-hourglass:before { content: "\e653"; } +.@{iconfont-css-prefix}-key:before { content: "\e654"; } +.@{iconfont-css-prefix}-flag:before { content: "\e655"; } +.@{iconfont-css-prefix}-layout:before { content: "\e656"; } +.@{iconfont-css-prefix}-login:before { content: "\e657"; } +.@{iconfont-css-prefix}-printer:before { content: "\e673"; } +.@{iconfont-css-prefix}-sound:before { content: "\e6e9"; } +.@{iconfont-css-prefix}-usb:before { content: "\e6d7"; } +.@{iconfont-css-prefix}-skin:before { content: "\e6d8"; } +.@{iconfont-css-prefix}-tool:before { content: "\e6d9"; } +.@{iconfont-css-prefix}-sync:before { content: "\e6da"; } +.@{iconfont-css-prefix}-wifi:before { content: "\e6d6"; } +.@{iconfont-css-prefix}-car:before { content: "\e6dc"; } +.@{iconfont-css-prefix}-copyright:before { content: "\e6de"; } +.@{iconfont-css-prefix}-schedule:before { content: "\e6df"; } +.@{iconfont-css-prefix}-user-add:before { content: "\e6ed"; } +.@{iconfont-css-prefix}-user-delete:before { content: "\e6e0"; } +.@{iconfont-css-prefix}-usergroup-add:before { content: "\e6dd"; } +.@{iconfont-css-prefix}-usergroup-delete:before { content: "\e6e1"; } +.@{iconfont-css-prefix}-man:before { content: "\e6e2"; } +.@{iconfont-css-prefix}-woman:before { content: "\e6ec"; } +.@{iconfont-css-prefix}-shop:before { content: "\e6e3"; } +.@{iconfont-css-prefix}-gift:before { content: "\e6e4"; } +.@{iconfont-css-prefix}-idcard:before { content: "\e6e5"; } +.@{iconfont-css-prefix}-medicine-box:before { content: "\e6e6"; } +.@{iconfont-css-prefix}-red-envelope:before { content: "\e6e7"; } +.@{iconfont-css-prefix}-coffee:before { content: "\e6e8"; } +.@{iconfont-css-prefix}-trademark:before { content: "\e651"; } +.@{iconfont-css-prefix}-safety:before { content: "\e6ea"; } +.@{iconfont-css-prefix}-wallet:before { content: "\e6eb"; } +.@{iconfont-css-prefix}-bank:before { content: "\e6ee"; } +.@{iconfont-css-prefix}-trophy:before { content: "\e6ef"; } +.@{iconfont-css-prefix}-contacts:before { content: "\e6f0"; } +.@{iconfont-css-prefix}-global:before { content: "\e6f1"; } +.@{iconfont-css-prefix}-shake:before { content: "\e94f"; } +.@{iconfont-css-prefix}-fork:before { content: "\e6f2"; } +.@{iconfont-css-prefix}-spin:before { + display: inline-block; + animation: loadingCircle 1s infinite linear; +} diff --git a/components/style/core/index.less b/components/style/core/index.less new file mode 100644 index 000000000..4901d0612 --- /dev/null +++ b/components/style/core/index.less @@ -0,0 +1,4 @@ +@import "../mixins/index"; +@import "base"; +@import "iconfont"; +@import "motion"; diff --git a/components/style/core/motion.less b/components/style/core/motion.less new file mode 100644 index 000000000..e47ce302a --- /dev/null +++ b/components/style/core/motion.less @@ -0,0 +1,15 @@ +@import "../mixins/motion"; +@import "motion/fade"; +@import "motion/move"; +@import "motion/other"; +@import "motion/slide"; +@import "motion/swing"; +@import "motion/zoom"; + +// For common/openAnimation +.ant-motion-collapse { + overflow: hidden; + &-active { + transition: height .15s @ease-in-out, opacity .15s @ease-in-out !important; + } +} diff --git a/components/style/core/motion/fade.less b/components/style/core/motion/fade.less new file mode 100644 index 000000000..fd9d621cb --- /dev/null +++ b/components/style/core/motion/fade.less @@ -0,0 +1,31 @@ +.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, antFade); + +@keyframes antFadeIn { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} + +@keyframes antFadeOut { + 0% { + opacity: 1; + } + 100% { + opacity: 0; + } +} diff --git a/components/style/core/motion/move.less b/components/style/core/motion/move.less new file mode 100644 index 000000000..2eed39bfc --- /dev/null +++ b/components/style/core/motion/move.less @@ -0,0 +1,120 @@ +.move-motion(@className, @keyframeName) { + .make-motion(@className, @keyframeName); + .@{className}-enter, + .@{className}-appear { + opacity: 0; + animation-timing-function: @ease-out-circ; + } + .@{className}-leave { + animation-timing-function: @ease-in-circ; + } +} + +.move-motion(move-up, antMoveUp); +.move-motion(move-down, antMoveDown); +.move-motion(move-left, antMoveLeft); +.move-motion(move-right, antMoveRight); + +@keyframes antMoveDownIn { + 0% { + transform-origin: 0 0; + transform: translateY(100%); + opacity: 0; + } + 100% { + transform-origin: 0 0; + transform: translateY(0%); + opacity: 1; + } +} + +@keyframes antMoveDownOut { + 0% { + transform-origin: 0 0; + transform: translateY(0%); + opacity: 1; + } + 100% { + transform-origin: 0 0; + transform: translateY(100%); + opacity: 0; + } +} + +@keyframes antMoveLeftIn { + 0% { + transform-origin: 0 0; + transform: translateX(-100%); + opacity: 0; + } + 100% { + transform-origin: 0 0; + transform: translateX(0%); + opacity: 1; + } +} + +@keyframes antMoveLeftOut { + 0% { + transform-origin: 0 0; + transform: translateX(0%); + opacity: 1; + } + 100% { + transform-origin: 0 0; + transform: translateX(-100%); + opacity: 0; + } +} + +@keyframes antMoveRightIn { + 0% { + opacity: 0; + transform-origin: 0 0; + transform: translateX(100%); + } + 100% { + opacity: 1; + transform-origin: 0 0; + transform: translateX(0%); + } +} + +@keyframes antMoveRightOut { + 0% { + transform-origin: 0 0; + transform: translateX(0%); + opacity: 1; + } + 100% { + transform-origin: 0 0; + transform: translateX(100%); + opacity: 0; + } +} + +@keyframes antMoveUpIn { + 0% { + transform-origin: 0 0; + transform: translateY(-100%); + opacity: 0; + } + 100% { + transform-origin: 0 0; + transform: translateY(0%); + opacity: 1; + } +} + +@keyframes antMoveUpOut { + 0% { + transform-origin: 0 0; + transform: translateY(0%); + opacity: 1; + } + 100% { + transform-origin: 0 0; + transform: translateY(-100%); + opacity: 0; + } +} diff --git a/components/style/core/motion/other.less b/components/style/core/motion/other.less new file mode 100644 index 000000000..f90f0912b --- /dev/null +++ b/components/style/core/motion/other.less @@ -0,0 +1,10 @@ +@keyframes loadingCircle { + 0% { + transform-origin: 50% 50%; + transform: rotate(0deg); + } + 100% { + transform-origin: 50% 50%; + transform: rotate(360deg); + } +} diff --git a/components/style/core/motion/slide.less b/components/style/core/motion/slide.less new file mode 100644 index 000000000..216cff084 --- /dev/null +++ b/components/style/core/motion/slide.less @@ -0,0 +1,120 @@ +.slide-motion(@className, @keyframeName) { + .make-motion(@className, @keyframeName); + .@{className}-enter, + .@{className}-appear { + opacity: 0; + animation-timing-function: @ease-out-quint; + } + .@{className}-leave { + animation-timing-function: @ease-in-quint; + } +} + +.slide-motion(slide-up, antSlideUp); +.slide-motion(slide-down, antSlideDown); +.slide-motion(slide-left, antSlideLeft); +.slide-motion(slide-right, antSlideRight); + +@keyframes antSlideUpIn { + 0% { + opacity: 0; + transform-origin: 0% 0%; + transform: scaleY(.8); + } + 100% { + opacity: 1; + transform-origin: 0% 0%; + transform: scaleY(1); + } +} + +@keyframes antSlideUpOut { + 0% { + opacity: 1; + transform-origin: 0% 0%; + transform: scaleY(1); + } + 100% { + opacity: 0; + transform-origin: 0% 0%; + transform: scaleY(.8); + } +} + +@keyframes antSlideDownIn { + 0% { + opacity: 0; + transform-origin: 100% 100%; + transform: scaleY(.8); + } + 100% { + opacity: 1; + transform-origin: 100% 100%; + transform: scaleY(1); + } +} + +@keyframes antSlideDownOut { + 0% { + opacity: 1; + transform-origin: 100% 100%; + transform: scaleY(1); + } + 100% { + opacity: 0; + transform-origin: 100% 100%; + transform: scaleY(.8); + } +} + +@keyframes antSlideLeftIn { + 0% { + opacity: 0; + transform-origin: 0% 0%; + transform: scaleX(.8); + } + 100% { + opacity: 1; + transform-origin: 0% 0%; + transform: scaleX(1); + } +} + +@keyframes antSlideLeftOut { + 0% { + opacity: 1; + transform-origin: 0% 0%; + transform: scaleX(1); + } + 100% { + opacity: 0; + transform-origin: 0% 0%; + transform: scaleX(.8); + } +} + +@keyframes antSlideRightIn { + 0% { + opacity: 0; + transform-origin: 100% 0%; + transform: scaleX(.8); + } + 100% { + opacity: 1; + transform-origin: 100% 0%; + transform: scaleX(1); + } +} + +@keyframes antSlideRightOut { + 0% { + opacity: 1; + transform-origin: 100% 0%; + transform: scaleX(1); + } + 100% { + opacity: 0; + transform-origin: 100% 0%; + transform: scaleX(.8); + } +} diff --git a/components/style/core/motion/swing.less b/components/style/core/motion/swing.less new file mode 100644 index 000000000..dcf299a01 --- /dev/null +++ b/components/style/core/motion/swing.less @@ -0,0 +1,33 @@ +.swing-motion(@className, @keyframeName) { + .@{className}-enter, + .@{className}-appear { + .motion-common(); + animation-play-state: paused; + } + .@{className}-enter.@{className}-enter-active, + .@{className}-appear.@{className}-appear-active { + animation-name: ~"@{keyframeName}In"; + animation-play-state: running; + } +} + +.swing-motion(swing, antSwing); + +@keyframes antSwingIn { + 0%, + 100% { + transform: translateX(0); + } + 20% { + transform: translateX(-10px); + } + 40% { + transform: translateX(10px); + } + 60% { + transform: translateX(-5px); + } + 80% { + transform: translateX(5px); + } +} diff --git a/components/style/core/motion/zoom.less b/components/style/core/motion/zoom.less new file mode 100644 index 000000000..420b42f8e --- /dev/null +++ b/components/style/core/motion/zoom.less @@ -0,0 +1,160 @@ +.zoom-motion(@className, @keyframeName, @duration: @animation-duration-base) { + .make-motion(@className, @keyframeName, @duration); + .@{className}-enter, + .@{className}-appear { + transform: scale(0); // need this by yiminghe + animation-timing-function: @ease-out-circ; + } + .@{className}-leave { + animation-timing-function: @ease-in-out-circ; + } +} + +// For Modal, Select choosen item +.zoom-motion(zoom, antZoom); +// For Popover, Popconfirm, Dropdown +.zoom-motion(zoom-big, antZoomBig); +// For Tooltip +.zoom-motion(zoom-big-fast, antZoomBig, @animation-duration-fast); + +.zoom-motion(zoom-up, antZoomUp); +.zoom-motion(zoom-down, antZoomDown); +.zoom-motion(zoom-left, antZoomLeft); +.zoom-motion(zoom-right, antZoomRight); + +@keyframes antZoomIn { + 0% { + opacity: 0; + transform: scale(0.2); + } + 100% { + opacity: 1; + transform: scale(1); + } +} + +@keyframes antZoomOut { + 0% { + transform: scale(1); + } + 100% { + opacity: 0; + transform: scale(0.2); + } +} + +@keyframes antZoomBigIn { + 0% { + opacity: 0; + transform: scale(.8); + } + 100% { + transform: scale(1); + } +} + +@keyframes antZoomBigOut { + 0% { + transform: scale(1); + } + 100% { + opacity: 0; + transform: scale(.8); + } +} + +@keyframes antZoomUpIn { + 0% { + opacity: 0; + transform-origin: 50% 0%; + transform: scale(.8); + } + 100% { + transform-origin: 50% 0%; + transform: scale(1); + } +} + +@keyframes antZoomUpOut { + 0% { + transform-origin: 50% 0%; + transform: scale(1); + } + 100% { + opacity: 0; + transform-origin: 50% 0%; + transform: scale(.8); + } +} + +@keyframes antZoomLeftIn { + 0% { + opacity: 0; + transform-origin: 0% 50%; + transform: scale(.8); + } + 100% { + transform-origin: 0% 50%; + transform: scale(1); + } +} + +@keyframes antZoomLeftOut { + 0% { + transform-origin: 0% 50%; + transform: scale(1); + } + 100% { + opacity: 0; + transform-origin: 0% 50%; + transform: scale(.8); + } +} + +@keyframes antZoomRightIn { + 0% { + opacity: 0; + transform-origin: 100% 50%; + transform: scale(.8); + } + 100% { + transform-origin: 100% 50%; + transform: scale(1); + } +} + +@keyframes antZoomRightOut { + 0% { + transform-origin: 100% 50%; + transform: scale(1); + } + 100% { + opacity: 0; + transform-origin: 100% 50%; + transform: scale(.8); + } +} + +@keyframes antZoomDownIn { + 0% { + opacity: 0; + transform-origin: 50% 100%; + transform: scale(.8); + } + 100% { + transform-origin: 50% 100%; + transform: scale(1); + } +} + +@keyframes antZoomDownOut { + 0% { + transform-origin: 50% 100%; + transform: scale(1); + } + 100% { + opacity: 0; + transform-origin: 50% 100%; + transform: scale(.8); + } +} diff --git a/components/style/core/normalize.less b/components/style/core/normalize.less new file mode 100644 index 000000000..bfc3448ea --- /dev/null +++ b/components/style/core/normalize.less @@ -0,0 +1,447 @@ +/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in + * IE on Windows Phone and in iOS. + */ + +html { + line-height: 1.15; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers (opinionated). + */ + +body { + margin: 0; +} + +/** + * Add the correct display in IE 9-. + */ + +article, +aside, +footer, +header, +nav, +section { + display: block; +} + +/** + * 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; +} + +/* Grouping content + ========================================================================== */ + +/** + * Add the correct display in IE 9-. + * 1. Add the correct display in IE. + */ + +figcaption, +figure, +main { /* 1 */ + display: block; +} + +/** + * 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 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ /* stylelint-disable-line */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * 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 */ +} + +/** + * 1. Remove the bottom border in Chrome 57- and 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; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ /* stylelint-disable-line */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font style in Android 4.3-. + */ + +dfn { + font-style: italic; +} + +/** + * 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 + ========================================================================== */ + +/** + * Add the correct display in IE 9-. + */ + +audio, +video { + display: inline-block; +} + +/** + * Add the correct display in iOS 4-7. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Remove the border on images inside links in IE 10-. + */ + +img { + border-style: none; +} + +/** + * Hide the overflow in IE. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers (opinionated). + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: sans-serif; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * 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; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 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 */ +} + +/** + * 1. Add the correct display in IE 9-. + * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ +} + +/** + * 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 macOS. + */ + +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 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 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in IE 9-. + * 1. Add the correct display in Edge, IE, and Firefox. + */ + +details, /* 1 */ +menu { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Scripting + ========================================================================== */ + +/** + * Add the correct display in IE 9-. + */ + +canvas { + display: inline-block; +} + +/** + * Add the correct display in IE. + */ + +template { + display: none; +} + +/* Hidden + ========================================================================== */ + +/** + * Add the correct display in IE 10-. + */ + +[hidden] { + display: none; +} diff --git a/components/style/index.js b/components/style/index.js new file mode 100644 index 000000000..1526e4dff --- /dev/null +++ b/components/style/index.js @@ -0,0 +1 @@ +import './index.less' diff --git a/components/style/index.less b/components/style/index.less new file mode 100644 index 000000000..a33fdfc3a --- /dev/null +++ b/components/style/index.less @@ -0,0 +1,2 @@ +@import "./themes/default"; +@import "./core/index"; diff --git a/components/style/mixins/clearfix.less b/components/style/mixins/clearfix.less new file mode 100644 index 000000000..d5bbf7670 --- /dev/null +++ b/components/style/mixins/clearfix.less @@ -0,0 +1,16 @@ +// mixins for clearfix +// ------------------------ +.clearfix() { + zoom: 1; + &:before, + &:after { + content: " "; + display: table; + } + &:after { + clear: both; + visibility: hidden; + font-size: 0; + height: 0; + } +} diff --git a/components/style/mixins/compatibility.less b/components/style/mixins/compatibility.less new file mode 100644 index 000000000..7e1202af4 --- /dev/null +++ b/components/style/mixins/compatibility.less @@ -0,0 +1,45 @@ +// Compatibility for browsers. + +// rotate for ie8 and blow +.ie-rotate(@rotation) { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation})"; +} + +// rotate for ie8 and blow +// degrees unit +.ie-rotate-via-degrees(@degrees) { + /* IE6-IE8 */ + @radians: ~`parseInt("@{degrees}") * Math.PI * 2 / 360`; + @costheta: ~`Math.cos("@{radians}")`; + @sintheta: ~`Math.sin("@{radians}")`; + @negsintheta: ~`"@{sintheta}" * -1`; + -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand', M11=@{costheta}, M12=@{negsintheta}, M21=@{sintheta}, M22=@{costheta})"; + zoom: 1; + + :root & { + filter: none; + } +} + +// support rotate for all browsers +.cross-rotate(@degrees) { + .rotate(@degrees); + .ie-rotate-via-degrees(@degrees); +} + +// Placeholder text +.placeholder(@color: @input-placeholder-color) { + // Firefox + &::-moz-placeholder { + color: @color; + opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526 + } + // Internet Explorer 10+ + &:-ms-input-placeholder { + color: @color; + } + // Safari and Chrome + &::-webkit-input-placeholder { + color: @color; + } +} diff --git a/components/style/mixins/iconfont.less b/components/style/mixins/iconfont.less new file mode 100644 index 000000000..cb85ddb51 --- /dev/null +++ b/components/style/mixins/iconfont.less @@ -0,0 +1,38 @@ +.iconfont-mixin() { + display: inline-block; + font-style: normal; + vertical-align: baseline; + text-align: center; + text-transform: none; + line-height: 1; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + &:before { + display: block; + font-family: "anticon" !important; + } +} + +.iconfont-font(@content) { + font-family: 'anticon'; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: @content; +} + +// for iconfont font size +// fix chrome 12px bug, support ie +.iconfont-size-under-12px(@size, @rotate: 0deg) { + display: inline-block; + @font-scale: unit(@size / 12px); + font-size: @font-size-base; + // ie8-9 + font-size: ~"@{size} \9"; // lesshint duplicateProperty: false + transform: scale(@font-scale) rotate(@rotate); + .ie-rotate-via-degrees(@rotate); + :root & { + font-size: @font-size-base; // reset ie9 and above + } +} diff --git a/components/style/mixins/index.less b/components/style/mixins/index.less new file mode 100644 index 000000000..c331b159f --- /dev/null +++ b/components/style/mixins/index.less @@ -0,0 +1,8 @@ +// Mixins +// -------------------------------------------------- +@import "opacity"; +@import "size"; +@import "compatibility"; +@import "clearfix"; +@import "iconfont"; +@import "motion"; diff --git a/components/style/mixins/motion.less b/components/style/mixins/motion.less new file mode 100644 index 000000000..84b2c82eb --- /dev/null +++ b/components/style/mixins/motion.less @@ -0,0 +1,33 @@ +@import '../themes/default'; + +.motion-common(@duration: @animation-duration-base) { + animation-duration: @duration; + animation-fill-mode: both; +} + +.motion-common-leave(@duration: @animation-duration-base) { + animation-duration: @duration; + animation-fill-mode: both; +} + +.make-motion(@className, @keyframeName, @duration: @animation-duration-base) { + .@{className}-enter, + .@{className}-appear { + .motion-common(@duration); + animation-play-state: paused; + } + .@{className}-leave { + .motion-common-leave(@duration); + animation-play-state: paused; + } + .@{className}-enter.@{className}-enter-active, + .@{className}-appear.@{className}-appear-active { + animation-name: ~"@{keyframeName}In"; + animation-play-state: running; + } + .@{className}-leave.@{className}-leave-active { + animation-name: ~"@{keyframeName}Out"; + animation-play-state: running; + pointer-events: none; + } +} diff --git a/components/style/mixins/opacity.less b/components/style/mixins/opacity.less new file mode 100644 index 000000000..33ed25ce6 --- /dev/null +++ b/components/style/mixins/opacity.less @@ -0,0 +1,8 @@ +// Opacity + +.opacity(@opacity) { + opacity: @opacity; + // IE8 filter + @opacity-ie: (@opacity * 100); + filter: ~"alpha(opacity=@{opacity-ie})"; +} diff --git a/components/style/mixins/size.less b/components/style/mixins/size.less new file mode 100644 index 000000000..a8be65089 --- /dev/null +++ b/components/style/mixins/size.less @@ -0,0 +1,10 @@ +// Sizing shortcuts + +.size(@width; @height) { + width: @width; + height: @height; +} + +.square(@size) { + .size(@size; @size); +} diff --git a/components/style/themes/default.less b/components/style/themes/default.less new file mode 100644 index 000000000..3179e6806 --- /dev/null +++ b/components/style/themes/default.less @@ -0,0 +1,362 @@ +/* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */ +@import "../color/colors"; + +// The prefix to use on all css classes from ant. +@ant-prefix : ant; + +// -------- Colors ----------- +@primary-color : @blue-6; +@info-color : @blue-6; +@success-color : @green-6; +@error-color : @red-6; +@highlight-color : @red-6; +@warning-color : @yellow-6; +@normal-color : #d9d9d9; + +// Color used by default to control hover and active backgrounds and for +// alert info backgrounds. +@primary-1: color(~`colorPalette("@{primary-color}", 1)`); // replace tint(@primary-color, 90%) +@primary-2: color(~`colorPalette("@{primary-color}", 2)`); // replace tint(@primary-color, 80%) +@primary-3: color(~`colorPalette("@{primary-color}", 3)`); // unused +@primary-4: color(~`colorPalette("@{primary-color}", 4)`); // unused +@primary-5: color(~`colorPalette("@{primary-color}", 5)`); // color used to control the text color in many active and hover states, replace tint(@primary-color, 20%) +@primary-6: @primary-color; // color used to control the text color of active buttons, don't use, use @primary-color +@primary-7: color(~`colorPalette("@{primary-color}", 7)`); // replace shade(@primary-color, 5%) +@primary-8: color(~`colorPalette("@{primary-color}", 8)`); // unused +@primary-9: color(~`colorPalette("@{primary-color}", 9)`); // unused +@primary-10: color(~`colorPalette("@{primary-color}", 10)`); // unused + +// Base Scaffolding Variables +// --- + +// Background color for `` +@body-background : #fff; +// Base background color for most components +@component-background : #fff; +@font-family-no-number : -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif; +@font-family : "Helvetica Neue For Number", @font-family-no-number; +@code-family : Consolas, Menlo, Courier, monospace; +@heading-color : fade(#000, 85%); +@text-color : fade(#000, 65%); +@text-color-secondary : fade(#000, 43%); +@heading-color-dark : fade(#fff, 97%); +@text-color-dark : fade(#fff, 91%); +@text-color-secondary-dark: fade(#fff, 67%); +@font-size-base : 12px; +@font-size-lg : @font-size-base + 2px; +@line-height-base : 1.5; +@border-radius-base : 4px; +@border-radius-sm : 2px; + +// The background colors for active and hover states for things like +// list items or table cells. +@item-active-bg : @primary-1; +@item-hover-bg : @primary-1; + +// ICONFONT +@iconfont-css-prefix : anticon; +@icon-url : "https://at.alicdn.com/t/font_zck90zmlh7hf47vi"; + +// LINK +@link-color : @primary-color; +@link-hover-color : @primary-5; +@link-active-color : @primary-7; +@link-decoration : none; +@link-hover-decoration : none; + +// Animation +@ease-out : cubic-bezier(0.215, 0.61, 0.355, 1); +@ease-in : cubic-bezier(0.55, 0.055, 0.675, 0.19); +@ease-in-out : cubic-bezier(0.645, 0.045, 0.355, 1); +@ease-out-back : cubic-bezier(0.12, 0.4, 0.29, 1.46); +@ease-in-back : cubic-bezier(0.71, -0.46, 0.88, 0.6); +@ease-in-out-back : cubic-bezier(0.71, -0.46, 0.29, 1.46); +@ease-out-circ : cubic-bezier(0.08, 0.82, 0.17, 1); +@ease-in-circ : cubic-bezier(0.6, 0.04, 0.98, 0.34); +@ease-in-out-circ : cubic-bezier(0.78, 0.14, 0.15, 0.86); +@ease-out-quint : cubic-bezier(0.23, 1, 0.32, 1); +@ease-in-quint : cubic-bezier(0.755, 0.05, 0.855, 0.06); +@ease-in-out-quint : cubic-bezier(0.86, 0, 0.07, 1); + +// Border color +@border-color-base : #d9d9d9; // base border outline a component +@border-color-split : #e9e9e9; // split border inside a component +@border-width-base : 1px; // width of the border for a component +@border-style-base : solid; // style of a components border + +// Outline +@outline-blur-size : 0; +@outline-width : 2px; +@outline-color : @primary-color; + +// Default background color for disabled states, Collapse wrappers, +// and several active and hover states. +@background-color-base : #f7f7f7; +@background-color-active: #eee; + +// Disabled states +@disabled-color : fade(#000, 25%); +@disabled-bg : @background-color-base; +@disabled-color-dark : fade(#fff, 35%); + +// Shadow +@shadow-color : rgba(0, 0, 0, .2); +@box-shadow-base : @shadow-1-down; +@shadow-1-up : 0 -1px 6px @shadow-color; +@shadow-1-down : 0 1px 6px @shadow-color; +@shadow-1-left : -1px 0 6px @shadow-color; +@shadow-1-right : 1px 0 6px @shadow-color; +@shadow-2 : 0 2px 8px @shadow-color; + +// Buttons +@btn-font-weight : 500; +@btn-border-radius-base : @border-radius-base; +@btn-border-radius-sm : @border-radius-base; + +@btn-primary-color : #fff; +@btn-primary-bg : @primary-color; + +@btn-default-color : @text-color; +@btn-default-bg : #fff; +@btn-default-border : @border-color-base; + +@btn-danger-color : @error-color; +@btn-danger-bg : @background-color-base; +@btn-danger-border : @border-color-base; + +@btn-disable-color : @disabled-color; +@btn-disable-bg : @disabled-bg; +@btn-disable-border : @border-color-base; + +@btn-padding-base : 0 15px; +@btn-font-size-lg : @font-size-lg; +@btn-padding-lg : @btn-padding-base; +@btn-padding-sm : 0 7px; + +@btn-height-base : 28px; +@btn-height-lg : 32px; +@btn-height-sm : 22px; + +@btn-circle-size : @btn-height-base; +@btn-circle-size-lg : @btn-height-lg; +@btn-circle-size-sm : @btn-height-sm; + +@btn-group-border : @primary-7; + +// Checkbox +@checkbox-size : 14px; + +// Radio buttons +@radio-button-bg : @btn-default-bg; +@radio-button-color : @btn-default-color; + +// Media queries breakpoints +// Extra small screen / phone +@screen-xs : 480px; +@screen-xs-min : @screen-xs; + +// Small screen / tablet +@screen-sm : 768px; +@screen-sm-min : @screen-sm; + +// Medium screen / desktop +@screen-md : 992px; +@screen-md-min : @screen-md; + +// Large screen / wide desktop +@screen-lg : 1200px; +@screen-lg-min : @screen-lg; + +// Extra Large screen / full hd +@screen-xl : 1600px; +@screen-xl-min : @screen-xl; + +// provide a maximum +@screen-xs-max : (@screen-sm-min - 1px); +@screen-sm-max : (@screen-md-min - 1px); +@screen-md-max : (@screen-lg-min - 1px); +@screen-lg-max : (@screen-xl-min - 1px); + +// Grid system +@grid-columns : 24; +@grid-gutter-width : 0; + +// Layout +@layout-body-background : #ececec; +@layout-header-background : #404040; +@layout-footer-background : @layout-body-background; +@layout-header-height : 64px; +@layout-header-padding : 0 50px; +@layout-footer-padding : 24px 50px; +@layout-sider-background : @layout-header-background; +@layout-trigger-height : 48px; +@layout-trigger-background : tint(@heading-color, 20%); +@layout-trigger-color : #fff; +@layout-zero-trigger-width : 36px; +@layout-zero-trigger-height : 42px; + +// z-index list +@zindex-affix : 10; +@zindex-back-top : 10; +@zindex-modal-mask : 1000; +@zindex-modal : 1000; +@zindex-notification : 1010; +@zindex-message : 1010; +@zindex-popover : 1030; +@zindex-picker : 1050; +@zindex-dropdown : 1050; +@zindex-tooltip : 1060; + +// Animation +@animation-duration-slow: .3s; // Modal +@animation-duration-base: .2s; +@animation-duration-fast: .1s; // Tooltip + +// Form +// --- +@label-required-color : @highlight-color; +@label-color : @heading-color; +@form-item-margin-bottom : 24px; +@form-item-trailing-colon : true; +@form-vertical-label-padding : 0 0 8px; +@form-vertical-label-margin : 0; + +// Input +// --- +@input-height-base : 28px; +@input-height-lg : 32px; +@input-height-sm : 22px; +@input-padding-horizontal : 7px; +@input-padding-horizontal-base : @input-padding-horizontal; +@input-padding-horizontal-sm : @input-padding-horizontal; +@input-padding-horizontal-lg : @input-padding-horizontal; +@input-padding-vertical-base : 4px; +@input-padding-vertical-sm : 1px; +@input-padding-vertical-lg : 6px; +@input-placeholder-color : hsv(0, 0, 75%); +@input-color : @text-color; +@input-border-color : @border-color-base; +@input-bg : #fff; +@input-addon-bg : #eee; +@input-hover-border-color : @primary-color; +@input-disabled-bg : @disabled-bg; + +// Tooltip +// --- +//* Tooltip max width +@tooltip-max-width: 250px; +//** Tooltip text color +@tooltip-color: #fff; +//** Tooltip background color +@tooltip-bg: rgba(0, 0, 0, .75); +//** Tooltip arrow width +@tooltip-arrow-width: 5px; +//** Tooltip distance with trigger +@tooltip-distance: @tooltip-arrow-width - 1px + 4px; +//** Tooltip arrow color +@tooltip-arrow-color: @tooltip-bg; + +// Popover +// --- +//** Popover body background color +@popover-bg: #fff; +//** Popover text color +@popover-color: @text-color; +//** Popover maximum width +@popover-min-width: 177px; +//** Popover arrow width +@popover-arrow-width: 4px; +//** Popover arrow color +@popover-arrow-color: @popover-bg; +//** Popover outer arrow width +@popover-arrow-outer-width: (@popover-arrow-width + 1px); +//** Popover outer arrow color +@popover-arrow-outer-color: fadeout(@border-color-base, 30%); +//** Popover distance with trigger +@popover-distance: @popover-arrow-width + 4px; + +// Modal +// -- +@modal-mask-bg: rgba(55, 55, 55, 0.6); + +// Progress +// -- +@process-default-color: @primary-color; +@progress-remaining-color: @background-color-base; + +// Menu +// --- +@menu-dark-bg: @layout-header-background; +@menu-dark-submenu-bg: #333; +@menu-collapsed-width: 64px; + +// Spin +// --- +@spin-dot-size-sm: 14px; +@spin-dot-size: 20px; +@spin-dot-size-lg: 32px; + +// Table +// -- +@table-header-bg: @background-color-base; +@table-header-sort-bg: @background-color-active; +@table-row-hover-bg: @primary-1; +@table-selected-row-bg: #fafafa; +@table-padding-vertical: 16px; +@table-padding-horizontal: 8px; + +// Tag +// -- +@tag-default-bg: #f3f3f3; +@tag-default-color: @text-color; +@tag-font-size: @font-size-base; + +// TimePicker +// --- +@time-picker-panel-column-width: 56px; +@time-picker-panel-width: @time-picker-panel-column-width * 3; +@time-picker-selected-bg: @background-color-base; + +// Carousel +// --- +@carousel-dot-width: 16px; +@carousel-dot-height: 3px; +@carousel-dot-active-width: 24px; + +// Badge +// --- +@badge-height: 20px; +@badge-dot-size: 8px; +@badge-font-size: @font-size-base; + +// Rate +// --- +@rate-star-color: #f5a623; +@rate-star-bg: #e9e9e9; + +// Card +// --- +@card-head-height: 48px; +@card-head-color: @heading-color; +@card-head-background: @component-background; + +// Tabs +// --- +@tabs-card-head-background: #f9f9f9; +@tabs-title-font-size: @font-size-lg; + +// BackTop +@back-top-color: #fff; +@back-top-bg: rgba(64, 64, 64, 0.4); +@back-top-hover-bg: rgba(64, 64, 64, 0.6); + +// Avatar +@avatar-size-base: 32px; +@avatar-size-lg: 40px; +@avatar-size-sm: 24px; +@avatar-font-size-base: 18px; +@avatar-font-size-lg: 24px; +@avatar-font-size-sm: 14px; +@avatar-bg: #ccc; +@avatar-color: #fff; +@avatar-border-radius: @border-radius-base; diff --git a/examples/button.vue b/examples/button.vue new file mode 100644 index 000000000..f3c007fc7 --- /dev/null +++ b/examples/button.vue @@ -0,0 +1,95 @@ + + diff --git a/examples/checkbox.vue b/examples/checkbox.vue new file mode 100644 index 000000000..42da048a0 --- /dev/null +++ b/examples/checkbox.vue @@ -0,0 +1,58 @@ + + diff --git a/examples/dialog.vue b/examples/dialog.vue new file mode 100644 index 000000000..63e70c3d4 --- /dev/null +++ b/examples/dialog.vue @@ -0,0 +1,29 @@ + + diff --git a/examples/index.html b/examples/index.html new file mode 100644 index 000000000..afca69c77 --- /dev/null +++ b/examples/index.html @@ -0,0 +1,11 @@ + + + + + + +
+ + + + diff --git a/examples/index.js b/examples/index.js new file mode 100644 index 000000000..e9a228266 --- /dev/null +++ b/examples/index.js @@ -0,0 +1,19 @@ +import Vue from 'vue' +import Checkbox from './checkbox.vue' +import Button from './button.vue' +// import Dialog from './dialog.vue' +import './index.less' +new Vue({ + el: '#app', + template: ` +
+ + +
+ `, + components: { + AntButton: Button, + // AntDialog: Dialog, + Checkbox, + }, +}) diff --git a/examples/index.less b/examples/index.less new file mode 100644 index 000000000..e69de29bb diff --git a/package.json b/package.json new file mode 100644 index 000000000..e953784ea --- /dev/null +++ b/package.json @@ -0,0 +1,56 @@ +{ + "name": "vue-ant-design", + "version": "1.0.0", + "description": "vue component", + "main": "index.js", + "scripts": { + "start": "NODE_ENV=development webpack-dev-server --open --hot", + "test": "echo \"Error: no test specified\" && exit 1", + "lint": "eslint -c ./.eslintrc --fix --ext .js ./src/", + "lint:style": "stylelint \"./src/**/*.less\" --syntax less" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/vueComponent/ant-design.git" + }, + "keywords": [ + "vue" + ], + "author": "", + "license": "MIT", + "bugs": { + "url": "https://github.com/vueComponent/ant-design/issues" + }, + "homepage": "https://github.com/vueComponent/ant-design#readme", + "pre-commit": [ + "lint", + "lint:style" + ], + "devDependencies": { + "babel-cli": "^6.26.0", + "babel-helper-vue-jsx-merge-props": "^2.0.2", + "babel-loader": "^7.1.2", + "babel-plugin-syntax-jsx": "^6.18.0", + "babel-plugin-transform-vue-jsx": "^3.5.0", + "babel-preset-env": "^1.6.0", + "css-loader": "^0.28.7", + "eslint": "^4.7.2", + "eslint-plugin-html": "^3.2.2", + "eslint-plugin-vue-libs": "^1.2.1", + "html-webpack-plugin": "^2.30.1", + "less": "^2.7.2", + "less-loader": "^4.0.5", + "pre-commit": "^1.2.2", + "style-loader": "^0.18.2", + "stylelint": "^8.1.1", + "stylelint-config-standard": "^17.0.0", + "vue": "^2.4.4", + "vue-loader": "^13.0.5", + "vue-template-compiler": "^2.4.4", + "webpack": "^3.6.0", + "webpack-dev-server": "^2.8.2" + }, + "dependencies": { + "eslint-plugin-vue": "^3.13.0" + } +} diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 000000000..d07132861 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,87 @@ +const path = require('path') +const webpack = require('webpack') + +module.exports = { + entry: { + index: [ + './examples/index.js', + ], + }, + output: { + path: path.resolve(__dirname, './dist'), + publicPath: '/dist/', + filename: 'build.js', + }, + module: { + rules: [ + { + test: /\.vue$/, + loader: 'vue-loader', + }, + { + test: /\.js$/, + loader: 'babel-loader', exclude: /node_modules/, + }, + { + test: /\.(png|jpg|gif|svg)$/, + loader: 'file-loader', + options: { + name: '[name].[ext]?[hash]', + }, + }, + { + test: /\.less$/, + use: [ + { loader: 'style-loader' }, + { + loader: 'css-loader', + options: { sourceMap: true }, + }, + { loader: 'less-loader', + options: { sourceMap: true }, + }, + ], + }, + ], + }, + resolve: { + extensions: ['.js', '.vue'], + alias: { + 'vue$': 'vue/dist/vue.esm.js', + }, + }, + devServer: { + port: 3000, + inline: true, + historyApiFallback: { + index: 'examples/index.html', + }, + disableHostCheck: true, + headers: { 'Access-Control-Allow-Origin': '*' }, + }, + performance: { + hints: false, + }, + devtool: '#eval-source-map', +} + +if (process.env.NODE_ENV === 'production') { + module.exports.devtool = '#source-map' + // http://vue-loader.vuejs.org/en/workflow/production.html + module.exports.plugins = (module.exports.plugins || []).concat([ + new webpack.DefinePlugin({ + 'process.env': { + NODE_ENV: '"production"', + }, + }), + new webpack.optimize.UglifyJsPlugin({ + sourceMap: true, + compress: { + warnings: false, + }, + }), + new webpack.LoaderOptionsPlugin({ + minimize: true, + }), + ]) +} From 894f6031faa36049b1f5a16016fac56c0b508614 Mon Sep 17 00:00:00 2001 From: wanlei Date: Thu, 26 Oct 2017 21:28:55 +0800 Subject: [PATCH 02/47] update: [BUG] wired bug for 'validator' --- .gitignore | 3 +- package.json | 20 ++++++++++- test/.eslintrc | 12 +++++++ test/index.js | 13 +++++++ test/karma.conf.js | 74 +++++++++++++++++++++++++++++++++++++++ test/specs/Button.spec.js | 14 ++++++++ 6 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 test/.eslintrc create mode 100644 test/index.js create mode 100644 test/karma.conf.js create mode 100644 test/specs/Button.spec.js diff --git a/.gitignore b/.gitignore index 00cbbdf53..6cbb08205 100644 --- a/.gitignore +++ b/.gitignore @@ -56,4 +56,5 @@ typings/ # dotenv environment variables file .env - +.idea +.DS_Store diff --git a/package.json b/package.json index e953784ea..52f8aef48 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "start": "NODE_ENV=development webpack-dev-server --open --hot", - "test": "echo \"Error: no test specified\" && exit 1", + "test": "karma start test/karma.conf.js --single-run", "lint": "eslint -c ./.eslintrc --fix --ext .js ./src/", "lint:style": "stylelint \"./src/**/*.less\" --syntax less" }, @@ -30,17 +30,35 @@ "babel-cli": "^6.26.0", "babel-helper-vue-jsx-merge-props": "^2.0.2", "babel-loader": "^7.1.2", + "babel-plugin-istanbul": "^4.1.1", "babel-plugin-syntax-jsx": "^6.18.0", "babel-plugin-transform-vue-jsx": "^3.5.0", "babel-preset-env": "^1.6.0", + "chai": "^4.1.2", "css-loader": "^0.28.7", "eslint": "^4.7.2", "eslint-plugin-html": "^3.2.2", "eslint-plugin-vue-libs": "^1.2.1", "html-webpack-plugin": "^2.30.1", + "istanbul-instrumenter-loader": "^3.0.0", + "karma": "^1.4.1", + "karma-coverage": "^1.1.1", + "karma-coverage-istanbul-reporter": "^1.3.0", + "karma-mocha": "^1.3.0", + "karma-phantomjs-launcher": "^1.0.2", + "karma-phantomjs-shim": "^1.4.0", + "karma-sinon-chai": "^1.3.1", + "karma-sourcemap-loader": "^0.3.7", + "karma-spec-reporter": "0.0.31", + "karma-webpack": "^2.0.2", "less": "^2.7.2", "less-loader": "^4.0.5", + "mocha": "^3.2.0", "pre-commit": "^1.2.2", + "selenium-server": "^3.0.1", + "semver": "^5.3.0", + "sinon": "^4.0.2", + "sinon-chai": "^2.8.0", "style-loader": "^0.18.2", "stylelint": "^8.1.1", "stylelint-config-standard": "^17.0.0", diff --git a/test/.eslintrc b/test/.eslintrc new file mode 100644 index 000000000..009f94936 --- /dev/null +++ b/test/.eslintrc @@ -0,0 +1,12 @@ +{ + "extends": ["plugin:vue-libs/recommended"], // ,"plugin:vue-libs/recommended" + "rules": { + "comma-dangle": [2, "always-multiline"], + "no-var": "error" + }, + "globals": { + "it": true, + "describe": true, + "expect": true + } +} diff --git a/test/index.js b/test/index.js new file mode 100644 index 000000000..26d0ce27a --- /dev/null +++ b/test/index.js @@ -0,0 +1,13 @@ +import Vue from 'vue' + +Vue.config.productionTip = false + +// require all test files (files that ends with .spec.js) +const testsContext = require.context('./specs', true, /\.spec$/) +testsContext.keys().forEach(testsContext) + +// require all src files except main.js for coverage. +// you can also change this to match only the subset of files that +// you want coverage for. +const srcContext = require.context('../components', true, /^\.(\.js|\.vue)?$/) +srcContext.keys().forEach(srcContext) diff --git a/test/karma.conf.js b/test/karma.conf.js new file mode 100644 index 000000000..14eae52a2 --- /dev/null +++ b/test/karma.conf.js @@ -0,0 +1,74 @@ +// This is a karma config file. For more details see +// http://karma-runner.github.io/0.13/config/configuration-file.html +// we are also using it with karma-webpack +// https://github.com/webpack/karma-webpack + +const webpack = require('webpack') +const webpackConfig = require('../webpack.config') + +module.exports = function (config) { + config.set({ + // to run in additional browsers: + // 1. install corresponding karma launcher + // http://karma-runner.github.io/0.13/config/browsers.html + // 2. add it to the `browsers` array below. + browsers: ['PhantomJS'], + frameworks: ['mocha', 'sinon-chai'], + reporters: ['spec', 'coverage-istanbul'], + files: ['./index.js'], + preprocessors: { + './index.js': ['webpack', 'sourcemap', 'coverage'], + }, + webpack: { + module: { + rules: [ + { + test: /\.vue$/, + loader: 'vue-loader', + options: { + loaders: { + js: 'babel-loader', + }, + postLoaders: { + js: 'istanbul-instrumenter-loader?esModules=true', + }, + }, + }, + { + test: /\.js$/, + loader: 'babel-loader', exclude: /node_modules/, + }, + { + test: /\.(png|jpg|gif|svg)$/, + loader: 'file-loader', + options: { + name: '[name].[ext]?[hash]', + }, + }, + { + test: /\.less$/, + use: [ + { loader: 'style-loader' }, + { + loader: 'css-loader', + options: { sourceMap: true }, + }, + { loader: 'less-loader', + options: { sourceMap: true }, + }, + ], + }, + ], + }, + }, + webpackMiddleware: { + noInfo: true, + }, + coverageReporter: { + dir: './coverage', + reporters: [ + { type: 'text-summary' }, + ], + }, + }) +} diff --git a/test/specs/Button.spec.js b/test/specs/Button.spec.js new file mode 100644 index 000000000..33564af39 --- /dev/null +++ b/test/specs/Button.spec.js @@ -0,0 +1,14 @@ +import Vue from 'vue' +import Button from '../../components/button' + +describe('Button.vue', () => { + it('should render correct contents', () => { + const Constructor = Vue.extend(Button) + const ele = document.createElement('div') + document.body.appendChild(ele) + const vm = new Constructor({ propsData: { type: 'primary' }}) + vm.$mount(ele) + expect(vm.$el.classList.contains('ant-btn-primary')) + .to.equal(true) + }) +}) From 3290cdf114670d14b9ba8949665115cdd05a50a7 Mon Sep 17 00:00:00 2001 From: wanlei Date: Fri, 27 Oct 2017 13:24:22 +0800 Subject: [PATCH 03/47] update: [Grid] merged from vue-component/grid --- .babelrc | 7 +- components/grid/col.vue | 85 ++++++++++++++++++++++++ components/grid/index.js | 7 ++ components/grid/row.vue | 79 +++++++++++++++++++++++ components/grid/style/index.js | 2 + components/grid/style/index.less | 107 +++++++++++++++++++++++++++++++ components/grid/style/mixin.less | 100 +++++++++++++++++++++++++++++ components/index.js | 3 + examples/grid.vue | 98 ++++++++++++++++++++++++++++ examples/index.js | 7 +- package.json | 3 + 11 files changed, 495 insertions(+), 3 deletions(-) create mode 100644 components/grid/col.vue create mode 100644 components/grid/index.js create mode 100644 components/grid/row.vue create mode 100644 components/grid/style/index.js create mode 100644 components/grid/style/index.less create mode 100644 components/grid/style/mixin.less create mode 100644 examples/grid.vue diff --git a/.babelrc b/.babelrc index 3bde2e0da..b30bba26a 100644 --- a/.babelrc +++ b/.babelrc @@ -1,4 +1,9 @@ { "presets": ["env"], - "plugins": ["transform-vue-jsx"] + "plugins": [ + "transform-vue-jsx", + "transform-es2015-destructuring", + "transform-es2015-parameters", + "transform-object-rest-spread" + ] } diff --git a/components/grid/col.vue b/components/grid/col.vue new file mode 100644 index 000000000..6a01bacfb --- /dev/null +++ b/components/grid/col.vue @@ -0,0 +1,85 @@ + + diff --git a/components/grid/index.js b/components/grid/index.js new file mode 100644 index 000000000..352a384d8 --- /dev/null +++ b/components/grid/index.js @@ -0,0 +1,7 @@ +import Row from './row.vue' +import Col from './col.vue' + +export default { + Col, Row, +} + diff --git a/components/grid/row.vue b/components/grid/row.vue new file mode 100644 index 000000000..65f76f579 --- /dev/null +++ b/components/grid/row.vue @@ -0,0 +1,79 @@ + + + diff --git a/components/grid/style/index.js b/components/grid/style/index.js new file mode 100644 index 000000000..cf31ed80f --- /dev/null +++ b/components/grid/style/index.js @@ -0,0 +1,2 @@ +import '../../style/index.less' +import './index.less' diff --git a/components/grid/style/index.less b/components/grid/style/index.less new file mode 100644 index 000000000..9671dc96d --- /dev/null +++ b/components/grid/style/index.less @@ -0,0 +1,107 @@ +@import "../../style/themes/default"; +@import "../../style/mixins/index"; +@import "./mixin"; + +// Grid system +.@{ant-prefix}-row { + .make-row(); + display: block; +} + +.@{ant-prefix}-row-flex { + display: flex; + flex-flow: row wrap; + + &:before, + &:after { + display: flex; + } +} + +// x轴原点 +.@{ant-prefix}-row-flex-start { + justify-content: flex-start; +} + +// x轴居中 +.@{ant-prefix}-row-flex-center { + justify-content: center; +} + +// x轴反方向 +.@{ant-prefix}-row-flex-end { + justify-content: flex-end; +} + +// x轴平分 +.@{ant-prefix}-row-flex-space-between { + justify-content: space-between; +} + +// x轴有间隔地平分 +.@{ant-prefix}-row-flex-space-around { + justify-content: space-around; +} + +// 顶部对齐 +.@{ant-prefix}-row-flex-top { + align-items: flex-start; +} + +// 居中对齐 +.@{ant-prefix}-row-flex-middle { + align-items: center; +} + +// 底部对齐 +.@{ant-prefix}-row-flex-bottom { + align-items: flex-end; +} + +.@{ant-prefix}-col { + position: relative; + display: block; +} + +.make-grid-columns(); +.make-grid(); + +// Extra small grid +// +// Columns, offsets, pushes, and pulls for extra small devices like +// smartphones. + +.make-grid(-xs); + +// Small grid +// +// Columns, offsets, pushes, and pulls for the small device range, from phones +// to tablets. + +@media (min-width: @screen-sm-min) { + .make-grid(-sm); +} + +// Medium grid +// +// Columns, offsets, pushes, and pulls for the desktop device range. + +@media (min-width: @screen-md-min) { + .make-grid(-md); +} + +// Large grid +// +// Columns, offsets, pushes, and pulls for the large desktop device range. + +@media (min-width: @screen-lg-min) { + .make-grid(-lg); +} + +// Extra Large grid +// +// Columns, offsets, pushes, and pulls for the full hd device range. + +@media (min-width: @screen-xl-min) { + .make-grid(-xl); +} diff --git a/components/grid/style/mixin.less b/components/grid/style/mixin.less new file mode 100644 index 000000000..ad6ed9623 --- /dev/null +++ b/components/grid/style/mixin.less @@ -0,0 +1,100 @@ +@import "../../style/mixins/index"; + +// mixins for grid system +// ------------------------ +.make-row(@gutter: @grid-gutter-width) { + position: relative; + margin-left: (@gutter / -2); + margin-right: (@gutter / -2); + height: auto; + .clearfix; +} + +.make-grid-columns() { + .col(@index) { + @item: ~".@{ant-prefix}-col-@{index}, .@{ant-prefix}-col-xs-@{index}, .@{ant-prefix}-col-sm-@{index}, .@{ant-prefix}-col-md-@{index}, .@{ant-prefix}-col-lg-@{index}"; + .col((@index + 1), @item); + } + .col(@index, @list) when (@index =< @grid-columns) { + @item: ~".@{ant-prefix}-col-@{index}, .@{ant-prefix}-col-xs-@{index}, .@{ant-prefix}-col-sm-@{index}, .@{ant-prefix}-col-md-@{index}, .@{ant-prefix}-col-lg-@{index}"; + .col((@index + 1), ~"@{list}, @{item}"); + } + .col(@index, @list) when (@index > @grid-columns) { + @{list} { + position: relative; + // Prevent columns from collapsing when empty + min-height: 1px; + padding-left: (@grid-gutter-width / 2); + padding-right: (@grid-gutter-width / 2); + } + } + .col(1); +} + +.float-grid-columns(@class) { + .col(@index) { // initial + @item: ~".@{ant-prefix}-col@{class}-@{index}"; + .col((@index + 1), @item); + } + .col(@index, @list) when (@index =< @grid-columns) { // general + @item: ~".@{ant-prefix}-col@{class}-@{index}"; + .col((@index + 1), ~"@{list}, @{item}"); + } + .col(@index, @list) when (@index > @grid-columns) { // terminal + @{list} { + float: left; + flex: 0 0 auto; + } + } + .col(1); // kickstart it +} + +// lesshint false +.loop-grid-columns(@index, @class) when (@index > 0) { + .@{ant-prefix}-col@{class}-@{index} { + display: block; + width: percentage((@index / @grid-columns)); + } + .@{ant-prefix}-col@{class}-push-@{index} { + left: percentage((@index / @grid-columns)); + } + .@{ant-prefix}-col@{class}-pull-@{index} { + right: percentage((@index / @grid-columns)); + } + .@{ant-prefix}-col@{class}-offset-@{index} { + margin-left: percentage((@index / @grid-columns)); + } + .@{ant-prefix}-col@{class}-order-@{index} { + order: @index; + } + .loop-grid-columns((@index - 1), @class); +} + +.loop-grid-columns(@index, @class) when (@index = 0) { + .@{ant-prefix}-col@{class}-@{index} { + display: none; + } + .@{ant-prefix}-col-push-@{index} { + left: auto; + } + .@{ant-prefix}-col-pull-@{index} { + right: auto; + } + .@{ant-prefix}-col@{class}-push-@{index} { + left: auto; + } + .@{ant-prefix}-col@{class}-pull-@{index} { + right: auto; + } + .@{ant-prefix}-col@{class}-offset-@{index} { + margin-left: 0; + } + .@{ant-prefix}-col@{class}-order-@{index} { + order: 0; + } +} + +.make-grid(@class: ~'') { + .float-grid-columns(@class); + .loop-grid-columns(@grid-columns, @class); +} diff --git a/components/index.js b/components/index.js index 8a85844b2..07c0894d2 100644 --- a/components/index.js +++ b/components/index.js @@ -1,9 +1,12 @@ import './button/style' import './checkbox/style' import './icon/style' +import './grid/style' export { default as Button } from './button' export { default as Checkbox } from './checkbox' export { default as Icon } from './icon' + +export { default as Grid } from './grid' diff --git a/examples/grid.vue b/examples/grid.vue new file mode 100644 index 000000000..a721853b9 --- /dev/null +++ b/examples/grid.vue @@ -0,0 +1,98 @@ + + + diff --git a/examples/index.js b/examples/index.js index e9a228266..aea31b30f 100644 --- a/examples/index.js +++ b/examples/index.js @@ -1,19 +1,22 @@ import Vue from 'vue' import Checkbox from './checkbox.vue' import Button from './button.vue' +import Grid from './grid.vue' // import Dialog from './dialog.vue' import './index.less' new Vue({ el: '#app', template: `
- - + + +
`, components: { AntButton: Button, // AntDialog: Dialog, Checkbox, + Grid, }, }) diff --git a/package.json b/package.json index 52f8aef48..fb59e8dae 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,9 @@ "babel-loader": "^7.1.2", "babel-plugin-istanbul": "^4.1.1", "babel-plugin-syntax-jsx": "^6.18.0", + "babel-plugin-transform-es2015-destructuring": "^6.23.0", + "babel-plugin-transform-es2015-parameters": "^6.24.1", + "babel-plugin-transform-object-rest-spread": "^6.26.0", "babel-plugin-transform-vue-jsx": "^3.5.0", "babel-preset-env": "^1.6.0", "chai": "^4.1.2", From 3983e6d5b8c1c313d97e9163bf6ef0f3245e9922 Mon Sep 17 00:00:00 2001 From: tangjinzhou <415800467@qq.com> Date: Fri, 27 Oct 2017 14:04:48 +0800 Subject: [PATCH 04/47] radio --- .../{checkbox-group.vue => Group.vue} | 6 +- components/checkbox/checkbox.vue | 3 - components/checkbox/index.js | 4 +- components/index.js | 3 + components/radio/Group.vue | 81 +++++ components/radio/Radio.vue | 79 +++++ components/radio/RadioButton.vue | 0 components/radio/index.js | 6 + components/radio/style/index.js | 2 + components/radio/style/index.less | 279 ++++++++++++++++++ examples/checkbox.vue | 2 +- examples/index.js | 3 + examples/radio.vue | 52 ++++ 13 files changed, 509 insertions(+), 11 deletions(-) rename components/checkbox/{checkbox-group.vue => Group.vue} (96%) create mode 100644 components/radio/Group.vue create mode 100644 components/radio/Radio.vue create mode 100644 components/radio/RadioButton.vue create mode 100644 components/radio/index.js create mode 100644 components/radio/style/index.js create mode 100644 components/radio/style/index.less create mode 100644 examples/radio.vue diff --git a/components/checkbox/checkbox-group.vue b/components/checkbox/Group.vue similarity index 96% rename from components/checkbox/checkbox-group.vue rename to components/checkbox/Group.vue index 684d939a9..8d1ddf51c 100644 --- a/components/checkbox/checkbox-group.vue +++ b/components/checkbox/Group.vue @@ -6,7 +6,7 @@ diff --git a/components/radio/Radio.vue b/components/radio/Radio.vue new file mode 100644 index 000000000..cfc568780 --- /dev/null +++ b/components/radio/Radio.vue @@ -0,0 +1,79 @@ + + diff --git a/components/radio/RadioButton.vue b/components/radio/RadioButton.vue new file mode 100644 index 000000000..e69de29bb diff --git a/components/radio/index.js b/components/radio/index.js new file mode 100644 index 000000000..56c40cc32 --- /dev/null +++ b/components/radio/index.js @@ -0,0 +1,6 @@ +import Radio from './Radio.vue' +import RadioGroup from './Group.vue' + +Radio.Group = RadioGroup +export default Radio + diff --git a/components/radio/style/index.js b/components/radio/style/index.js new file mode 100644 index 000000000..cf31ed80f --- /dev/null +++ b/components/radio/style/index.js @@ -0,0 +1,2 @@ +import '../../style/index.less' +import './index.less' diff --git a/components/radio/style/index.less b/components/radio/style/index.less new file mode 100644 index 000000000..7d9c4b06e --- /dev/null +++ b/components/radio/style/index.less @@ -0,0 +1,279 @@ +@import "../../style/themes/default"; +@import "../../style/mixins/index"; + +@radio-prefix-cls: ~"@{ant-prefix}-radio"; +@radio-group-prefix-cls: ~"@{radio-prefix-cls}-group"; +@radio-inner-prefix-cls: ~"@{radio-prefix-cls}-inner"; +@radio-duration: .3s; + +.@{radio-group-prefix-cls} { + display: inline-block; + font-size: @font-size-base; +} + +// 一般状态 +.@{radio-prefix-cls}-wrapper { + font-size: @font-size-base; + display: inline-block; + position: relative; + white-space: nowrap; + margin-right: 8px; + cursor: pointer; +} + +.@{radio-prefix-cls} { + white-space: nowrap; + outline: none; + display: inline-block; + position: relative; + line-height: 1; + vertical-align: text-bottom; + cursor: pointer; + .@{radio-prefix-cls}-wrapper:hover &, + &:hover, + &-focused { + .@{radio-inner-prefix-cls} { + border-color: @primary-color; + } + } + &-checked:after { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border-radius: 50%; + border: 1px solid @primary-color; + content: ''; + animation: antRadioEffect 0.36s ease-in-out; + animation-fill-mode: both; + visibility: hidden; + } + &:hover:after, + .@{radio-prefix-cls}-wrapper:hover &:after { + visibility: visible; + } + &-inner { + &:after { + position: absolute; + width: 6px; + height: 6px; + left: 3px; + top: 3px; + border-radius: @border-radius-base; + display: table; + border-top: 0; + border-left: 0; + content: ' '; + background-color: @primary-color; + opacity: 0; + transform: scale(0); + transition: all @radio-duration @ease-in-out-circ; + } + + position: relative; + top: 0; + left: 0; + display: block; + width: 14px; + height: 14px; + border-width: 1px; + border-style: solid; + border-radius: 14px; + border-color: @border-color-base; + background-color: @radio-button-bg; + transition: all @radio-duration; + } + + &-input { + position: absolute; + left: 0; + z-index: 1; + cursor: pointer; + opacity: 0; + top: 0; + bottom: 0; + right: 0; + } +} + +// 选中状态 +.@{radio-prefix-cls}-checked { + .@{radio-inner-prefix-cls} { + border-color: @primary-color; + &:after { + transform: scale(1); + opacity: 1; + transition: all @radio-duration @ease-in-out-circ; + } + } +} + +.@{radio-prefix-cls}-disabled { + .@{radio-inner-prefix-cls} { + border-color: @border-color-base !important; + background-color: @input-disabled-bg; + &:after { + background-color: #ccc; + } + } + + .@{radio-prefix-cls}-input { + cursor: not-allowed; + } + + & + span { + color: @disabled-color; + cursor: not-allowed; + } +} + +span.@{radio-prefix-cls} + * { + padding-left: 8px; + padding-right: 8px; +} + +.@{radio-prefix-cls}-button-wrapper { + margin: 0; + height: @input-height-base; + line-height: @input-height-base - 2px; + color: @radio-button-color; + display: inline-block; + transition: all 0.3s ease; + cursor: pointer; + border: @border-width-base @border-style-base @border-color-base; + border-left: 0; + background: @radio-button-bg; + padding: 0 16px; + position: relative; + + a { + color: @radio-button-color; + } + + > .@{radio-prefix-cls}-button { + margin-left: 0; + display: block; + width: 0; + height: 0; + } + + .@{radio-group-prefix-cls}-large & { + height: @input-height-lg; + line-height: @input-height-lg - 2px; + } + + .@{radio-group-prefix-cls}-small & { + height: @input-height-sm; + line-height: @input-height-sm - 2px; + padding: 0 12px; + &:first-child { + border-radius: @border-radius-sm 0 0 @border-radius-sm; + } + &:last-child { + border-radius: 0 @border-radius-sm @border-radius-sm 0; + } + } + + &:not(:first-child) { + &::before { + content: ""; + display: block; + top: 0; + left: -1px; + width: 1px; + height: 100%; + position: absolute; + background-color: @border-color-base; + } + } + &:first-child { + border-radius: @border-radius-base 0 0 @border-radius-base; + border-left: @border-width-base @border-style-base @border-color-base; + } + + &:last-child { + border-radius: 0 @border-radius-base @border-radius-base 0; + } + + &:first-child:last-child { + border-radius: @border-radius-base; + } + + &:hover, + &-focused { + color: @primary-color; + position: relative; + } + + .@{radio-prefix-cls}-inner, + input[type="checkbox"], + input[type="radio"] { + .opacity(0); + width: 0; + height: 0; + } + + &-checked { + background: @radio-button-bg; + border-color: @primary-color; + color: @primary-color; + box-shadow: -1px 0 0 0 @primary-color; + z-index: 1; + &::before { + background-color: @primary-color !important; + opacity: 0.1; + } + &:first-child { + border-color: @primary-color; + box-shadow: none !important; + } + + &:hover { + border-color: @primary-5; + box-shadow: -1px 0 0 0 @primary-5; + color: @primary-5; + } + + &:active { + border-color: @primary-7; + box-shadow: -1px 0 0 0 @primary-7; + color: @primary-7; + } + } + + &-disabled { + border-color: @border-color-base; + background-color: @input-disabled-bg; + cursor: not-allowed; + color: @disabled-color; + + &:first-child, + &:hover { + border-color: @border-color-base; + background-color: @input-disabled-bg; + color: @disabled-color; + } + &:first-child { + border-left-color: @border-color-base; + } + } + + &-disabled&-checked { + color: #fff; + background-color: #e6e6e6; + border-color: @border-color-base; + box-shadow: none; + } +} + +@keyframes antRadioEffect { + 0% { + transform: scale(1); + opacity: 0.5; + } + 100% { + transform: scale(1.6); + opacity: 0; + } +} diff --git a/examples/checkbox.vue b/examples/checkbox.vue index 42da048a0..0c0e3865a 100644 --- a/examples/checkbox.vue +++ b/examples/checkbox.vue @@ -1,6 +1,6 @@ diff --git a/components/rate/Star.vue b/components/rate/Star.vue new file mode 100644 index 000000000..3c4ec3d30 --- /dev/null +++ b/components/rate/Star.vue @@ -0,0 +1,52 @@ + + diff --git a/components/rate/index.js b/components/rate/index.js new file mode 100644 index 000000000..0c1d021f2 --- /dev/null +++ b/components/rate/index.js @@ -0,0 +1,3 @@ +import Rate from './Rate'; + +export default Rate; diff --git a/components/rate/style/index.js b/components/rate/style/index.js new file mode 100644 index 000000000..3a3ab0de5 --- /dev/null +++ b/components/rate/style/index.js @@ -0,0 +1,2 @@ +import '../../style/index.less'; +import './index.less'; diff --git a/components/rate/style/index.less b/components/rate/style/index.less new file mode 100644 index 000000000..e22dbbd0d --- /dev/null +++ b/components/rate/style/index.less @@ -0,0 +1,73 @@ +@import "../../style/themes/default"; +@import "../../style/mixins/index"; + +@rate-prefix-cls: ~"@{ant-prefix}-rate"; + +.@{rate-prefix-cls} { + margin: 0; + padding: 0; + list-style: none; + font-size: 20px; + display: inline-block; + vertical-align: middle; + + &-disabled &-star { + cursor: not-allowed; + &:hover { + transform: scale(1); + } + } + + &-star { + margin: 0; + padding: 0; + display: inline-block; + margin-right: 8px; + position: relative; + transition: all .3s; + color: @rate-star-bg; + cursor: pointer; + + &-first, + &-second { + user-select: none; + transition: all .3s; + } + + &:hover { + transform: scale(1.1); + } + + &-first { + position: absolute; + left: 0; + top: 0; + width: 50%; + height: 100%; + overflow: hidden; + opacity: 0; + } + + &-half &-first, + &-half &-second { + opacity: 1; + } + + &-half &-first, + &-full &-second { + color: @rate-star-color; + } + + &-half:hover &-first, + &-full:hover &-second { + color: tint(@rate-star-color, 20%); + } + } + + &-text { + margin-left: 8px; + vertical-align: middle; + display: inline-block; + font-size: @font-size-base; + } +} diff --git a/components/util/util.js b/components/util/util.js new file mode 100644 index 000000000..6d0070323 --- /dev/null +++ b/components/util/util.js @@ -0,0 +1,40 @@ +function getScroll(w, top) { + let ret = top ? w.pageYOffset : w.pageXOffset; + const method = top ? 'scrollTop' : 'scrollLeft'; + if (typeof ret !== 'number') { + const d = w.document; + // ie6,7,8 standard mode + ret = d.documentElement[method]; + if (typeof ret !== 'number') { + // quirks mode + ret = d.body[method]; + } + } + return ret; +} + +function getClientPosition(elem) { + let box; + let x; + let y; + const doc = elem.ownerDocument; + const body = doc.body; + const docElem = doc && doc.documentElement; + box = elem.getBoundingClientRect(); + x = box.left; + y = box.top; + x -= docElem.clientLeft || body.clientLeft || 0; + y -= docElem.clientTop || body.clientTop || 0; + return { + left: x, + top: y, + }; +} + +export const getOffsetLeft = (el) => { + const pos = getClientPosition(el); + const doc = el.ownerDocument; + const w = doc.defaultView || doc.parentWindow; + pos.left += getScroll(w); + return pos.left; +} diff --git a/examples/index.js b/examples/index.js index 4a4d55917..39fea342b 100644 --- a/examples/index.js +++ b/examples/index.js @@ -4,6 +4,7 @@ import Button from './button.vue' import Radio from './radio.vue' import Grid from './grid.vue' // import Dialog from './dialog.vue' +import Rate from './rate.vue' import './index.less' new Vue({ el: '#app', @@ -13,6 +14,7 @@ new Vue({ + `, components: { @@ -21,5 +23,6 @@ new Vue({ Checkbox, Grid, Radio, + Rate, }, }) diff --git a/examples/rate.vue b/examples/rate.vue new file mode 100644 index 000000000..b6f624e7f --- /dev/null +++ b/examples/rate.vue @@ -0,0 +1,63 @@ + + From 46ed40777dfa89bdc8f4b8aa5c0e3874f36aa858 Mon Sep 17 00:00:00 2001 From: tangjinzhou <415800467@qq.com> Date: Thu, 2 Nov 2017 10:42:34 +0800 Subject: [PATCH 08/47] tab --- components/_util/isFlexSupported.js | 10 + components/tabs/TabContent.vue | 0 components/tabs/TabPane.vue | 0 components/tabs/Tabs.vue | 0 components/tabs/index.js | 6 + components/tabs/style/card-style.less | 142 +++++++++ components/tabs/style/index.js | 2 + components/tabs/style/index.less | 395 ++++++++++++++++++++++++++ components/tabs/utils.js | 59 ++++ 9 files changed, 614 insertions(+) create mode 100644 components/_util/isFlexSupported.js create mode 100644 components/tabs/TabContent.vue create mode 100644 components/tabs/TabPane.vue create mode 100644 components/tabs/Tabs.vue create mode 100644 components/tabs/index.js create mode 100644 components/tabs/style/card-style.less create mode 100644 components/tabs/style/index.js create mode 100644 components/tabs/style/index.less create mode 100644 components/tabs/utils.js diff --git a/components/_util/isFlexSupported.js b/components/_util/isFlexSupported.js new file mode 100644 index 000000000..d9d8a8887 --- /dev/null +++ b/components/_util/isFlexSupported.js @@ -0,0 +1,10 @@ +export default function isFlexSupported () { + if (typeof window !== 'undefined' && window.document && window.document.documentElement) { + const { documentElement } = window.document + return 'flex' in documentElement.style || + 'webkitFlex' in documentElement.style || + 'Flex' in documentElement.style || + 'msFlex' in documentElement.style + } + return false +} diff --git a/components/tabs/TabContent.vue b/components/tabs/TabContent.vue new file mode 100644 index 000000000..e69de29bb diff --git a/components/tabs/TabPane.vue b/components/tabs/TabPane.vue new file mode 100644 index 000000000..e69de29bb diff --git a/components/tabs/Tabs.vue b/components/tabs/Tabs.vue new file mode 100644 index 000000000..e69de29bb diff --git a/components/tabs/index.js b/components/tabs/index.js new file mode 100644 index 000000000..74d5a2707 --- /dev/null +++ b/components/tabs/index.js @@ -0,0 +1,6 @@ +import Tabs from './Tabs' +import TabPane from './TabPane' +import TabContent from './TabContent' + +export default Tabs +export { TabPane, TabContent } diff --git a/components/tabs/style/card-style.less b/components/tabs/style/card-style.less new file mode 100644 index 000000000..7c3e25ca9 --- /dev/null +++ b/components/tabs/style/card-style.less @@ -0,0 +1,142 @@ +@import "../../style/themes/default"; +@import "../../style/mixins/index"; +@tab-prefix-cls: ~"@{ant-prefix}-tabs"; + +// card style +.@{tab-prefix-cls} { + &&-card > &-bar &-nav-container { + height: 32px; + } + &&-card > &-bar &-ink-bar { + visibility: hidden; + } + &&-card > &-bar &-tab { + margin: 0; + border: @border-width-base @border-style-base @border-color-base; + border-bottom: 0; + border-radius: @border-radius-base @border-radius-base 0 0; + transition: all 0.3s @ease-in-out; + background: @tabs-card-head-background; + margin-right: 2px; + } + &&-card > &-bar &-tab { + padding: 5px 16px 4px; + transition: all 0.3s @ease-in-out; + } + &&-card > &-bar &-tab-active { + background: @component-background; + border-color: @border-color-base; + color: @primary-color; + padding-bottom: 5px; + } + &&-card > &-bar &-tab-inactive { + padding: 0; + } + &&-card > &-bar &-nav-wrap { + margin-bottom: 0; + } + &&-card > &-bar &-tab .@{iconfont-css-prefix}-close { + color: @text-color-secondary; + transition: all .3s; + .iconfont-size-under-12px(10px); + margin-right: 0; + opacity: 0; + position: absolute; + right: 2px; + top: 50%; + margin-top: -5px; + overflow: hidden; + text-align: center; + border-radius: 2px; + width: 14px; + height: 14px; + line-height: 1; + &:hover { + color: @heading-color; + } + } + + &&-card &-content > &-tabpane, + &&-editable-card &-content > &-tabpane { + transition: none !important; + &-inactive { + overflow: hidden; + } + } + + &&-card > &-bar &-tab:hover .@{iconfont-css-prefix}-close { + opacity: 1; + } + + &-extra-content { + line-height: 32px; + + .@{tab-prefix-cls}-new-tab { + width: 20px; + height: 20px; + line-height: 20px; + text-align: center; + cursor: pointer; + border-radius: @border-radius-base; + border: @border-width-base @border-style-base @border-color-base; + font-size: @font-size-base; + .iconfont-size-under-12px(10px); + color: @text-color-secondary; + transition: all .3s; + &:hover { + color: @primary-color; + border-color: @primary-color; + } + } + } + + // https://github.com/ant-design/ant-design/issues/4669 + &-vertical&-card > .@{tab-prefix-cls}-bar { + .@{tab-prefix-cls}-nav-container { + height: auto; + } + .@{tab-prefix-cls}-tab { + border-bottom: @border-width-base @border-style-base @border-color-base; + margin-bottom: 8px; + &-active { + padding-bottom: 4px; + } + &:last-child { + margin-bottom: 8px; + } + } + .@{tab-prefix-cls}-new-tab { + width: 90%; + } + } + + &-vertical&-card&-left > .@{tab-prefix-cls}-bar { + .@{tab-prefix-cls}-nav-wrap { + margin-right: 0; + } + .@{tab-prefix-cls}-tab { + border-right: 0; + border-radius: @border-radius-base 0 0 @border-radius-base; + margin-right: 1px; + &-active { + margin-right: -1px; + padding-right: 18px; + } + } + } + + &-vertical&-card&-right > .@{tab-prefix-cls}-bar { + .@{tab-prefix-cls}-nav-wrap { + margin-left: 0; + } + .@{tab-prefix-cls}-tab { + border-left: 0; + border-radius: 0 @border-radius-base @border-radius-base 0; + margin-left: 1px; + &-active { + margin-left: -1px; + padding-left: 18px; + } + } + } +} diff --git a/components/tabs/style/index.js b/components/tabs/style/index.js new file mode 100644 index 000000000..cf31ed80f --- /dev/null +++ b/components/tabs/style/index.js @@ -0,0 +1,2 @@ +import '../../style/index.less' +import './index.less' diff --git a/components/tabs/style/index.less b/components/tabs/style/index.less new file mode 100644 index 000000000..a15b4bc16 --- /dev/null +++ b/components/tabs/style/index.less @@ -0,0 +1,395 @@ +@import "../../style/themes/default"; +@import "../../style/mixins/index"; +@tab-prefix-cls: ~"@{ant-prefix}-tabs"; + +@import "./card-style"; + +.@{tab-prefix-cls} { + box-sizing: border-box; + position: relative; + overflow: hidden; + .clearfix; + color: @text-color; + + &-ink-bar { + z-index: 1; + position: absolute; + left: 0; + bottom: 1px; + box-sizing: border-box; + height: 2px; + background-color: @primary-color; + transform-origin: 0 0; + } + + &-bar { + border-bottom: @border-width-base @border-style-base @border-color-base; + margin-bottom: 16px; + outline: none; + transition: padding .3s @ease-in-out; + } + + &-nav-container { + overflow: hidden; + font-size: @tabs-title-font-size; + line-height: @line-height-base; + box-sizing: border-box; + position: relative; + white-space: nowrap; + margin-bottom: -1px; + transition: padding .3s @ease-in-out; + .clearfix; + + &-scrolling { + padding-left: 32px; + padding-right: 32px; + } + } + + &-tab-prev, + &-tab-next { + user-select: none; + z-index: 2; + width: 0; + height: 100%; + line-height: 32px; + cursor: pointer; + border: 0; + background-color: transparent; + position: absolute; + text-align: center; + color: @text-color-secondary; + transition: width .3s @ease-in-out, opacity .3s @ease-in-out, color .3s @ease-in-out; + opacity: 0; + pointer-events: none; + + &.@{tab-prefix-cls}-tab-arrow-show { + opacity: 1; + width: 32px; + height: 100%; + pointer-events: auto; + } + + &:hover { + color: @text-color; + } + + &-icon { + font-style: normal; + font-weight: bold; + font-variant: normal; + line-height: inherit; + vertical-align: baseline; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + text-align: center; + text-transform: none; + + &:before { + display: block; + font-family: "anticon" !important; + .iconfont-size-under-12px(10px); + } + } + } + + &-tab-btn-disabled { + cursor: not-allowed; + &, + &:hover { + color: @disabled-color; + } + } + + &-tab-next { + right: 2px; + + &-icon:before { + content: "\e61f"; + } + } + + &-tab-prev { + left: 0; + &-icon:before { + content: "\e620"; + } + :root & { + filter: none; + } + } + + &-nav-wrap { + overflow: hidden; + margin-bottom: -1px; + } + + &-nav-scroll { + overflow: hidden; + white-space: nowrap; + } + + &-nav { + box-sizing: border-box; + padding-left: 0; + transition: transform 0.3s @ease-in-out; + position: relative; + margin: 0; + list-style: none; + display: inline-block; + + &:before, + &:after { + display: table; + content: " "; + } + + &:after { + clear: both; + } + + .@{tab-prefix-cls}-tab-disabled { + pointer-events: none; + cursor: default; + color: @disabled-color; + } + + .@{tab-prefix-cls}-tab { + display: inline-block; + height: 100%; + margin-right: 24px; + box-sizing: border-box; + position: relative; + + &:last-child { + margin-right: 0; + } + + padding: 8px 20px; + transition: color 0.3s @ease-in-out; + cursor: pointer; + text-decoration: none; + + &:hover { + color: @primary-5; + } + + &:active { + color: @primary-7; + } + .@{iconfont-css-prefix} { + width: 14px; + height: 14px; + margin-right: 8px; + } + } + + .@{tab-prefix-cls}-tab-active { + color: @primary-color; + } + } + + &-mini &-nav-container { + font-size: @font-size-base; + } + + &-mini &-tab { + margin-right: 0; + padding: 8px 16px; + } + + &:not(&-vertical) { + > .@{tab-prefix-cls}-content { + width: 100%; + + > .@{tab-prefix-cls}-tabpane { + flex-shrink: 0; + width: 100%; + transition: opacity .45s; + opacity: 1; + } + + > .@{tab-prefix-cls}-tabpane-inactive { + opacity: 0; + height: 0; + padding: 0 !important; + pointer-events: none; + } + } + > .@{tab-prefix-cls}-content-animated { + display: flex; + flex-direction: row; + will-change: margin-left; + transition: margin-left 0.3s @ease-in-out; + } + } + + &-vertical { + > .@{tab-prefix-cls}-bar { + border-bottom: 0; + height: 100%; + &-tab-prev, &-tab-next { + width: 32px; + height: 0; + transition: height .3s @ease-in-out, opacity .3s @ease-in-out, color .3s @ease-in-out; + } + &-tab-prev.@{tab-prefix-cls}-tab-arrow-show, + &-tab-next.@{tab-prefix-cls}-tab-arrow-show { + width: 100%; + height: 32px; + } + + .@{tab-prefix-cls}-tab { + float: none; + margin-right: 0; + margin-bottom: 16px; + display: block; + padding: 8px 24px; + + &:last-child { + margin-bottom: 0; + } + } + + .@{tab-prefix-cls}-extra-content { + text-align: center; + } + + .@{tab-prefix-cls}-nav-scroll { + width: auto; + } + + .@{tab-prefix-cls}-nav-container, + .@{tab-prefix-cls}-nav-wrap { + height: 100%; + } + + .@{tab-prefix-cls}-nav-container { + margin-bottom: 0; + + &.@{tab-prefix-cls}-nav-container-scrolling { + padding: 32px 0; + } + } + + .@{tab-prefix-cls}-nav-wrap { + margin-bottom: 0; + } + + .@{tab-prefix-cls}-nav { + width: 100%; + } + + .@{tab-prefix-cls}-ink-bar { + width: 2px; + left: auto; + height: auto; + top: 0; + } + } + + > .@{tab-prefix-cls}-content { + overflow: hidden; + width: auto; + margin-top: 0 !important; + } + + > .@{tab-prefix-cls}-bar { + .@{tab-prefix-cls}-tab-next { + width: 100%; + bottom: 0; + height: 32px; + &-icon:before { + content: "\e61d"; + } + } + + .@{tab-prefix-cls}-tab-prev { + top: 0; + width: 100%; + height: 32px; + &-icon:before { + content: "\e61e"; + } + } + } + } + + &-vertical&-left { + > .@{tab-prefix-cls}-bar { + float: left; + border-right: @border-width-base @border-style-base @border-color-split; + margin-right: -1px; + margin-bottom: 0; + .@{tab-prefix-cls}-tab { + text-align: right; + } + .@{tab-prefix-cls}-nav-container { + margin-right: -1px; + } + .@{tab-prefix-cls}-nav-wrap { + margin-right: -1px; + } + .@{tab-prefix-cls}-ink-bar { + right: 1px; + } + } + > .@{tab-prefix-cls}-content { + padding-left: 24px; + border-left: @border-width-base @border-style-base @border-color-split; + } + } + + &-vertical&-right { + > .@{tab-prefix-cls}-bar { + float: right; + border-left: @border-width-base @border-style-base @border-color-split; + margin-left: -1px; + margin-bottom: 0; + .@{tab-prefix-cls}-nav-container { + margin-left: -1px; + } + .@{tab-prefix-cls}-nav-wrap { + margin-left: -1px; + } + .@{tab-prefix-cls}-ink-bar { + left: 1px; + } + } + > .@{tab-prefix-cls}-content { + padding-right: 24px; + border-right: @border-width-base @border-style-base @border-color-split; + } + } + + &-bottom > &-bar { + margin-bottom: 0; + margin-top: 16px; + } +} + +.@{tab-prefix-cls}-top .@{tab-prefix-cls}-ink-bar-animated, +.@{tab-prefix-cls}-bottom .@{tab-prefix-cls}-ink-bar-animated { + transition: transform .3s @ease-in-out, width .3s @ease-in-out; +} + +.@{tab-prefix-cls}-left .@{tab-prefix-cls}-ink-bar-animated, +.@{tab-prefix-cls}-right .@{tab-prefix-cls}-ink-bar-animated { + transition: transform .3s @ease-in-out, height .3s @ease-in-out; +} + +.no-flex, +.@{tab-prefix-cls}-no-animation, +.@{tab-prefix-cls}-vertical { + > .@{tab-prefix-cls}-content { + &-animated { + transform: none !important; + margin-left: 0 !important; + } + > .@{tab-prefix-cls}-tabpane-inactive { + display: none; + } + } +} diff --git a/components/tabs/utils.js b/components/tabs/utils.js new file mode 100644 index 000000000..5c9323e2f --- /dev/null +++ b/components/tabs/utils.js @@ -0,0 +1,59 @@ + +export function setTransform (style, v) { + style.transform = v + style.webkitTransform = v + style.mozTransform = v +} + +export function isTransformSupported (style) { + return 'transform' in style || + 'webkitTransform' in style || + 'MozTransform' in style +} + +export function setTransition (style, v) { + style.transition = v + style.webkitTransition = v + style.MozTransition = v +} +export function getTransformPropValue (v) { + return { + transform: v, + WebkitTransform: v, + MozTransform: v, + } +} + +export function isVertical (tabBarPosition) { + return tabBarPosition === 'left' || tabBarPosition === 'right' +} + +export function getTransformByIndex (index, tabBarPosition) { + const translate = isVertical(tabBarPosition) ? 'translateY' : 'translateX' + return `${translate}(${-index * 100}%) translateZ(0)` +} + +export function getMarginStyle (index, tabBarPosition) { + const marginDirection = isVertical(tabBarPosition) ? 'marginTop' : 'marginLeft' + return { + [marginDirection]: `${-index * 100}%`, + } +} + +export function getStyle (el, property) { + return +window.getComputedStyle(el).getPropertyValue(property).replace('px', '') +} + +export function setPxStyle (el, value, vertical) { + value = vertical ? `0px, ${value}px, 0px` : `${value}px, 0px, 0px` + setTransform(el.style, `translate3d(${value})`) +} + +export function getDataAttr (props) { + return Object.keys(props).reduce((prev, key) => { + if (key.substr(0, 5) === 'aria-' || key.substr(0, 5) === 'data-' || key === 'role') { + prev[key] = props[key] + } + return prev + }, {}) +} From e6b898ef64a4b51bc6833d561369154a94e63cf0 Mon Sep 17 00:00:00 2001 From: wangxueliang Date: Thu, 2 Nov 2017 10:56:18 +0800 Subject: [PATCH 09/47] optimize rate component --- components/rate/Rate.vue | 21 +++++++++++++++------ components/rate/Star.vue | 2 +- examples/rate.vue | 25 ++++++++++++++++--------- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/components/rate/Rate.vue b/components/rate/Rate.vue index ee6f9276b..9ef546c15 100644 --- a/components/rate/Rate.vue +++ b/components/rate/Rate.vue @@ -15,7 +15,7 @@ :key="i"> @@ -24,6 +24,7 @@ diff --git a/examples/rate.vue b/examples/rate.vue index b6f624e7f..741809bb9 100644 --- a/examples/rate.vue +++ b/examples/rate.vue @@ -1,13 +1,15 @@ From e0c4090e8575c9a2a5fd030fa1db81634423fc94 Mon Sep 17 00:00:00 2001 From: tangjinzhou <415800467@qq.com> Date: Thu, 2 Nov 2017 11:48:38 +0800 Subject: [PATCH 10/47] fix --- components/checkbox/Group.vue | 32 ++++++++++++++++++++++++-------- components/checkbox/checkbox.vue | 31 +++++++++++++++++++++++-------- examples/checkbox.vue | 7 ++++--- 3 files changed, 51 insertions(+), 19 deletions(-) diff --git a/components/checkbox/Group.vue b/components/checkbox/Group.vue index 23999dc52..7408105e5 100644 --- a/components/checkbox/Group.vue +++ b/components/checkbox/Group.vue @@ -14,10 +14,14 @@ export default { default: 'ant-checkbox-group', type: String, }, - value: { + defaultValue: { default: () => [], type: Array, }, + value: { + default: undefined, + type: Array, + }, options: { default: () => [], type: Array, @@ -26,9 +30,15 @@ export default { model: { prop: 'value', }, + data () { + const { value, defaultValue } = this + return { + stateValue: value || defaultValue, + } + }, computed: { checkedStatus () { - return new Set(this.value) + return new Set(this.stateValue) }, }, created () { @@ -40,17 +50,22 @@ export default { return false } const target = event.target - const { value, checked } = target + const { value: targetValue, checked } = target + const { stateValue, value } = this let newVal = [] if (checked) { - newVal = [...this.value, value] + newVal = [...stateValue, targetValue] } else { - newVal = [...this.value] - const index = newVal.indexOf(value) + newVal = [...stateValue] + const index = newVal.indexOf(targetValue) index >= 0 && newVal.splice(index, 1) } - this.$emit('input', [...new Set(newVal)]) - this.$emit('change', [...new Set(newVal)]) + newVal = [...new Set(newVal)] + if (value === undefined) { + this.stateValue = newVal + } + this.$emit('input', newVal) + this.$emit('change', newVal) }, setChildCheckbox (children = []) { const { options, $slots, checkedStatus } = this @@ -75,6 +90,7 @@ export default { }, watch: { value (val) { + this.stateValue = val this.setChildCheckbox(this.$slots.default) }, }, diff --git a/components/checkbox/checkbox.vue b/components/checkbox/checkbox.vue index 26caa0fa4..d98fa3da1 100644 --- a/components/checkbox/checkbox.vue +++ b/components/checkbox/checkbox.vue @@ -2,7 +2,7 @@