From 5719ffdeb48894c36467e071db6ee8f7fa4d9ebc Mon Sep 17 00:00:00 2001
From: Hubbe <57641199+HubbeDev@users.noreply.github.com>
Date: Sun, 7 Jan 2024 02:39:14 +0100
Subject: [PATCH] feat: add textarea & email support (#6)
* Move form field to a seperate comp & started to work on textarea
* More textarea work & default confirmation text
* Fix linting
---
.../src/lib/components/field/field.svelte | 71 +++++++++++++++++
.../src/lib/components/field/index.ts | 38 ++++++++++
.../src/lib/components/form/index.ts | 16 ++--
.../src/lib/components/index.ts | 2 +-
.../src/lib/components/input/input.svelte | 8 ++
.../src/lib/components/root.svelte | 64 +++++++---------
.../src/lib/components/textarea/index.ts | 13 ++++
.../lib/components/textarea/textarea.svelte | 29 +++++++
.../components/validation/validation.svelte | 2 +-
.../src/lib/internal/gf.ts | 76 +++++++++++++++++--
.../src/lib/internal/types.ts | 17 ++++-
11 files changed, 280 insertions(+), 56 deletions(-)
create mode 100644 apps/svelte-gravity-forms/src/lib/components/field/field.svelte
create mode 100644 apps/svelte-gravity-forms/src/lib/components/field/index.ts
create mode 100644 apps/svelte-gravity-forms/src/lib/components/textarea/index.ts
create mode 100644 apps/svelte-gravity-forms/src/lib/components/textarea/textarea.svelte
diff --git a/apps/svelte-gravity-forms/src/lib/components/field/field.svelte b/apps/svelte-gravity-forms/src/lib/components/field/field.svelte
new file mode 100644
index 0000000..02cb814
--- /dev/null
+++ b/apps/svelte-gravity-forms/src/lib/components/field/field.svelte
@@ -0,0 +1,71 @@
+
+
+
+
+
+ {#if label && showFieldLabel(labelPosition, 'above')}
+
+ {label}
+ {#if isRequired}
+ {#if $formRequiredIndicator == 'asterisk'}
+ *
+ {:else if $formRequiredIndicator == 'text'}
+ (required)
+ {/if}
+ {/if}
+
+ {/if}
+
+ {#if description && showDescription(descriptionPosition, 'above')}
+ {description}
+ {/if}
+
+ {#if type === 'text'}
+
+ {:else if type === 'email'}
+
+ {:else if type === 'textarea'}
+
+ {/if}
+
+ {#if description && showDescription(descriptionPosition, 'below')}
+ {description}
+ {/if}
+
+
+
+
+
diff --git a/apps/svelte-gravity-forms/src/lib/components/field/index.ts b/apps/svelte-gravity-forms/src/lib/components/field/index.ts
new file mode 100644
index 0000000..4a3a4e0
--- /dev/null
+++ b/apps/svelte-gravity-forms/src/lib/components/field/index.ts
@@ -0,0 +1,38 @@
+import Root from './field.svelte';
+import type { HTMLInputAttributes } from 'svelte/elements';
+import type { InputEvents } from '../input/index.js';
+import type { SuperForm } from 'sveltekit-superforms/client';
+import type { ZodValidation } from 'sveltekit-superforms';
+import type { AnyZodObject } from 'zod';
+
+export type Form = {
+ schema: T;
+ form: SuperForm;
+};
+
+export type Arrayable = T | T[];
+
+export type FormValidation = ZodValidation;
+
+type Props = HTMLInputAttributes & {
+ fieldId: number;
+ config: Form;
+ label?: string;
+ labelPosition?: string;
+ description?: string;
+ descriptionPosition?: string;
+ isRequired?: boolean;
+ defaultValue?: string;
+ columnSpan?: number;
+ placeholder?: string;
+ index?: number;
+ type?: string;
+};
+
+export {
+ Root,
+ type Props,
+ type InputEvents,
+ //
+ Root as FormField
+};
diff --git a/apps/svelte-gravity-forms/src/lib/components/form/index.ts b/apps/svelte-gravity-forms/src/lib/components/form/index.ts
index 6c6be64..20ab64d 100644
--- a/apps/svelte-gravity-forms/src/lib/components/form/index.ts
+++ b/apps/svelte-gravity-forms/src/lib/components/form/index.ts
@@ -1,13 +1,13 @@
-import { Form as FormPrimitive, getFormField } from 'formsnap';
+import { Form as FormPrimitive } from 'formsnap';
import * as RadioGroupComp from '$lib/components/ui/radio-group/index.js';
import * as SelectComp from '$lib/components/ui/select/index.js';
-import type { Writable } from 'svelte/store';
import { Item } from '$components/item/index.js';
import { Input } from '$components/input/index.js';
+import { Textarea } from '$components/textarea/index.js';
import { Description } from '$components/description/index.js';
import { Label } from '$components/label/index.js';
import { Validation } from '$components/validation/index.js';
-
+import { FormField } from '$components/field/index.js';
import { Button } from '$components/button/index.js';
const Root = FormPrimitive.Root;
@@ -21,10 +21,6 @@ const SelectGroup = SelectComp.Group;
const SelectItem = SelectComp.Item;
const SelectSeparator = SelectComp.Separator;
-export type TextareaGetFormField = Omit, 'value'> & {
- value: Writable;
-};
-
export type Props = {
formId?: number;
};
@@ -32,9 +28,11 @@ export type Props = {
export {
Root,
Field,
+ FormField,
Control,
Item,
Input,
+ Textarea,
Label,
Button,
Validation,
@@ -48,10 +46,12 @@ export {
NativeRadio,
//
Root as Form,
- Field as FormField,
+ Field as BitsField,
+ FormField as GFFormField,
Control as FormControl,
Item as FormItem,
Input as FormInput,
+ Textarea as FormTextarea,
Description as FormDescription,
Label as FormLabel,
Validation as FormValidation,
diff --git a/apps/svelte-gravity-forms/src/lib/components/index.ts b/apps/svelte-gravity-forms/src/lib/components/index.ts
index 921427e..95a96bf 100644
--- a/apps/svelte-gravity-forms/src/lib/components/index.ts
+++ b/apps/svelte-gravity-forms/src/lib/components/index.ts
@@ -1,3 +1,3 @@
import { default as GFButton } from './button/button.svelte';
-export { GFForm, GFButton };
+export { GFButton };
diff --git a/apps/svelte-gravity-forms/src/lib/components/input/input.svelte b/apps/svelte-gravity-forms/src/lib/components/input/input.svelte
index 19f8017..7b61599 100644
--- a/apps/svelte-gravity-forms/src/lib/components/input/input.svelte
+++ b/apps/svelte-gravity-forms/src/lib/components/input/input.svelte
@@ -10,10 +10,18 @@
/* const { attrStore, value } = getFormField(); */
const { attrStore, value } = getFormField();
let className: $$Props['class'] = undefined;
+ export let type: $$Props['type'] = 'text';
+
export { className as class };
+
+ function typeAction(node: HTMLInputElement) {
+ if (!type) return;
+ node.type = type;
+ }
- {#if $formFields}
- {#each $formFields as field, i}
-
-
-
- {#if field.label && showFieldLabel(field.labelPlacement, 'above')}
-
- {field.label}
- {#if field.isRequired}
- {#if $formRequiredIndicator == 'asterisk'}
- *
- {:else if $formRequiredIndicator == 'text'}
- (required)
- {/if}
- {/if}
-
- {#if field.description && field.descriptionPlacement == 'above'}
- {field.description}
- {/if}
-
- {#if field.label && showFieldLabel(field.labelPlacement, 'below')}
- {field.description}
- {/if}
- {/if}
-
-
-
-
- {/each}
+ {#if $isSubmitted}
+
+ {@html $defaultConfirmation.message}
+
+ {:else}
+ {#if $formFields}
+ {#each $formFields as field, i}
+
+ {/each}
+ {/if}
+
{/if}
-
{/if}
diff --git a/apps/svelte-gravity-forms/src/lib/components/textarea/index.ts b/apps/svelte-gravity-forms/src/lib/components/textarea/index.ts
new file mode 100644
index 0000000..13a6f86
--- /dev/null
+++ b/apps/svelte-gravity-forms/src/lib/components/textarea/index.ts
@@ -0,0 +1,13 @@
+import Root from './textarea.svelte';
+import { getFormField } from 'formsnap';
+import type { Writable } from 'svelte/store';
+
+export type TextareaGetFormField = Omit, 'value'> & {
+ value: Writable;
+};
+
+export {
+ Root,
+ //
+ Root as Textarea
+};
diff --git a/apps/svelte-gravity-forms/src/lib/components/textarea/textarea.svelte b/apps/svelte-gravity-forms/src/lib/components/textarea/textarea.svelte
new file mode 100644
index 0000000..a88419c
--- /dev/null
+++ b/apps/svelte-gravity-forms/src/lib/components/textarea/textarea.svelte
@@ -0,0 +1,29 @@
+
+
+
diff --git a/apps/svelte-gravity-forms/src/lib/components/validation/validation.svelte b/apps/svelte-gravity-forms/src/lib/components/validation/validation.svelte
index 28d26a6..141bf04 100644
--- a/apps/svelte-gravity-forms/src/lib/components/validation/validation.svelte
+++ b/apps/svelte-gravity-forms/src/lib/components/validation/validation.svelte
@@ -9,6 +9,6 @@
diff --git a/apps/svelte-gravity-forms/src/lib/internal/gf.ts b/apps/svelte-gravity-forms/src/lib/internal/gf.ts
index 96f63f7..aee4f74 100644
--- a/apps/svelte-gravity-forms/src/lib/internal/gf.ts
+++ b/apps/svelte-gravity-forms/src/lib/internal/gf.ts
@@ -4,7 +4,12 @@ import { PUBLIC_GF_API_URL } from '$env/static/public';
import { z, type AnyZodObject } from 'zod';
import { effect, omit, removeUndefined, toWritableStores } from '$lib/internal/helpers/index.js';
-import type { GFButtonProps, GFFieldsProps, GFFormObjectProps } from './types.js';
+import type {
+ GFButtonProps,
+ GFComfirmationProps,
+ GFFieldsProps,
+ GFFormObjectProps
+} from './types.js';
import type { HTMLAttributes } from 'svelte/elements';
export type CreateGravityFromsProps = {
@@ -35,6 +40,8 @@ export function createSvelteGravityFroms(props: CreateGravityFromsProps) {
const formSchema = writable();
const formRequiredIndicator = writable(undefined);
const formSubmtiButton = writable(undefined);
+ const defaultConfirmation = writable(undefined);
+ const isSubmitted = writable(false);
// Fetch form object from Gravity Forms API
async function getFormObject(formId: number) {
@@ -45,7 +52,7 @@ export function createSvelteGravityFroms(props: CreateGravityFromsProps) {
// Handle form submission
async function onSubmitForm(_formData: unknown) {
- //console.log('onSubmitForm', formData);
+ isSubmitted.set(true);
}
// Calculate column span for a field
@@ -104,7 +111,7 @@ export function createSvelteGravityFroms(props: CreateGravityFromsProps) {
return 'col-span-12';
}
- // Determine whether to show field label
+ // Determines whether to show the field label based on the field label placement.
function showFieldLabel(fieldLabelPlacement: string | undefined, position = 'above') {
const formData = get(formObject);
@@ -129,6 +136,24 @@ export function createSvelteGravityFroms(props: CreateGravityFromsProps) {
return fieldLabelPlacement === position;
}
+ /**
+ * Determines whether to show the description based on the field description placement.
+ */
+ function showDescription(
+ fieldDescriptionPlacement: string | undefined,
+ position = 'above'
+ ): boolean {
+ const formData = get(formObject);
+ const defaultPlacement = formData?.descriptionPlacement;
+
+ // Use the default placement if fieldDescriptionPlacement is an empty string
+ fieldDescriptionPlacement =
+ fieldDescriptionPlacement === '' ? defaultPlacement : fieldDescriptionPlacement;
+
+ // Return true if the field description placement matches the position
+ return fieldDescriptionPlacement === position;
+ }
+
// Fetch and set form object on mount
onMount(async () => {
if (!get(formIdStore)) {
@@ -150,15 +175,51 @@ export function createSvelteGravityFroms(props: CreateGravityFromsProps) {
}
});
+ /**
+ * set default confirmation on mount if exists in form object data
+ */
+ effect([formObject], ([$formObject]) => {
+ if ($formObject) {
+ if (!$formObject.confirmations) {
+ return;
+ }
+
+ // find default confirmation by isDefault key
+ const defaultConfirmationObject = Object.values($formObject.confirmations).find(
+ (confirmation) => confirmation.isDefault
+ );
+
+ if (!defaultConfirmationObject) {
+ return;
+ }
+
+ defaultConfirmation.set(defaultConfirmationObject);
+ }
+ });
+
// Set form schema
effect([formFields], ([$formFields]) => {
if (!$formFields) {
return;
}
+
const fieldsForSchema = $formFields.map((field) => {
const name = `input_${field.id}`;
- let fieldType = z.string();
+ let fieldType;
+
+ switch (field.type) {
+ case 'text':
+ fieldType = z.string();
+ break;
+ case 'textarea':
+ fieldType = z.string();
+ break;
+ default:
+ fieldType = z.string();
+ break;
+ }
+
if (field.isRequired) {
fieldType = fieldType.min(1, `${field.label} is required`);
}
@@ -210,7 +271,9 @@ export function createSvelteGravityFroms(props: CreateGravityFromsProps) {
formObject,
formFields,
formRequiredIndicator,
- formSubmtiButton
+ formSubmtiButton,
+ isSubmitted,
+ defaultConfirmation
},
methods: {
onSubmitForm
@@ -218,7 +281,8 @@ export function createSvelteGravityFroms(props: CreateGravityFromsProps) {
helpers: {
getColumnSpan,
showFieldLabel,
- getButtonWidth
+ getButtonWidth,
+ showDescription
},
refs: {
formRef,
diff --git a/apps/svelte-gravity-forms/src/lib/internal/types.ts b/apps/svelte-gravity-forms/src/lib/internal/types.ts
index 0a53b1d..aab7514 100644
--- a/apps/svelte-gravity-forms/src/lib/internal/types.ts
+++ b/apps/svelte-gravity-forms/src/lib/internal/types.ts
@@ -1,6 +1,6 @@
export type GFFieldsProps = {
type?: string;
- id?: number;
+ id: number;
formId?: number;
label?: string;
adminLabel?: string;
@@ -58,6 +58,18 @@ export type GFButtonProps = {
id?: string;
};
+type GFComfirmationProps = {
+ type?: string;
+ id?: string;
+ isDefault?: boolean;
+ message?: string;
+ name?: string;
+ disableAutoformat?: boolean;
+ pageId?: number;
+ url?: string;
+ queryString?: string;
+};
+
/**
* @todo: fix any types in this file
*/
@@ -75,11 +87,12 @@ export type GFFormObjectProps = {
fields?: GFFieldsProps[];
button?: GFButtonProps;
notifications?: unknown[];
- confirmations?: unknown[];
+ confirmations?: GFComfirmationProps[];
confirmation?: unknown[];
save?: unknown[];
personalData?: unknown[];
pagination?: unknown[];
lastPageButton?: unknown[];
nextFieldId?: number;
+ descriptionPlacement?: string;
};