├── .editorconfig ├── .envrc ├── .eslintignore ├── .eslintrc.js ├── .github └── FUNDING.yml ├── .gitignore ├── .lintstagedrc.json ├── LICENSE ├── README.md ├── babel.config.js ├── docs ├── .vuepress │ ├── config.js │ ├── enhanceApp.js │ ├── public │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ └── hero.png │ └── theme │ │ ├── components │ │ ├── FormInput.vue │ │ ├── Home.vue │ │ ├── PageProps.vue │ │ ├── animals.js │ │ └── item-template.vue │ │ ├── index.js │ │ ├── layouts │ │ └── LayoutProps.vue │ │ ├── styles │ │ └── wrapper.styl │ │ └── util.js ├── README.md └── documentation │ ├── README.md │ ├── events.md │ ├── getting-started.md │ ├── installation.md │ ├── next.md │ ├── props.md │ ├── slots.md │ ├── typescript-support.md │ └── v1.md ├── jest.config.js ├── package-lock.json ├── package.json ├── src ├── components │ └── vue-suggestion.vue ├── index.js └── utils.js └── vue.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 2 4 | end_of_line = lf 5 | trim_trailing_whitespace = true 6 | insert_final_newline = true 7 | max_line_length = 100 8 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | PATH_add bin 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /config/ 3 | /dist/ 4 | /dist-legacy/ 5 | /*.js 6 | /test/unit/coverage/ 7 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // https://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | env: { 6 | 'node': true, 7 | }, 8 | extends: [ 9 | 'plugin:vue/essential', 10 | '@vue/airbnb', 11 | 'plugin:jest/recommended', 12 | ], 13 | plugins: ['vue'], 14 | parserOptions: { 15 | parser: '@babel/eslint-parser', 16 | }, 17 | // add your custom rules here 18 | rules: { 19 | // disallow reassignment of function parameters 20 | // disallow parameter object manipulation except for specific exclusions 21 | 'no-param-reassign': ['error', { 22 | props: true, 23 | ignorePropertyModificationsFor: [ 24 | 'el', 25 | ] 26 | }], 27 | 'func-names': 'off', 28 | 'no-console': [ 29 | 'warn', 30 | { allow: ['warn', 'error'] }, 31 | ], 32 | // allow debugger during development 33 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 34 | 'jest/prefer-to-have-length': 'warn', 35 | }, 36 | } 37 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: iamstevendao 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | npm-debug.log 4 | yarn-error.log 5 | .idea/ 6 | docs/.vuepress/.dist/ 7 | docs/.vuepress/.cache/ 8 | docs/.vuepress/.temp/ 9 | dist-modern/ 10 | dist/ 11 | Icon** 12 | -------------------------------------------------------------------------------- /.lintstagedrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "*.{js,vue}": [ 3 | "eslint --quiet --fix", 4 | "git add" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Steven Dao 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | vue-suggestion-logo 3 |

4 | 5 | # vue-suggestion 6 | 7 | Suggestion list input for Vue 8 | 9 | [![npm](https://img.shields.io/npm/dt/vue-suggestion.svg)](https://www.npmjs.com/package/vue-suggestion) [![stars](https://img.shields.io/github/stars/iamstevendao/vue-suggestion.svg)](https://github.com/iamstevendao/vue-suggestion) 10 | 11 |

12 | In-action GIF 13 |

14 | 15 | ## Documentation and Demo 16 | 17 | [Visit the website](https://iamstevendao.github.io/vue-suggestion/) 18 | 19 | ## Changelog 20 | 21 | [Go to Github Releases](https://github.com/iamstevendao/vue-suggestion/releases) 22 | 23 | ## Getting started 24 | 25 | - Install the plugin: 26 | 27 | ``` 28 | npm install vue-suggestion 29 | ``` 30 | 31 | - Add the plugin into your app: 32 | 33 | ```javascript 34 | import Vue from 'vue'; 35 | import VueSuggestion from 'vue-suggestion'; 36 | 37 | Vue.use(VueSuggestion); 38 | ``` 39 | 40 | [More info on installation](#installation) 41 | 42 | - Use the `vue-suggestion` component: 43 | 44 | ```html 45 | 56 | 57 | 86 | ``` 87 | 88 | **ItemTemplate example:** 89 | 90 | ```html 91 | 97 | 98 | 105 | ``` 106 | 107 | ## Installation 108 | 109 | ### npm 110 | 111 | ```bash 112 | npm install vue-suggestion 113 | ``` 114 | 115 | Install the plugin into Vue: 116 | 117 | ```javascript 118 | import Vue from 'vue'; 119 | import VueSuggestion from 'vue-suggestion'; 120 | 121 | Vue.use(VueSuggestion, [(globalOptions = {})]); // Define default global options here (optional) 122 | ``` 123 | 124 | > View all available options in [Props](#props). 125 | 126 | Or use the component directly: 127 | 128 | ```html 129 | 130 | 133 | 134 | 135 | 169 | 170 | 179 | ``` 180 | 181 | ### Browser 182 | 183 | Include [vue-suggestion](/dist/vue-suggestion.min.js) in the page. 184 | 185 | ```html 186 | 187 | ``` 188 | 189 | **If Vue is detected in the Page, the plugin is installed automatically.** 190 | 191 | Manually install the plugin into Vue: 192 | 193 | ```javascript 194 | Vue.use(VueSuggestion); 195 | ``` 196 | 197 | Or use the component directly: 198 | 199 | ```javascript 200 | Vue.component('vue-suggestion', VueSuggestion.VueSuggestion); 201 | ``` 202 | 203 | ## License 204 | 205 | Copyright (c) 2018 Steven Dao. 206 | Released under the [MIT License](https://github.com/iamstevendao/vue-suggestion/blob/master/LICENSE). 207 | 208 | made with ❤ by [Steven](https://github.com/iamstevendao). 209 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@vue/cli-plugin-babel/preset', 5 | process.env.MODERN ? { 6 | targets: { 7 | browsers: "last 2 chrome version, last 2 firefox version, last 2 edge version, last 1 safari version", 8 | }, 9 | useBuiltIns: 'usage', 10 | corejs: { version: 3, proposals: true }, 11 | exclude: ['transform-async-to-generator', 'transform-regenerator'], 12 | } : { 13 | targets: { 14 | browsers: "> .5%, last 2 versions, not dead", 15 | }, 16 | useBuiltIns: 'usage', 17 | corejs: { version: 3, proposals: true }, 18 | }, 19 | ], 20 | ], 21 | }; 22 | -------------------------------------------------------------------------------- /docs/.vuepress/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | base: '/vue-suggestion/', 3 | locales: { 4 | '/': { 5 | lang: 'en-US', 6 | title: 'Vue Suggestion', 7 | description: 'Documentation site for Vue Suggestion' 8 | } 9 | }, 10 | head: [ 11 | ['link', { rel: "icon", type: "image/png", sizes: "16x16", href: "favicon-16x16.png" }], 12 | ['link', { rel: "icon", type: "image/png", sizes: "32x32", href: "favicon-32x32.png" }], 13 | ], 14 | themeConfig: { 15 | repo: '', 16 | docsDir: 'docs', 17 | search: false, 18 | displayAllHeaders: true, 19 | locales: { 20 | '/': { 21 | label: 'English', 22 | selectText: 'Languages', 23 | lastUpdated: 'Last Updated', 24 | // service worker is configured but will only register in production 25 | serviceWorker: { 26 | updatePopup: { 27 | message: 'New content is available.', 28 | buttonText: 'Refresh' 29 | } 30 | }, 31 | nav: [ 32 | { text: 'Documentation', link: '/documentation/' }, 33 | { text: 'Sponsor', link: 'https://github.com/sponsors/iamstevendao' }, 34 | { text: 'Changelog', link: 'https://github.com/iamstevendao/vue-suggestion/releases' }, 35 | { text: 'GitHub', link: 'https://github.com/iamstevendao/vue-suggestion' } 36 | ], 37 | sidebar: { 38 | '/documentation/': [ 39 | { 40 | title: 'Guide', 41 | collapsable: false, 42 | children: [ 43 | 'getting-started', 44 | 'installation', 45 | 'next', 46 | ] 47 | }, 48 | { 49 | title: 'Usage', 50 | collapsable: false, 51 | children: [ 52 | 'props', 53 | 'events', 54 | 'slots', 55 | ] 56 | }, 57 | { 58 | title: 'Others', 59 | collapsable: false, 60 | children: [ 61 | 'v1', 62 | ], 63 | }, 64 | ] 65 | } 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /docs/.vuepress/enhanceApp.js: -------------------------------------------------------------------------------- 1 | // enhanceApp.js 2 | 3 | import VueSuggestion from '../../src/index.js'; 4 | 5 | export default ({ Vue, options }) => { 6 | Vue.use(VueSuggestion); 7 | Vue.config.productionTip = false; 8 | } 9 | -------------------------------------------------------------------------------- /docs/.vuepress/public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iamstevendao/vue-suggestion/37ebdf77c17ba6587cb8f5040b4e6cabb82519f7/docs/.vuepress/public/favicon-16x16.png -------------------------------------------------------------------------------- /docs/.vuepress/public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iamstevendao/vue-suggestion/37ebdf77c17ba6587cb8f5040b4e6cabb82519f7/docs/.vuepress/public/favicon-32x32.png -------------------------------------------------------------------------------- /docs/.vuepress/public/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iamstevendao/vue-suggestion/37ebdf77c17ba6587cb8f5040b4e6cabb82519f7/docs/.vuepress/public/hero.png -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/FormInput.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 45 | 46 | 100 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/Home.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 94 | 95 | 245 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/PageProps.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 69 | 70 | 78 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/animals.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { id: 1, name: 'Golden Retriever', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 3 | { id: 2, name: 'Cat', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 4 | { id: 3, name: 'Squirrel', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 5 | { id: 4, name: 'Cougar', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 6 | { id: 5, name: 'Rave', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 7 | { id: 6, name: 'Alligator', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 8 | { id: 7, name: 'Black Bear', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 9 | { id: 8, name: 'Possu', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 10 | { id: 9, name: 'Lion', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 11 | { id: 10, name: 'Crocodile', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 12 | { id: 11, name: 'Brown Bear', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 13 | { id: 12, name: 'Koal', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 14 | { id: 13, name: 'Tiger', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 15 | { id: 14, name: 'Chipmunks', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 16 | { id: 15, name: 'Grizzly Bear', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 17 | { id: 16, name: 'Swa', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 18 | { id: 17, name: 'Rabbit', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 19 | { id: 18, name: 'Whale', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 20 | { id: 19, name: 'Platypu', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 21 | { id: 20, name: 'Goat', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 22 | { id: 21, name: 'Duck', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 23 | { id: 22, name: 'Octopu', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 24 | { id: 23, name: 'Sheep', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 25 | { id: 24, name: 'Zebra', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 26 | { id: 25, name: 'Anacond', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 27 | { id: 26, name: 'Cow', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 28 | { id: 27, name: 'Goose', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 29 | { id: 28, name: 'Bald Eagl', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 30 | { id: 29, name: 'Pig', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 31 | { id: 30, name: 'Donkey', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 32 | { id: 31, name: 'Ospre', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 33 | { id: 32, name: 'Parrot', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 34 | { id: 33, name: 'Panda', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 35 | { id: 34, name: 'Poodl', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 36 | { id: 35, name: 'Bear', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 37 | { id: 36, name: 'Elephant', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 38 | { id: 37, name: 'Skun', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 39 | { id: 38, name: 'Bull', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 40 | { id: 39, name: 'Dolphin', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 41 | { id: 40, name: 'Jagua', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 42 | { id: 41, name: 'Rooster', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 43 | { id: 42, name: 'Salamander', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 44 | { id: 43, name: 'Tortois', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 45 | { id: 44, name: 'Chicken', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 46 | { id: 45, name: 'Raccoon', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 47 | { id: 46, name: 'Hedgeho', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 48 | { id: 47, name: 'Piranha', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 49 | { id: 48, name: 'Penguin', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 50 | { id: 49, name: 'Iguan', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 51 | { id: 50, name: 'Turkey', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 52 | { id: 51, name: 'Polar Bear', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 53 | { id: 52, name: 'Flaming', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 54 | { id: 53, name: 'Crow', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 55 | { id: 54, name: 'Walrus', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 56 | { id: 55, name: 'Worm', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 57 | { id: 56, name: 'Ape', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 58 | { id: 57, name: 'Jellyfish', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 59 | { id: 58, name: 'Fro', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 60 | { id: 59, name: 'Monkey', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 61 | { id: 60, name: 'Giraffe', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 62 | { id: 61, name: 'Slot', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 63 | { id: 62, name: 'Pigeon', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 64 | { id: 63, name: 'Ostrich', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 65 | { id: 64, name: 'Lobste', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 66 | { id: 65, name: 'Yellow fin tuna', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 67 | { id: 66, name: 'Wolf', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 68 | { id: 67, name: 'Swordfis', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 69 | { id: 68, name: 'Cod', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 70 | { id: 69, name: 'Deer', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 71 | { id: 70, name: 'Mackere', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 72 | { id: 71, name: 'Gecko', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 73 | { id: 72, name: 'Antelope', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 74 | { id: 73, name: 'Bonit', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 75 | { id: 74, name: 'Spider', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 76 | { id: 75, name: 'Catfish', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 77 | { id: 76, name: 'Trou', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 78 | { id: 77, name: 'Cobra', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 79 | { id: 78, name: 'Beluga Whale', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 80 | { id: 79, name: 'Peregrine Falco', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 81 | { id: 80, name: 'Hamster', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 82 | { id: 81, name: 'Fox', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 83 | { id: 82, name: 'Chimpanze', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 84 | { id: 83, name: 'Seal', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 85 | { id: 84, name: 'Lama', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 86 | { id: 85, name: 'Kangaro', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 87 | { id: 86, name: 'Leopard', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 88 | { id: 87, name: 'Camel', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 89 | { id: 88, name: 'Porcupine', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 90 | { id: 89, name: 'Cheetah', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 91 | { id: 90, name: 'Gorilla', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 92 | { id: 91, name: 'Hyen', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 93 | { id: 92, name: 'Crab', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 94 | { id: 93, name: 'Toad', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 95 | { id: 94, name: 'Hipp', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 96 | { id: 95, name: 'Mouse', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 97 | { id: 96, name: 'Quail', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 98 | { id: 97, name: 'Rhin', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 99 | { id: 98, name: 'Rat', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 100 | { id: 99, name: 'Moose', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 101 | { id: 100, name: 'Cra', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 102 | { id: 100, name: '123456', description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, 103 | ]; 104 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/item-template.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 17 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extend: '@vuepress/theme-default' 3 | } 4 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/layouts/LayoutProps.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 138 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/wrapper.styl: -------------------------------------------------------------------------------- 1 | $wrapper 2 | max-width $contentWidth 3 | margin 0 auto 4 | padding 2rem 2.5rem 5 | @media (max-width: $MQNarrow) 6 | padding 2rem 7 | @media (max-width: $MQMobileNarrow) 8 | padding 1.5rem 9 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/util.js: -------------------------------------------------------------------------------- 1 | export const hashRE = /#.*$/ 2 | export const extRE = /\.(md|html)$/ 3 | export const endingSlashRE = /\/$/ 4 | export const outboundRE = /^[a-z]+:/i 5 | 6 | export function normalize(path) { 7 | return decodeURI(path) 8 | .replace(hashRE, '') 9 | .replace(extRE, '') 10 | } 11 | 12 | export function getHash(path) { 13 | const match = path.match(hashRE) 14 | if (match) { 15 | return match[0] 16 | } 17 | } 18 | 19 | export function isExternal(path) { 20 | return outboundRE.test(path) 21 | } 22 | 23 | export function isMailto(path) { 24 | return /^mailto:/.test(path) 25 | } 26 | 27 | export function isTel(path) { 28 | return /^tel:/.test(path) 29 | } 30 | 31 | export function ensureExt(path) { 32 | if (isExternal(path)) { 33 | return path 34 | } 35 | const hashMatch = path.match(hashRE) 36 | const hash = hashMatch ? hashMatch[0] : '' 37 | const normalized = normalize(path) 38 | 39 | if (endingSlashRE.test(normalized)) { 40 | return path 41 | } 42 | return normalized + '.html' + hash 43 | } 44 | 45 | export function isActive(route, path) { 46 | const routeHash = decodeURIComponent(route.hash) 47 | const linkHash = getHash(path) 48 | if (linkHash && routeHash !== linkHash) { 49 | return false 50 | } 51 | const routePath = normalize(route.path) 52 | const pagePath = normalize(path) 53 | return routePath === pagePath 54 | } 55 | 56 | export function resolvePage(pages, rawPath, base) { 57 | if (isExternal(rawPath)) { 58 | return { 59 | type: 'external', 60 | path: rawPath 61 | } 62 | } 63 | if (base) { 64 | rawPath = resolvePath(rawPath, base) 65 | } 66 | const path = normalize(rawPath) 67 | for (let i = 0; i < pages.length; i++) { 68 | if (normalize(pages[i].regularPath) === path) { 69 | return Object.assign({}, pages[i], { 70 | type: 'page', 71 | path: ensureExt(pages[i].path) 72 | }) 73 | } 74 | } 75 | console.error(`[vuepress] No matching page found for sidebar item "${rawPath}"`) 76 | return {} 77 | } 78 | 79 | function resolvePath(relative, base, append) { 80 | const firstChar = relative.charAt(0) 81 | if (firstChar === '/') { 82 | return relative 83 | } 84 | 85 | if (firstChar === '?' || firstChar === '#') { 86 | return base + relative 87 | } 88 | 89 | const stack = base.split('/') 90 | 91 | // remove trailing segment if: 92 | // - not appending 93 | // - appending to trailing slash (last segment is empty) 94 | if (!append || !stack[stack.length - 1]) { 95 | stack.pop() 96 | } 97 | 98 | // resolve relative path 99 | const segments = relative.replace(/^\//, '').split('/') 100 | for (let i = 0; i < segments.length; i++) { 101 | const segment = segments[i] 102 | if (segment === '..') { 103 | stack.pop() 104 | } else if (segment !== '.') { 105 | stack.push(segment) 106 | } 107 | } 108 | 109 | // ensure leading slash 110 | if (stack[0] !== '') { 111 | stack.unshift('') 112 | } 113 | 114 | return stack.join('/') 115 | } 116 | 117 | /** 118 | * @param { Page } page 119 | * @param { string } regularPath 120 | * @param { SiteData } site 121 | * @param { string } localePath 122 | * @returns { SidebarGroup } 123 | */ 124 | export function resolveSidebarItems(page, regularPath, site, localePath) { 125 | const { pages, themeConfig } = site 126 | 127 | const localeConfig = localePath && themeConfig.locales 128 | ? themeConfig.locales[localePath] || themeConfig 129 | : themeConfig 130 | 131 | const pageSidebarConfig = page.frontmatter.sidebar || localeConfig.sidebar || themeConfig.sidebar 132 | if (pageSidebarConfig === 'auto') { 133 | return resolveHeaders(page) 134 | } 135 | 136 | const sidebarConfig = localeConfig.sidebar || themeConfig.sidebar 137 | if (!sidebarConfig) { 138 | return [] 139 | } else { 140 | const { base, config } = resolveMatchingConfig(regularPath, sidebarConfig) 141 | if (config === 'auto') { 142 | return resolveHeaders(page) 143 | } 144 | return config 145 | ? config.map(item => resolveItem(item, pages, base)) 146 | : [] 147 | } 148 | } 149 | 150 | /** 151 | * @param { Page } page 152 | * @returns { SidebarGroup } 153 | */ 154 | function resolveHeaders(page) { 155 | const headers = groupHeaders(page.headers || []) 156 | return [{ 157 | type: 'group', 158 | collapsable: false, 159 | title: page.title, 160 | path: null, 161 | children: headers.map(h => ({ 162 | type: 'auto', 163 | title: h.title, 164 | basePath: page.path, 165 | path: page.path + '#' + h.slug, 166 | children: h.children || [] 167 | })) 168 | }] 169 | } 170 | 171 | export function groupHeaders(headers) { 172 | // group h3s under h2 173 | headers = headers.map(h => Object.assign({}, h)) 174 | let lastH2 175 | headers.forEach(h => { 176 | if (h.level === 2) { 177 | lastH2 = h 178 | } else if (lastH2) { 179 | (lastH2.children || (lastH2.children = [])).push(h) 180 | } 181 | }) 182 | return headers.filter(h => h.level === 2) 183 | } 184 | 185 | export function resolveNavLinkItem(linkItem) { 186 | return Object.assign(linkItem, { 187 | type: linkItem.items && linkItem.items.length ? 'links' : 'link' 188 | }) 189 | } 190 | 191 | /** 192 | * @param { Route } route 193 | * @param { Array | Array | [link: string]: SidebarConfig } config 194 | * @returns { base: string, config: SidebarConfig } 195 | */ 196 | export function resolveMatchingConfig(regularPath, config) { 197 | if (Array.isArray(config)) { 198 | return { 199 | base: '/', 200 | config: config 201 | } 202 | } 203 | for (const base in config) { 204 | if (ensureEndingSlash(regularPath).indexOf(encodeURI(base)) === 0) { 205 | return { 206 | base, 207 | config: config[base] 208 | } 209 | } 210 | } 211 | return {} 212 | } 213 | 214 | function ensureEndingSlash(path) { 215 | return /(\.html|\/)$/.test(path) 216 | ? path 217 | : path + '/' 218 | } 219 | 220 | function resolveItem(item, pages, base, groupDepth = 1) { 221 | if (typeof item === 'string') { 222 | return resolvePage(pages, item, base) 223 | } else if (Array.isArray(item)) { 224 | return Object.assign(resolvePage(pages, item[0], base), { 225 | title: item[1] 226 | }) 227 | } else { 228 | const children = item.children || [] 229 | if (children.length === 0 && item.path) { 230 | return Object.assign(resolvePage(pages, item.path, base), { 231 | title: item.title 232 | }) 233 | } 234 | return { 235 | type: 'group', 236 | path: item.path, 237 | title: item.title, 238 | sidebarDepth: item.sidebarDepth, 239 | initialOpenGroupIndex: item.initialOpenGroupIndex, 240 | children: children.map(child => resolveItem(child, pages, base, groupDepth + 1)), 241 | collapsable: item.collapsable !== false 242 | } 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | layout: Home 4 | --- 5 | -------------------------------------------------------------------------------- /docs/documentation/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | - Install the plugin: 4 | 5 | ```sh 6 | npm install vue-suggestion 7 | ``` 8 | 9 | - Add the plugin into your app: 10 | 11 | ```javascript 12 | import Vue from 'vue'; 13 | import VueSuggestion from 'vue-suggestion'; 14 | 15 | Vue.use(VueSuggestion); 16 | ``` 17 | 18 | [More info on installation](/vue-suggestion/documentation/installation) 19 | 20 | - Use the `vue-suggestion` component: 21 | 22 | ```html 23 | 34 | 35 | 64 | ``` 65 | 66 | ```html 67 | 68 | 74 | 75 | 82 | ``` 83 | -------------------------------------------------------------------------------- /docs/documentation/events.md: -------------------------------------------------------------------------------- 1 | # Events 2 | 3 | ### @changed (searchText: String) 4 | 5 | Fires when the input changes with the argument is the current input text. 6 | 7 | ### @selected (item: String|Object) 8 | 9 | Fires when user selects a suggestion 10 | 11 | ### @enter 12 | 13 | Native enter/return key press event 14 | 15 | ### @clear 16 | 17 | Fires when user clicks the "clear" (x) button on the input (not supported by all browsers) 18 | 19 | ### @key-up 20 | 21 | Native `keydown.up` event 22 | 23 | ### @key-down 24 | 25 | Native `keydown.down` event 26 | 27 | ### @focus 28 | 29 | Native `focus` event 30 | 31 | ### @blur 32 | 33 | Native `blur` event 34 | -------------------------------------------------------------------------------- /docs/documentation/getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | - Install the plugin: 4 | 5 | ```sh 6 | npm install vue-suggestion 7 | ``` 8 | 9 | - Add the plugin into your app: 10 | 11 | ```javascript 12 | import Vue from 'vue'; 13 | import VueSuggestion from 'vue-suggestion'; 14 | 15 | Vue.use(VueSuggestion); 16 | ``` 17 | 18 | [More info on installation](/vue-suggestion/documentation/installation) 19 | 20 | - Use the `vue-suggestion` component: 21 | 22 | ```html 23 | 34 | 35 | 64 | ``` 65 | 66 | **ItemTemplate example:** 67 | 68 | ```html 69 | 75 | 76 | 83 | ``` 84 | -------------------------------------------------------------------------------- /docs/documentation/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | ### npm 4 | 5 | ```bash 6 | npm install vue-suggestion 7 | ``` 8 | 9 | Install the plugin into Vue: 10 | 11 | ```javascript 12 | import Vue from 'vue'; 13 | import VueSuggestion from 'vue-suggestion'; 14 | 15 | Vue.use(VueSuggestion, [(globalOptions = {})]); // Define default global options here (optional) 16 | ``` 17 | 18 | > View all available options in [Props](#props). 19 | 20 | Or use the component directly: 21 | 22 | ```html 23 | 24 | 27 | 28 | 29 | 63 | 64 | 73 | ``` 74 | 75 | ### Browser 76 | 77 | Include [vue-suggestion](/dist/vue-suggestion.min.js) in the page. 78 | 79 | ```html 80 | 81 | ``` 82 | 83 | **If Vue is detected in the Page, the plugin is installed automatically.** 84 | 85 | Manually install the plugin into Vue: 86 | 87 | ```javascript 88 | Vue.use(VueSuggestion); 89 | ``` 90 | 91 | Or use the component directly: 92 | 93 | ```javascript 94 | Vue.component('vue-suggestion', VueSuggestion.VueSuggestion); 95 | ``` 96 | -------------------------------------------------------------------------------- /docs/documentation/next.md: -------------------------------------------------------------------------------- 1 | # Vue 3 Support 2 | 3 | Coming soon 4 | -------------------------------------------------------------------------------- /docs/documentation/props.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: LayoutProps 3 | --- 4 | 5 | # Props 6 | -------------------------------------------------------------------------------- /docs/documentation/slots.md: -------------------------------------------------------------------------------- 1 | # Slots 2 | 3 | ### input-append 4 | 5 | Next to the input, for the custom search icon or button... 6 | 7 | ### loading 8 | 9 | Slot to show when loading (with prop `loading: true`) 10 | -------------------------------------------------------------------------------- /docs/documentation/typescript-support.md: -------------------------------------------------------------------------------- 1 | # Typescript Support 2 | 3 | > Coming soon 4 | -------------------------------------------------------------------------------- /docs/documentation/v1.md: -------------------------------------------------------------------------------- 1 | # Docs for v1.x.x 2 | 3 | ### Getting started 4 | 5 | - Install the plugin: 6 | 7 | ``` 8 | npm install vue-suggestion 9 | ``` 10 | 11 | - Add the plugin into your app: 12 | 13 | ```javascript 14 | import Vue from 'vue'; 15 | import VueSuggestion from 'vue-suggestion'; 16 | 17 | Vue.use(VueSuggestion); 18 | ``` 19 | 20 | [More info on installation](#installation) 21 | 22 | - Use the `vue-suggestion` component: 23 | 24 | ```html 25 | 36 | 37 | 66 | ``` 67 | 68 | **ItemTemplate example:** 69 | 70 | ```html 71 | 77 | 78 | 85 | ``` 86 | 87 | ### Installation 88 | 89 | #### npm 90 | 91 | ```bash 92 | npm install vue-suggestion 93 | ``` 94 | 95 | Install the plugin into Vue: 96 | 97 | ```javascript 98 | import Vue from 'vue'; 99 | import VueSuggestion from 'vue-suggestion'; 100 | 101 | Vue.use(VueSuggestion, [(globalOptions = {})]); // Define default global options here (optional) 102 | ``` 103 | 104 | > View all available options in [Props](#props). 105 | 106 | Or use the component directly: 107 | 108 | ```html 109 | 110 | 113 | 114 | 115 | 149 | 150 | 159 | ``` 160 | 161 | #### Browser 162 | 163 | Include [vue-suggestion](/dist/vue-suggestion.min.js) in the page. 164 | 165 | ```html 166 | 167 | ``` 168 | 169 | **If Vue is detected in the Page, the plugin is installed automatically.** 170 | 171 | Manually install the plugin into Vue: 172 | 173 | ```javascript 174 | Vue.use(VueSuggestion); 175 | ``` 176 | 177 | Or use the component directly: 178 | 179 | ```javascript 180 | Vue.component('vue-suggestion', VueSuggestion.VueSuggestion); 181 | ``` 182 | 183 | ### Usage 184 | 185 | #### Props 186 | 187 | | Property | Type | Default value | Description | 188 | | -------------- | ------------- | ------------- | ----------------------------------------------------------------------- | 189 | | `itemTemplate` | Vue component | | Template for item in suggestion list | 190 | | `inputClasses` | `string` | | Custom classes. eg: 'form-control, is-valid'. | 191 | | `setLabel` | `function` | | Value of chosen input, be shown in the input | 192 | | `items` | `Array` | `[]` | Suggestion array, should be updated dynamically after `onInputChange()` | 193 | | `minLen` | `Number` | `2` | Minimum number of characters inputted to start searching | 194 | | `maxLen` | `Number` | `100` | Native input 'maxlength' attribute | 195 | | `disabled` | `Boolean` | `false` | Disable the input | 196 | | `placeholder` | `String` | `''` | Placeholder of the input | 197 | 198 | #### Events 199 | 200 | | Event | Arguments | Description | 201 | | ---------- | --------- | ------------------------------------------------------------------------- | 202 | | `changed` | `String` | Fires when the input changes with the argument is the current input text. | 203 | | `selected` | `Object` | Fires when user selects a suggestion | 204 | | `enter` | `Object` | Native enter/return key press event | 205 | | `key-up` | `Object` | Native key up event | 206 | | `key-down` | `Object` | Native key down event | 207 | | `focus` | `Object` | Native focus event | 208 | | `blur` | `Object` | Native blur event | 209 | 210 | #### Slots 211 | 212 | | Slot | Description | 213 | | ------------ | ---------------------------------------------------------- | 214 | | `searchSlot` | Next to the input, for the custom search icon or button... | 215 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: '@vue/cli-plugin-unit-jest', 3 | "testMatch": [ 4 | "**/**.test.(js|jsx|ts|tsx)" 5 | ], 6 | }; 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-suggestion", 3 | "version": "2.1.0", 4 | "description": "Suggestion list input with Vue", 5 | "author": "Steven Dao ", 6 | "license": "MIT", 7 | "repository": "https://github.com/iamstevendao/vue-suggestion", 8 | "scripts": { 9 | "serve": "vuepress dev docs", 10 | "build": "vue-cli-service build --target lib src/index.js --dest dist", 11 | "build:modern": "MODERN=true vue-cli-service build --target lib src/index.js --dest dist-modern", 12 | "docs:dev": "vuepress dev docs", 13 | "docs:build": "vuepress build docs", 14 | "test:unit": "vue-cli-service test:unit", 15 | "lint": "vue-cli-service lint", 16 | "lint:fix": "vue-cli-service lint --fix", 17 | "prepublishOnly": "npm run build && npm run build:modern" 18 | }, 19 | "files": [ 20 | "dist/", 21 | "dist-modern/" 22 | ], 23 | "main": "dist/vue-suggestion.umd.min.js", 24 | "unpkg": "dist/vue-suggestion.umd.min.js", 25 | "jsdelivr": "dist/vue-suggestion.umd.min.js", 26 | "keywords": [ 27 | "vue", 28 | "suggestion", 29 | "vue-suggestion", 30 | "suggestion-vue", 31 | "v-suggestion" 32 | ], 33 | "dependencies": { 34 | "core-js": "^3.14.0", 35 | "vue": "2.6.14" 36 | }, 37 | "gitHooks": { 38 | "pre-commit": "lint-staged" 39 | }, 40 | "devDependencies": { 41 | "@babel/eslint-parser": "^7.14.5", 42 | "@vue/cli-plugin-babel": "~5.0.0-beta.2", 43 | "@vue/cli-plugin-eslint": "~5.0.0-beta.2", 44 | "@vue/cli-plugin-unit-jest": "~5.0.0-beta.2", 45 | "@vue/cli-service": "~5.0.0-beta.2", 46 | "@vue/eslint-config-airbnb": "^5.3.0", 47 | "@vue/test-utils": "^1.2.1", 48 | "eslint": "^7.26.0", 49 | "eslint-plugin-import": "^2.23.4", 50 | "eslint-plugin-jest": "^24.3.6", 51 | "eslint-plugin-vue": "^7.11.1", 52 | "lint-staged": "^11.0.0", 53 | "postcss": "^8.3.6", 54 | "vue-jest": "^4.0.1", 55 | "vue-template-compiler": "2.6.14", 56 | "vue-server-renderer": "2.6.14", 57 | "vuepress": "1.8.2", 58 | "webpack": "^4.8.1" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/components/vue-suggestion.vue: -------------------------------------------------------------------------------- 1 | 56 | 57 | 222 | 223 | 238 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import utils, { defaultOptions } from './utils'; 2 | import VueSuggestion from './components/vue-suggestion.vue'; 3 | 4 | export function install(app, customOptions = {}) { 5 | if (install.installed) return; 6 | install.installed = true; 7 | 8 | const { 9 | suggestionOptions: customSuggestionOptions, 10 | inputOptions: customInputOptions, 11 | ...otherCustomOptions 12 | } = customOptions; 13 | const { 14 | suggestionOptions: defaultSuggestionOptions, 15 | inputOptions: defaultInputOptions, 16 | ...otherDefaultOptions 17 | } = defaultOptions; 18 | 19 | utils.options = { 20 | inputOptions: { 21 | ...defaultInputOptions, 22 | ...customInputOptions, 23 | }, 24 | suggestionOptions: { 25 | ...defaultSuggestionOptions, 26 | ...customSuggestionOptions, 27 | }, 28 | ...otherDefaultOptions, 29 | ...otherCustomOptions, 30 | }; 31 | 32 | app.component('vue-suggestion', VueSuggestion); 33 | } 34 | 35 | export { VueSuggestion }; 36 | 37 | const plugin = { 38 | install, 39 | }; 40 | 41 | // Auto-install 42 | let GlobalVue = null; 43 | if (typeof window !== 'undefined') { 44 | GlobalVue = window.Vue; 45 | } else if (typeof global !== 'undefined') { 46 | GlobalVue = global.Vue; 47 | } 48 | if (GlobalVue) { 49 | GlobalVue.use(plugin); 50 | } 51 | 52 | export default plugin; 53 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | export const allProps = [ 2 | { 3 | name: 'itemTemplate', 4 | type: 'Vue component', 5 | default: null, 6 | description: 'Template for item in suggestion list', 7 | inDemo: false, 8 | }, 9 | { 10 | name: 'items', 11 | type: Array, 12 | default: [], 13 | description: 'Suggestion array, should be updated dynamically after `onInputChange()`', 14 | inDemo: false, 15 | }, 16 | { 17 | name: 'setLabel', 18 | type: Function, 19 | default: (item) => item, 20 | description: 'Value of chosen input, be shown in the input`', 21 | inDemo: false, 22 | }, 23 | { 24 | name: 'loading', 25 | type: Boolean, 26 | default: false, 27 | description: '!!', 28 | inDemo: false, 29 | }, 30 | { 31 | name: 'minLen', 32 | type: Number, 33 | default: 2, 34 | description: 'Minimum number of characters inputted to start searching', 35 | inDemo: false, 36 | }, 37 | { 38 | name: 'styleClasses', 39 | type: [String, Array, Object], 40 | default: '', 41 | description: 'Custom classes for the wrapper', 42 | inDemo: false, 43 | }, 44 | { 45 | name: 'inputOptions.id', 46 | default: '', 47 | type: String, 48 | description: 'Native input id attribute', 49 | inDemo: false, 50 | }, 51 | { 52 | name: 'inputOptions.maxlength', 53 | type: Number, 54 | default: 100, 55 | description: 'Native input `maxlength` attribute', 56 | inDemo: false, 57 | }, 58 | { 59 | name: 'inputOptions.type', 60 | type: String, 61 | default: 'search', 62 | description: 'Native input `type` attribute', 63 | inDemo: false, 64 | }, 65 | { 66 | name: 'inputOptions.placeholder', 67 | type: String, 68 | default: '', 69 | description: 'Placeholder of the input', 70 | inDemo: false, 71 | }, 72 | { 73 | name: 'inputOptions.styleClasses', 74 | type: [String, Array, Object], 75 | default: '', 76 | description: 'Custom classes for the input', 77 | inDemo: false, 78 | }, 79 | { 80 | name: 'inputOptions.wrapperStyleClasses', 81 | type: [String, Array, Object], 82 | default: '', 83 | description: 'Custom classes for the input', 84 | inDemo: false, 85 | }, 86 | { 87 | name: 'suggestionOptions.listStyleClasses', 88 | type: [String, Array, Object], 89 | default: '', 90 | description: 'Custom classes for the input', 91 | inDemo: false, 92 | }, 93 | { 94 | name: 'suggestionOptions.groupStyleClasses', 95 | type: [String, Array, Object], 96 | default: '', 97 | description: 'Custom classes for the input', 98 | inDemo: false, 99 | }, 100 | { 101 | name: 'suggestionOptions.groupHeaderStyleClasses', 102 | type: [String, Array, Object], 103 | default: '', 104 | description: 'Custom classes for the input', 105 | inDemo: false, 106 | }, 107 | { 108 | name: 'suggestionOptions.groupHeaderStyleClasses', 109 | type: [String, Array, Object], 110 | default: '', 111 | description: 'Custom classes for the input', 112 | inDemo: false, 113 | }, 114 | { 115 | name: 'suggestionOptions.groupHeaderStyleClasses', 116 | type: [String, Array, Object], 117 | default: '', 118 | description: 'Custom classes for the input', 119 | inDemo: false, 120 | }, 121 | { 122 | name: 'suggestionOptions.itemWrapperStyleClasses', 123 | type: [String, Array, Object], 124 | default: '', 125 | description: 'Custom classes for the input', 126 | inDemo: false, 127 | }, 128 | { 129 | name: 'suggestionOptions.itemStyleClasses', 130 | type: [String, Array, Object], 131 | default: '', 132 | description: 'Custom classes for the input', 133 | inDemo: false, 134 | }, 135 | { 136 | name: 'disabled', 137 | type: Boolean, 138 | default: false, 139 | description: 'Disable the input', 140 | inDemo: false, 141 | }, 142 | ]; 143 | 144 | export const defaultOptions = [...allProps] 145 | .reduce((prv, crr) => { 146 | if (crr.name.includes('.')) { 147 | const [key, nestedKey] = crr.name.split('.'); 148 | if (prv[key]) { 149 | Object.assign(prv[key], { [nestedKey]: crr.default }); 150 | } else { 151 | Object.assign(prv, { [key]: { [nestedKey]: crr.default } }); 152 | } 153 | } else { 154 | Object.assign(prv, { [crr.name]: crr.default }); 155 | } 156 | return prv; 157 | }, {}); 158 | 159 | export default { 160 | options: { ...defaultOptions }, 161 | }; 162 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | lintOnSave: true, 3 | } 4 | --------------------------------------------------------------------------------