diff --git a/package.json b/package.json index 6062855..645cfe3 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,9 @@ "Firefox ESR", "last 3 versions" ], - "peerDependencies": {}, + "peerDependencies": { + "vue": ">=2.3.0" + }, "devDependencies": { "@types/chai": "^4.0.3", "@types/copy-webpack-plugin": "^4.0.0", @@ -109,7 +111,6 @@ }, "dependencies": { "array-filter": "^1.0.0", - "string-similarity": "^1.2.0", - "vuex": "^3.0.0" + "string-similarity": "^1.2.0" } } diff --git a/src/components/AddressForm.vue b/src/components/AddressForm.vue index 29135b8..d403eda 100644 --- a/src/components/AddressForm.vue +++ b/src/components/AddressForm.vue @@ -2,22 +2,40 @@ .typeahead-address-form .row .col - typeahead-input(target='district', :label='subdistrictLabel') + typeahead-input( + :dataSource='dataSource', + target='district', + :label='subdistrictLabel', + @itemselect='onItemSelect' + ) .col - typeahead-input(target='amphoe', :label='districtLabel') + typeahead-input( + :dataSource='dataSource', + target='amphoe', + :label='districtLabel', + @itemselect='onItemSelect' + ) .row .col - typeahead-input(target='province', :label='provinceLabel') + typeahead-input( + :dataSource='dataSource', + target='province', + :label='provinceLabel', + @itemselect='onItemSelect' + ) .col - typeahead-input(target='zipcode', :label='zipcodeLabel') + typeahead-input( + :dataSource='dataSource', + target='zipcode', + :label='zipcodeLabel', + @itemselect='onItemSelect' + ) diff --git a/src/components/Autocomplete.vue b/src/components/Autocomplete.vue index c36b683..5f0621f 100644 --- a/src/components/Autocomplete.vue +++ b/src/components/Autocomplete.vue @@ -19,6 +19,8 @@ import { addressToString, getDataItemKeys } from '@/lib/utils'; @Component({ name: 'autocomplete', props: { + query: String, + possibles: Array, target: { type: String, required: true @@ -35,6 +37,8 @@ import { addressToString, getDataItemKeys } from '@/lib/utils'; }) export default class Autocomplete extends Vue { // Props + query: string; + possibles: AddressEntry[]; target: string; // A property name in data item. maxHeight: number; // Max autocomplete height. selectedIndex: number; @@ -45,14 +49,11 @@ export default class Autocomplete extends Vue { 'max-height': `${this.maxHeight}px` }; } - get query(): string { - return this.$store.state[this.target].value; - } get hasData(): boolean { - return this.$store.getters[`${this.target}/hasAutocomplete`]; + return this.possibles && (this.possibles.length > 0); } get autocompleteList() { - let autocomplete: AddressEntry[] = this.$store.getters[`${this.target}/autocomplete`]; + let autocomplete: AddressEntry[] = this.possibles; return autocomplete.map(item => { return { @@ -63,11 +64,8 @@ export default class Autocomplete extends Vue { } // Methods - onItemClick(data: AddressEntry): void { - let keys: string[] = getDataItemKeys(data); - keys.forEach(key => { - this.$store.dispatch(`${key}/updateValue`, data[key]); - }); + onItemClick(item: AddressEntry): void { + this.$emit('itemclick', item); } changeSelectedIndex(index: number): void { if ((index >= 0) && (index < this.autocompleteList.length)) { diff --git a/src/components/TypeaheadInput.vue b/src/components/TypeaheadInput.vue index d04c2b7..acb6ebf 100644 --- a/src/components/TypeaheadInput.vue +++ b/src/components/TypeaheadInput.vue @@ -13,9 +13,15 @@ @keyup.esc='closeAutocomplete', @keyup.up='moveSelectedIndex(-1)', @keyup.down='moveSelectedIndex(1)', - @keyup.enter.prevent='fillItemData' + @keyup.enter.prevent='selectItemData' ) - autocomplete(:query='query', :target='target', :selectedIndex.sync='selectedIndex') + autocomplete( + :query='query', + :possibles='possibles', + :target='target', + :selectedIndex.sync='selectedIndex', + @itemclick='onItemClick' + ) //- When no label template(v-else) input.typeahead-input( @@ -27,9 +33,15 @@ @keyup.esc='closeAutocomplete', @keyup.up='moveSelectedIndex(-1)', @keyup.down='moveSelectedIndex(1)', - @keyup.enter.prevent='fillItemData' + @keyup.enter.prevent='selectItemData' + ) + autocomplete( + :query='query', + :possibles='possibles', + :target='target', + :selectedIndex.sync='selectedIndex', + @itemclick='onItemClick' ) - autocomplete(:query='query', :target='target', :list='list', :selectedIndex.sync='selectedIndex') diff --git a/src/index.ts b/src/index.ts index 5f84280..773d67a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,7 +13,7 @@ declare global { * * @param {typeof Vue} vue Vue instance. */ -function install(vue: typeof Vue): void { +function install(vue): void { vue.component('address-form', AddressForm); } diff --git a/src/store/actions.ts b/src/store/actions.ts deleted file mode 100644 index 98d47a2..0000000 --- a/src/store/actions.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ActionContext, ActionTree } from 'vuex'; -import { DATA_SOURCE } from './mutation-types'; -import { State } from './state'; - -const updateDataSource = ({ commit }: ActionContext, newDataSource: AddressEntry[]) => { - commit(DATA_SOURCE, newDataSource); -}; -const clearAutocompleteList = ({ dispatch }: ActionContext) => { - dispatch('district/clearList'); - dispatch('amphoe/clearList'); - dispatch('province/clearList'); - dispatch('zipcode/clearList'); -}; - -const actions: ActionTree = { - updateDataSource, - clearAutocompleteList -}; - -export default actions; diff --git a/src/store/index.ts b/src/store/index.ts deleted file mode 100644 index 1fc4b7e..0000000 --- a/src/store/index.ts +++ /dev/null @@ -1,29 +0,0 @@ -import Vue from 'vue'; -import Vuex, { Store } from 'vuex'; - -import actions from './actions'; -import mutations from './mutations'; -import { State } from './state'; - -// Module -import { InputModule } from './modules/input-module'; - -// Prevent duplicate calling use when in browser. -if (!((typeof window !== 'undefined') && window.Vue)) { - Vue.use(Vuex); -} - -const debug = process.env.NODE_ENV !== 'production'; - -export default new Store({ - state: new State(), - mutations, - actions, - modules: { - district: new InputModule(), - amphoe: new InputModule(), - province: new InputModule(), - zipcode: new InputModule() - }, - strict: debug -}); diff --git a/src/store/modules/input-module/actions.ts b/src/store/modules/input-module/actions.ts deleted file mode 100644 index 9f7e553..0000000 --- a/src/store/modules/input-module/actions.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ActionContext, ActionTree } from 'vuex'; - -import { LIST, VALUE } from '@/store/mutation-types'; -import { State as RootState } from '@/store/state'; -import { InputState } from './state'; - -const actions: ActionTree = { - updateValue({ commit }: ActionContext, newValue: string) { - commit(VALUE, newValue); - }, - updateList({ commit }: ActionContext, newList: AddressEntry[]) { - commit(LIST, newList); - }, - clearList({ commit }: ActionContext) { - commit(LIST, []); - } -}; - -export default actions; diff --git a/src/store/modules/input-module/getters.ts b/src/store/modules/input-module/getters.ts deleted file mode 100644 index c83740c..0000000 --- a/src/store/modules/input-module/getters.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { GetterTree } from 'vuex'; - -import { State as RootState } from '@/store/state'; -import { InputState } from './state'; - -const getters: GetterTree = { - hasAutocomplete(state: InputState): boolean { - return state.autocompleteList.length > 0; - }, - autocomplete(state: InputState): AddressEntry[] { - return state.autocompleteList; - } -}; - -export default getters; diff --git a/src/store/modules/input-module/index.ts b/src/store/modules/input-module/index.ts deleted file mode 100644 index 02e49d5..0000000 --- a/src/store/modules/input-module/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ActionTree, GetterTree, Module, MutationTree } from 'vuex'; // tslint:disable-line - -import { State as RootState } from '@/store/state'; -import actions from './actions'; -import getters from './getters'; -import mutations from './mutations'; -import { InputState } from './state'; - -export class InputModule implements Module { - public namespaced: boolean = true; - - public state: InputState; - public getters = getters; - public mutations = mutations; - public actions = actions; - - constructor() { - this.state = new InputState(); - } -} diff --git a/src/store/modules/input-module/mutations.ts b/src/store/modules/input-module/mutations.ts deleted file mode 100644 index 0ab601c..0000000 --- a/src/store/modules/input-module/mutations.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { MutationTree } from 'vuex'; - -import { LIST, VALUE } from '@/store/mutation-types'; -import { InputState } from './state'; - -const mutations: MutationTree = { - [VALUE](state: InputState, newValue: string) { - state.value = newValue; - }, - [LIST](state: InputState, newList: AddressEntry[]) { - state.autocompleteList = newList.slice(0); - } -}; - -export default mutations; diff --git a/src/store/modules/input-module/state.ts b/src/store/modules/input-module/state.ts deleted file mode 100644 index 24b6f9c..0000000 --- a/src/store/modules/input-module/state.ts +++ /dev/null @@ -1,4 +0,0 @@ -export class InputState { - public value: string = ''; - public autocompleteList: AddressEntry[] = []; -} diff --git a/src/store/mutation-types.ts b/src/store/mutation-types.ts deleted file mode 100644 index 5bccbd3..0000000 --- a/src/store/mutation-types.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const DATA_SOURCE = 'DATA_SOURCE'; -export const VALUE = 'VAULE'; -export const LIST = 'LIST'; diff --git a/src/store/mutations.ts b/src/store/mutations.ts deleted file mode 100644 index 51a861a..0000000 --- a/src/store/mutations.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { MutationTree } from 'vuex'; -import { DATA_SOURCE } from './mutation-types'; -import { State } from './state'; - -const mutations: MutationTree = { - [DATA_SOURCE](state: State, newDataSource: AddressEntry[]) { - state.dataSource = newDataSource; - } -}; - -export default mutations; diff --git a/src/store/state.ts b/src/store/state.ts deleted file mode 100644 index bb50307..0000000 --- a/src/store/state.ts +++ /dev/null @@ -1,3 +0,0 @@ -export class State { - public dataSource: AddressEntry[] = null; -} diff --git a/test/Autocomplete.spec.ts b/test/Autocomplete.spec.ts index 45f879d..f42afc8 100644 --- a/test/Autocomplete.spec.ts +++ b/test/Autocomplete.spec.ts @@ -3,11 +3,9 @@ import { mount } from 'avoriaz'; import { expect } from 'chai'; import Autocomplete from '@/components/Autocomplete.vue'; -import store from '@/store'; describe('Autocomplete', () => { const wrapper = mount(Autocomplete, { - store, propsData: { target: 'amphoe', maxHeight: 500 @@ -33,9 +31,6 @@ describe('Autocomplete', () => { it(`should has 'style' computed`, () => { expect(computed.style).to.exist; }); - it(`should has 'query' computed`, () => { - expect(computed.query).to.exist; - }); it(`should has 'hasData' computed`, () => { expect(computed.hasData).to.exist; }); diff --git a/test/TypeaheadInput.spec.ts b/test/TypeaheadInput.spec.ts index ca68be9..9ac7257 100644 --- a/test/TypeaheadInput.spec.ts +++ b/test/TypeaheadInput.spec.ts @@ -3,11 +3,9 @@ import { mount } from 'avoriaz'; import { expect } from 'chai'; import TypeaheadInput from '@/components/TypeaheadInput.vue'; -import store from '@/store'; describe('TypeaheadInput', () => { const wrapper = mount(TypeaheadInput, { - store, propsData: { target: 'province', label: 'Province' @@ -43,17 +41,8 @@ describe('TypeaheadInput', () => { describe('Computed', () => { let computed: any = wrapper.computed(); - it(`should has 'dataSource' computed`, () => { - expect(computed.dataSource).to.exist; - }); - it(`should has 'possibles' computed`, () => { - expect(computed.possibles).to.exist; - }); - it(`should has 'query' computed`, () => { - expect(computed.query).to.exist; - }); it(`should has 'hasLabel' computed`, () => { - expect(computed.dataSource).to.exist; + expect(computed.hasLabel).to.exist; }); }); describe('Methods', () => { @@ -68,8 +57,8 @@ describe('TypeaheadInput', () => { it(`should has 'moveSelectedIndex' method`, () => { expect(typeof methods.moveSelectedIndex).to.equal('function'); }); - it(`should has 'fillItemData' method`, () => { - expect(typeof methods.fillItemData).to.equal('function'); + it(`should has 'selectItemData' method`, () => { + expect(typeof methods.selectItemData).to.equal('function'); }); }); }); diff --git a/tsconfig.json b/tsconfig.json index 5de72de..27422ab 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,7 +7,7 @@ "es2015" ], "moduleResolution": "node", - "module": "es2015", + "module": "esnext", "target": "es5", "experimentalDecorators": true, "outDir": "./dist/", diff --git a/yarn.lock b/yarn.lock index a0156dd..aef27d0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6644,10 +6644,6 @@ vue@^2.3.3, vue@^2.5.2: version "2.5.2" resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.2.tgz#fd367a87bae7535e47f9dc5c9ec3b496e5feb5a4" -vuex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.0.0.tgz#98b4b5c4954b1c1c1f5b29fa0476a23580315814" - ware@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ware/-/ware-1.3.0.tgz#d1b14f39d2e2cb4ab8c4098f756fe4b164e473d4"