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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@vee-validate/rules": "^4.1.20",
"@vueform/multiselect": "^2.0.1",
"esno": "0.4.4",
"maska": "^1.4.4",
"vee-validate": "4.4.4",
"vue": "3.1.1"
},
Expand Down
22 changes: 20 additions & 2 deletions src/components/LcForm/LcForm.stories.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { action } from '@storybook/addon-actions'

import LcForm from './LcForm'

export default {
Expand All @@ -10,7 +12,11 @@ const Template = (args: any) => ({
setup() {
return { args }
},
template: '<lc-form v-bind="args"/>',
template: '<lc-form v-bind="args" @onSubmit="onSubmit" @onCancel="onCancel"/>',
methods: {
onSubmit: action('onSubmit'),
onCancel: action('onCancel'),
},
})

export const Base = Template.bind({}) as any
Expand All @@ -34,7 +40,7 @@ Base.args = {
},
fields: [
{
model: '',
model: 'Bob',
inputType: 'input',
attr: {
disabled: true,
Expand Down Expand Up @@ -104,5 +110,17 @@ Base.args = {
wrapperClass: 'mb-4',
},
},
{
model: '',
inputType: 'mask',
attr: {
label: 'Siret',
mask: '### ### ### #####',
name: 'siret',
placeholder: '### ### ### #####',
rules: { required: true, regex: /^[0-9]{3} [0-9]{3} [0-9]{3} [0-9]{5}$/ },
wrapperClass: 'w-full lc-col mb-4',
},
},
],
}
9 changes: 9 additions & 0 deletions src/components/LcForm/LcForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
:options="field.options || []"
v-bind="field.attr"
/>
<lc-mask-input
v-if="field.inputType === 'mask' && !field.hidden"
v-model="field.model"
v-bind="field.attr"
/>
</div>

<slot name="before-submit-button" />
Expand Down Expand Up @@ -76,6 +81,7 @@ import { defineComponent, ref } from 'vue'

import { Form as vForm, defineRule, configure } from 'vee-validate'
import {
regex,
required,
email,
min,
Expand All @@ -90,6 +96,7 @@ import LcButton from '../LcButton'
import LcMultiselect from '../LcMultiselect'
import LcCheckbox from '../LcCheckbox'
import LcInput from '../LcInput'
import LcMaskInput from '../LcMaskInput'
import LcTextarea from '../LcTextarea'
import { LcRadioGroup } from '../LcRadio'
import { FieldClassContainer, FormValues } from './types'
Expand All @@ -101,6 +108,7 @@ configure({
})

defineRule('required', required)
defineRule('regex', regex)
defineRule('email', email)
defineRule('min', min)
defineRule('numeric', numeric)
Expand All @@ -113,6 +121,7 @@ export default defineComponent({
LcButton,
LcCheckbox,
LcInput,
LcMaskInput,
LcMultiselect,
LcTextarea,
LcRadioGroup,
Expand Down
5 changes: 1 addition & 4 deletions src/components/LcInput/LcInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
@blur="onBlur"
>

<error-message :name="name" as="span" class="lc-input--error" />
<error-message :name="name" as="span" class="lc-form--error" />
</div>
</template>

Expand Down Expand Up @@ -136,7 +136,4 @@ export default defineComponent({
.lc-input[disabled=disabled] {
-webkit-text-fill-color: #aaaaaa;
}
.lc-input--error {
@apply text-sm text-error;
}
</style>
3 changes: 3 additions & 0 deletions src/components/LcMaskInput/LcMaskInput.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
39 changes: 39 additions & 0 deletions src/components/LcMaskInput/LcMaskInput.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { action } from '@storybook/addon-actions'

import LcMaskInput from './LcMaskInput'

export default {
title: 'Example/LcMaskInput',
component: LcMaskInput,
}

const Template = (args: any) => ({
components: { LcMaskInput },
setup() {
return { args }
},
template: `<lc-mask-input
v-bind="args"
@blur="onBlur"
@raw-value="rawValue"
/>`,
methods: {
onBlur: action('onBlur'),
rawValue: action('rawValue'),
},
})

export const Base = Template.bind({}) as any
Base.args = {
label: 'Siret',
name: 'siret',
modelValue: '',
wrapperClass: 'w-full',
mask: '### ### ### #####',
}

export const Value = Template.bind({}) as any
Value.args = {
...Base.args,
modelValue: '11122233355555',
}
145 changes: 145 additions & 0 deletions src/components/LcMaskInput/LcMaskInput.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<template>
<div :class="wrapperClass">
<slot name="label">
<label
v-if="label"
:for="$attrs.id || name"
>
{{ label }}
</label>
</slot>

<input
:id="$attrs.id || name"
:ref="name"
v-maska="mask"
:class="computedClass"
:name="name"
:placeholder="placeholder"
:value="inputValue"
data-testid="lc-mask-input"
v-bind="$attrs"
@blur="onBlur"
@maska="onChange"
>
<error-message :name="name" as="span" class="lc-form--error" />
</div>
</template>

<script lang="ts">
import { maska } from 'maska'
import { defineComponent, computed } from 'vue'
import { ErrorMessage, useField } from 'vee-validate'

export default defineComponent({
name: 'LcInput',
directives: { maska },
components: {
ErrorMessage,
},
inheritAttrs: false,
props: {
disabled: {
type: Boolean,
default: false,
},
label: {
type: String,
default: '',
},
mask: {
type: [String, Array],
default: '',
},
modelValue: {
type: [String, Number],
default: '',
},
name: {
type: String,
required: true,
},
noBorder: {
type: Boolean,
default: false,
},
placeholder: {
type: String,
default: '',
},
rules: {
type: [String, Object],
default: '',
},
wrapperClass: {
type: String,
default: 'w-full mb-4',
},
},
emits: ['update:modelValue', 'blur', 'raw-value'],
setup(props, { emit }) {
const {
value: inputValue,
handleBlur,
handleChange,
errors,
} = useField<string|number>(props.name, props.rules, {
initialValue: props.modelValue,
})

const isError = computed(() => Boolean(errors.value.length))

function onBlur(): void {
handleBlur()
emit('blur')
}

function onChange(event: Event & { target: HTMLInputElement }): void {
handleChange(event.target.value)
emit('raw-value', event.target.dataset.maskRawValue)
}

return {
inputValue,
handleChange,
isError,
onBlur,
onChange,
}
},
computed: {
computedClass(): any[] {
return [
'lc-mask-input',
{ 'lc-mask-input--hasBorder': !this.noBorder },
{ 'lc-mask-input--disabled': this.disabled },
{ 'lc-mask-input--hasError-hasBorder': this.isError && !this.noBorder },
{ 'lc-mask-input--hasntError-hasBorder': !this.isError && !this.noBorder },
]
},
},
})
</script>

<style scoped>
.lc-mask-input {
height: 51px;
transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
@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;
}
.lc-mask-input--hasBorder {
@apply border rounded-sm;
}
.lc-mask-input--disabled {
@apply bg-gray-300 pointer-events-none text-gray-500;
}
.lc-mask-input--hasError-hasBorder {
@apply border-error;
}
.lc-mask-input--hasntError-hasBorder {
@apply border-gray-400;
}
.lc-mask-input[disabled=disabled] {
-webkit-text-fill-color: #aaaaaa;
}
</style>
Loading