Skip to content

Commit

Permalink
feat: fixes input typings
Browse files Browse the repository at this point in the history
  • Loading branch information
aviemet committed Apr 2, 2024
1 parent c3f1e31 commit aad7860
Show file tree
Hide file tree
Showing 41 changed files with 329 additions and 475 deletions.
4 changes: 2 additions & 2 deletions app/frontend/Components/Flash/Flash.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { useEffect } from 'react'
import { usePage } from '@inertiajs/react'
import { showNotification } from '@mantine/notifications'
import { usePageProps } from '@/lib/hooks'

const Flash = () => {
const { flash } = usePage<SharedInertiaProps>().props
const { flash } = usePageProps()

useEffect(() => {
let key: keyof FlashMessage
Expand Down
13 changes: 3 additions & 10 deletions app/frontend/Components/Form/Form.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,17 @@
import React from 'react'
import { Box } from '@mantine/core'
import cx from 'clsx'
import { Form as InertiaForm, type FormProps, type NestedObject } from 'use-inertia-form'
import { Form as InertiaForm, type FormProps as FormProps, type NestedObject } from 'use-inertia-form'
import * as classes from './Form.css'


interface IFormProps<TForm> extends FormProps<TForm> {
grid?: boolean
}

export interface ExtendableFormProps<TForm> extends Omit<IFormProps<TForm>, 'data'> {}

const Form = <TForm extends NestedObject>(
{ children, data, grid = true, className, railsAttributes = true, ...props }: IFormProps<TForm>,
{ children, data, className, railsAttributes = true, ...props }: FormProps<TForm>,
) => {
return (
<Box className={ cx('form') }>
<InertiaForm
data={ data }
className={ cx({ 'format-grid': grid }, classes.form, className) }
className={ cx(classes.form, className) }
railsAttributes={ railsAttributes }
{ ...props }
>
Expand Down
21 changes: 12 additions & 9 deletions app/frontend/Components/Form/Inputs/Checkbox.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import React, { forwardRef } from 'react'
import Field from '../Field'
import CheckboxInput, { type ICheckboxProps } from '@/Components/Inputs/Checkbox'
import CheckboxInput, { type CheckboxProps } from '@/Components/Inputs/Checkbox'
import { useInertiaInput } from 'use-inertia-form'
import ConditionalWrapper from '@/Components/ConditionalWrapper'
import { type BaseFormInputProps, type InputConflicts } from '.'

interface IFormCheckboxProps extends Omit<ICheckboxProps, 'name'|'onBlur'|'onChange'|'defaultChecked'>, IInertiaInputProps {
field?: boolean
}
interface FormCheckboxProps
extends
Omit<CheckboxProps, InputConflicts>,
Omit<BaseFormInputProps<boolean>, 'onFocus'> {}

const FormCheckboxComponent = forwardRef<HTMLInputElement, IFormCheckboxProps>((
const FormCheckboxComponent = forwardRef<HTMLInputElement, FormCheckboxProps>((
{
name,
onChange,
Expand All @@ -18,19 +20,20 @@ const FormCheckboxComponent = forwardRef<HTMLInputElement, IFormCheckboxProps>((
className,
model,
field = true,
...props
...props
},
ref,
) => {
const { form, inputName, inputId, value, setValue, error } = useInertiaInput<boolean>({ name, model })

const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setValue(e.target.checked)
if(onChange) onChange(e, form)
const checked = e.target.checked
setValue(checked)
onChange?.(checked, form)
}

const handleBlur = () => {
if(onBlur) onBlur(value, form)
onBlur?.(value, form)
}

return (
Expand Down
15 changes: 6 additions & 9 deletions app/frontend/Components/Form/Inputs/CurrencyInput.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
import React, { forwardRef } from 'react'
import CurrencyInput, { type ICurrencyInputProps } from '@/Components/Inputs/CurrencyInput'
import CurrencyInput, { type CurrencyInputProps } from '@/Components/Inputs/CurrencyInput'
import Field from '../Field'
import cx from 'clsx'
import { useInertiaInput } from 'use-inertia-form'
import ConditionalWrapper from '@/Components/ConditionalWrapper'
import { type BaseFormInputProps, type InputConflicts } from '.'

interface INumberInputProps extends Omit<ICurrencyInputProps, 'name'|'onChange'|'onBlur'>, IInertiaInputProps {
field?: boolean
}
interface INumberInputProps extends Omit<CurrencyInputProps, InputConflicts>, BaseFormInputProps {}

const FormInput = forwardRef<HTMLInputElement, INumberInputProps>((
{
name,
model,
onChange,
onBlur,
onFocus,
id,
required,
compact = false,
field = true,
...props
},
Expand All @@ -41,25 +39,24 @@ const FormInput = forwardRef<HTMLInputElement, INumberInputProps>((

return (
<ConditionalWrapper
condition={ props.hidden !== true && field }
wrapper={ children => (
<Field
type="text"
required={ required }
className={ cx({ compact }) }
errors={ !!error }
>
{ children }
</Field>
) }
condition={ field }
>
<CurrencyInput
id={ id || inputId }
className={ cx({ compact }) }
name={ inputName }
value={ value }
onChange={ handleChange }
onBlur={ handleBlur }
onFocus={ e => onFocus?.(e.target.value, form) }
error={ error }
ref={ ref }
{ ...props }
Expand Down
26 changes: 20 additions & 6 deletions app/frontend/Components/Form/Inputs/DateTime.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
import React from 'react'
import Field from '../Field'
import DateTimeInput, { type IDateTimeProps } from '@/Components/Inputs/DateTime'
import { useInertiaInput } from 'use-inertia-form'
import DateTimeInput, { type DateTimeInputProps } from '@/Components/Inputs/DateTime'
import { UseFormProps, useInertiaInput } from 'use-inertia-form'
import ConditionalWrapper from '@/Components/ConditionalWrapper'
import { type BaseFormInputProps, type InputConflicts } from '.'

interface IDateTimeFormProps extends Omit<IDateTimeProps, 'name'|'onChange'|'onBlur'>, IInertiaInputProps {
field?: boolean
interface IDateTimeFormProps
extends
Omit<DateTimeInputProps, InputConflicts>,
Omit<BaseFormInputProps, InputConflicts> {

name: string
onChange: (date: Date, form: UseFormProps) => void
onBlur: (date: Date, form: UseFormProps) => void
onFocus: (date: Date, form: UseFormProps) => void
}

const DateTime = ({
name,
required,
onChange,
onBlur,
onFocus,
id,
model,
field = true,
Expand All @@ -23,11 +32,15 @@ const DateTime = ({
const handleChange = (date: Date) => {
setValue(date)

if(onChange) onChange(date, form)
onChange?.(date, form)
}

const handleBlur = () => {
if(onBlur) onBlur(value, form)
onBlur?.(value, form)
}

const handleFocus = () => {
onFocus?.(value, form)
}

return (
Expand All @@ -49,6 +62,7 @@ const DateTime = ({
value={ value }
onChange={ handleChange }
onBlur={ handleBlur }
onFocus={ handleFocus }
required={ required }
error={ error }
{ ...props }
Expand Down
13 changes: 7 additions & 6 deletions app/frontend/Components/Form/Inputs/HiddenInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import React, { forwardRef } from 'react'
import { HiddenInput } from '@/Components/Inputs'
import { useInertiaInput } from 'use-inertia-form'
import { InputProps } from 'react-html-props'
import { type BaseFormInputProps, type InputConflicts } from '.'

interface ITextInputProps extends Omit<InputProps, 'name'|'ref'|'onBlur'|'onChange'>, IInertiaInputProps {
name: string
model?: string
}
interface FormHiddenInputProps
extends
Omit<InputProps, InputConflicts>,
Omit<BaseFormInputProps, 'onFocus'|'onBlur'> {}

const FormInput = forwardRef<HTMLInputElement, ITextInputProps>((
{ name, model, onChange, onBlur, id, ...props },
const FormInput = forwardRef<HTMLInputElement, FormHiddenInputProps>((
{ name, model, onChange, id, ...props },
ref,
) => {
const { form, inputName, inputId, value, setValue } = useInertiaInput({ name, model })
Expand Down
38 changes: 22 additions & 16 deletions app/frontend/Components/Form/Inputs/MultiSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
import React from 'react'
import { NestedObject, UseFormProps, useInertiaInput } from 'use-inertia-form'
import { IFormInputProps } from '.'
import { ConditionalWrapper } from '@/Components'
import Field from '../Field'
import MultiSelect, { type IMultiSelectProps } from '@/Components/Inputs/MultiSelect'
import MultiSelect, { type MultiSelectProps } from '@/Components/Inputs/MultiSelect'
import { type ComboboxData } from '@mantine/core'
import { type BaseFormInputProps } from '.'

type OmittedDropdownTypes = 'name'|'onBlur'|'onChange'|'onDropdownOpen'|'onDropdownClose'
export interface IFormDropdownProps<TForm extends NestedObject = NestedObject>
extends Omit<IMultiSelectProps, OmittedDropdownTypes>,
IFormInputProps<string[], TForm> {
onDropdownOpen?: (form: UseFormProps<any>) => void
onDropdownClose?: (form: UseFormProps<any>) => void
type OmittedOverwrittenTypes = 'onFocus'|'onBlur'|'onChange'|'onClear'|'onDropdownOpen'|'onDropdownClose'|'onOptionSubmit'
export interface FormMultiSelectProps<TForm extends NestedObject = NestedObject>
extends Omit<MultiSelectProps, OmittedOverwrittenTypes|'name'>,
Omit<BaseFormInputProps, OmittedOverwrittenTypes> {

onChange?: (values: string[], options: ComboboxData, form: UseFormProps<TForm>) => void
onBlur?: (values: string[], options: ComboboxData, form: UseFormProps<TForm>) => void
onFocus?: (values: string[], options: ComboboxData, form: UseFormProps<TForm>) => void
onClear?: (options: ComboboxData, form: UseFormProps<TForm>) => void
onDropdownOpen?: (options: ComboboxData, form: UseFormProps<TForm>) => void
onDropdownClose?: (options: ComboboxData, form: UseFormProps<TForm>) => void
onOptionSubmit?: (values: string[], options: ComboboxData, form: UseFormProps<TForm>) => void
}

const MultiSelectComponent = <TForm extends NestedObject = NestedObject>(
{
name,
options = [],
label,
required,
id,
name,
errorKey,
model,
field = true,
Expand All @@ -28,30 +35,31 @@ const MultiSelectComponent = <TForm extends NestedObject = NestedObject>(
onDropdownOpen,
onDropdownClose,
...props
}: IFormDropdownProps<TForm>,
}: FormMultiSelectProps<TForm>,
) => {
const { form, inputName, inputId, value, setValue, error } = useInertiaInput<string[], TForm>({ name, model, errorKey })

const handleBlur = () => {
if(onBlur) onBlur(value, form)
onBlur?.(value, options || [], form)
}

const handleChange = (values: string[]) => {
setValue(values)

onChange?.(values, form)
onChange?.(values, options || [], form)
}

const handleDropdownOpen = () => {
if(onDropdownOpen) onDropdownOpen(form)
onDropdownOpen?.(options || [],form)
}

const handleDropdownClose = () => {
if(onDropdownClose) onDropdownClose(form)
onDropdownClose?.(options || [],form)
}

return (
<ConditionalWrapper
condition={ props.hidden !== true && field }
wrapper={ children => (
<Field
type="select"
Expand All @@ -61,7 +69,6 @@ const MultiSelectComponent = <TForm extends NestedObject = NestedObject>(
{ children }
</Field>
) }
condition={ field }
>
<MultiSelect
// Add "search" suffix to prevent password managers trying to autofill dropdowns
Expand All @@ -76,7 +83,6 @@ const MultiSelectComponent = <TForm extends NestedObject = NestedObject>(
onChange={ handleChange }
onDropdownClose={ handleDropdownClose }
onDropdownOpen={ handleDropdownOpen }
wrapper={ false }
{ ...props }
/>
</ConditionalWrapper>
Expand Down
32 changes: 12 additions & 20 deletions app/frontend/Components/Form/Inputs/NumberInput.tsx
Original file line number Diff line number Diff line change
@@ -1,62 +1,54 @@
import React, { forwardRef } from 'react'
import NumberInput, { type INumberInputProps } from '@/Components/Inputs/NumberInput'
import NumberInput, { type NumberInputProps } from '@/Components/Inputs/NumberInput'
import Field from '../Field'
import cx from 'clsx'
import { useInertiaInput } from 'use-inertia-form'
import ConditionalWrapper from '@/Components/ConditionalWrapper'
import { type BaseFormInputProps, type InputConflicts } from '.'

interface INumberFormInputProps extends Omit<INumberInputProps, 'onBlur'|'onChange'|'name'>, IInertiaInputProps {
field?: boolean
}
interface FormNumberInputProps extends Omit<NumberInputProps, InputConflicts>, BaseFormInputProps<number> {}

const FormInput = forwardRef<HTMLInputElement, INumberFormInputProps>((
const FormInput = forwardRef<HTMLInputElement, FormNumberInputProps>((
{
name,
model,
onChange,
onBlur,
onFocus,
id,
required,
compact = false,
field = true,
...props
},
ref,
) => {
const { form, inputName, inputId, value, setValue, error } = useInertiaInput({ name, model })
const { form, inputName, inputId, value, setValue, error } = useInertiaInput<number>({ name, model })

const handleChange = (e: number) => {
const v = e
setValue(v)
const handleChange = (val: string|number) => {
setValue(Number(val))

if(onChange) onChange(v, form)
}

const handleBlur = (e: React.FocusEvent<HTMLInputElement, Element>) => {
if(onBlur) onBlur(value as number, form)
onChange?.(Number(val), form)
}

return (
<ConditionalWrapper
condition={ props.hidden !== true && field }
wrapper={ children => (
<Field
type="number"
required={ required }
className={ cx({ compact }) }
errors={ !!error }
>
{ children }
</Field>
) }
condition={ field }
>
<NumberInput
id={ id || inputId }
className={ cx({ compact }) }
name={ inputName }
value={ value as number }
onChange={ handleChange }
onBlur={ handleBlur }
onBlur={ () => onBlur?.(value, form) }
onFocus={ () => onFocus?.(value, form) }
error={ error }
ref={ ref }
{ ...props }
Expand Down
Loading

0 comments on commit aad7860

Please sign in to comment.