-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
23 changed files
with
851 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
export default { | ||
extends: ['@commitlint/config-conventional'], | ||
rules: { | ||
'footer-max-length': [2, 'never'] | ||
'footer-max-length': [0] | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
<template> | ||
<form :id="id" :name="name" class="pdap-form" @submit.prevent="submit"> | ||
<slot v-if="$slots.error" name="error" /> | ||
<div | ||
v-else-if="typeof errorMessage === 'string'" | ||
class="pdap-form-error-message" | ||
> | ||
{{ errorMessage }} | ||
</div> | ||
|
||
<slot /> | ||
</form> | ||
</template> | ||
<script setup lang="ts"> | ||
// Globals | ||
import { provide, ref, watchEffect } from 'vue'; | ||
import { useVuelidate } from '@vuelidate/core'; | ||
// Types | ||
import { PdapFormPropsV2 } from './types'; | ||
import { provideKey, makeRules } from './util'; | ||
// Props | ||
const { defaultValues, error, schema } = withDefaults( | ||
defineProps<PdapFormPropsV2>(), | ||
{ | ||
error: null, | ||
} | ||
); | ||
// Emits | ||
const emit = defineEmits(['submit']); | ||
// Constants | ||
const errorMessage = ref(error); | ||
const values = ref(defaultValues ?? {}); | ||
const rules = makeRules(schema); | ||
const v$ = useVuelidate(rules, values, { $autoDirty: false, $lazy: true }); | ||
// Provide | ||
provide(provideKey, { | ||
setValues, | ||
values, | ||
rules, | ||
v$, | ||
}); | ||
// Expose | ||
defineExpose({ | ||
setValues, | ||
}); | ||
// Helpers | ||
function setValues(val: Partial<typeof values.value>) { | ||
values.value = { ...values.value, ...val }; | ||
} | ||
function resetForm() { | ||
v$.value.$reset(); | ||
values.value = Object.entries(values.value).reduce((acc, [key]) => { | ||
return { | ||
...acc, | ||
[key]: | ||
typeof values.value[key] === 'string' | ||
? '' | ||
: Boolean(defaultValues?.[key]), | ||
}; | ||
}, {}); | ||
} | ||
async function submit(e: Event) { | ||
// Check form submission | ||
const isValidSubmission = await v$.value.$validate(); | ||
if (isValidSubmission) { | ||
// Emit submit event (spread to new object to create new object, this allows us to reset `values` without messing with the data returned) | ||
emit('submit', { ...values.value }, e); | ||
resetForm(); | ||
} | ||
} | ||
// Effects | ||
// Effect - Updates form error state based on input error state and/or props | ||
watchEffect(() => { | ||
if (error) errorMessage.value = error; | ||
else if (errorMessage.value && v$.value.$errors.length === 0) | ||
errorMessage.value = null; | ||
else if (!errorMessage.value && v$.value.$errors.length > 0) | ||
errorMessage.value = 'Please update this form to correct the errors'; | ||
}); | ||
</script> | ||
|
||
<style> | ||
@tailwind components; | ||
@layer components { | ||
.pdap-form-error-message { | ||
@apply items-center justify-start basis-full flex-shrink flex bg-red-300 text-red-800 mb-3 p-2 text-sm; | ||
} | ||
} | ||
</style> |
139 changes: 139 additions & 0 deletions
139
src/components/FormV2/__snapshots__/formv2.spec.ts.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html | ||
|
||
exports[`PdapFormV2 > calls submit event with form values on valid submission 1`] = ` | ||
<form class="pdap-form" id="test" name="test"> | ||
<!--v-if--> | ||
<div class="pdap-input"> | ||
<!--v-if--> | ||
<input id="name" name="name" placeholder="Name" type="text"> | ||
<label for="name">Name</label> | ||
</div> | ||
<div class="pdap-input"> | ||
<!--v-if--> | ||
<input id="email" name="email" placeholder="Email" type="text"> | ||
<label for="email">Email</label> | ||
</div> | ||
<div class="pdap-input pdap-input-password"> | ||
<!--v-if--> | ||
<div class="pdap-input-password-wrapper"> | ||
<input id="password" name="password" placeholder="Password" type="password"> | ||
<button aria-label="Show text" class="pdap-input-password-toggle" type="button"> | ||
<svg aria-hidden="true" class="svg-inline--fa fa-eye" data-icon="eye" data-prefix="fas" focusable="false" role="img" viewBox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"> | ||
<path class="" d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM144 256a144 144 0 1 1 288 0 144 144 0 1 1 -288 0zm144-64c0 35.3-28.7 64-64 64c-7.1 0-13.9-1.2-20.3-3.3c-5.5-1.8-11.9 1.6-11.7 7.4c.3 6.9 1.3 13.8 3.2 20.7c13.7 51.2 66.4 81.6 117.6 67.9s81.6-66.4 67.9-117.6c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3z" fill="currentColor" /> | ||
</svg> | ||
</button> | ||
</div> | ||
<label for="password">Password</label> | ||
</div> | ||
<div class="pdap-input pdap-input-checkbox"> | ||
<!--v-if--> | ||
<input checked id="ice-cream" name="ice-cream" type="checkbox" value="true"> | ||
<label for="ice-cream">Ice Cream</label> | ||
</div> | ||
</form> | ||
`; | ||
exports[`PdapFormV2 > renders default error message when form has errors 1`] = ` | ||
<form class="pdap-form" id="test" name="test"> | ||
<div class="pdap-form-error-message">Please update this form to correct the errors</div> | ||
<div class="pdap-input pdap-input-error"> | ||
<div class="pdap-input-error-message">Value is required</div> | ||
<input id="name" name="name" placeholder="Name" type="text"> | ||
<label for="name">Name</label> | ||
</div> | ||
<div class="pdap-input pdap-input-error"> | ||
<div class="pdap-input-error-message">Value is required</div> | ||
<input id="email" name="email" placeholder="Email" type="text"> | ||
<label for="email">Email</label> | ||
</div> | ||
<div class="pdap-input pdap-input-password"> | ||
<!--v-if--> | ||
<div class="pdap-input-password-wrapper"> | ||
<input id="password" name="password" placeholder="Password" type="password"> | ||
<button aria-label="Show text" class="pdap-input-password-toggle" type="button"> | ||
<svg aria-hidden="true" class="svg-inline--fa fa-eye" data-icon="eye" data-prefix="fas" focusable="false" role="img" viewBox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"> | ||
<path class="" d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM144 256a144 144 0 1 1 288 0 144 144 0 1 1 -288 0zm144-64c0 35.3-28.7 64-64 64c-7.1 0-13.9-1.2-20.3-3.3c-5.5-1.8-11.9 1.6-11.7 7.4c.3 6.9 1.3 13.8 3.2 20.7c13.7 51.2 66.4 81.6 117.6 67.9s81.6-66.4 67.9-117.6c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3z" fill="currentColor" /> | ||
</svg> | ||
</button> | ||
</div> | ||
<label for="password">Password</label> | ||
</div> | ||
<div class="pdap-input pdap-input-checkbox"> | ||
<!--v-if--> | ||
<input id="ice-cream" name="ice-cream" type="checkbox" value="false"> | ||
<label for="ice-cream">Ice Cream</label> | ||
</div> | ||
</form> | ||
`; | ||
exports[`PdapFormV2 > renders error message slot when provided 1`] = ` | ||
<form class="pdap-form" id="test" name="test"> | ||
<div>Custom Error Message</div> | ||
</form> | ||
`; | ||
exports[`PdapFormV2 > renders error message when errorMessage prop is provided 1`] = ` | ||
<form class="pdap-form" id="test" name="test"> | ||
<div class="pdap-form-error-message">Form Error</div> | ||
<div class="pdap-input"> | ||
<!--v-if--> | ||
<input id="name" name="name" placeholder="Name" type="text"> | ||
<label for="name">Name</label> | ||
</div> | ||
<div class="pdap-input"> | ||
<!--v-if--> | ||
<input id="email" name="email" placeholder="Email" type="text"> | ||
<label for="email">Email</label> | ||
</div> | ||
<div class="pdap-input pdap-input-password"> | ||
<!--v-if--> | ||
<div class="pdap-input-password-wrapper"> | ||
<input id="password" name="password" placeholder="Password" type="password"> | ||
<button aria-label="Show text" class="pdap-input-password-toggle" type="button"> | ||
<svg aria-hidden="true" class="svg-inline--fa fa-eye" data-icon="eye" data-prefix="fas" focusable="false" role="img" viewBox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"> | ||
<path class="" d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM144 256a144 144 0 1 1 288 0 144 144 0 1 1 -288 0zm144-64c0 35.3-28.7 64-64 64c-7.1 0-13.9-1.2-20.3-3.3c-5.5-1.8-11.9 1.6-11.7 7.4c.3 6.9 1.3 13.8 3.2 20.7c13.7 51.2 66.4 81.6 117.6 67.9s81.6-66.4 67.9-117.6c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3z" fill="currentColor" /> | ||
</svg> | ||
</button> | ||
</div> | ||
<label for="password">Password</label> | ||
</div> | ||
<div class="pdap-input pdap-input-checkbox"> | ||
<!--v-if--> | ||
<input id="ice-cream" name="ice-cream" type="checkbox" value="false"> | ||
<label for="ice-cream">Ice Cream</label> | ||
</div> | ||
</form> | ||
`; | ||
exports[`PdapFormV2 > renders the form element 1`] = ` | ||
<form class="pdap-form" id="test" name="test"> | ||
<!--v-if--> | ||
<div class="pdap-input"> | ||
<!--v-if--> | ||
<input id="name" name="name" placeholder="Name" type="text"> | ||
<label for="name">Name</label> | ||
</div> | ||
<div class="pdap-input"> | ||
<!--v-if--> | ||
<input id="email" name="email" placeholder="Email" type="text"> | ||
<label for="email">Email</label> | ||
</div> | ||
<div class="pdap-input pdap-input-password"> | ||
<!--v-if--> | ||
<div class="pdap-input-password-wrapper"> | ||
<input id="password" name="password" placeholder="Password" type="password"> | ||
<button aria-label="Show text" class="pdap-input-password-toggle" type="button"> | ||
<svg aria-hidden="true" class="svg-inline--fa fa-eye" data-icon="eye" data-prefix="fas" focusable="false" role="img" viewBox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"> | ||
<path class="" d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM144 256a144 144 0 1 1 288 0 144 144 0 1 1 -288 0zm144-64c0 35.3-28.7 64-64 64c-7.1 0-13.9-1.2-20.3-3.3c-5.5-1.8-11.9 1.6-11.7 7.4c.3 6.9 1.3 13.8 3.2 20.7c13.7 51.2 66.4 81.6 117.6 67.9s81.6-66.4 67.9-117.6c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3z" fill="currentColor" /> | ||
</svg> | ||
</button> | ||
</div> | ||
<label for="password">Password</label> | ||
</div> | ||
<div class="pdap-input pdap-input-checkbox"> | ||
<!--v-if--> | ||
<input id="ice-cream" name="ice-cream" type="checkbox" value="false"> | ||
<label for="ice-cream">Ice Cream</label> | ||
</div> | ||
</form> | ||
`; |
Oops, something went wrong.