Browse Source

Merge branch 'v2' of https://github.com/jdf2e/nutui into v2

dushoujun 5 years ago
parent
commit
9b181c96cc

File diff suppressed because it is too large
+ 518 - 515
src/config.json


+ 204 - 201
src/nutui.js

@@ -1,153 +1,156 @@
-import { version } from "../package.json";
-import { packages as pkgList } from "./config.json";
-import { locale } from "./locales";
-import Cell from "./packages/cell/index.js";
-import "./packages/cell/cell.scss";
-import Dialog from "./packages/dialog/index.js";
-import "./packages/dialog/dialog.scss";
-import Icon from "./packages/icon/index.js";
-import "./packages/icon/icon.scss";
-import Toast from "./packages/toast/index.js";
-import "./packages/toast/toast.scss";
-import ActionSheet from "./packages/actionsheet/index.js";
-import "./packages/actionsheet/actionsheet.scss";
-import Tab from "./packages/tab/index.js";
-import "./packages/tab/tab.scss";
-import TabPanel from "./packages/tabpanel/index.js";
-import "./packages/tabpanel/tabpanel.scss";
-import TabBar from "./packages/tabbar/index.js";
-import "./packages/tabbar/tabbar.scss";
-import Calendar from "./packages/calendar/index.js";
-import "./packages/calendar/calendar.scss";
-import DatePicker from "./packages/datepicker/index.js";
-import "./packages/datepicker/datepicker.scss";
-import NavBar from "./packages/navbar/index.js";
-import "./packages/navbar/navbar.scss";
-import NoticeBar from "./packages/noticebar/index.js";
-import "./packages/noticebar/noticebar.scss";
-import Switch from "./packages/switch/index.js";
-import "./packages/switch/switch.scss";
-import Slider from "./packages/slider/index.js";
-import "./packages/slider/slider.scss";
-import Range from "./packages/range/index.js";
-import "./packages/range/range.scss";
-import Picker from "./packages/picker/index.js";
-import "./packages/picker/picker.scss";
-import Progress from "./packages/progress/index.js";
-import "./packages/progress/progress.scss";
-import Price from "./packages/price/index.js";
-import "./packages/price/price.scss";
-import Flex from "./packages/flex/index.js";
-import "./packages/flex/flex.scss";
-import Col from "./packages/col/index.js";
-import "./packages/col/col.scss";
-import Row from "./packages/row/index.js";
-import "./packages/row/row.scss";
-import Steps from "./packages/steps/index.js";
-import "./packages/steps/steps.scss";
-import Button from "./packages/button/index.js";
-import "./packages/button/button.scss";
-import Badge from "./packages/badge/index.js";
-import "./packages/badge/badge.scss";
-import Rate from "./packages/rate/index.js";
-import "./packages/rate/rate.scss";
-import Swiper from "./packages/swiper/index.js";
-import "./packages/swiper/swiper.scss";
-import Menu from "./packages/menu/index.js";
-import "./packages/menu/menu.scss";
-import Stepper from "./packages/stepper/index.js";
-import "./packages/stepper/stepper.scss";
-import ButtonGroup from "./packages/buttongroup/index.js";
-import "./packages/buttongroup/buttongroup.scss";
-import SearchBar from "./packages/searchbar/index.js";
-import "./packages/searchbar/searchbar.scss";
-import ImagePicker from "./packages/imagepicker/index.js";
-import "./packages/imagepicker/imagepicker.scss";
-import Radio from "./packages/radio/index.js";
-import "./packages/radio/radio.scss";
-import RadioGroup from "./packages/radiogroup/index.js";
-import "./packages/radiogroup/radiogroup.scss";
-import CheckBox from "./packages/checkbox/index.js";
-import "./packages/checkbox/checkbox.scss";
-import CheckBoxGroup from "./packages/checkboxgroup/index.js";
-import "./packages/checkboxgroup/checkboxgroup.scss";
-import ShortPassword from "./packages/shortpassword/index.js";
-import "./packages/shortpassword/shortpassword.scss";
-import Skeleton from "./packages/skeleton/index.js";
-import "./packages/skeleton/skeleton.scss";
-import Scroller from "./packages/scroller/index.js";
-import "./packages/scroller/scroller.scss";
-import BackTop from "./packages/backtop/index.js";
-import "./packages/backtop/backtop.scss";
-import CountDown from "./packages/countdown/index.js";
-import "./packages/countdown/countdown.scss";
-import InfiniteLoading from "./packages/infiniteloading/index.js";
-import "./packages/infiniteloading/infiniteloading.scss";
-import Uploader from "./packages/uploader/index.js";
-import "./packages/uploader/uploader.scss";
-import TextInput from "./packages/textinput/index.js";
-import "./packages/textinput/textinput.scss";
-import Avatar from "./packages/avatar/index.js";
-import "./packages/avatar/avatar.scss";
-import Lazyload from "./packages/lazyload/index.js";
-import "./packages/textbox/textbox.scss";
-import TextBox from "./packages/textbox/index.js";
-import Elevator from "./packages/elevator/index.js";
-import "./packages/elevator/elevator.scss";
-import Popup from "./packages/popup/index.js";
-import "./packages/popup/popup.scss";
+import {version} from '../package.json';
+import {packages as pkgList} from './config.json';
+import {locale} from './locales';
+import Cell from './packages/cell/index.js';
+import './packages/cell/cell.scss';
+import Dialog from './packages/dialog/index.js';
+import './packages/dialog/dialog.scss';
+import Icon from './packages/icon/index.js';
+import './packages/icon/icon.scss';
+import Toast from './packages/toast/index.js';
+import './packages/toast/toast.scss';
+import ActionSheet from './packages/actionsheet/index.js';
+import './packages/actionsheet/actionsheet.scss';
+import Tab from './packages/tab/index.js';
+import './packages/tab/tab.scss';
+import TabPanel from './packages/tabpanel/index.js';
+import './packages/tabpanel/tabpanel.scss';
+import TabBar from './packages/tabbar/index.js';
+import './packages/tabbar/tabbar.scss';
+import Calendar from './packages/calendar/index.js';
+import './packages/calendar/calendar.scss';
+import DatePicker from './packages/datepicker/index.js';
+import './packages/datepicker/datepicker.scss';
+import NavBar from './packages/navbar/index.js';
+import './packages/navbar/navbar.scss';
+import NoticeBar from './packages/noticebar/index.js';
+import './packages/noticebar/noticebar.scss';
+import Switch from './packages/switch/index.js';
+import './packages/switch/switch.scss';
+import Slider from './packages/slider/index.js';
+import './packages/slider/slider.scss';
+import Range from './packages/range/index.js';
+import './packages/range/range.scss';
+import Picker from './packages/picker/index.js';
+import './packages/picker/picker.scss';
+import Progress from './packages/progress/index.js';
+import './packages/progress/progress.scss';
+import Price from './packages/price/index.js';
+import './packages/price/price.scss';
+import Flex from './packages/flex/index.js';
+import './packages/flex/flex.scss';
+import Col from './packages/col/index.js';
+import './packages/col/col.scss';
+import Row from './packages/row/index.js';
+import './packages/row/row.scss';
+import Steps from './packages/steps/index.js';
+import './packages/steps/steps.scss';
+import Button from './packages/button/index.js';
+import './packages/button/button.scss';
+import Badge from './packages/badge/index.js';
+import './packages/badge/badge.scss';
+import Rate from './packages/rate/index.js';
+import './packages/rate/rate.scss';
+import Swiper from './packages/swiper/index.js';
+import './packages/swiper/swiper.scss';
+import Menu from './packages/menu/index.js';
+import './packages/menu/menu.scss';
+import Stepper from './packages/stepper/index.js';
+import './packages/stepper/stepper.scss';
+import ButtonGroup from './packages/buttongroup/index.js';
+import './packages/buttongroup/buttongroup.scss';
+import SearchBar from './packages/searchbar/index.js';
+import './packages/searchbar/searchbar.scss';
+import ImagePicker from './packages/imagepicker/index.js';
+import './packages/imagepicker/imagepicker.scss';
+import Radio from './packages/radio/index.js';
+import './packages/radio/radio.scss';
+import RadioGroup from './packages/radiogroup/index.js';
+import './packages/radiogroup/radiogroup.scss';
+import CheckBox from './packages/checkbox/index.js';
+import './packages/checkbox/checkbox.scss';
+import CheckBoxGroup from './packages/checkboxgroup/index.js';
+import './packages/checkboxgroup/checkboxgroup.scss';
+import ShortPassword from './packages/shortpassword/index.js';
+import './packages/shortpassword/shortpassword.scss';
+import Skeleton from './packages/skeleton/index.js';
+import './packages/skeleton/skeleton.scss';
+import Scroller from './packages/scroller/index.js';
+import './packages/scroller/scroller.scss';
+import BackTop from './packages/backtop/index.js';
+import './packages/backtop/backtop.scss';
+import CountDown from './packages/countdown/index.js';
+import './packages/countdown/countdown.scss';
+import InfiniteLoading from './packages/infiniteloading/index.js';
+import './packages/infiniteloading/infiniteloading.scss';
+import Uploader from './packages/uploader/index.js';
+import './packages/uploader/uploader.scss';
+import TextInput from './packages/textinput/index.js';
+import './packages/textinput/textinput.scss';
+import Avatar from './packages/avatar/index.js';
+import './packages/avatar/avatar.scss';
+import Lazyload from './packages/lazyload/index.js';
+import './packages/textbox/textbox.scss';
+import TextBox from './packages/textbox/index.js';
+import Elevator from './packages/elevator/index.js';
+import './packages/elevator/elevator.scss';
+import Popup from './packages/popup/index.js';
+import LeftSlip from './packages/leftslip/index.js';
+import './packages/leftslip/leftslip.scss';
 import TabSelect from "./packages/tabselect/index.js";
 import "./packages/tabselect/tabselect.scss";
 
+import './packages/popup/popup.scss';
 const packages = {
-  Cell,
-  Dialog,
-  Icon,
-  Toast,
-  ActionSheet,
-  Tab,
-  TabPanel,
-  TabBar,
-  Calendar,
-  DatePicker,
-  NavBar,
-  NoticeBar,
-  Switch,
-  Slider,
-  Range,
-  Picker,
-  Progress,
-  Price,
-  Flex,
-  Col,
-  Row,
-  Steps,
-  Button,
-  Badge,
-  Rate,
-  Swiper,
-  Menu,
-  Stepper,
-  ButtonGroup,
-  SearchBar,
-  ImagePicker,
-  Radio,
-  RadioGroup,
-  CheckBox,
-  CheckBoxGroup,
-  ShortPassword,
-  Skeleton,
-  Scroller,
-  BackTop,
-  CountDown,
-  InfiniteLoading,
-  Uploader,
-  TextInput,
-  TextBox,
-  Avatar,
-  Elevator,
-  Popup,
-  TabSelect: TabSelect
+    Cell,
+    Dialog,
+    Icon,
+    Toast,
+    ActionSheet,
+    Tab,
+    TabPanel,
+    TabBar,
+    Calendar,
+    DatePicker,
+    NavBar,
+    NoticeBar,
+    Switch,
+    Slider,
+    Range,
+    Picker,
+    Progress,
+    Price,
+    Flex,
+    Col,
+    Row,
+    Steps,
+    Button,
+    Badge,
+    Rate,
+    Swiper,
+    Menu,
+    Stepper,
+    ButtonGroup,
+    SearchBar,
+    ImagePicker,
+    Radio,
+    RadioGroup,
+    CheckBox,
+    CheckBoxGroup,
+    ShortPassword,
+    Skeleton,
+    Scroller,
+    BackTop,
+    CountDown,
+    InfiniteLoading,
+    Uploader,
+    TextInput,
+    TextBox,
+    Avatar,
+    Elevator,
+    Popup,
+    LeftSlip,
+    TabSelect: TabSelect
 };
 
 const components = {};
@@ -155,79 +158,79 @@ const methods = {};
 const filters = {};
 const directives = {};
 pkgList.map(item => {
-  const pkg = packages[item.name];
-  if (!pkg) return;
+    const pkg = packages[item.name];
+    if (!pkg) return;
 
-  if (item.type == "component") {
-    if (pkg.name) {
-      components[pkg.name] = pkg;
-    } else {
-      for (let n in pkg) {
-        components[n] = pkg[n];
-      }
+    if (item.type == 'component') {
+        if (pkg.name) {
+            components[pkg.name] = pkg;
+        } else {
+            for (let n in pkg) {
+                components[n] = pkg[n];
+            }
+        }
+    } else if (item.type == 'method') {
+        methods[item.name] = pkg;
+    } else if (item.type == 'filter') {
+        filters[item.name] = pkg;
+    } else if (item.type == 'directive') {
+        directives[item.name] = pkg;
     }
-  } else if (item.type == "method") {
-    methods[item.name] = pkg;
-  } else if (item.type == "filter") {
-    filters[item.name] = pkg;
-  } else if (item.type == "directive") {
-    directives[item.name] = pkg;
-  }
 });
 
-const install = function (Vue, opts = {}) {
-  if (install.installed) return;
+const install = function(Vue, opts = {}) {
+    if (install.installed) return;
 
-  if (opts.locale) {
-    Vue.config.lang = opts.locale;
-  }
+    if (opts.locale) {
+        Vue.config.lang = opts.locale;
+    }
 
-  if (opts.lang) locale(Vue.config.lang, opts.lang);
+    if (opts.lang) locale(Vue.config.lang, opts.lang);
 
-  for (let cptName in methods) {
-    if (Array.isArray(methods[cptName])) {
-      Vue.prototype["$" + cptName.toLowerCase()] = methods[cptName][0];
-      Vue.component(methods[cptName][1].name, methods[cptName][1]);
-    } else {
-      Vue.prototype["$" + cptName.toLowerCase()] = methods[cptName];
+    for (let cptName in methods) {
+        if (Array.isArray(methods[cptName])) {
+            Vue.prototype['$' + cptName.toLowerCase()] = methods[cptName][0];
+            Vue.component(methods[cptName][1].name, methods[cptName][1]);
+        } else {
+            Vue.prototype['$' + cptName.toLowerCase()] = methods[cptName];
+        }
     }
-  }
 
-  for (let cptName in components) {
-    if (components[cptName] && components[cptName].name) {
-      Vue.component(components[cptName].name, components[cptName]);
+    for (let cptName in components) {
+        if (components[cptName] && components[cptName].name) {
+            Vue.component(components[cptName].name, components[cptName]);
+        }
     }
-  }
 
-  for (let cptName in filters) {
-    if (filters[cptName] && filters[cptName].name) {
-      Vue.filter(cptName, filters[cptName]);
+    for (let cptName in filters) {
+        if (filters[cptName] && filters[cptName].name) {
+            Vue.filter(cptName, filters[cptName]);
+        }
     }
-  }
 
-  for (let cptName in directives) {
-    if (directives[cptName] && directives[cptName].name) {
-      Vue.directive(directives[cptName].name, directives[cptName]);
+    for (let cptName in directives) {
+        if (directives[cptName] && directives[cptName].name) {
+            Vue.directive(directives[cptName].name, directives[cptName]);
+        }
     }
-  }
 
-  Vue.use(Lazyload, {
-    lazyComponent: true,
-    loading: "//img12.360buyimg.com/imagetools/jfs/t1/73967/28/14561/916/5dc142e4E0666555b/bf33454553c6035e.png"
-  });
+    Vue.use(Lazyload, {
+        lazyComponent: true,
+        loading: '//img12.360buyimg.com/imagetools/jfs/t1/73967/28/14561/916/5dc142e4E0666555b/bf33454553c6035e.png'
+    });
 };
 
-if (typeof window !== "undefined" && window.Vue) {
-  install(window.Vue);
+if (typeof window !== 'undefined' && window.Vue) {
+    install(window.Vue);
 }
 
 export default {
-  version,
-  locale,
-  install,
-  Lazyload,
-  ...components,
-  ...filters,
-  ...directives,
-  ...methods
+    version,
+    locale,
+    install,
+    Lazyload,
+    ...components,
+    ...filters,
+    ...directives,
+    ...methods
 };

+ 5 - 3
src/packages/calendar/__test__/calendar.spec.js

@@ -6,7 +6,9 @@ import Vue from 'vue';
 describe('Calendar.vue', () => {
     const wrapper = shallowMount(Calendar, {
         propsData: { 
-            defaultValue: '2022-01-12'
+            defaultValue: '2022-01-12',
+            startDate: '2020-02-01',
+            endDate:'2028-04-11'
         }
     });
 
@@ -19,7 +21,7 @@ describe('Calendar.vue', () => {
 
     it('设置默认日期', () => {
         return Vue.nextTick().then(function () {
-            expect(wrapper.findAll('.nut-calendar-month-title').at(0).text()).toBe('2021年01月');
+            expect(wrapper.findAll('.nut-calendar-month-title').at(0).text()).toBe('2022年01月');
             expect(wrapper.findAll('.nut-calendar-month-item').at(0).find('.nut-calendar-month-day-active').text()).toBe('12');
         })
     });
@@ -27,7 +29,7 @@ describe('Calendar.vue', () => {
     it('选择日期', () => {
         wrapper.findAll('.nut-calendar-month-item').at(0).findAll('.nut-calendar-month-day').at(10).trigger('click');
         return Vue.nextTick().then(function () {
-            expect(wrapper.findAll('.nut-calendar-month-item').at(0).findAll('.nut-calendar-month-day-active').at(0).text()).toBe('6');
+            expect(wrapper.findAll('.nut-calendar-month-item').at(0).findAll('.nut-calendar-month-day-active').at(0).text()).toBe('5');
 
         })
     });

+ 160 - 157
src/packages/checkboxgroup/checkboxgroup.vue

@@ -1,181 +1,184 @@
 <template>
-    <div :class="['nut-checkboxgroup',{'vertical':vertical},customClass]" >
-        <div class="checkbox-item" v-for="(item,index) in checkBoxData" :key="item[keys.id]">
-            <nut-checkbox 
-            :name="name||item[keys.name]" 
-            :disabled=" disabled || item[keys.disabled]" 
-            :label="item[keys.label]"
-            :animation="animation"
-            :size="item.size ? item.size : size"
-            
-            :id="item[keys.id]"
-            :checked.sync="item.checked"
-            
-            
-            v-model="checkboxValues[index]"
-            @change="changeEvt(arguments,item)"
-
-            >{{ item[keys.label] || item[keys.value] || item}}
-            </nut-checkbox>
-        </div>
+  <div :class="['nut-checkboxgroup', { vertical: vertical }, customClass]">
+    <div
+      class="checkbox-item"
+      v-for="(item, index) in initData"
+      :key="item[keys.id]"
+    >
+      <nut-checkbox
+        :name="name || item[keys.name]"
+        :disabled="disabled || item[keys.disabled]"
+        :label="item[keys.label]"
+        :animation="animation"
+        :size="item.size ? item.size : size"
+        :id="item[keys.id]"
+        :checked.sync="item.checked"
+        v-model="checkboxValues[index]"
+        @change="changeEvt(arguments, item)"
+        >{{ item[keys.label] || item[keys.value] || item }}
+      </nut-checkbox>
     </div>
+  </div>
 </template>
 <script>
 import nutcheckbox from "../checkbox/checkbox.vue";
-import "../checkbox/checkbox.scss";	
+import "../checkbox/checkbox.scss";
 export default {
-    name:'nut-checkboxgroup',
-    props: {
-        name: String,
-    	checkBoxData:{
-    		type:Array,
-            required:true,
-            
-    	},
+  name: "nut-checkboxgroup",
+  props: {
+    name: String,
+    checkBoxData: {
+      type: Array,
+      required: true
+    },
 
-        value: {
-            type: Array,
-            required: true
-        },
-        keys: {
-            type: Object,
-            default() {
-                return {
-                    id: 'id',
-                    name: 'name',
-                    class: 'class',
-                    label: 'label',
-                    value: 'value',
-                    disabled: 'disabled'
-                };
-            }
-        },
-        customClass:{
-            type: String,
-            default: ''
-        },
-        label:{
-            type: [String, Number, Boolean],
-            default: ''
-        },
-        size: {
-            type: [String, Number],
-            default: 'base'
-        },
-        disabled: {
-            type: Boolean,
-            default: false
-        },
-        animation: {
-            type: Boolean,
-            default: true
-        },
-        vertical:{
-            type: Boolean,
-            default: false
-        }
+    value: {
+      type: Array,
+      required: true
     },
-    data() {
+    keys: {
+      type: Object,
+      default() {
         return {
-            ignoreChange: false,
-        	checkboxValues: [],
-            initialValue: []
+          id: "id",
+          name: "name",
+          class: "class",
+          label: "label",
+          value: "value",
+          disabled: "disabled"
         };
+      }
+    },
+    customClass: {
+      type: String,
+      default: ""
     },
-    components: {
-	    [nutcheckbox.name]: nutcheckbox
+    label: {
+      type: [String, Number, Boolean],
+      default: ""
     },
-    watch:{
-        value(){
-            this.init();
+    size: {
+      type: [String, Number],
+      default: "base"
+    },
+    disabled: {
+      type: Boolean,
+      default: false
+    },
+    animation: {
+      type: Boolean,
+      default: true
+    },
+    vertical: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      ignoreChange: false,
+      initData: [],
+      checkboxValues: [],
+      initialValue: []
+    };
+  },
+  components: {
+    [nutcheckbox.name]: nutcheckbox
+  },
+  watch: {
+    value() {
+      this.init();
+    }
+  },
+  mounted() {
+    this.init();
+  },
+  methods: {
+    init() {
+      this.initialValue = this.value;
+      this.checkBoxData.map(item => {
+        if (typeof item === "object") {
+          item.checked = this.isOptionCheckedByDefault(item);
         }
+      });
     },
-    mounted(){
-        this.init()
+    isObject(obj) {
+      return obj !== null && typeof obj === "object";
     },
-    methods: {
-        init(){
-            this.initialValue = this.value;
-            this.checkBoxData.map(item=>{
-                if(typeof item ==="object"){
-                    item.checked = this.isOptionCheckedByDefault(item)
-                }
-            })
-        },
-        isObject(obj) {
-            return obj !== null && typeof obj === 'object';
-        },
-        looseIndexOf(arr, val) {
-            for (let i = 0; i < arr.length; i++) {
-                if (this.looseEqual(arr[i], val)) {
-                    return i;
-                }
-            }
-
-            return -1;
-        },
-        isOptionCheckedByDefault(item) {
-            return this.looseIndexOf(this.initialValue, item[this.keys.value] || item) > -1;
-        },
-        looseEqual(a, b) {
-            return a == b || (
-               this.isObject(a) && this.isObject(b) ? JSON.stringify(a) === JSON.stringify(b) : false
-            );
-        },
-        changeEvt(args,item) {
-            if (this.ignoreChange) {
-                return;
-            }
+    looseIndexOf(arr, val) {
+      for (let i = 0; i < arr.length; i++) {
+        if (this.looseEqual(arr[i], val)) {
+          return i;
+        }
+      }
 
-            const checked = args[0];
-            const label = args[1];
-            const e = args[2];
+      return -1;
+    },
+    isOptionCheckedByDefault(item) {
+      return (
+        this.looseIndexOf(this.initialValue, item[this.keys.value] || item) > -1
+      );
+    },
+    looseEqual(a, b) {
+      return (
+        a == b ||
+        (this.isObject(a) && this.isObject(b)
+          ? JSON.stringify(a) === JSON.stringify(b)
+          : false)
+      );
+    },
+    changeEvt(args, item) {
+      if (this.ignoreChange) {
+        return;
+      }
 
-            let value = [];
-            const itemValue = item[this.keys.value] || item;
-            const i = this.looseIndexOf(this.value, itemValue);
+      const checked = args[0];
+      const label = args[1];
+      const e = args[2];
 
-            if (checked && i < 0) {
-                value = this.value.concat(itemValue);
-            }
+      let value = [];
+      const itemValue = item[this.keys.value] || item;
+      const i = this.looseIndexOf(this.value, itemValue);
 
-            if (!checked && i > -1) {
-                value = this.value.slice(0, i).concat(this.value.slice(i + 1));
-            }
+      if (checked && i < 0) {
+        value = this.value.concat(itemValue);
+      }
 
-            this.$emit('input', value);
-            this.$emit('change', value,label, e);
+      if (!checked && i > -1) {
+        value = this.value.slice(0, i).concat(this.value.slice(i + 1));
+      }
 
-           
-        },
-        toggleAll(checked) {
-            if (checked === false) {
-                this.$emit("input", []);
-                return;
-            }
-            if(checked === true){
-                this.checkBoxData.map(item => {
-                    item.checked = true;
-                });
-            }
-            if (!checked) {
-                this.checkBoxData.map(item => {
-                    item.checked = !item.checked;
-                });
-            }
+      this.$emit("input", value);
+      this.$emit("change", value, label, e);
+    },
+    toggleAll(checked) {
+      if (checked === false) {
+        this.$emit("input", []);
+        return;
+      }
+      if (checked === true) {
+        this.checkBoxData.map(item => {
+          item.checked = true;
+        });
+      }
+      if (!checked) {
+        this.checkBoxData.map(item => {
+          item.checked = !item.checked;
+        });
+      }
 
-            let value = [],
-                label = [];
-            let resData = this.checkBoxData.filter(item => {
-                if (item.checked) {
-                value.push(item.value);
-                label.push(item.label);
-                }
-                return item.checked;
-            });
-            this.$emit("input",value);
-            this.$emit("change", value, label, null);
+      let value = [],
+        label = [];
+      let resData = this.checkBoxData.filter(item => {
+        if (item.checked) {
+          value.push(item.value);
+          label.push(item.label);
         }
+        return item.checked;
+      });
+      this.$emit("input", value);
+      this.$emit("change", value, label, null);
     }
-}
-</script>
+  }
+};
+</script>

+ 13 - 0
src/packages/infiniteloading/infiniteloading.vue

@@ -136,6 +136,19 @@ export default {
         }
     },
 
+    activated() {
+        if(this.keepAlive){
+            this.keepAlive = false;
+            this.scrollListener();
+        }
+    },
+
+    deactivated() {
+        this.keepAlive = true;
+        window.removeEventListener('scroll', this.handleScroll, false);
+        window.removeEventListener('resize', this.handleScroll, false);
+    },
+
     destroyed() {
         window.removeEventListener('scroll', this.handleScroll, false);
         window.removeEventListener('resize', this.handleScroll, false);

File diff suppressed because it is too large
+ 148 - 0
src/packages/leftslip/demo.vue


+ 119 - 0
src/packages/leftslip/doc.md

@@ -0,0 +1,119 @@
+# LeftSlip 左滑删除
+
+列表元素向左滑出现删除等按钮
+
+## 基本用法
+
+```html
+<div>
+    <nut-leftslip>
+        <div slot="slip-main" class="slip-main">向左滑动我</div>
+        <div slot="slipbtns" class="slipbtns"><a href="javascript:;">删除</a><a href="javascript:;" class="favorite">收藏</a></div>
+    </nut-leftslip>
+</div>
+```
+
+### 单个按钮
+
+```html
+<div>
+    <nut-leftslip>
+        <div slot="slip-main" class="slip-main">单一按钮</div>
+        <div slot="slipbtns" class="slipbtns"><a href="javascript:;">删除</a></div>
+    </nut-leftslip>
+</div>
+```
+
+### 单个按钮左滑一键删除
+
+```html
+<nut-leftslip onlyDel @oneDelete="oneDel">
+    <div slot="slip-main" class="slip-main">向左滑滑滑~一键删除</div>
+</nut-leftslip>
+```
+
+```javascript
+export default {
+    oneDel(par) {
+        par.remove();
+    }
+};
+```
+
+### 多个按钮
+
+```html
+<div>
+    <nut-leftslip>
+        <div slot="slip-main" class="slip-main">向左滑动,多个按钮有超出限制哦~</div>
+        <div slot="slipbtns" class="slipbtns"
+            ><a href="javascript:;">删除</a>
+            <a href="javascript:;" class="favorite">收藏</a>
+            <a href="javascript:;" class="favorite org1"><nut-icon type="trolley" size="20px" color="#fff"></nut-icon></a>
+            <a href="javascript:;" class="favorite org2"><nut-icon type="cross" size="15px" color="#fff"></nut-icon></a>
+            <a href="javascript:;" class="favorite org3">确认</a>
+            <a href="javascript:;" class="favorite org1">加购物车</a>
+            <a href="javascript:;" class="favorite">收藏2</a>
+            <a href="javascript:;" class="favorite">收藏3</a>
+        </div>
+    </nut-leftslip>
+</div>
+```
+
+### 列表
+
+```html
+<div>
+    <nut-leftslip v-for="(item, index) in list" :key="item.id" ref="leftslip">
+        <div slot="slip-main" class="slip-main">
+            <div class="addr">
+                <p class="name-mobile">159****8888</p>
+                <p class="full-addr">北京市大兴区亦庄经济开发中心京东大厦B座1</p>
+            </div>
+            <a class="addr-edit" href="javascript:void(0)"></a>
+        </div>
+        <div slot="slipbtns" class="slipbtns"
+            ><a href="javascript:;" @click="delItem(index)">删除</a><a href="javascript:;" class="favorite">收藏</a></div
+        >
+    </nut-leftslip>
+</div>
+```
+
+```javascript
+export default {
+    components: {},
+    data() {
+        return {
+            list: [
+                {id: 'add1', addr: '北京市大兴区亦庄经济开发中心京东大厦B座1', tel: '159****8888'},
+                {id: 'add2', addr: '北京市大兴区亦庄经济开发中心京东大厦B座2', tel: '159****8888'},
+                {id: 'add3', addr: '北京市大兴区亦庄经济开发中心京东大厦B座3', tel: '159****8888'},
+                {id: 'add4', addr: '北京市大兴区亦庄经济开发中心京东大厦B座4', tel: '159****8888'},
+                {id: 'add5', addr: '北京市大兴区亦庄经济开发中心京东大厦B座5', tel: '159****8888'},
+                {id: 'add6', addr: '北京市大兴区亦庄经济开发中心京东大厦B座6', tel: '159****8888'},
+                {id: 'add7', addr: '北京市大兴区亦庄经济开发中心京东大厦B座7', tel: '159****8888'},
+                {id: 'add8', addr: '北京市大兴区亦庄经济开发中心京东大厦B座8', tel: '159****8888'}
+            ]
+        };
+    },
+    methods: {
+        delItem(index) {
+            this.list.splice(index, 1);
+        }
+    }
+};
+```
+
+## Prop
+
+| 字段           | 说明                                           | 类型    | 默认值 |
+| -------------- | ---------------------------------------------- | ------- | ------ |
+| slot:slip-main | 列表主内容自定义区域                           | html    | -      |
+| slot:slipbtns  | 左滑按钮自定义区域                             | html    | -      |
+| onlyDel        | 显示只有一个删除按钮的列表样式(支持一键删除) | Boolean | false  |
+
+## Event
+
+| 字段      | 说明                       | 回调参数 |
+| --------- | -------------------------- | -------- |
+| oneDelete | 单一删除按钮模式下删除事件 | 无       |

+ 8 - 0
src/packages/leftslip/index.js

@@ -0,0 +1,8 @@
+import LeftSlip from "./leftslip.vue";
+import "./leftslip.scss";
+
+LeftSlip.install = function(Vue) {
+  Vue.component(LeftSlip.name, LeftSlip);
+};
+
+export default LeftSlip;

+ 66 - 0
src/packages/leftslip/leftslip.scss

@@ -0,0 +1,66 @@
+.nut-leftslip {
+    position: relative;
+    overflow: hidden;
+    &:first-child .slip-main {
+        border-top: 1px solid #d8d8d8;
+    }
+    .slip-main {
+        padding: 10px;
+        position: relative;
+        overflow: hidden;
+        display: flex;
+        border-bottom: 1px solid #d8d8d8;
+        background: #fff;
+    }
+    .leftslip-item {
+        transition: all 0.6s ease;
+    }
+    .delbtn{
+        position: absolute;
+        right: -50px;
+        top: 0;
+        min-width: 40px;
+        height: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        // transform: translateX(100%);
+        background: #ff4949;
+        color: #fff;
+        padding: 0 5px;
+        font-size: 14px;
+        span{
+            // width: 40px;
+            display: flex;
+            position: absolute;
+            right: 0;
+            width: 50px;
+            align-items: center;
+            justify-content: center;
+            height: 100%;
+        }
+    }
+    .slipbtns {
+        position: absolute;
+        right: -0px;
+        top: 0;
+        // width: 80px;
+        height: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        transform: translateX(100%);
+        a {
+            display: flex;
+            width: 40px;
+            background: #ff4949;
+            color: #fff;
+            height: 100%;
+            padding: 0 5px;
+            font-size: 14px;
+            align-items: center;
+            justify-content: center;
+            text-align: center;
+        }
+    }
+}

+ 202 - 0
src/packages/leftslip/leftslip.vue

@@ -0,0 +1,202 @@
+<template>
+    <div class="nut-leftslip">
+        <div class="leftslip-item" ref="slipItem" :style="deleteSlider">
+            <div @touchstart="touchStart($event)" @touchmove="touchMove($event)" @touchend="touchEnd($event)">
+                <slot name="slip-main"></slot>
+            </div>
+
+            <div v-if="onlyDel" class="delbtn" ref="delBtn"
+                ><div :style="delBtnStyle" class="trans"></div><span @click.prevent="onlyDelClick($event)">删除</span></div
+            >
+            <div v-else>
+                <!-- <a @click.prevent="onlyDelClick($event)">删除</a> -->
+                <slot name="slipbtns"></slot>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+export default {
+    name: 'nut-leftslip',
+    props: {
+        onlyDel: {
+            type: [Boolean],
+            default: false
+        }
+    },
+    data() {
+        return {
+            startX: 0,
+            startY: 0,
+            moveX: 0,
+            moveY: 0,
+            left: 0,
+            buttonWidth: 0,
+            disX: 0, //移动距离
+            deleteSlider: '', //滑动时的效果,使用v-bind:style="deleteSlider"
+            delBtnStyle: '' //单个删除键拖拽删除效果
+        };
+    },
+    mounted() {
+        this.$nextTick(() => {
+            if (this.onlyDel) {
+                return;
+            }
+            for (var slot of this.$slots.slipbtns) {
+                this.buttonWidth = this.buttonWidth + slot.elm.offsetWidth;
+            }
+        });
+        var that = this;
+        this.$on('bridge', () => {
+            that.restSlide();
+        }); //设置接收父组件的方法
+
+        window.addEventListener('scroll', this.handleScroll, true);
+    },
+    beforeDestroy() {
+        // 移除监听
+        window.removeEventListener('scroll', this.handleScroll, true);
+    },
+    methods: {
+        handleScroll() {
+            if (this.disX) {
+                this.restSlide();
+            }
+            // this.restSlide();
+        },
+        handleClick() {
+            this.restSlide();
+        },
+        onlyDelClick() {
+            // this.$emit('onlyDelBtnClick', this.$refs.slipItem);
+            this.$emit('oneDelete', this.$refs.slipItem);
+            this.restSlide();
+        },
+        touchStart(e) {
+            this.restSlide();
+            // console.log('rest', e.touches.length);
+            e = e || event;
+
+            //tounches类数组,等于1时表示此时有只有一只手指在触摸屏幕
+            if (e.touches.length == 1) {
+                // 记录开始位置
+                this.startX = e.touches[0].clientX;
+                this.startY = e.touches[0].clientY;
+            }
+        },
+        touchMove(e) {
+            e = e || event;
+            // let parentElement = e.currentTarget.parentElement;
+            //获取删除按钮的宽度,此宽度为滑块左滑的最大距离
+            let itemWd = this.$refs.slipItem.offsetWidth;
+            // console.log(this.$refs.delBtn.offsetWidth);
+            let wd = this.onlyDel ? 40 : this.buttonWidth;
+            if (e.touches.length == 1) {
+                // 滑动时距离浏览器左侧实时距离
+                this.moveY = e.touches[0].clientY;
+                this.moveX = e.touches[0].clientX;
+                if (Math.abs(this.moveY - this.startY) < 40) {
+                    //起始位置减去 实时的滑动的距离,得到手指实时偏移距离
+                    this.disX = this.startX - this.moveX;
+                    // console.log(this.disX);
+                    if (this.onlyDel) {
+                        //单一删除,左滑一键删除
+                        if (this.disX < 0 || this.disX == 0) {
+                            this.deleteSlider = 'transform:translateX(0px)';
+                            // parentElement.dataset.type = 0;
+                            // 大于0,表示左滑了,此时滑块开始滑动
+                        }
+                        this.deleteSlider = 'transform:translateX(-' + this.disX + 'px)';
+                        this.delBtnStyle = 'width:' + this.disX + 'px';
+                    } else {
+                        // 如果是向右滑动或者不滑动,不改变滑块的位置
+                        if (this.disX < wd / 4 || this.disX == 0) {
+                            this.deleteSlider = 'transform:translateX(0px)';
+                            // parentElement.dataset.type = 0;
+                            // 大于0,表示左滑了,此时滑块开始滑动
+                        } else if (this.disX > wd / 4) {
+                            //具体滑动距离我取的是 手指偏移距离*5。
+                            // parentElement.dataset.type = 1;
+                            this.deleteSlider = 'transform:translateX(-' + this.disX + 'px)';
+
+                            // 最大也只能等于删除按钮宽度
+                            if (this.disX * 1.5 >= wd) {
+                                // parentElement.dataset.type = 1;
+                                if (wd >= itemWd) {
+                                    this.deleteSlider = 'transform:translateX(-' + (itemWd - 40) + 'px)';
+                                } else {
+                                    this.deleteSlider = 'transform:translateX(-' + wd + 'px)';
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        },
+        touchEnd(e) {
+            e = e || event;
+            // let parentElement = e.currentTarget.parentElement;
+            let itemWd = this.$refs.slipItem.offsetWidth;
+            let wd = this.onlyDel ? 40 : this.buttonWidth;
+            if (e.changedTouches.length == 1) {
+                let endY = e.changedTouches[0].clientY;
+                if (Math.abs(this.startY - endY) < 40) {
+                    let endX = e.changedTouches[0].clientX;
+                    this.disX = this.startX - endX;
+                    // console.log('touchEndthis.disX:', this.disX);
+                    if (this.onlyDel) {
+                        //单一按钮,左滑一键删除
+                        if (this.disX < 0 || this.disX == 0) {
+                            this.deleteSlider = 'transform:translateX(0px)';
+                            // parentElement.dataset.type = 0;
+                            // 大于0,表示左滑了,此时滑块开始滑动
+                        } else if (this.disX < itemWd - 20) {
+                            // parentElement.dataset.type = 0;
+                            this.deleteSlider = 'transform:translateX(-50px);';
+                            this.delBtnStyle = ' width:0px;';
+                        } else {
+                            this.deleteSlider = 'transform:translateX(-' + itemWd + 'px);';
+                            this.delBtnStyle = ' width:' + itemWd + 'px;';
+                            // this.$emit('oneDelete', this.$refs.slipItem);
+                            // this.restSlide();
+                            this.onlyDelClick();
+                        }
+                    } else {
+                        //如果距离小于删除按钮的四分之一,强行回到起点
+
+                        if (this.disX < wd / 4) {
+                            // parentElement.dataset.type = 0;
+                            this.deleteSlider = 'transform:translateX(0px)';
+                        } else {
+                            //大于一半 滑动到最大值
+                            // parentElement.dataset.type = 1;
+                            if (wd >= itemWd) {
+                                //按钮数不可超出整行宽度
+                                this.deleteSlider = 'transform:translateX(-' + (itemWd - 40) + 'px)';
+                            } else {
+                                this.deleteSlider = 'transform:translateX(-' + wd + 'px)';
+                            }
+                        }
+                    }
+
+                    // console.log('touchEnd:dataset', parentElement.dataset.type);
+                }
+            }
+        },
+        restSlide() {
+            let listItems = document.querySelectorAll('.leftslip-item');
+            let delBtns = document.querySelectorAll('.delbtn .trans');
+            // console.log(delBtns);
+            // 复位
+            for (let i = 0; i < listItems.length; i++) {
+                listItems[i].style = 'transform:translateX(0' + 'px)';
+            }
+            for (let j = 0; j < delBtns.length; j++) {
+                delBtns[j].style = '';
+            }
+
+            // this.delBtnStyle = '';
+        }
+    }
+};
+</script>

+ 1 - 0
src/packages/picker/picker.scss

@@ -71,6 +71,7 @@
         white-space: nowrap;
         overflow: hidden;
         text-overflow: ellipsis;
+        height: 36px;
         line-height: 36px;
         color: $title-color;
         font-size: $font-size-base;

+ 47 - 1
src/packages/popup/demo.vue

@@ -58,6 +58,49 @@
       v-model="showRight"
       :style="{ width: '20%', height: '100%' }"
     ></nut-popup>
+    <h2 class="title">关闭图标</h2>
+    <nut-cell
+      isLink
+      title="关闭图标"
+      :showIcon="true"
+      @click.native="showIcon = true">
+    </nut-cell>
+    <nut-popup
+      position="bottom"
+      closeable 
+      v-model="showIcon"
+      :style="{ height: '20%' }"
+    ></nut-popup>
+
+    <nut-cell
+      isLink
+      title="图标位置"
+      :showIcon="true"
+      @click.native="showIconPosition = true">
+    </nut-cell>
+    <nut-popup
+      position="bottom"
+      closeable 
+      close-icon-position="top-left"
+      v-model="showIconPosition"
+      :style="{ height: '20%' }"
+    ></nut-popup>
+
+
+    <nut-cell
+      isLink
+      title="自定义图标"
+      :showIcon="true"
+      @click.native="showCloseIcon = true">
+    </nut-cell>
+    <nut-popup
+      position="bottom"
+      closeable 
+      close-icon="tick"
+      v-model="showCloseIcon"
+      :style="{ height: '20%' }"
+    ></nut-popup>
+
 
     <h2 class="title">圆角弹框</h2>
     <nut-cell
@@ -85,7 +128,10 @@ export default {
       showBottom: false,
       showLeft: false,
       showRight: false,
-      showRound: false
+      showIcon: false,
+      showRound: false,
+      showIconPosition: false,
+      showCloseIcon: false
     };
   },
   methods: {

+ 12 - 0
src/packages/popup/doc.md

@@ -35,6 +35,14 @@ export default {
 <nut-popup v-model="show" position="top" :style="{ height: '20%' }" />
 ```
 
+## 关闭图标
+
+设置closeable属性后,会在弹出层的右上角显示关闭图标,并且可以通过close-icon属性自定义图标,使用close-icon-position属性可以自定义图标位置
+
+```html
+<nut-popup position="bottom" closeable  close-icon="tick" v-model="showCloseIcon" :style="{ height: '20%' }" close-icon-position="top-left"></nut-popup>
+```
+
 ## 圆角弹窗
 
 设置 round 属性后,弹窗会根据弹出位置添加不同的圆角样式
@@ -53,3 +61,7 @@ export default {
 | duration   | 动画时长,单位秒                         | Number  | -      |
 | round      | 是否显示圆角                             | boolean | -      |
 | transition | 动画类名,等价于 transtion 的 name 属性  | string  | -      |
+| closeable  | 是否显示关闭图标                        | Boolean  | false     |
+| close-icon | 关闭图标名称                  | string  | cross     |
+| close-icon-position | 关闭图标位置,可选值为top-left bottom-left bottom-right | string  | top-right  |
+

+ 2 - 11
src/packages/popup/mask.vue

@@ -1,6 +1,6 @@
 <template>
   <transition name="popup-fade">
-    <div v-show="show" class="bg nut-mask" @click="onClick"></div>
+    <div v-show="show" class="bg nut-mask" ></div>
   </transition>
 </template>
 <script>
@@ -8,16 +8,7 @@ export default {
   name: "nut-popup-mask",
   props: {
     show: { type: Boolean, default: true }
-  },
-  data() {
-    return {};
-  },
-
-  methods: {
-    onClick() {
-      this.$emit("input", false);
-    }
-  }
+  },    
 };
 </script>
 <style lang="scss" scoped>

+ 43 - 4
src/packages/popup/popup.scss

@@ -1,8 +1,9 @@
+$popup-close-icon-margin: 16px; 
 .popup-fade-enter-active {
-    animation: 0.2s nut-fade-in;
+    animation: 0.3s nut-fade-in;
   }
   .popup-fade-leave-active {
-    animation: 0.2s nut-fade-out;
+    animation: 0.3s nut-fade-out;
   }
   
   .popup-slide {
@@ -68,7 +69,7 @@
     max-height: 100%;
     overflow-y: auto;
     background-color: #fff;
-    transition: transform 0.2s;
+    transition: transform 0.3s;
     -webkit-overflow-scrolling: touch;
     z-index: 2028;
   }
@@ -92,4 +93,42 @@
     }
   }
  
-  
+  
+ 
+
+.nutui-popup{
+    &__close-icon{
+        position: absolute;
+        z-index: 1;
+        color: #969799;
+        font-size: 18px;
+        cursor: pointer;
+       
+        &:active {
+            opacity: .7;
+        }
+
+        &--top-left {
+            top: $popup-close-icon-margin;
+            left: $popup-close-icon-margin;
+        }
+
+        &--top-right {
+            top: $popup-close-icon-margin;
+            right: $popup-close-icon-margin;
+        }
+
+        &--bottom-left {
+            bottom: $popup-close-icon-margin;
+            left: $popup-close-icon-margin;
+        }
+
+        &--bottom-right {
+            right: $popup-close-icon-margin;
+            bottom: $popup-close-icon-margin;
+        }
+    }
+}
+ 
+
+ 

+ 15 - 1
src/packages/popup/popup.vue

@@ -6,7 +6,9 @@
       class="popup-box"
       :class="[`popup-${position}`, { round }]"
     >
-      <slot></slot>
+        <slot></slot>
+        <nut-icon v-if='closeable' @click.native='$emit("input", false)' :type="closeIcon" size="12px"  class="nutui-popup__close-icon" :class="'nutui-popup__close-icon--'+closeIconPosition">
+        </nut-icon>
     </div>
   </transition>
 </template>
@@ -28,6 +30,18 @@ export default {
       type: Boolean,
       default: true
     },
+    closeable:{
+        type: Boolean,
+        default: false 
+    },
+    closeIconPosition: {
+      type: String,
+      default: 'top-right'
+    },
+    closeIcon:{
+        type: String,
+        default: 'cross'
+    },
     round: Boolean
   },
   created() {

+ 1 - 1
src/packages/tabselect/tabselect.scss

@@ -94,7 +94,7 @@
     margin-bottom: 10px;
     border-radius: 2px;
     cursor: pointer;
-    &.nut-tab-panel-active {
+    &.nut-tab-panel-list-active {
       color: #e2231a;
       border: 1px solid #e2231a;
       background: #fcedeb;

+ 2 - 0
types/nutui.d.ts

@@ -64,4 +64,6 @@ export declare class Avatar extends UIComponent {}
 export declare class Infiniteloading extends UIComponent {}
 export declare class Lazyload extends UIComponent {}
 export declare class Elevator extends UIComponent {}
+export declare class SlipesideBotdeslip[Cefttonutton extends UIComponent {}
 export declare class TabSelect extends UIComponent {}
+