srcdev-nuxt-forms 0.0.17 → 0.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.prettierrc CHANGED
@@ -1,4 +1,4 @@
1
1
  {
2
- "semi": false,
3
- "singleQuote": true
4
- }
2
+ "semi": true,
3
+ "singleQuote": true
4
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "username": {
3
+ "pattern": "^[a-zA-Z0-9_\\-'.]{8,20}$",
4
+ "minlength": 8,
5
+ "maxlength": 20,
6
+ "hint": "Uppercase letters and numbers, with ,.- and space"
7
+ },
8
+ "usernameWeak": {
9
+ "pattern": "^[a-zA-Z0-9]{6,20}$",
10
+ "minlength": 6,
11
+ "maxlength": 20,
12
+ "hint": "Mixed case letters"
13
+ },
14
+ "password": {
15
+ "pattern": "^(?=.*\\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[^\\w\\d\\s:])([^\\s]){8,16}$",
16
+ "minlength": 8,
17
+ "maxlength": 20,
18
+ "hint": "!Pa55word"
19
+ },
20
+ "passwordWeak": {
21
+ "pattern": "^[a-zA-Z0-9]{6,20}$",
22
+ "minlength": 6,
23
+ "maxlength": 20,
24
+ "hint": "password"
25
+ },
26
+ "emailaddress": {
27
+ "pattern": "^(?!@)((?!([\\.]))([\\w\\.\\-\\+']{1,}))?((@)([\\w\\-]{2,})+((\\.)([\\w]{2,}))+)$",
28
+ "minlength": 7,
29
+ "maxlength": 255,
30
+ "hint": "you@your-email.com"
31
+ },
32
+ "url": {
33
+ "pattern": "^((http|https)://){1}([\\w\\-]{2,}(\\.))+([\\w]{2,})((/))*((/)[\\w\\-]{1,})*((/)[\\w]{1,}(/))*(/)*$",
34
+ "minlength": 13,
35
+ "maxlength": 255,
36
+ "hint": "https://your-website.com"
37
+ },
38
+ "telephone": {
39
+ "pattern": "^(0|\\+44|\\+353)([\\d\\- ]{10})$",
40
+ "minlength": 11,
41
+ "maxlength": 14,
42
+ "hint": "+441632123123"
43
+ }
44
+ }
@@ -0,0 +1,6 @@
1
+ import en from './en.json'
2
+
3
+ export const validationConfig: any = {
4
+ 'en-GB': en,
5
+ }
6
+ export default validationConfig
@@ -0,0 +1,123 @@
1
+ <template>
2
+ <input
3
+ :type
4
+ :placeholder="c12.placeholder"
5
+ :id
6
+ :name
7
+ :pattern="componentValidation.pattern"
8
+ :maxlength="componentValidation.maxlength"
9
+ :required
10
+ :class="['input-text', 'text-normal', { error: fieldHasError() }]"
11
+ v-model="modelValue.data[name]"
12
+ ref="inputField"
13
+ @focusin="isFocused = true"
14
+ @focusout="isFocused = false"
15
+ />
16
+ </template>
17
+
18
+ <script setup lang="ts">
19
+ import type { InpuTextC12, IFormData } from '@/types/types.forms';
20
+ import { validationConfig } from '@/components/forms/c12/validation-patterns';
21
+
22
+ const props = defineProps({
23
+ type: {
24
+ // type: String as PropType<"text" | "password" | "tel" | "number" | "email" | "url">, // This breaks props setup in unit tests
25
+ type: String,
26
+ validator(value: string) {
27
+ return ['text', 'password', 'tel', 'number', 'email', 'url'].includes(
28
+ value
29
+ );
30
+ },
31
+ },
32
+ id: {
33
+ // type: String as PropType<string>,
34
+ type: String,
35
+ required: true,
36
+ },
37
+ name: {
38
+ type: String,
39
+ default: null,
40
+ },
41
+ validation: {
42
+ type: String,
43
+ default: '',
44
+ },
45
+ required: {
46
+ type: Boolean,
47
+ value: false,
48
+ },
49
+ isPending: {
50
+ type: Boolean,
51
+ value: false,
52
+ },
53
+ c12: {
54
+ type: Object as PropType<InpuTextC12>,
55
+ required: true,
56
+ },
57
+ });
58
+
59
+ const modelValue = defineModel() as Ref<IFormData>;
60
+ const isFocused = defineModel('isFocused') as Ref<boolean>;
61
+
62
+ const name = computed(() => {
63
+ return props.name !== null ? props.name : props.id;
64
+ });
65
+ const validatorLocale = toRef(useRuntimeConfig().public.validatorLocale);
66
+
67
+ const componentValidation =
68
+ validationConfig[validatorLocale.value][props.validation];
69
+ const inputField = ref<HTMLInputElement | null>(null);
70
+
71
+ const { hasCustomError, removeCustomError } = useErrorMessage(
72
+ name.value,
73
+ modelValue
74
+ );
75
+
76
+ const fieldHasError = () => {
77
+ const hasApiErrorMessage = hasCustomError();
78
+ const inputBad = !inputField.value?.validity.valid;
79
+
80
+ if (modelValue.value.isPending) {
81
+ modelValue.value!.validityState[name.value] =
82
+ inputField.value?.validity.valid ?? false;
83
+ return hasApiErrorMessage ? hasApiErrorMessage : inputBad;
84
+ }
85
+ return false;
86
+ };
87
+
88
+ // watchEffect(() => {
89
+ // console.log('Form value changed to: ', modelValue.value.data[name.value]);
90
+ // });
91
+
92
+ const isValid = () => {
93
+ setTimeout(() => {
94
+ modelValue.value!.validityState[name.value] =
95
+ inputField.value?.validity.valid ?? false;
96
+ }, 0);
97
+ };
98
+
99
+ // Keep an eye on this for performance issue
100
+ watch(
101
+ () => modelValue.value.data[name.value],
102
+ () => {
103
+ modelValue.value!.validityState[name.value] =
104
+ inputField.value?.validity.valid ?? false;
105
+ if (hasCustomError()) {
106
+ removeCustomError(inputField.value?.validity.valid);
107
+ }
108
+ },
109
+ { deep: true }
110
+ );
111
+
112
+ onMounted(() => {
113
+ isValid();
114
+ });
115
+ </script>
116
+
117
+ <style lang="css">
118
+ .input-text {
119
+ transition: all linear 200ms;
120
+ padding-left: 4px;
121
+ width: 100%;
122
+ }
123
+ </style>
package/nuxt.config.ts CHANGED
@@ -5,10 +5,16 @@ const { resolve } = createResolver(import.meta.url)
5
5
  export default defineNuxtConfig({
6
6
  devtools: { enabled: true },
7
7
  css: [resolve('./assets/styles/main.css')],
8
+ runtimeConfig: {
9
+ public: {
10
+ validatorLocale: 'en-GB',
11
+ },
12
+ },
13
+
8
14
  components: [
9
15
  {
10
- path: '~/components',
11
- pathPrefix: true,
16
+ path: './components',
17
+ pathPrefix: false,
12
18
  },
13
19
  ],
14
20
  })
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "srcdev-nuxt-forms",
3
3
  "type": "module",
4
- "version": "0.0.17",
4
+ "version": "0.0.19",
5
5
  "main": "./nuxt.config.ts",
6
6
  "scripts": {
7
7
  "reinstall": "rm -rf node_modules && npm install",
package/pages/index.vue CHANGED
@@ -5,29 +5,53 @@
5
5
  <div>
6
6
  <h1>Sample form page</h1>
7
7
 
8
- <FormsUiFormWrapper width="medium">
8
+ <FormWrapper width="medium">
9
9
  <template #default>
10
- <form>
10
+ <form @submit.prevent="isPending">
11
11
  <p>Form content</p>
12
- <FormsUiFormField width="wide" :has-gutter="true">
12
+ <FormField width="wide" :has-gutter="true">
13
13
  <template #default>
14
14
  <p>Input text</p>
15
- <FormsInputTextCore />
15
+ <InputTextCore
16
+ id="username"
17
+ type="text"
18
+ validation="username"
19
+ :required="true"
20
+ v-model="formData"
21
+ :c12="{
22
+ label: 'Choose Username',
23
+ placeholder: 'eg. YourUserName',
24
+ errorMessage: 'Please enter a valid username',
25
+ }"
26
+ />
16
27
  </template>
17
- </FormsUiFormField>
28
+ </FormField>
29
+ <input
30
+ type="submit"
31
+ @click.prevent="isPending"
32
+ value="Submit"
33
+ />
18
34
  </form>
19
35
  </template>
20
- </FormsUiFormWrapper>
36
+ </FormWrapper>
21
37
  </div>
38
+ <ClientOnly>
39
+ <p>Client only content</p>
40
+ <pre>
41
+ {{ formData }}
42
+ </pre>
43
+ </ClientOnly>
22
44
  </template>
23
45
  </NuxtLayout>
24
46
  </div>
25
47
  </template>
26
48
 
27
49
  <script setup lang="ts">
50
+ import type { IFieldsInitialState, IOptionsConfig } from '@/types/types.forms';
51
+
28
52
  definePageMeta({
29
53
  layout: false,
30
- })
54
+ });
31
55
 
32
56
  useHead({
33
57
  title: 'Homepage',
@@ -35,7 +59,38 @@ useHead({
35
59
  bodyAttrs: {
36
60
  class: '',
37
61
  },
38
- })
62
+ });
63
+
64
+ /*
65
+ * Setup forms
66
+ */
67
+ const fieldsInitialState = ref<IFieldsInitialState>({
68
+ username: '',
69
+ });
70
+
71
+ // Setup formData
72
+ const {
73
+ formData,
74
+ initFormData,
75
+ getErrorCount,
76
+ updateCustomErrors,
77
+ resetForm,
78
+ formIsValid,
79
+ showErrors,
80
+ } = useFormControl(fieldsInitialState);
81
+
82
+ await initFormData();
83
+
84
+ const isPending = async () => {
85
+ formData.value.isPending = true;
86
+ await getErrorCount();
87
+
88
+ if (formIsValid.value) {
89
+ console.log('Form is good - post it!');
90
+ } else {
91
+ console.warn('Form has errors');
92
+ }
93
+ };
39
94
  </script>
40
95
 
41
96
  <style lang="css">
@@ -17,7 +17,14 @@ export interface IOptionsValueArr {
17
17
  }
18
18
 
19
19
  export interface IFieldsInitialState {
20
- [key: string]: null | string | boolean | number | URL | object | IOptionsValueArr[];
20
+ [key: string]:
21
+ | null
22
+ | string
23
+ | boolean
24
+ | number
25
+ | URL
26
+ | object
27
+ | IOptionsValueArr[];
21
28
  }
22
29
 
23
30
  export interface IValidityState {
@@ -59,6 +66,12 @@ export interface ICustomErrorMessage {
59
66
  message: string;
60
67
  }
61
68
 
69
+ export interface InpuTextC12 {
70
+ label: string;
71
+ placeholder: string;
72
+ errorMessage: string;
73
+ }
74
+
62
75
  export interface ICustomErrorMessagesArr {
63
76
  [x: string]: ICustomErrorMessage;
64
77
  }