Skip to content

Commit 5e8830f

Browse files
committed
feat(LcMaskInput): [ch5577] add component lc-mask-input (maska)
1 parent 05f45a9 commit 5e8830f

File tree

11 files changed

+333
-6
lines changed

11 files changed

+333
-6
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"@vee-validate/rules": "^4.1.20",
3434
"@vueform/multiselect": "^2.0.1",
3535
"esno": "0.4.4",
36+
"maska": "^1.4.4",
3637
"vee-validate": "4.4.4",
3738
"vue": "3.1.1"
3839
},

src/components/LcForm/LcForm.stories.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { action } from '@storybook/addon-actions'
2+
13
import LcForm from './LcForm'
24

35
export default {
@@ -10,7 +12,11 @@ const Template = (args: any) => ({
1012
setup() {
1113
return { args }
1214
},
13-
template: '<lc-form v-bind="args"/>',
15+
template: '<lc-form v-bind="args" @onSubmit="onSubmit" @onCancel="onCancel"/>',
16+
methods: {
17+
onSubmit: action('onSubmit'),
18+
onCancel: action('onCancel'),
19+
},
1420
})
1521

1622
export const Base = Template.bind({}) as any
@@ -34,7 +40,7 @@ Base.args = {
3440
},
3541
fields: [
3642
{
37-
model: '',
43+
model: 'Bob',
3844
inputType: 'input',
3945
attr: {
4046
disabled: true,
@@ -104,5 +110,17 @@ Base.args = {
104110
wrapperClass: 'mb-4',
105111
},
106112
},
113+
{
114+
model: '',
115+
inputType: 'mask',
116+
attr: {
117+
label: 'Siret',
118+
mask: '### ### ### #####',
119+
name: 'siret',
120+
placeholder: '### ### ### #####',
121+
rules: { required: true, regex: /^[0-9]{3} [0-9]{3} [0-9]{3} [0-9]{5}$/ },
122+
wrapperClass: 'w-full lc-col mb-4',
123+
},
124+
},
107125
],
108126
}

src/components/LcForm/LcForm.vue

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@
4040
:options="field.options || []"
4141
v-bind="field.attr"
4242
/>
43+
<lc-mask-input
44+
v-if="field.inputType === 'mask' && !field.hidden"
45+
v-model="field.model"
46+
v-bind="field.attr"
47+
/>
4348
</div>
4449

4550
<slot name="before-submit-button" />
@@ -76,6 +81,7 @@ import { defineComponent, ref } from 'vue'
7681
7782
import { Form as vForm, defineRule, configure } from 'vee-validate'
7883
import {
84+
regex,
7985
required,
8086
email,
8187
min,
@@ -90,6 +96,7 @@ import LcButton from '../LcButton'
9096
import LcMultiselect from '../LcMultiselect'
9197
import LcCheckbox from '../LcCheckbox'
9298
import LcInput from '../LcInput'
99+
import LcMaskInput from '../LcMaskInput'
93100
import LcTextarea from '../LcTextarea'
94101
import { LcRadioGroup } from '../LcRadio'
95102
import { FieldClassContainer, FormValues } from './types'
@@ -101,6 +108,7 @@ configure({
101108
})
102109
103110
defineRule('required', required)
111+
defineRule('regex', regex)
104112
defineRule('email', email)
105113
defineRule('min', min)
106114
defineRule('numeric', numeric)
@@ -113,6 +121,7 @@ export default defineComponent({
113121
LcButton,
114122
LcCheckbox,
115123
LcInput,
124+
LcMaskInput,
116125
LcMultiselect,
117126
LcTextarea,
118127
LcRadioGroup,

src/components/LcInput/LcInput.vue

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
@blur="onBlur"
2323
>
2424

25-
<error-message :name="name" as="span" class="lc-input--error" />
25+
<error-message :name="name" as="span" class="lc-form--error" />
2626
</div>
2727
</template>
2828

@@ -136,7 +136,4 @@ export default defineComponent({
136136
.lc-input[disabled=disabled] {
137137
-webkit-text-fill-color: #aaaaaa;
138138
}
139-
.lc-input--error {
140-
@apply text-sm text-error;
141-
}
142139
</style>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { DefineComponent } from 'vue'
2+
const component: DefineComponent<{}, {}, any>
3+
export default component
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { action } from '@storybook/addon-actions'
2+
3+
import LcMaskInput from './LcMaskInput'
4+
5+
export default {
6+
title: 'Example/LcMaskInput',
7+
component: LcMaskInput,
8+
}
9+
10+
const Template = (args: any) => ({
11+
components: { LcMaskInput },
12+
setup() {
13+
return { args }
14+
},
15+
template: `<lc-mask-input
16+
v-bind="args"
17+
@blur="onBlur"
18+
@raw-value="rawValue"
19+
/>`,
20+
methods: {
21+
onBlur: action('onBlur'),
22+
rawValue: action('rawValue'),
23+
},
24+
})
25+
26+
export const Base = Template.bind({}) as any
27+
Base.args = {
28+
label: 'Siret',
29+
name: 'siret',
30+
modelValue: '',
31+
wrapperClass: 'w-full',
32+
mask: '### ### ### #####',
33+
}
34+
35+
export const Value = Template.bind({}) as any
36+
Value.args = {
37+
...Base.args,
38+
modelValue: '11122233355555',
39+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
<template>
2+
<div :class="wrapperClass">
3+
<slot name="label">
4+
<label
5+
v-if="label"
6+
:for="$attrs.id || name"
7+
>
8+
{{ label }}
9+
</label>
10+
</slot>
11+
12+
<input
13+
:id="$attrs.id || name"
14+
:ref="name"
15+
v-maska="mask"
16+
:class="computedClass"
17+
:name="name"
18+
:placeholder="placeholder"
19+
:value="inputValue"
20+
data-testid="lc-mask-input"
21+
v-bind="$attrs"
22+
@blur="onBlur"
23+
@maska="onChange"
24+
>
25+
<error-message :name="name" as="span" class="lc-form--error" />
26+
</div>
27+
</template>
28+
29+
<script lang="ts">
30+
import { maska } from 'maska'
31+
import { defineComponent, computed } from 'vue'
32+
import { ErrorMessage, useField } from 'vee-validate'
33+
34+
export default defineComponent({
35+
name: 'LcInput',
36+
directives: { maska },
37+
components: {
38+
ErrorMessage,
39+
},
40+
inheritAttrs: false,
41+
props: {
42+
disabled: {
43+
type: Boolean,
44+
default: false,
45+
},
46+
label: {
47+
type: String,
48+
default: '',
49+
},
50+
mask: {
51+
type: [String, Array],
52+
default: '',
53+
},
54+
modelValue: {
55+
type: [String, Number],
56+
default: '',
57+
},
58+
name: {
59+
type: String,
60+
required: true,
61+
},
62+
noBorder: {
63+
type: Boolean,
64+
default: false,
65+
},
66+
placeholder: {
67+
type: String,
68+
default: '',
69+
},
70+
rules: {
71+
type: [String, Object],
72+
default: '',
73+
},
74+
wrapperClass: {
75+
type: String,
76+
default: 'w-full mb-4',
77+
},
78+
},
79+
emits: ['update:modelValue', 'blur', 'raw-value'],
80+
setup(props, { emit }) {
81+
const {
82+
value: inputValue,
83+
handleBlur,
84+
handleChange,
85+
errors,
86+
} = useField<string|number>(props.name, props.rules, {
87+
initialValue: props.modelValue,
88+
})
89+
90+
const isError = computed(() => Boolean(errors.value.length))
91+
92+
function onBlur(): void {
93+
handleBlur()
94+
emit('blur')
95+
}
96+
97+
function onChange(event: Event & { target: HTMLInputElement }): void {
98+
handleChange(event.target.value)
99+
emit('raw-value', event.target.dataset.maskRawValue)
100+
}
101+
102+
return {
103+
inputValue,
104+
handleChange,
105+
isError,
106+
onBlur,
107+
onChange,
108+
}
109+
},
110+
computed: {
111+
computedClass(): any[] {
112+
return [
113+
'lc-mask-input',
114+
{ 'lc-mask-input--hasBorder': !this.noBorder },
115+
{ 'lc-mask-input--disabled': this.disabled },
116+
{ 'lc-mask-input--hasError-hasBorder': this.isError && !this.noBorder },
117+
{ 'lc-mask-input--hasntError-hasBorder': !this.isError && !this.noBorder },
118+
]
119+
},
120+
},
121+
})
122+
</script>
123+
124+
<style scoped>
125+
.lc-mask-input {
126+
height: 51px;
127+
transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
128+
@apply block bg-clip-padding w-full text-gray-700 font-normal text-base leading-normal py-1.5 px-4 bg-white focus:text-gray-700 focus:bg-white focus:border-primary-focus focus:shadow-focus focus:outline-none;
129+
}
130+
.lc-mask-input--hasBorder {
131+
@apply border rounded-sm;
132+
}
133+
.lc-mask-input--disabled {
134+
@apply bg-gray-300 pointer-events-none text-gray-500;
135+
}
136+
.lc-mask-input--hasError-hasBorder {
137+
@apply border-error;
138+
}
139+
.lc-mask-input--hasntError-hasBorder {
140+
@apply border-gray-400;
141+
}
142+
.lc-mask-input[disabled=disabled] {
143+
-webkit-text-fill-color: #aaaaaa;
144+
}
145+
</style>

0 commit comments

Comments
 (0)