├── .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 |
3 |
4 |
5 | # vue-suggestion
6 |
7 | Suggestion list input for Vue
8 |
9 | [](https://www.npmjs.com/package/vue-suggestion) [](https://github.com/iamstevendao/vue-suggestion)
10 |
11 |
12 |
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 |
46 |
54 |
55 |
56 |
57 |
86 | ```
87 |
88 | **ItemTemplate example:**
89 |
90 | ```html
91 |
92 |
93 | #{{ item.id }}
94 | {{ item.name }}
95 |
96 |
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 |
131 |
132 |
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 |
2 |
18 |
19 |
20 |
45 |
46 |
100 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Suggestion Input with Vue
6 |
7 |

10 |

13 |
14 |
15 | made with ❤ by
16 | Steven.
17 |
18 |
19 |
20 |
28 |
29 |
30 | Selected item:
31 | {{ item }}
32 |
33 |
34 |
35 |
36 |
37 |
94 |
95 |
245 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/PageProps.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {{ prop.name }}
9 |
10 | - Type:
11 | -
12 | Default:
13 |
{{ getDefault(prop) }}
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
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 |
2 |
3 | #{{ item.id }}
4 | {{ item.name }}
5 |
6 | {{ item.description }}
7 |
8 |
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 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
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 |
24 |
32 |
33 |
34 |
35 |
64 | ```
65 |
66 | ```html
67 |
68 |
69 |
70 | #{{ item.id }}
71 | {{ item.name }}
72 |
73 |
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 |
24 |
32 |
33 |
34 |
35 |
64 | ```
65 |
66 | **ItemTemplate example:**
67 |
68 | ```html
69 |
70 |
71 | #{{ item.id }}
72 | {{ item.name }}
73 |
74 |
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 |
25 |
26 |
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 |
26 |
34 |
35 |
36 |
37 |
66 | ```
67 |
68 | **ItemTemplate example:**
69 |
70 | ```html
71 |
72 |
73 | #{{ item.id }}
74 | {{ item.name }}
75 |
76 |
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 |
111 |
112 |
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 |
2 |
3 |
4 |
20 |
21 |
22 |
23 | Loading...
24 |
25 |
26 |
27 |
32 |
36 | {{ group.header }}
37 |
38 |
51 |
52 |
53 |
54 |
55 |
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 |
--------------------------------------------------------------------------------