Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import icon from './widgets/icon/widget.vue';
import view from './widgets/view/widget.vue';
import navigation from './widgets/navigation/widget.vue';
import status from './widgets/status/widget.vue';
import textfield from './widgets/textfield/widget.vue';

import _store from './core/store';
import _bus from './core/eventBus';
Expand All @@ -21,6 +22,7 @@ export const Icon = icon;
export const View = view;
export const Navigation = navigation;
export const Status = status;
export const Textfield = textfield;

export const bus = _bus;
export const store = _store;
Expand Down
67 changes: 67 additions & 0 deletions src/widgets/textfield/widget.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import Textfield from './widget';


describe('Textfield widget', () => {
let context;
let result;

describe('#data', () => {
it('returns the initial data', () => {
result = Textfield.data();

expect(result).toEqual({
focused: false,
localValue: '',
});
});
});

describe('methods', () => {
describe('#onInput', () => {

beforeEach(() => {
context = {
localValue: 'my value',
$emit: jest.fn(),
e: {
stopPropagation: jest.fn(),
},
};

Textfield.methods.onInput.call(context, context.e);
});

it('calls stop propagation from event', () => {
expect(context.e.stopPropagation).toHaveBeenCalled();
});

it('emits input event with localValue', () => {
expect(context.$emit).toHaveBeenCalledWith('input', context.localValue);
});
});

describe('#removeFocus', () => {
it('sets focused to false if focused is true', () => {
context = {
focused: true,
}

Textfield.methods.removeFocus.call(context);

expect(context.focused).toEqual(false);
})
});

describe('#setFocus', () => {
it('sets focused to false if focused is true', () => {
context = {
focused: false,
}

Textfield.methods.setFocus.call(context);

expect(context.focused).toEqual(true);
})
});
});
});
139 changes: 139 additions & 0 deletions src/widgets/textfield/widget.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<!-- eslint-disable vue/no-v-html -->
<template>
<div
:class="[
{'text-field_focused': focused},
'text-field',
]"
@focusin="setFocus"
@focusout="removeFocus"
>
<label for="textfield">{{ label }}</label>
<div class="text-field__wrapper">
<div class="text-field__body">
<input
v-model="localValue"
name="textfield"
class="text-field__input"
type="text"
@input="onInput"
>
</div>
</div>
</div>
</template>

<script>
export default {
props: {
label: {
type: String,
default: '',
},
},
emits: ['input'],
data() {
return {
focused: false,
localValue: '',
}
},

methods: {
onInput(e) {
e.stopPropagation();
this.$emit('input', this.localValue );
},

removeFocus() {
if (this.focused) {
this.focused = false;
}
},

setFocus() {
if (this.focused) return;

this.focused = true;
},
},
}
</script>

<style lang="stylus">
.text-field {
font-family: 'Roboto';
font-size: 14px;
line-height: 20px;
font-weight: 400;
display: flex;
flex-flow: column nowrap;
color: #212121;

label {
font-weight 500;
font-size: 14px;
}

&___r {
display: flex;
flex-flow: row nowrap;
align-items: center;
}

&__body {
flex-grow: 1;

display: flex;
flex-flow: row nowrap;
align-items: center;

max-height: 44px;
padding: 11px;
border: 1px solid #D8D8D8;
border-radius: 2px;
background-color: #FBFBFB;
cursor: pointer;

.text-field_disabled &,
[disabled] &,
:disabled & {
border-style: dashed;
cursor: default;
}

.text-field_focused & {
border-color: #4797f2;
border-width: 2px ;
}
}

&__input {
flex-grow: 1;
outline: none;
border-style: none;
background-color: transparent;

&:hover,
&:focus {
outline: none;
}

&:-webkit-autofill,
&:-webkit-autofill:hover,
&:-webkit-autofill:focus,
&:-webkit-autofill:active {
-webkit-box-shadow: 0 0 0 30px #FBFBFB inset !important;
}

&::placeholder {
color: #707070;
}

.text-field_disabled & {
color: #BDBDBD;
}
}
}
</style>