From 609f4ea6f20b65eaba4b2777d498dbe7fc311ee2 Mon Sep 17 00:00:00 2001
From: "songwanli2025@163.com" <songwanli2025@163.com>
Date: Fri, 17 Apr 2020 18:44:30 +0800
Subject: [PATCH] add(DynamicTags)

---
 .../components/tag/enUS/dynamicTags.md        |  39 ++++++
 .../components/tag/enUS/index.md              |  22 +++-
 .../components/tag/zhCN/dynamicTags.md        |  39 ++++++
 .../components/tag/zhCN/index.md              |  19 +++
 src/Tag/index.js                              |   2 +
 src/Tag/src/DynamicTags.vue                   | 121 ++++++++++++++++++
 src/_interoperation/darkStyleScheme.scss      |   1 +
 src/_interoperation/lightStyleScheme.scss     |   3 +-
 styles/DynamicTags.scss                       |  12 ++
 styles/index.scss                             |   3 +-
 10 files changed, 258 insertions(+), 3 deletions(-)
 create mode 100644 demo/documentation/components/tag/enUS/dynamicTags.md
 create mode 100644 demo/documentation/components/tag/zhCN/dynamicTags.md
 create mode 100644 src/Tag/src/DynamicTags.vue
 create mode 100644 styles/DynamicTags.scss

diff --git a/demo/documentation/components/tag/enUS/dynamicTags.md b/demo/documentation/components/tag/enUS/dynamicTags.md
new file mode 100644
index 000000000..91eeff714
--- /dev/null
+++ b/demo/documentation/components/tag/enUS/dynamicTags.md
@@ -0,0 +1,39 @@
+# Edit Dynamically
+```html
+<n-dynamic-tags v-model="model.tags" @change="hanleChange" />
+
+Use in form.
+<n-form :model="model" :rules="rules">
+  <n-form-item
+    path="tags"
+  >
+    <n-dynamic-tags v-model="model.tags" />
+  </n-form-item>
+</n-form>
+{{model.tags}}
+```
+```js
+export default {
+  data () {
+    return {
+      model: {
+        tags: ['teacher', 'programmer']
+      },
+      rules: {
+        tags: {
+          trigger: ['change'],
+          validator (rule, value) {
+            if (value.length >= 5) return new Error('Up to 4 tags')
+            return true
+          }
+        }
+      }
+    }
+  },
+  methods: {
+    hanleChange (tags) {
+      console.log('tags', tags)
+    }
+  }
+}
+```
\ No newline at end of file
diff --git a/demo/documentation/components/tag/enUS/index.md b/demo/documentation/components/tag/enUS/index.md
index 86dcdcd4f..f32ee5b9c 100644
--- a/demo/documentation/components/tag/enUS/index.md
+++ b/demo/documentation/components/tag/enUS/index.md
@@ -8,6 +8,7 @@ disabled
 size
 checkable
 shape
+dynamicTags
 ```
 ## V-model
 |Prop|Event|
@@ -15,6 +16,7 @@ shape
 |checked|checked-change|
 
 ## Props
+### Tag
 |Name|Type|Default|Description|
 |-|-|-|-|
 |theme|`'light' \| 'dark'`|`null`||
@@ -26,13 +28,31 @@ shape
 |checked|`boolean`|`false`||
 |closable|`boolean`|`false`||
 
+### DynamicTags
+|Name|Type|Default|Description|
+|-|-|-|-|
+|value|`array`|`[]`||
+|theme|`'light' \| 'dark'`|`null`||
+|type|`'default' \| 'info' \| 'succcess' \| 'warning' \| 'error'`|`'default'`||
+|size|`'small' \| 'medium' \| 'large'`|`'medium'`||
+|disabled|`boolean`|`false`||
+|round|`boolean`|`false`||
+|closable|`boolean`|`false`||
+
+
 ## Slots
 |Name|Parameters|Description|
 |-|-|-|
 |default|`()`||
 
 ## Events
+### Tag
 |Name|Parameters|Description|
 |-|-|-|
 |close|`()`|
-|checked-change|`(checked: boolean)`||
\ No newline at end of file
+|checked-change|`(checked: boolean)`||
+
+### DynamicTags
+|Name|Parameters|Description|
+|-|-|-|
+|change|`(tags: array)`||
\ No newline at end of file
diff --git a/demo/documentation/components/tag/zhCN/dynamicTags.md b/demo/documentation/components/tag/zhCN/dynamicTags.md
new file mode 100644
index 000000000..ffe719944
--- /dev/null
+++ b/demo/documentation/components/tag/zhCN/dynamicTags.md
@@ -0,0 +1,39 @@
+# 动态编辑标签
+```html
+<n-dynamic-tags v-model="model.tags" @change="hanleChange" />
+
+在表单中使用
+<n-form :model="model" :rules="rules">
+  <n-form-item
+    path="tags"
+  >
+    <n-dynamic-tags v-model="model.tags" />
+  </n-form-item>
+</n-form>
+{{model.tags}}
+```
+```js
+export default {
+  data () {
+    return {
+      model: {
+        tags: ['武汉', '广东']
+      },
+      rules: {
+        tags: {
+          trigger: ['change'],
+          validator (rule, value) {
+            if (value.length >= 5) return new Error('最多四个')
+            return true
+          }
+        }
+      }
+    }
+  },
+  methods: {
+    hanleChange (tags) {
+      console.log('所有标签值', tags)
+    }
+  }
+}
+```
\ No newline at end of file
diff --git a/demo/documentation/components/tag/zhCN/index.md b/demo/documentation/components/tag/zhCN/index.md
index b751d2a36..84bd95c7e 100644
--- a/demo/documentation/components/tag/zhCN/index.md
+++ b/demo/documentation/components/tag/zhCN/index.md
@@ -9,6 +9,7 @@ disabled
 size
 checkable
 shape
+dynamicTags
 ```
 
 ## V-model
@@ -17,6 +18,7 @@ shape
 |checked|checked-change|
 
 ## Props
+### Tag
 |名称|类型|默认值|说明|
 |-|-|-|-|
 |theme|`'light' \| 'dark'`|`null`||
@@ -28,13 +30,30 @@ shape
 |checked|`boolean`|`false`||
 |closable|`boolean`|`false`||
 
+### DynamicTags
+|名称|类型|默认值|说明|
+|-|-|-|-|
+|value|`array`|`[]`||
+|theme|`'light' \| 'dark'`|`null`||
+|type|`'default' \| 'info' \| 'succcess' \| 'warning' \| 'error'`|`'default'`||
+|size|`'small' \| 'medium' \| 'large'`|`'medium'`||
+|disabled|`boolean`|`false`||
+|round|`boolean`|`false`||
+|closable|`boolean`|`false`||
+
 ## Slots
 |名称|参数|说明|
 |-|-|-|
 |default|`()`||
 
 ## Events
+### Tag
 |名称|参数|说明|
 |-|-|-|
 |close|`()`|
 |checked-change|`(checked: boolean)`||
+
+### DynamicTags
+|名称|参数|说明|
+|-|-|-|
+|change|`(tags: array)`||
\ No newline at end of file
diff --git a/src/Tag/index.js b/src/Tag/index.js
index 6f52eed82..cdea075b5 100644
--- a/src/Tag/index.js
+++ b/src/Tag/index.js
@@ -1,8 +1,10 @@
 /* istanbul ignore file */
 import Tag from './src/main.vue'
+import DynamicTags from './src/DynamicTags.vue'
 
 Tag.install = function (Vue) {
   Vue.component(Tag.name, Tag)
+  Vue.component(DynamicTags.name, DynamicTags)
 }
 
 export default Tag
diff --git a/src/Tag/src/DynamicTags.vue b/src/Tag/src/DynamicTags.vue
new file mode 100644
index 000000000..2edb1e5c2
--- /dev/null
+++ b/src/Tag/src/DynamicTags.vue
@@ -0,0 +1,121 @@
+<template>
+  <div class="n-dynamic-tags">
+    <n-tag
+      v-for="(tag, index) in value"
+      :key="tag + index"
+      :style="{marginRight: spacing + 'px' }"
+      :type="type"
+      :round="round"
+      :size="size"
+      :closable="closable"
+      :disabled="disabled"
+      @close="handleCloseClick(index)"
+    >
+      {{ tag }}
+    </n-tag>
+    <n-input
+      v-if="inputVisible"
+      ref="tagInput"
+      v-model="inputValue"
+      style="width:50px;"
+      size="small"
+      @keyup.enter.native="handleInputConfirm"
+      @blur="handleInputConfirm"
+    />
+    <n-button
+      v-else
+      size="small"
+      @click="handleClickAdd"
+    >
+      + Add
+    </n-button>
+  </div>
+</template>
+
+<script>
+import withapp from '../../_mixins/withapp'
+import themeable from '../../_mixins/themeable'
+import NTag from './main'
+import asformitem from '../../_mixins/asformitem'
+
+export default {
+  name: 'NDynamicTags',
+  components: {
+    NTag
+  },
+  mixins: [withapp, themeable, asformitem({
+    change: 'change',
+    input: 'input'
+  })],
+  props: {
+    value: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    },
+    type: {
+      validator (value) {
+        return ['default', 'success', 'info', 'warning', 'error'].includes(value)
+      },
+      default: 'default'
+    },
+    round: {
+      type: Boolean,
+      default: false
+    },
+    size: {
+      validator (value) {
+        return ['small', 'medium', 'large'].includes(value)
+      },
+      default: 'medium'
+    },
+    closable: {
+      type: Boolean,
+      default: true
+    },
+    disabled: {
+      type: Boolean,
+      default: false
+    },
+    spacing: {
+      type: Number,
+      default: 5
+    }
+  },
+  data () {
+    return {
+      inputValue: '',
+      inputVisible: false
+    }
+  },
+  watch: {
+    value (tags) {
+      this.$emit('change', tags)
+    }
+  },
+  methods: {
+    handleCloseClick (index) {
+      const tags = this.value.slice(0)
+      tags.splice(index, 1)
+      this.$emit('input', tags)
+    },
+    handleInputConfirm () {
+      if (this.inputValue) {
+        const tags = this.value.slice(0)
+        tags.push(this.inputValue)
+        this.$emit('input', tags)
+      }
+      this.inputVisible = false
+      this.inputValue = ''
+    },
+    handleClickAdd () {
+      this.inputVisible = true
+      this.$nextTick(_ => {
+        this.$refs.tagInput.$refs.input.focus()
+      })
+    }
+  }
+
+}
+</script>
diff --git a/src/_interoperation/darkStyleScheme.scss b/src/_interoperation/darkStyleScheme.scss
index bac9fecff..d8e9e4ceb 100644
--- a/src/_interoperation/darkStyleScheme.scss
+++ b/src/_interoperation/darkStyleScheme.scss
@@ -32,4 +32,5 @@
   borderColor: $--n-border-color;
   easeInOutCubicBezier: $--n-ease-in-out-cubic-bezier;
   tableHeaderColor: composite-color($--neutral-card, $--overlay-action);
+  inputBackgroundColor:  $--overlay-input;
 }
diff --git a/src/_interoperation/lightStyleScheme.scss b/src/_interoperation/lightStyleScheme.scss
index 30285ac8d..05b2e5958 100644
--- a/src/_interoperation/lightStyleScheme.scss
+++ b/src/_interoperation/lightStyleScheme.scss
@@ -32,5 +32,6 @@
   dividerColor: $--overlay-divider;
   borderColor: $--n-border-color;
   easeInOutCubicBezier: $--n-ease-in-out-cubic-bezier;
-  tableHeaderColor: composite-color($--neutral-card, $--overlay-action);
+  // tableHeaderColor: composite-color($--neutral-card, $--overlay-action);
+  inputBackgroundColor:  $--overlay-input;
 }
diff --git a/styles/DynamicTags.scss b/styles/DynamicTags.scss
new file mode 100644
index 000000000..2a96662ab
--- /dev/null
+++ b/styles/DynamicTags.scss
@@ -0,0 +1,12 @@
+@import './mixins/mixins.scss';
+
+@include themes-mixin {
+  @include once {
+    @include b(dynamic-tags) {
+      width: 100%;
+      @include b(tag) {
+        margin-bottom: 5px;
+      }
+    }
+  }
+}
diff --git a/styles/index.scss b/styles/index.scss
index 8eaed607a..7820f972f 100644
--- a/styles/index.scss
+++ b/styles/index.scss
@@ -70,4 +70,5 @@
 @import "./Empty.scss";
 @import "./Log.scss";
 @import "./Typography.scss";
-@import "./Upload.scss";
\ No newline at end of file
+@import "./Upload.scss";
+@import "./DynamicTags.scss";
\ No newline at end of file