├── src
├── index.js
├── lib.js
├── assets
│ └── ic_close_black_16px.svg
├── tag.vue
├── webpack.config.js
├── input.vue
└── typing.vue
├── anim.gif
├── index.html
├── example
├── index.js
├── minimal.vue
└── full.vue
├── .eslintrc.yml
├── .gitignore
├── LICENSE
├── README.md
├── webpack.config.js
├── package.json
└── dist
├── vue-tagsinput.js
└── vue-tagsinput.js.map
/src/index.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./input.vue')
2 |
--------------------------------------------------------------------------------
/anim.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ginhing/vue-tagsinput/HEAD/anim.gif
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue-tagsinput demo
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/lib.js:
--------------------------------------------------------------------------------
1 | export const KEY_CODE = {
2 | LEFT: 37,
3 | RIGHT: 39,
4 | TAB: 9,
5 | BACKSPACE: 8
6 | }
7 |
8 | export const klass = {
9 | container: 'tags-input',
10 | input: 'input',
11 | gap: 'gap',
12 | tag: 'tag',
13 | placeholder: 'placeholder'
14 | }
15 |
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import MinimalExample from './minimal.vue'
3 | import FullExample from './full.vue'
4 |
5 | new Vue({
6 | el: '#example',
7 | render(h) {
8 | return h('div', [
9 | MinimalExample,
10 | FullExample
11 | ].map(h))
12 | }
13 | })
14 |
--------------------------------------------------------------------------------
/src/assets/ic_close_black_16px.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.eslintrc.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # parser: babel-eslint
3 | parserOptions:
4 | sourceType: module
5 | ecmaVersion: 7
6 | ecmaFeatures:
7 | jsx: true
8 | plugins:
9 | - react
10 | - vue
11 | extends:
12 | - eslint:recommended
13 | - plugin:react/recommended
14 | env:
15 | jest: true
16 | es6: true
17 | rules:
18 | no-var: 2
19 | no-unused-vars: 1
20 | semi: [1, never]
21 |
--------------------------------------------------------------------------------
/example/minimal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
minimal example
4 |
8 |
9 |
10 |
11 |
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
18 | .grunt
19 |
20 | # node-waf configuration
21 | .lock-wscript
22 |
23 | # Compiled binary addons (http://nodejs.org/api/addons.html)
24 | build/Release
25 |
26 | # Dependency directory
27 | node_modules
28 |
29 | # Optional npm cache directory
30 | .npm
31 |
32 | # Optional REPL history
33 | .node_repl_history
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Ginhing
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/tag.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{text}}
4 |
10 |
11 |
12 |
36 |
57 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | >## This Project Is Deprecated
2 | # vue-tagsinput
3 | [![][npm-image]][npm-url]
4 |
5 | [npm-image]: https://img.shields.io/npm/v/vue-tagsinput.svg
6 | [npm-url]: https://npmjs.org/package/vue-tagsinput
7 |
8 | >kerboard supported(left, right, backspace, tab).
9 | 
10 |
11 | ## Requirement
12 | - vue: `^2.1.0`
13 |
14 | ## Usage
15 | ```html
16 |
17 |
21 |
22 | ```
23 |
24 | ## Example
25 | [Live example](http://www.webpackbin.com/Vyc_H61fG)
26 |
27 | ## Props
28 | - tags(array\<{ text: string, readOnly: ?boolean, invalid: ?boolean }>, required):
29 | your tags to render
30 | - placeholder(string): a hint to the user
31 | - klass(object): override the class name (see below)
32 |
33 | ## Events
34 | - tags-change: (index: number, text: ?string) => void
35 | `text` will be undefined if the tag was removed
36 | - focus: (index: number) => void
37 | - blur: (index: number) => void
38 |
39 | ## Class Names
40 | ```javascript
41 | {
42 | container: 'tags-input',
43 | input: 'input',
44 | placeholder: 'placeholder',
45 | gap: 'gap',
46 | tag: 'tag'
47 | }
48 | ```
49 |
50 | ## Migration from 0.x
51 | Because of the two-way props was obsoleted in Vue@2, we should deal with tags by one-way props and onChange callback explicitly.
52 | So most states will be handled in your scope. See the [full example](./example/full.vue).
53 |
54 | ## License
55 |
56 | [MIT](LICENSE)
57 |
--------------------------------------------------------------------------------
/src/webpack.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 | const path = require('path')
3 | const webpack = require('webpack')
4 |
5 | const {NODE_ENV} = process.env
6 |
7 | let config = {
8 | entry: './src/index.js',
9 | output: {
10 | path: path.resolve(__dirname, 'dist/'),
11 | filename: 'vue-tagsinput.js',
12 | libraryTarget: 'commonjs'
13 | },
14 | module: {
15 | loaders: [
16 | {test: /\.js$/, exclude: /node_modules/, loader: 'babel'},
17 | {test: /\.css$/, loader: 'style!css'},
18 | {test: /\.vue$/, loader: 'vue'},
19 | ]
20 | },
21 | plugins: [],
22 | devtool: 'source-map',
23 | babel: {
24 | presets: ['es2015', 'stage-2'],
25 | plugins: []
26 | },
27 | vue: {
28 | loaders: {
29 | scss: 'style!css'
30 | }
31 | }
32 | }
33 |
34 | // for production build
35 | if (NODE_ENV === 'production') {
36 | config.externals = {
37 | vue: 'commonjs vue'
38 | },
39 | // config.babel.plugins.push('transform-runtime')
40 | config.plugins.push(
41 | new webpack.DefinePlugin({
42 | 'process.env': {
43 | NODE_ENV: '"production"'
44 | }
45 | })
46 | )
47 | } else if (NODE_ENV === 'development') {
48 | config = Object.assign(config, {
49 | entry: './example/index.js',
50 | output: {
51 | path: path.resolve(__dirname, 'example'),
52 | filename: 'example.js'
53 | },
54 | devtool: 'eval'
55 | })
56 | }
57 |
58 | module.exports = config
59 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 | const path = require('path')
3 | const webpack = require('webpack')
4 |
5 | const {NODE_ENV} = process.env
6 |
7 | let config = {
8 | entry: './src/index.js',
9 | output: {
10 | path: path.resolve(__dirname, 'dist/'),
11 | filename: 'vue-tagsinput.js',
12 | libraryTarget: 'commonjs'
13 | },
14 | module: {
15 | loaders: [
16 | {test: /\.js$/, exclude: /node_modules/, loader: 'babel'},
17 | {test: /\.css$/, loader: 'style!css'},
18 | {test: /\.vue$/, loader: 'vue'},
19 | {test: /\.svg$/, loader: 'url?limit=1000'}
20 | ]
21 | },
22 | plugins: [],
23 | devtool: 'source-map',
24 | babel: {
25 | presets: ['es2015', 'stage-2'],
26 | plugins: []
27 | },
28 | vue: {
29 | loaders: {
30 | scss: 'style!css'
31 | }
32 | }
33 | }
34 |
35 | // for production build
36 | if (NODE_ENV === 'production') {
37 | config.externals = {
38 | vue: 'commonjs vue'
39 | },
40 | // config.babel.plugins.push('transform-runtime')
41 | config.plugins.push(
42 | new webpack.DefinePlugin({
43 | 'process.env': {
44 | NODE_ENV: '"production"'
45 | }
46 | })
47 | )
48 | } else if (NODE_ENV === 'development') {
49 | config = Object.assign(config, {
50 | entry: './example/index.js',
51 | output: {
52 | path: path.resolve(__dirname, 'example'),
53 | filename: 'example.js'
54 | },
55 | devtool: 'eval'
56 | })
57 | }
58 |
59 | module.exports = config
60 |
--------------------------------------------------------------------------------
/example/full.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
full example
4 |
10 |
11 |
12 |
13 |
62 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-tagsinput",
3 | "version": "2.0.1",
4 | "description": "a tags input component based on Vue.js",
5 | "main": "dist/vue-tagsinput.js",
6 | "files": [
7 | "dist/",
8 | "src/"
9 | ],
10 | "scripts": {
11 | "test": "eslint src/ --ext vue --ext js",
12 | "build": "NODE_ENV=production webpack",
13 | "prepublish": "npm run build",
14 | "dev": "NODE_ENV=development webpack-dev-server --hot --inline"
15 | },
16 | "repository": {
17 | "type": "git",
18 | "url": "git+https://github.com/Ginhing/vue-tagsinput.git"
19 | },
20 | "keywords": [
21 | "tagsinput",
22 | "vue",
23 | "input"
24 | ],
25 | "author": "Ginhing",
26 | "license": "MIT",
27 | "bugs": {
28 | "url": "https://github.com/Ginhing/vue-tagsinput/issues"
29 | },
30 | "homepage": "https://github.com/Ginhing/vue-tagsinput#readme",
31 | "peerDependencies": {
32 | "vue": "^2.1.10"
33 | },
34 | "devDependencies": {
35 | "babel-core": "^6.8.0",
36 | "babel-loader": "^6.2.4",
37 | "babel-plugin-transform-runtime": "^6.8.0",
38 | "babel-preset-es2015": "^6.6.0",
39 | "babel-preset-stage-2": "^6.5.0",
40 | "babel-runtime": "^6.0.0",
41 | "css-loader": "^0.23.1",
42 | "eslint": "^3.10.2",
43 | "eslint-plugin-vue": "^1.0.0",
44 | "file-loader": "^0.10.0",
45 | "style-loader": "^0.13.0",
46 | "url-loader": "^0.5.7",
47 | "vue": "^2.1.10",
48 | "vue-hot-reload-api": "^1.2.2",
49 | "vue-html-loader": "^1.0.0",
50 | "vue-loader": "^10.0.1",
51 | "vue-style-loader": "^1.0.0",
52 | "vue-template-compiler": "^2.1.10",
53 | "webpack": "^1.12.9",
54 | "webpack-dev-server": "^1.14.0"
55 | },
56 | "dependencies": {
57 | "vuept": "^1.2.0"
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/input.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 | {{placeholder}}
14 |
15 |
17 |
18 |
19 |
20 |
21 |
39 |
108 |
--------------------------------------------------------------------------------
/src/typing.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
14 |
15 |
29 |
112 |
--------------------------------------------------------------------------------
/dist/vue-tagsinput.js:
--------------------------------------------------------------------------------
1 | (function(e, a) { for(var i in a) e[i] = a[i]; }(exports, /******/ (function(modules) { // webpackBootstrap
2 | /******/ // The module cache
3 | /******/ var installedModules = {};
4 | /******/
5 | /******/ // The require function
6 | /******/ function __webpack_require__(moduleId) {
7 | /******/
8 | /******/ // Check if module is in cache
9 | /******/ if(installedModules[moduleId])
10 | /******/ return installedModules[moduleId].exports;
11 | /******/
12 | /******/ // Create a new module (and put it into the cache)
13 | /******/ var module = installedModules[moduleId] = {
14 | /******/ exports: {},
15 | /******/ id: moduleId,
16 | /******/ loaded: false
17 | /******/ };
18 | /******/
19 | /******/ // Execute the module function
20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21 | /******/
22 | /******/ // Flag the module as loaded
23 | /******/ module.loaded = true;
24 | /******/
25 | /******/ // Return the exports of the module
26 | /******/ return module.exports;
27 | /******/ }
28 | /******/
29 | /******/
30 | /******/ // expose the modules object (__webpack_modules__)
31 | /******/ __webpack_require__.m = modules;
32 | /******/
33 | /******/ // expose the module cache
34 | /******/ __webpack_require__.c = installedModules;
35 | /******/
36 | /******/ // __webpack_public_path__
37 | /******/ __webpack_require__.p = "";
38 | /******/
39 | /******/ // Load entry module and return exports
40 | /******/ return __webpack_require__(0);
41 | /******/ })
42 | /************************************************************************/
43 | /******/ ([
44 | /* 0 */
45 | /***/ function(module, exports, __webpack_require__) {
46 |
47 | 'use strict';
48 |
49 | module.exports = __webpack_require__(1);
50 |
51 | /***/ },
52 | /* 1 */
53 | /***/ function(module, exports, __webpack_require__) {
54 |
55 |
56 | /* styles */
57 | __webpack_require__(2)
58 |
59 | var Component = __webpack_require__(7)(
60 | /* script */
61 | __webpack_require__(8),
62 | /* template */
63 | __webpack_require__(22),
64 | /* scopeId */
65 | "data-v-4a2297bc",
66 | /* cssModules */
67 | null
68 | )
69 |
70 | module.exports = Component.exports
71 |
72 |
73 | /***/ },
74 | /* 2 */
75 | /***/ function(module, exports, __webpack_require__) {
76 |
77 | // style-loader: Adds some css to the DOM by adding a \n\n\n\n\n// WEBPACK FOOTER //\n// input.vue?718e3e85","'use strict';\n\nvar types = {\n num: Number,\n str: String,\n bool: Boolean,\n func: Function,\n obj: Object,\n arr: Array,\n any: null\n};\n\nvar props = {\n validator: function validator(func) {\n return { validator: func };\n }\n};\nvar proto = {\n get required() {\n return {\n type: this._type,\n required: true\n };\n },\n default: function _default(_default2) {\n return {\n type: this._type,\n default: _default2\n };\n }\n};\n\nObject.keys(types).forEach(function (t) {\n props[t] = Object.create(proto, {\n _type: {\n value: types[t]\n }\n });\n});\n\nmodule.exports = props;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/vuept/dist/vuept.js\n// module id = 9\n// module chunks = 0","export const KEY_CODE = {\n LEFT: 37,\n RIGHT: 39,\n TAB: 9,\n BACKSPACE: 8\n}\n\nexport const klass = {\n container: 'tags-input',\n input: 'input',\n gap: 'gap',\n tag: 'tag',\n placeholder: 'placeholder'\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/lib.js","\n/* styles */\nrequire(\"!!vue-loader/node_modules/vue-style-loader!css-loader?minimize!../node_modules/vue-loader/lib/style-rewriter?id=data-v-bf3d33e8&scoped=true!../node_modules/vue-loader/lib/selector?type=styles&index=0!./tag.vue\")\n\nvar Component = require(\"!../node_modules/vue-loader/lib/component-normalizer\")(\n /* script */\n require(\"!!babel-loader!../node_modules/vue-loader/lib/selector?type=script&index=0!./tag.vue\"),\n /* template */\n require(\"!!../node_modules/vue-loader/lib/template-compiler?id=data-v-bf3d33e8!../node_modules/vue-loader/lib/selector?type=template&index=0!./tag.vue\"),\n /* scopeId */\n \"data-v-bf3d33e8\",\n /* cssModules */\n null\n)\n\nmodule.exports = Component.exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/tag.vue\n// module id = 11\n// module chunks = 0","// style-loader: Adds some css to the DOM by adding a \n\n\n\n\n// WEBPACK FOOTER //\n// tag.vue?ab9a0dc2","module.exports = \"data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjMDAwMDAwIiBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik0xOSA2LjQxTDE3LjU5IDUgMTIgMTAuNTkgNi40MSA1IDUgNi40MSAxMC41OSAxMiA1IDE3LjU5IDYuNDEgMTkgMTIgMTMuNDEgMTcuNTkgMTkgMTkgMTcuNTkgMTMuNDEgMTJ6Ii8+CiAgICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+Cjwvc3ZnPg==\"\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/assets/ic_close_black_16px.svg\n// module id = 15\n// module chunks = 0","module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;\n return _c('span', {\n class: _vm.klass.tag,\n attrs: {\n \"invalid\": _vm.invalid\n }\n }, [_vm._v(\"\\n \" + _vm._s(_vm.text) + \"\\n \"), (_vm.remove) ? _c('img', {\n staticClass: \"hl-click\",\n attrs: {\n \"src\": _vm.crossIcon,\n \"alt\": \"close\"\n },\n on: {\n \"click\": _vm.remove\n }\n }) : _vm._e()])\n},staticRenderFns: []}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/vue-loader/lib/template-compiler.js?id=data-v-bf3d33e8!./~/vue-loader/lib/selector.js?type=template&index=0!./src/tag.vue\n// module id = 16\n// module chunks = 0","\n/* styles */\nrequire(\"!!vue-loader/node_modules/vue-style-loader!css-loader?minimize!../node_modules/vue-loader/lib/style-rewriter?id=data-v-5643ad75&scoped=true!../node_modules/vue-loader/lib/selector?type=styles&index=0!./typing.vue\")\n\nvar Component = require(\"!../node_modules/vue-loader/lib/component-normalizer\")(\n /* script */\n require(\"!!babel-loader!../node_modules/vue-loader/lib/selector?type=script&index=0!./typing.vue\"),\n /* template */\n require(\"!!../node_modules/vue-loader/lib/template-compiler?id=data-v-5643ad75!../node_modules/vue-loader/lib/selector?type=template&index=0!./typing.vue\"),\n /* scopeId */\n \"data-v-5643ad75\",\n /* cssModules */\n null\n)\n\nmodule.exports = Component.exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/typing.vue\n// module id = 17\n// module chunks = 0","// style-loader: Adds some css to the DOM by adding a \n\n\n\n\n// WEBPACK FOOTER //\n// typing.vue?ffa0e1d8","module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;\n return _c('span', {\n class: _vm.klass.gap,\n on: {\n \"click\": function($event) {\n _vm.$emit('click')\n }\n }\n }, [_c('input', {\n directives: [{\n name: \"model\",\n rawName: \"v-model\",\n value: (_vm.text),\n expression: \"text\"\n }],\n ref: \"input\",\n class: _vm.klass.input,\n style: ({\n width: _vm.baseWidth + _vm.charLen(_vm.text) + 'ch'\n }),\n attrs: {\n \"type\": \"text\"\n },\n domProps: {\n \"value\": _vm._s(_vm.text)\n },\n on: {\n \"mousedown\": _vm.preventNativeActive,\n \"blur\": _vm.finishEditing,\n \"keydown\": _vm.keyPress,\n \"input\": function($event) {\n if ($event.target.composing) { return; }\n _vm.text = $event.target.value\n }\n }\n }), _vm._v(\" \"), (!_vm.typing) ? _vm._t(\"default\") : _vm._e()], 2)\n},staticRenderFns: []}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/vue-loader/lib/template-compiler.js?id=data-v-5643ad75!./~/vue-loader/lib/selector.js?type=template&index=0!./src/typing.vue\n// module id = 21\n// module chunks = 0","module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;\n return _c('div', {\n class: _vm.klass.container\n }, [_vm._l((_vm.normalizeTagItems), function(item, index) {\n return [_c('typing', {\n attrs: {\n \"index\": index,\n \"typing\": index === _vm.typingIndex,\n \"handle-insert\": _vm.insertTag,\n \"handle-remove\": _vm.removeTag,\n \"active-other\": _vm.activeOther\n },\n on: {\n \"click\": function($event) {\n _vm.focus(index)\n },\n \"blur\": function($event) {\n _vm.blur(index)\n }\n }\n }, [_c('span', {\n directives: [{\n name: \"show\",\n rawName: \"v-show\",\n value: (index === _vm.length && _vm.showPlaceholder),\n expression: \"index === length && showPlaceholder\"\n }],\n class: _vm.klass.placeholder\n }, [_vm._v(_vm._s(_vm.placeholder))])]), _vm._v(\" \"), (index !== _vm.length) ? _c('tag', {\n attrs: {\n \"text\": item.text,\n \"remove\": _vm.getRemoveHandle(item, index),\n \"invalid\": item.invalid\n }\n }) : _vm._e()]\n })], 2)\n},staticRenderFns: []}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/vue-loader/lib/template-compiler.js?id=data-v-4a2297bc!./~/vue-loader/lib/selector.js?type=template&index=0!./src/input.vue\n// module id = 22\n// module chunks = 0"],"sourceRoot":""}
--------------------------------------------------------------------------------