Skip to content

Commit

Permalink
feat: Number input & form improvments (#10)
Browse files Browse the repository at this point in the history
- WIP: number input.
- Rearrange form setup
- All around work on form components
  • Loading branch information
HubbeDev authored Jan 14, 2024
2 parents 3527763 + d2d2861 commit 389a030
Show file tree
Hide file tree
Showing 19 changed files with 266 additions and 130 deletions.
5 changes: 5 additions & 0 deletions apps/svelte-gravity-forms/src/app.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,8 @@
@apply bg-background text-foreground;
}
}
@layer components {
.super-debug--code {
width: 500px;
}
}
23 changes: 16 additions & 7 deletions apps/svelte-gravity-forms/src/lib/components/field/field.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
{#if field}
<div
data-svelte-gf-field-id={index}
data-svelte-gf-field-type={field.type}
class={field.layoutGridColumnSpan ? getColumnSpan(field.layoutGridColumnSpan) : ''}
>
<GFform.Field {config} name={`input_${field.id}`}>
Expand All @@ -42,15 +43,18 @@
{/if}

{#if field.type === 'text'}
<GFform.Input
value={field.defaultValue ?? undefined}
placeholder={field.placeholder ?? ''}
/>
<GFform.Input />
{:else if field.type === 'email'}
<GFform.Input
type="email"
value={field.defaultValue ?? undefined}
value={field.defaultValue == '' ? null : field.defaultValue}
placeholder={field.placeholder ?? ''}
/>
{:else if field.type === 'number'}
<GFform.NumberInput
value={field.defaultValue == '' ? undefined : field.defaultValue}
placeholder={field.placeholder ?? ''}
numberFormat={field.numberFormat}
/>
{:else if field.type === 'textarea'}
<GFform.Textarea
Expand All @@ -62,19 +66,24 @@
{#if field.enableEnhancedUI}
<GFform.Select choices={field.choices} placeholder={field.placeholder} />
{:else}
<GFform.FormNativeSelect class="w-full">
<GFform.NativeSelect>
<option value="">{field.placeholder}</option>
{#each field.choices as choice}
<option value={choice.value}>{choice.text}</option>
{/each}
</GFform.FormNativeSelect>
</GFform.NativeSelect>
{/if}
{/if}
{/if}

{#if field.description && showDescription(field.descriptionPlacement, 'below')}
<GFform.Description>{field.description}</GFform.Description>
{/if}
{#if field.type === 'number'}
<GFform.Description>
Please enter a number from {field.rangeMin} to {field.rangeMax}.
</GFform.Description>
{/if}

<GFform.Validation />
</GFform.Item>
Expand Down
10 changes: 0 additions & 10 deletions apps/svelte-gravity-forms/src/lib/components/field/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,9 @@ export type Arrayable<T> = T | T[];
export type FormValidation = ZodValidation<AnyZodObject>;

type Props = HTMLInputAttributes & {
/* fieldId: number; */
config: Form<FormValidation>;
field?: GFFieldProps;
/* label?: string;
labelPosition?: string;
description?: string;
descriptionPosition?: string;
isRequired?: boolean;
defaultValue?: string;
columnSpan?: number;
placeholder?: string; */
index?: number;
/* type?: string; */
};

export {
Expand Down
17 changes: 3 additions & 14 deletions apps/svelte-gravity-forms/src/lib/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Form as FormPrimitive } from 'formsnap';
import * as SelectComp from '$lib/components/ui/select/index.js'; */
import { Item } from '$components/item/index.js';
import { Input } from '$components/input/index.js';
import { NumberInput } from '$components/number/index.js';
import { Textarea } from '$components/textarea/index.js';
import { Description } from '$components/description/index.js';
import { Label } from '$components/label/index.js';
Expand Down Expand Up @@ -36,19 +37,7 @@ export {
NativeRadio,
Select,
NativeSelect,
NumberInput,
//
Root as Form,
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,
NativeRadio as FormNativeRadio,
Button as FormButton,
Select as FormSelect,
NativeSelect as FormNativeSelect
Root as Form
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Root from './input.svelte';
type FormInputEvent<T extends Event = Event> = T & {
currentTarget: EventTarget & HTMLInputElement;
};

export type InputEvents = {
blur: FormInputEvent<FocusEvent>;
change: FormInputEvent<Event>;
Expand Down
15 changes: 10 additions & 5 deletions apps/svelte-gravity-forms/src/lib/components/input/input.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
import { getFormField } from 'formsnap';
import type { HTMLInputAttributes } from 'svelte/elements';
import { cn } from '$lib/utils.js';
import type { InputEvents } from './index.js';
type $$Props = HTMLInputAttributes;
type $$Events = InputEvents;
let className: $$Props['class'] = undefined;
const { attrStore, value } = getFormField();
const { attrStore, errors, actions, value } = getFormField();
$: attrs = {
'data-svelte-gf-input': '',
'data-svelte-gf-error': $errors ? '' : undefined,
...$attrStore
};
export { className as class };
</script>
Expand All @@ -19,9 +23,8 @@
'flex h-10 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
className
)}
{...$attrStore}
{...attrs}
bind:value={$value}
{...$$restProps}
on:blur
on:change
on:click
Expand All @@ -34,4 +37,6 @@
on:mouseleave
on:paste
on:input
use:actions.input
{...$$restProps}
/>
32 changes: 13 additions & 19 deletions apps/svelte-gravity-forms/src/lib/components/label/label.svelte
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
<script lang="ts">
import { Label as LabelPrimitive } from 'bits-ui';
import { getFormField } from 'formsnap';
import { cn } from '$lib/utils.js';
import { getFormField, type LabelProps } from 'formsnap';
type $$Props = LabelPrimitive.Props;
type $$Events = LabelPrimitive.Events;
let className: $$Props['class'] = undefined;
export { className as class };
const { errors } = getFormField();
$: className = $errors ? cn($errors && 'text-destructive', className) : className;
type $$Props = LabelProps;
const { actions, errors, ids } = getFormField();
$: attrs = {
'data-fs-label': '',
'data-fs-error': $errors ? '' : undefined,
for: $ids.input
};
</script>

<LabelPrimitive.Root
class={cn(
'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
className
)}
<label
class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
use:actions.label
{...$$restProps}
on:mousedown
{...attrs}
>
<slot />
</LabelPrimitive.Root>
</label>
10 changes: 10 additions & 0 deletions apps/svelte-gravity-forms/src/lib/components/number/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Root from './input.svelte';
import type { InputEvents } from '../input/index.js';

export {
Root,
//
Root as NumberInput,
//
type InputEvents
};
74 changes: 74 additions & 0 deletions apps/svelte-gravity-forms/src/lib/components/number/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<script lang="ts" context="module">
import type { HTMLInputAttributes } from 'svelte/elements';
import type { InputEvents } from './index.js';
import type { NumberFormats } from '$lib/internal/types.js';
</script>

<script lang="ts">
import { writable } from 'svelte/store';
import { getFormField } from 'formsnap';
import { cn } from '$lib/utils.js';
import { Input } from '../input/index.js';
type $$Props = HTMLInputAttributes & {
numberFormat?: NumberFormats;
};
type $$Events = InputEvents;
let className: $$Props['class'] = undefined;
export let numberFormat: $$Props['numberFormat'] = undefined;
const { attrStore, errors, value } = getFormField();
$: attrs = {
'data-svelte-gf-input': '',
'data-svelte-gf-error': $errors ? '' : undefined,
...$attrStore
};
export { className as class };
function handleKeyPress(e: KeyboardEvent) {
const charCode = e.which ? e.which : e.keyCode;
if (
charCode > 31 &&
(charCode < 48 || charCode > 57) &&
charCode !== 46 &&
!(numberFormat === 'decimal_comma' && charCode === 44) &&
!(numberFormat === 'decimal_dot' && charCode === 46)
) {
e.preventDefault();
}
}
let numericValue = writable<number | unknown>(undefined);
let inputValue = writable<string | number | unknown>($value);
$: {
if (!isNaN(Number($value)) && $value !== '') {
$numericValue = Number($value);
} else {
$numericValue = undefined; // allow the input to be empty
}
if ($numericValue !== undefined && $numericValue !== '') {
$value = $numericValue;
} else {
$value = undefined;
}
$inputValue =
$numericValue !== undefined && $numericValue !== '' ? Number($numericValue) : undefined;
}
</script>

<Input
class={cn(
'flex h-10 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
className
)}
{...attrs}
type="number"
step="1.00"
bind:value={$value}
on:keypress={handleKeyPress}
{...$$restProps}
/>
Loading

0 comments on commit 389a030

Please sign in to comment.