Skip to content

Commit e0f0ac6

Browse files
committed
feat(FieldColor): option for extra text input
1 parent 6b094e1 commit e0f0ac6

File tree

6 files changed

+81
-17
lines changed

6 files changed

+81
-17
lines changed

src/fields/core/FieldColor.vue

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,52 @@
11
<template>
2-
<input
3-
:id="props.id"
4-
class="field-color"
5-
type="color"
6-
:name="props.field.name"
7-
:value="currentModelValue"
8-
:required="isRequired"
9-
@change="onFieldValueChanged"
10-
@blur="onBlur"
11-
>
2+
<div class="field-color-wrapper">
3+
<input
4+
v-if="props.field.withInput"
5+
v-maska="maskOptions"
6+
class="field-color-input"
7+
type="text"
8+
:value="currentModelValue"
9+
placeholder="#ffffff"
10+
@input="onFieldValueChanged"
11+
@blur="onBlur"
12+
>
13+
<input
14+
:id="props.id"
15+
class="field-color"
16+
type="color"
17+
:name="props.field.name"
18+
:value="currentModelValue"
19+
:required="isRequired"
20+
@input="onFieldValueChanged"
21+
@blur="onBlur"
22+
>
23+
</div>
1224
</template>
1325

1426
<script setup>
15-
import { toRefs } from 'vue'
27+
import validators from '@/validators'
28+
import { toRefs, onBeforeMount } from 'vue'
1629
import {
1730
useFormModel,
1831
useFieldAttributes,
1932
useFieldValidate,
2033
useFieldProps,
2134
useFieldEmits
2235
} from '@/composables/index.ts'
36+
import { vMaska } from 'maska/vue'
2337
2438
const emits = defineEmits(useFieldEmits())
2539
const props = defineProps(useFieldProps())
2640
41+
const maskOptions = {
42+
mask: '!#HHHHHH',
43+
tokens: {
44+
H: {
45+
pattern: /[A-Fa-f0-9]/
46+
}
47+
}
48+
}
49+
2750
const { field, model } = toRefs(props)
2851
2952
const { currentModelValue } = useFormModel(model.value, field.value)
@@ -38,7 +61,7 @@ const { errors, validate } = useFieldValidate(
3861
)
3962
4063
const onBlur = () => {
41-
validate().then((validationErrors) => {
64+
validate(currentModelValue.value).then((validationErrors) => {
4265
emits('validated',
4366
validationErrors.length === 0,
4467
validationErrors,
@@ -49,8 +72,26 @@ const onBlur = () => {
4972
5073
const onFieldValueChanged = ({ target }) => {
5174
errors.value = []
52-
emits('onInput', target.value)
75+
// Ensure a change doesn't emit twice, we need this because both inputs might trigger this function at once.
76+
if (target.value !== currentModelValue.value) {
77+
emits('onInput', target.value)
78+
}
5379
}
5480
55-
defineExpose({ isVisible })
81+
onBeforeMount(() => {
82+
if (field.value.withInput) {
83+
const fieldValidators = []
84+
if (Array.isArray(field.value.validator)) {
85+
fieldValidators.push(...field.value.validator)
86+
} else if (field.value.validator !== undefined) {
87+
fieldValidators.push(field.value.validator)
88+
}
89+
// Keep in mind that the native color picker only supports 6 digit hex codes,
90+
// so even though a value might technically be valid, it won't display the right color on the color picker input.
91+
fieldValidators.push(validators.hexColorValue)
92+
field.value.validator = fieldValidators
93+
}
94+
})
95+
96+
defineExpose({ isVisible, errors })
5697
</script>

src/scss/shared/fieldColor.scss

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.field-color-wrapper {
2+
display: flex;
3+
flex-direction: row-reverse;
4+
align-items: stretch;
5+
justify-content: start;
6+
7+
.field-color-input {
8+
max-width: 100px;
9+
}
10+
}

src/scss/themes/basic.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
@import '../modules/base';
44
@import '../modules/colors';
55
@import '../shared/fieldSelect';
6+
@import '../shared/fieldColor';
67

78
$input-padding: .3rem .4rem;
89

src/scss/themes/legacy.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
@import '../modules/colors';
22
@import '../shared/fieldSelect';
3+
@import '../shared/fieldColor';
34

45
$field-switch-width: 120px;
56
$field-switch-height: 30px;

src/validators/index.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ export default {
7575
// eslint-disable-next-line @typescript-eslint/no-unused-vars
7676
email (value: FieldValue, field: Field, model: Record<string, any>): boolean {
7777
if (typeof value !== 'string') return false
78-
// eslint-disable-next-line max-len
7978
const regex = new RegExp('^([^<>()\\[\\]\\\\.,;:\\s@"]+(?:\\.[^<>()\\[\\]\\\\.,;:\\s@"]+)*|".+")@(\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}]|(?:[a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,})$', 'i')
8079
return Boolean(value.match(regex))
8180
},
@@ -89,7 +88,6 @@ export default {
8988
if (typeof value !== 'string') return false
9089

9190
const regex = new RegExp(
92-
// eslint-disable-next-line max-len
9391
'^\\+\\d{1,3}\\s\\d{2,3}\\s\\d{2,3}\\s\\d{4}|^\\+\\d{1,3}\\s\\d{1,14}(\\s\\d{1,13})?|^\\(\\d{3}\\)\\s\\d{3}\\s\\d{4}?',
9492
'i'
9593
)
@@ -106,6 +104,18 @@ export default {
106104

107105
const regex = new RegExp('(\\+316[0-9]{8})|(06[0-9]{8})', 'i')
108106
return Boolean(value.match(regex))
107+
},
108+
109+
/**
110+
* Check if a value is a valid HEX color value.
111+
* @returns {boolean} - Returns `true` if value matches the format, otherwise false.
112+
*/
113+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
114+
hexColorValue (value: FieldValue, field: Field, model: Record<string, any>): boolean {
115+
if (typeof value !== 'string') return false
116+
117+
const regex = new RegExp('^\#([a-f0-9]{3}|[a-f0-9]{6})$', 'i')
118+
return Boolean(value.match(regex))
109119
}
110120

111121

src/validators/messages.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ let messages: Record<string, string> = {
44
number: 'Value must be a number',
55
email: 'E-mail is invalid',
66
phoneNumberE164andE123: 'Phone number is invalid (must be valid E164 or E123 format, e.g. +31 612345678)',
7-
mobilePhoneNL: 'Phone number is invalid (must be a valid Dutch phone number, e.g. +31612345678)'
7+
mobilePhoneNL: 'Phone number is invalid (must be a valid Dutch phone number, e.g. +31612345678)',
8+
hexColorValue: 'Invalid hex value (e.g. #ff0000 or #ff0)'
89
}
910

1011
/**

0 commit comments

Comments
 (0)