-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e754480
commit 30dbad1
Showing
7 changed files
with
306 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import Autocomplete from '~widgets/autocomplete/widget.vue'; | ||
import registerWidget from '~core/registerWidget'; | ||
|
||
registerWidget('ui-autocomplete', Autocomplete); | ||
|
||
export const Basic = { | ||
name: 'Basic options', | ||
render: (args) => ({ | ||
setup() { | ||
return { args }; | ||
}, | ||
template: '<ui-autocomplete v-bind="args" style="width:400px;"></ui-autocomplete>', | ||
}), | ||
|
||
args: { | ||
label: 'Label text', | ||
options: ['Andorra', 'Peru', 'Poland', 'Spain', 'USA'], | ||
}, | ||
}; | ||
|
||
export const Object = { | ||
name: 'Array of objects in options', | ||
render: Basic.render, | ||
args: { | ||
...Basic.args, | ||
propValue: 'value', | ||
propText: 'label', | ||
options: [ | ||
{ value: 'AR', label: 'Argentina' }, | ||
{ value: 'AD', label: 'Andorra' }, | ||
{ value: 'PL', label: 'Poland' }, | ||
], | ||
}, | ||
}; | ||
|
||
export const Validation = { | ||
name: 'Input validation', | ||
render: Basic.render, | ||
|
||
args: { | ||
...Basic.args, | ||
label: 'Select input with validation', | ||
hint: 'Select the second option if you want the validation to be successful', | ||
propValue: 'id', | ||
propText: 'name', | ||
required: true, | ||
options: [ | ||
{ id: 'OBJ-123', name: 'The first object' }, | ||
{ id: 'OBJ-456', name: 'The second object' }, | ||
{ id: 'OBJ-789', name: 'The third object' }, | ||
], | ||
rules: [(value) => value === 'OBJ-456' || 'You picked the wrong option :( '], | ||
}, | ||
}; | ||
|
||
export default { | ||
title: 'Components/Autocomplete', | ||
component: Autocomplete, | ||
parameters: { | ||
layout: 'centered', | ||
}, | ||
argTypes: { | ||
label: 'text', | ||
modelValue: 'text', | ||
hint: 'text', | ||
propValue: 'text', | ||
propText: 'text', | ||
required: 'boolean', | ||
options: { control: 'array' }, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import { mount } from '@vue/test-utils'; | ||
import Autocomplete from './widget.vue'; | ||
|
||
describe('Autocomplete', () => { | ||
let wrapper; | ||
|
||
const options = [ | ||
{ id: '1', name: 'Andorra' }, | ||
{ id: '2', name: 'Poland' }, | ||
{ id: '3', name: 'Spain' }, | ||
]; | ||
|
||
beforeEach(() => { | ||
wrapper = mount(Autocomplete, { | ||
props: { | ||
label: 'Countries', | ||
options, | ||
propText: 'name', | ||
propValue: 'id', | ||
required: true, | ||
hint: 'Select a country', | ||
}, | ||
}); | ||
}); | ||
|
||
describe('render', () => { | ||
it('renders the base component', () => { | ||
expect(wrapper.exists()).toBe(true); | ||
expect(wrapper.find('.autocomplete').exists()).toBe(true); | ||
expect(wrapper.find('ui-select').exists()).toBe(true); | ||
expect(wrapper.find('ui-textfield').exists()).toBe(true); | ||
}); | ||
|
||
it('filters options based on user input', async () => { | ||
const textField = wrapper.find('ui-textfield'); | ||
|
||
await textField.trigger('input', { detail: ['an'] }); | ||
|
||
const filteredOptions = wrapper.vm.filteredOptions; | ||
|
||
expect(filteredOptions.length).toBe(2); | ||
expect(filteredOptions).toEqual([ | ||
{ id: '1', name: 'Andorra' }, | ||
{ id: '2', name: 'Poland' }, | ||
]); | ||
}); | ||
|
||
it('updates selected value correctly', async () => { | ||
const select = wrapper.find('ui-select'); | ||
|
||
await select.trigger('update:modelValue', { detail: ['some option'] }); | ||
|
||
const selected = wrapper.vm.selected; | ||
|
||
expect(selected).toBe('some option'); | ||
}); | ||
|
||
it('clears the user input after selection', async () => { | ||
const select = wrapper.find('ui-select'); | ||
const textfield = wrapper.find('ui-textfield'); | ||
|
||
await textfield.trigger('input', { detail: ['spa'] }); | ||
|
||
let userInput = wrapper.vm.userInput; | ||
|
||
expect(userInput).toBe('spa'); | ||
|
||
await select.trigger('update:modelValue', { detail: ['Spain'] }); | ||
|
||
userInput = wrapper.vm.userInput; | ||
|
||
expect(userInput).toBe(''); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
<template> | ||
<div class="autocomplete"> | ||
<ui-select | ||
:options="filteredOptions" | ||
:label="label" | ||
:modelValue="selected" | ||
:required="required" | ||
:propText="propText" | ||
:propValue="propValue" | ||
:rules="rules" | ||
:hint="hint" | ||
@update:modelValue="updateSelected" | ||
Check warning on line 12 in components/src/widgets/autocomplete/widget.vue GitHub Actions / Node 18
Check warning on line 12 in components/src/widgets/autocomplete/widget.vue GitHub Actions / Node 20
Check warning on line 12 in components/src/widgets/autocomplete/widget.vue GitHub Actions / Node 18
Check warning on line 12 in components/src/widgets/autocomplete/widget.vue GitHub Actions / Node 20
|
||
> | ||
<div | ||
slot="search-input" | ||
class="autocomplete__search" | ||
> | ||
<ui-textfield | ||
:value="userInput" | ||
:noBorders="true" | ||
:browserAutocomplete="false" | ||
@input="onUserInput" | ||
></ui-textfield> | ||
</div> | ||
</ui-select> | ||
</div> | ||
</template> | ||
|
||
<script setup> | ||
import { ref, computed } from 'vue'; | ||
import Select from '~widgets/select/widget.vue'; | ||
import TextField from '~widgets/textfield/widget.vue'; | ||
import registerWidget from '~core/registerWidget'; | ||
registerWidget('ui-select', Select); | ||
registerWidget('ui-textfield', TextField); | ||
const props = defineProps({ | ||
label: { | ||
type: String, | ||
default: '', | ||
}, | ||
optionTextFn: { | ||
type: Function, | ||
default: null, | ||
}, | ||
propText: { | ||
type: String, | ||
default: 'id', | ||
}, | ||
propValue: { | ||
type: String, | ||
default: 'id', | ||
}, | ||
required: { | ||
type: Boolean, | ||
default: false, | ||
}, | ||
options: { | ||
type: Array, | ||
required: true, | ||
}, | ||
rules: { | ||
type: Array, | ||
default: () => [], | ||
}, | ||
hint: { | ||
type: String, | ||
default: '', | ||
}, | ||
}); | ||
let userInput = ref(''); | ||
let selected = ref(''); | ||
const getOptionText = (option) => (typeof option === 'object' ? option[props.propText] : option); | ||
const filteredOptions = computed(() => { | ||
if (userInput.value === '') { | ||
return props.options; | ||
} | ||
return props.options.filter((option) => | ||
getOptionText(option).toLowerCase().includes(userInput.value.toLowerCase()), | ||
); | ||
}); | ||
const onUserInput = (e) => { | ||
userInput.value = e.detail[0]; | ||
}; | ||
const updateSelected = (e) => { | ||
selected.value = e.detail[0]; | ||
userInput.value = ''; | ||
}; | ||
</script> | ||
|
||
<style lang="stylus" scoped> | ||
.autocomplete { | ||
&__search { | ||
color: inherit; | ||
-webkit-appearance: none; | ||
-moz-appearance: none; | ||
appearance: none; | ||
line-height: 20px; | ||
font-size: 14px; | ||
border: 1px solid transparent; | ||
border-left: none; | ||
outline: none; | ||
margin: 0; | ||
background: none; | ||
box-shadow: none; | ||
width: 0; | ||
max-width: 100%; | ||
flex-grow: 1; | ||
z-index: 1; | ||
} | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.