srcdev-nuxt-forms 0.0.22 → 0.1.0
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 +2 -1
- package/assets/styles/forms/themes/_error.css +12 -0
- package/assets/styles/forms/themes/_ghost.css +11 -0
- package/assets/styles/forms/themes/_primary.css +9 -1
- package/assets/styles/forms/themes/_secondary.css +11 -0
- package/assets/styles/forms/themes/_success.css +12 -0
- package/assets/styles/forms/themes/_tertiary.css +11 -0
- package/assets/styles/forms/themes/_warning.css +11 -0
- package/assets/styles/forms/themes/index.css +6 -0
- package/assets/styles/forms/variables/_theme.css +64 -1
- package/assets/styles/variables/colors/_orange.css +1 -1
- package/assets/styles/variables/colors/_red.css +1 -1
- package/components/forms/c12/prop-validators/index.ts +25 -0
- package/components/forms/c12/validation-patterns/en.json +1 -1
- package/components/forms/input-button/InputButtonCore.vue +367 -0
- package/components/forms/input-button/variants/InputButtonConfirm.vue +78 -0
- package/components/forms/input-button/variants/InputButtonSubmit.vue +74 -0
- package/components/forms/input-text/InputTextCore.vue +77 -59
- package/components/forms/input-text/variants/material/InputEmailMaterial.vue +72 -0
- package/components/forms/input-text/variants/material/InputPasswordMaterial.vue +88 -0
- package/components/forms/input-text/variants/material/InputTextMaterial.vue +75 -0
- package/components/forms/input-text/variants/material/InputTextMaterialCore.vue +258 -0
- package/components/forms/ui/FormField.vue +7 -2
- package/components/forms/ui/FormWrapper.vue +2 -2
- package/composables/useErrorMessages.ts +4 -4
- package/composables/useFormControl.ts +36 -16
- package/composables/useUpdateStyleClassPassthrough.ts +29 -0
- package/layouts/default.vue +33 -2
- package/nuxt.config.ts +4 -3
- package/package.json +3 -1
- package/pages/forms/examples/buttons/index.vue +154 -0
- package/pages/forms/examples/material/text-fields-compact.vue +136 -0
- package/pages/forms/examples/material/text-fields.vue +136 -0
- package/pages/index.vue +2 -70
- package/types/types.forms.ts +6 -11
- package/components/forms/input-text/InputTextField.vue +0 -22
- package/components/forms/input-text/variants/InputTextMaterial.vue +0 -159
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<NuxtLayout name="default">
|
|
4
|
+
<template #layout-content>
|
|
5
|
+
<div>
|
|
6
|
+
<h1>Example buttons</h1>
|
|
7
|
+
<p>Primary submit</p>
|
|
8
|
+
|
|
9
|
+
<p>Themes switcher</p>
|
|
10
|
+
<ul class="flex-group">
|
|
11
|
+
<li>
|
|
12
|
+
<InputButtonSubmit @click.stop.prevent="swapTheme('primary')" :is-pending="false" button-text="Primary" theme="primary" size="normal" />
|
|
13
|
+
</li>
|
|
14
|
+
<li>
|
|
15
|
+
<InputButtonSubmit @click.stop.prevent="swapTheme('secondary')" :is-pending="false" button-text="Secondary" theme="secondary" size="normal" />
|
|
16
|
+
</li>
|
|
17
|
+
<li>
|
|
18
|
+
<InputButtonSubmit @click.stop.prevent="swapTheme('tertiary')" :is-pending="false" button-text="Tertiary" theme="tertiary" size="normal" />
|
|
19
|
+
</li>
|
|
20
|
+
<li>
|
|
21
|
+
<InputButtonSubmit @click.stop.prevent="swapTheme('warning')" :is-pending="false" button-text="Warning" theme="warning" size="normal" />
|
|
22
|
+
</li>
|
|
23
|
+
<li>
|
|
24
|
+
<InputButtonSubmit @click.stop.prevent="swapTheme('success')" :is-pending="false" button-text="Success" theme="success" size="normal" />
|
|
25
|
+
</li>
|
|
26
|
+
<li>
|
|
27
|
+
<InputButtonSubmit @click.stop.prevent="swapTheme('error')" :is-pending="false" button-text="Error" theme="error" size="normal" />
|
|
28
|
+
</li>
|
|
29
|
+
<li>
|
|
30
|
+
<InputButtonSubmit @click.stop.prevent="swapTheme('ghost')" :is-pending="false" button-text="Ghost" theme="ghost" size="normal" />
|
|
31
|
+
</li>
|
|
32
|
+
</ul>
|
|
33
|
+
|
|
34
|
+
<FormWrapper width="medium">
|
|
35
|
+
<template #default>
|
|
36
|
+
<form @submit.prevent="submitForm">
|
|
37
|
+
<div class="flex-group">
|
|
38
|
+
<InputButtonSubmit @click.stop.prevent="submitForm" :is-pending="false" button-text="Submit" :theme size="x-small" />
|
|
39
|
+
|
|
40
|
+
<InputButtonSubmit @click.stop.prevent="submitForm" :is-pending="false" button-text="Submit" :theme size="small" />
|
|
41
|
+
|
|
42
|
+
<InputButtonSubmit @click.stop.prevent="submitForm" :is-pending="false" button-text="Submit" :theme size="normal" />
|
|
43
|
+
<InputButtonSubmit @click.stop.prevent="submitForm" :is-pending="false" button-text="Submit" :theme size="medium" />
|
|
44
|
+
<InputButtonSubmit @click.stop.prevent="submitForm" :is-pending="false" button-text="Submit" :theme size="large" />
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<div class="flex-group">
|
|
48
|
+
<InputButtonConfirm @click.stop.prevent="submitForm" :is-pending="false" button-text="Confirm" :theme size="x-small" />
|
|
49
|
+
<InputButtonConfirm @click.stop.prevent="submitForm" :is-pending="false" button-text="Confirm" :theme size="small" />
|
|
50
|
+
<InputButtonConfirm @click.stop.prevent="submitForm" :is-pending="false" button-text="Confirm" :theme size="normal" />
|
|
51
|
+
<InputButtonConfirm @click.stop.prevent="submitForm" :is-pending="false" button-text="Confirm" :theme size="medium" />
|
|
52
|
+
<InputButtonConfirm @click.stop.prevent="submitForm" :is-pending="false" button-text="Confirm" :theme size="large" />
|
|
53
|
+
</div>
|
|
54
|
+
<div class="flex-group">
|
|
55
|
+
<InputButtonCore @click.stop.prevent="submitForm" :is-pending="false" button-text="Submit" :theme size="x-small">
|
|
56
|
+
<template #iconOnly>
|
|
57
|
+
<Icon name="radix-icons:eye-none" class="icon" />
|
|
58
|
+
</template>
|
|
59
|
+
</InputButtonCore>
|
|
60
|
+
|
|
61
|
+
<InputButtonCore @click.stop.prevent="submitForm" :is-pending="false" button-text="Submit" :theme size="small">
|
|
62
|
+
<template #iconOnly>
|
|
63
|
+
<Icon name="radix-icons:eye-none" class="icon" />
|
|
64
|
+
</template>
|
|
65
|
+
</InputButtonCore>
|
|
66
|
+
|
|
67
|
+
<InputButtonCore @click.stop.prevent="submitForm" :is-pending="false" button-text="Submit" :theme size="normal">
|
|
68
|
+
<template #iconOnly>
|
|
69
|
+
<Icon name="radix-icons:eye-none" class="icon" />
|
|
70
|
+
</template>
|
|
71
|
+
</InputButtonCore>
|
|
72
|
+
|
|
73
|
+
<InputButtonCore @click.stop.prevent="submitForm" :is-pending="false" button-text="Submit" :theme size="medium">
|
|
74
|
+
<template #iconOnly>
|
|
75
|
+
<Icon name="radix-icons:eye-none" class="icon" />
|
|
76
|
+
</template>
|
|
77
|
+
</InputButtonCore>
|
|
78
|
+
|
|
79
|
+
<InputButtonCore @click.stop.prevent="submitForm" :is-pending="false" button-text="Submit" :theme size="large">
|
|
80
|
+
<template #iconOnly>
|
|
81
|
+
<Icon name="radix-icons:eye-none" class="icon" />
|
|
82
|
+
</template>
|
|
83
|
+
</InputButtonCore>
|
|
84
|
+
</div>
|
|
85
|
+
</form>
|
|
86
|
+
</template>
|
|
87
|
+
</FormWrapper>
|
|
88
|
+
</div>
|
|
89
|
+
</template>
|
|
90
|
+
</NuxtLayout>
|
|
91
|
+
</div>
|
|
92
|
+
</template>
|
|
93
|
+
|
|
94
|
+
<script setup lang="ts">
|
|
95
|
+
import type { IFieldsInitialState, IOptionsConfig } from '@/types/types.forms';
|
|
96
|
+
|
|
97
|
+
definePageMeta({
|
|
98
|
+
layout: false,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
useHead({
|
|
102
|
+
title: 'Homepage',
|
|
103
|
+
meta: [{ name: 'description', content: 'Homepage' }],
|
|
104
|
+
bodyAttrs: {
|
|
105
|
+
class: '',
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const theme = ref('primary');
|
|
110
|
+
|
|
111
|
+
const swapTheme = (newTheme: string) => {
|
|
112
|
+
theme.value = newTheme;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/*
|
|
116
|
+
* Setup forms
|
|
117
|
+
*/
|
|
118
|
+
const fieldsInitialState = ref<IFieldsInitialState>({
|
|
119
|
+
emailAddress: '',
|
|
120
|
+
username: '',
|
|
121
|
+
password: '',
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Setup formData
|
|
125
|
+
const { formData, getErrorCount, updateCustomErrors, resetForm, formIsValid, submitDisabled } = useFormControl(fieldsInitialState);
|
|
126
|
+
|
|
127
|
+
const submitForm = async () => {
|
|
128
|
+
await getErrorCount(true);
|
|
129
|
+
|
|
130
|
+
if (formIsValid.value) {
|
|
131
|
+
formData.value.isPending = true;
|
|
132
|
+
console.log('Form is good - post it!');
|
|
133
|
+
// await useSleep(2000);
|
|
134
|
+
// formData.value.isPending = false;
|
|
135
|
+
} else {
|
|
136
|
+
console.warn('Form has errors');
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
</script>
|
|
140
|
+
|
|
141
|
+
<style lang="css">
|
|
142
|
+
.flex-group {
|
|
143
|
+
align-items: flex-start;
|
|
144
|
+
display: flex;
|
|
145
|
+
flex-wrap: wrap;
|
|
146
|
+
gap: 24px;
|
|
147
|
+
margin-bottom: 32px;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
ul.flex-group {
|
|
151
|
+
list-style-type: none;
|
|
152
|
+
padding: 0;
|
|
153
|
+
}
|
|
154
|
+
</style>
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<NuxtLayout name="default">
|
|
4
|
+
<template #layout-content>
|
|
5
|
+
<div>
|
|
6
|
+
<h1>Material UI text fields (compact)</h1>
|
|
7
|
+
<p>Example test fields in "compact" material UI</p>
|
|
8
|
+
|
|
9
|
+
<FormWrapper width="medium">
|
|
10
|
+
<template #default>
|
|
11
|
+
<form @submit.prevent="submitForm">
|
|
12
|
+
<FormField width="wide" :has-gutter="true">
|
|
13
|
+
<template #default>
|
|
14
|
+
<InputEmailMaterial
|
|
15
|
+
id="emailAddress"
|
|
16
|
+
name="emailAddress"
|
|
17
|
+
validation="emailaddress"
|
|
18
|
+
:required="true"
|
|
19
|
+
:c12="{
|
|
20
|
+
label: 'Your Email Address',
|
|
21
|
+
placeholder: 'eg. joe@example.com',
|
|
22
|
+
errorMessage: 'Please enter a valid email address',
|
|
23
|
+
}"
|
|
24
|
+
v-model="formData"
|
|
25
|
+
theme="secondary"
|
|
26
|
+
:compact
|
|
27
|
+
/>
|
|
28
|
+
</template>
|
|
29
|
+
</FormField>
|
|
30
|
+
|
|
31
|
+
<FormField width="wide" :has-gutter="true">
|
|
32
|
+
<template #default>
|
|
33
|
+
<InputTextMaterial
|
|
34
|
+
id="username"
|
|
35
|
+
name="username"
|
|
36
|
+
validation="username"
|
|
37
|
+
:required="true"
|
|
38
|
+
:c12="{
|
|
39
|
+
label: 'Your Username',
|
|
40
|
+
placeholder: 'eg. YourUserName',
|
|
41
|
+
errorMessage: 'Please enter a valid username',
|
|
42
|
+
}"
|
|
43
|
+
v-model="formData"
|
|
44
|
+
theme="secondary"
|
|
45
|
+
:compact
|
|
46
|
+
/>
|
|
47
|
+
</template>
|
|
48
|
+
</FormField>
|
|
49
|
+
|
|
50
|
+
<FormField width="wide" :has-gutter="true">
|
|
51
|
+
<template #default>
|
|
52
|
+
<InputPasswordMaterial
|
|
53
|
+
id="password"
|
|
54
|
+
name="password"
|
|
55
|
+
validation="password"
|
|
56
|
+
:required="true"
|
|
57
|
+
:c12="{
|
|
58
|
+
label: 'Password',
|
|
59
|
+
placeholder: 'eg. Your5illYPa55w0rd',
|
|
60
|
+
errorMessage: 'Please enter a valid password',
|
|
61
|
+
}"
|
|
62
|
+
v-model="formData"
|
|
63
|
+
theme="secondary"
|
|
64
|
+
:compact
|
|
65
|
+
/>
|
|
66
|
+
</template>
|
|
67
|
+
</FormField>
|
|
68
|
+
|
|
69
|
+
<FormField width="wide" :has-gutter="true">
|
|
70
|
+
<template #default>
|
|
71
|
+
<InputButtonSubmit @click.stop.prevent="submitForm" :is-pending="false" :readonly="submitDisabled" button-text="Submit" theme="secondary" size="medium" />
|
|
72
|
+
</template>
|
|
73
|
+
</FormField>
|
|
74
|
+
</form>
|
|
75
|
+
</template>
|
|
76
|
+
</FormWrapper>
|
|
77
|
+
</div>
|
|
78
|
+
<ClientOnly>
|
|
79
|
+
<p>Client only content</p>
|
|
80
|
+
<pre>
|
|
81
|
+
{{ formData }}
|
|
82
|
+
</pre>
|
|
83
|
+
</ClientOnly>
|
|
84
|
+
</template>
|
|
85
|
+
</NuxtLayout>
|
|
86
|
+
</div>
|
|
87
|
+
</template>
|
|
88
|
+
|
|
89
|
+
<script setup lang="ts">
|
|
90
|
+
import type { IFieldsInitialState, IOptionsConfig } from '@/types/types.forms';
|
|
91
|
+
|
|
92
|
+
definePageMeta({
|
|
93
|
+
layout: false,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
useHead({
|
|
97
|
+
title: 'Homepage',
|
|
98
|
+
meta: [{ name: 'description', content: 'Homepage' }],
|
|
99
|
+
bodyAttrs: {
|
|
100
|
+
class: '',
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const compact = ref(true);
|
|
105
|
+
|
|
106
|
+
/*
|
|
107
|
+
* Setup forms
|
|
108
|
+
*/
|
|
109
|
+
const fieldsInitialState = ref<IFieldsInitialState>({
|
|
110
|
+
emailAddress: '',
|
|
111
|
+
username: '',
|
|
112
|
+
password: '',
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Setup formData
|
|
116
|
+
const { formData, getErrorCount, updateCustomErrors, resetForm, formIsValid, submitDisabled } = useFormControl(fieldsInitialState);
|
|
117
|
+
|
|
118
|
+
const submitForm = async () => {
|
|
119
|
+
await getErrorCount(true);
|
|
120
|
+
|
|
121
|
+
if (formIsValid.value) {
|
|
122
|
+
formData.value.isPending = true;
|
|
123
|
+
console.log('Form is good - post it!');
|
|
124
|
+
// await useSleep(2000);
|
|
125
|
+
// formData.value.isPending = false;
|
|
126
|
+
} else {
|
|
127
|
+
console.warn('Form has errors');
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
</script>
|
|
131
|
+
|
|
132
|
+
<style lang="css">
|
|
133
|
+
p {
|
|
134
|
+
color: initial;
|
|
135
|
+
}
|
|
136
|
+
</style>
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<NuxtLayout name="default">
|
|
4
|
+
<template #layout-content>
|
|
5
|
+
<div>
|
|
6
|
+
<h1>Material UI text fields (default)</h1>
|
|
7
|
+
<p>Example test fields in default material UI</p>
|
|
8
|
+
|
|
9
|
+
<FormWrapper width="medium">
|
|
10
|
+
<template #default>
|
|
11
|
+
<form @submit.prevent="submitForm">
|
|
12
|
+
<FormField width="wide" :has-gutter="true">
|
|
13
|
+
<template #default>
|
|
14
|
+
<InputEmailMaterial
|
|
15
|
+
id="emailAddress"
|
|
16
|
+
name="emailAddress"
|
|
17
|
+
validation="emailaddress"
|
|
18
|
+
:required="true"
|
|
19
|
+
:c12="{
|
|
20
|
+
label: 'Your Email Address',
|
|
21
|
+
placeholder: 'eg. joe@example.com',
|
|
22
|
+
errorMessage: 'Please enter a valid email address',
|
|
23
|
+
}"
|
|
24
|
+
v-model="formData"
|
|
25
|
+
theme="secondary"
|
|
26
|
+
:compact
|
|
27
|
+
/>
|
|
28
|
+
</template>
|
|
29
|
+
</FormField>
|
|
30
|
+
|
|
31
|
+
<FormField width="wide" :has-gutter="true">
|
|
32
|
+
<template #default>
|
|
33
|
+
<InputTextMaterial
|
|
34
|
+
id="username"
|
|
35
|
+
name="username"
|
|
36
|
+
validation="username"
|
|
37
|
+
:required="true"
|
|
38
|
+
:c12="{
|
|
39
|
+
label: 'Your Username',
|
|
40
|
+
placeholder: 'eg. YourUserName',
|
|
41
|
+
errorMessage: 'Please enter a valid username',
|
|
42
|
+
}"
|
|
43
|
+
v-model="formData"
|
|
44
|
+
theme="secondary"
|
|
45
|
+
:compact
|
|
46
|
+
/>
|
|
47
|
+
</template>
|
|
48
|
+
</FormField>
|
|
49
|
+
|
|
50
|
+
<FormField width="wide" :has-gutter="true">
|
|
51
|
+
<template #default>
|
|
52
|
+
<InputPasswordMaterial
|
|
53
|
+
id="password"
|
|
54
|
+
name="password"
|
|
55
|
+
validation="password"
|
|
56
|
+
:required="true"
|
|
57
|
+
:c12="{
|
|
58
|
+
label: 'Password',
|
|
59
|
+
placeholder: 'eg. Your5illYPa55w0rd',
|
|
60
|
+
errorMessage: 'Please enter a valid password',
|
|
61
|
+
}"
|
|
62
|
+
v-model="formData"
|
|
63
|
+
theme="secondary"
|
|
64
|
+
:compact
|
|
65
|
+
/>
|
|
66
|
+
</template>
|
|
67
|
+
</FormField>
|
|
68
|
+
|
|
69
|
+
<FormField width="wide" :has-gutter="true">
|
|
70
|
+
<template #default>
|
|
71
|
+
<InputButtonSubmit @click.stop.prevent="submitForm" :is-pending="false" :readonly="submitDisabled" button-text="Submit" theme="secondary" size="medium" />
|
|
72
|
+
</template>
|
|
73
|
+
</FormField>
|
|
74
|
+
</form>
|
|
75
|
+
</template>
|
|
76
|
+
</FormWrapper>
|
|
77
|
+
</div>
|
|
78
|
+
<ClientOnly>
|
|
79
|
+
<p>Client only content</p>
|
|
80
|
+
<pre>
|
|
81
|
+
{{ formData }}
|
|
82
|
+
</pre>
|
|
83
|
+
</ClientOnly>
|
|
84
|
+
</template>
|
|
85
|
+
</NuxtLayout>
|
|
86
|
+
</div>
|
|
87
|
+
</template>
|
|
88
|
+
|
|
89
|
+
<script setup lang="ts">
|
|
90
|
+
import type { IFieldsInitialState, IOptionsConfig } from '@/types/types.forms';
|
|
91
|
+
|
|
92
|
+
definePageMeta({
|
|
93
|
+
layout: false,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
useHead({
|
|
97
|
+
title: 'Homepage',
|
|
98
|
+
meta: [{ name: 'description', content: 'Homepage' }],
|
|
99
|
+
bodyAttrs: {
|
|
100
|
+
class: '',
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const compact = ref(false);
|
|
105
|
+
|
|
106
|
+
/*
|
|
107
|
+
* Setup forms
|
|
108
|
+
*/
|
|
109
|
+
const fieldsInitialState = ref<IFieldsInitialState>({
|
|
110
|
+
emailAddress: '',
|
|
111
|
+
username: '',
|
|
112
|
+
password: '',
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Setup formData
|
|
116
|
+
const { formData, getErrorCount, updateCustomErrors, resetForm, formIsValid, submitDisabled } = useFormControl(fieldsInitialState);
|
|
117
|
+
|
|
118
|
+
const submitForm = async () => {
|
|
119
|
+
await getErrorCount(true);
|
|
120
|
+
|
|
121
|
+
if (formIsValid.value) {
|
|
122
|
+
formData.value.isPending = true;
|
|
123
|
+
console.log('Form is good - post it!');
|
|
124
|
+
// await useSleep(2000);
|
|
125
|
+
// formData.value.isPending = false;
|
|
126
|
+
} else {
|
|
127
|
+
console.warn('Form has errors');
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
</script>
|
|
131
|
+
|
|
132
|
+
<style lang="css">
|
|
133
|
+
p {
|
|
134
|
+
color: initial;
|
|
135
|
+
}
|
|
136
|
+
</style>
|
package/pages/index.vue
CHANGED
|
@@ -3,53 +3,16 @@
|
|
|
3
3
|
<NuxtLayout name="default">
|
|
4
4
|
<template #layout-content>
|
|
5
5
|
<div>
|
|
6
|
-
<h1>Sample form page</h1>
|
|
6
|
+
<h1>Sample form page pages</h1>
|
|
7
7
|
|
|
8
|
-
<
|
|
9
|
-
<template #default>
|
|
10
|
-
<form @submit.prevent="isPending">
|
|
11
|
-
<p>Form content</p>
|
|
12
|
-
<FormField width="wide" :has-gutter="true">
|
|
13
|
-
<template #default>
|
|
14
|
-
<p>Input text</p>
|
|
15
|
-
<InputTextMaterial
|
|
16
|
-
id="username"
|
|
17
|
-
name="username"
|
|
18
|
-
type="text"
|
|
19
|
-
validation="username"
|
|
20
|
-
:required="true"
|
|
21
|
-
:c12="{
|
|
22
|
-
label: 'Choose Username',
|
|
23
|
-
placeholder: 'eg. YourUserName',
|
|
24
|
-
errorMessage: 'Please enter a valid username',
|
|
25
|
-
}"
|
|
26
|
-
v-model="formData"
|
|
27
|
-
/>
|
|
28
|
-
</template>
|
|
29
|
-
</FormField>
|
|
30
|
-
<input
|
|
31
|
-
type="submit"
|
|
32
|
-
@click.prevent="isPending"
|
|
33
|
-
value="Submit"
|
|
34
|
-
/>
|
|
35
|
-
</form>
|
|
36
|
-
</template>
|
|
37
|
-
</FormWrapper>
|
|
8
|
+
<p>Example test fields in default material UI</p>
|
|
38
9
|
</div>
|
|
39
|
-
<ClientOnly>
|
|
40
|
-
<p>Client only content</p>
|
|
41
|
-
<pre>
|
|
42
|
-
{{ formData }}
|
|
43
|
-
</pre>
|
|
44
|
-
</ClientOnly>
|
|
45
10
|
</template>
|
|
46
11
|
</NuxtLayout>
|
|
47
12
|
</div>
|
|
48
13
|
</template>
|
|
49
14
|
|
|
50
15
|
<script setup lang="ts">
|
|
51
|
-
import type { IFieldsInitialState, IOptionsConfig } from '@/types/types.forms';
|
|
52
|
-
|
|
53
16
|
definePageMeta({
|
|
54
17
|
layout: false,
|
|
55
18
|
});
|
|
@@ -61,37 +24,6 @@ useHead({
|
|
|
61
24
|
class: '',
|
|
62
25
|
},
|
|
63
26
|
});
|
|
64
|
-
|
|
65
|
-
/*
|
|
66
|
-
* Setup forms
|
|
67
|
-
*/
|
|
68
|
-
const fieldsInitialState = ref<IFieldsInitialState>({
|
|
69
|
-
username: '',
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
// Setup formData
|
|
73
|
-
const {
|
|
74
|
-
formData,
|
|
75
|
-
initFormData,
|
|
76
|
-
getErrorCount,
|
|
77
|
-
updateCustomErrors,
|
|
78
|
-
resetForm,
|
|
79
|
-
formIsValid,
|
|
80
|
-
showErrors,
|
|
81
|
-
} = useFormControl(fieldsInitialState);
|
|
82
|
-
|
|
83
|
-
await initFormData();
|
|
84
|
-
|
|
85
|
-
const isPending = async () => {
|
|
86
|
-
formData.value.isPending = true;
|
|
87
|
-
await getErrorCount();
|
|
88
|
-
|
|
89
|
-
if (formIsValid.value) {
|
|
90
|
-
console.log('Form is good - post it!');
|
|
91
|
-
} else {
|
|
92
|
-
console.warn('Form has errors');
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
27
|
</script>
|
|
96
28
|
|
|
97
29
|
<style lang="css">
|
package/types/types.forms.ts
CHANGED
|
@@ -17,14 +17,7 @@ export interface IOptionsValueArr {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export interface IFieldsInitialState {
|
|
20
|
-
[key: string]:
|
|
21
|
-
| null
|
|
22
|
-
| string
|
|
23
|
-
| boolean
|
|
24
|
-
| number
|
|
25
|
-
| URL
|
|
26
|
-
| object
|
|
27
|
-
| IOptionsValueArr[];
|
|
20
|
+
[key: string]: null | string | boolean | number | URL | object | IOptionsValueArr[];
|
|
28
21
|
}
|
|
29
22
|
|
|
30
23
|
export interface IValidityState {
|
|
@@ -57,7 +50,7 @@ export interface IValidityStateArr {
|
|
|
57
50
|
};
|
|
58
51
|
}
|
|
59
52
|
|
|
60
|
-
export interface
|
|
53
|
+
export interface IFormFieldsState {
|
|
61
54
|
[key: string]: boolean;
|
|
62
55
|
}
|
|
63
56
|
|
|
@@ -79,11 +72,13 @@ export interface ICustomErrorMessagesArr {
|
|
|
79
72
|
export interface IFormData {
|
|
80
73
|
[x: string]: string | boolean | number | URL | object;
|
|
81
74
|
data: IFieldsInitialState;
|
|
82
|
-
validityState:
|
|
75
|
+
validityState: IFormFieldsState;
|
|
76
|
+
dirtyFields: IFormFieldsState;
|
|
77
|
+
focusedField: string;
|
|
83
78
|
isPending: boolean;
|
|
84
79
|
errorCount: number;
|
|
85
80
|
customErrorMessages: ICustomErrorMessagesArr;
|
|
86
81
|
formIsValid: boolean;
|
|
87
|
-
showErrors: boolean;
|
|
88
82
|
submitSuccess: boolean;
|
|
83
|
+
submitDisabled: boolean;
|
|
89
84
|
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div>
|
|
3
|
-
<input type="text" class="input-text" v-model="formValue" />
|
|
4
|
-
</div>
|
|
5
|
-
</template>
|
|
6
|
-
<script setup lang="ts">
|
|
7
|
-
console.log('InputText component loaded')
|
|
8
|
-
|
|
9
|
-
const formValue = ref('')
|
|
10
|
-
|
|
11
|
-
watchEffect(() => {
|
|
12
|
-
console.log('Form value changed to: ', formValue.value)
|
|
13
|
-
})
|
|
14
|
-
</script>
|
|
15
|
-
|
|
16
|
-
<style lang="css">
|
|
17
|
-
.input-text {
|
|
18
|
-
border: var(--input-border-width-thin) solid var(--input-border);
|
|
19
|
-
border-radius: var(--input-border-radius);
|
|
20
|
-
padding: 10px;
|
|
21
|
-
}
|
|
22
|
-
</style>
|