mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2024-11-29 10:24:20 +01:00
(archi) organize react-hook-form components in a separate folder
This commit is contained in:
parent
a9bbae12a9
commit
c2a245ce08
@ -1,50 +0,0 @@
|
||||
import React, { SelectHTMLAttributes } from 'react';
|
||||
import Select from 'react-select';
|
||||
import { Controller, Path } from 'react-hook-form';
|
||||
import { Control } from 'react-hook-form/dist/types/form';
|
||||
import { FieldValues } from 'react-hook-form/dist/types/fields';
|
||||
import { FieldPath } from 'react-hook-form/dist/types/path';
|
||||
import { FieldPathValue, UnpackNestedValue } from 'react-hook-form/dist/types';
|
||||
|
||||
interface FabSelectProps<TFieldValues, TContext extends object, TOptionValue> extends SelectHTMLAttributes<HTMLSelectElement> {
|
||||
id: string,
|
||||
label?: string,
|
||||
className?: string,
|
||||
control: Control<TFieldValues, TContext>,
|
||||
placeholder?: string,
|
||||
options: Array<selectOption<TOptionValue>>,
|
||||
valuesDefault?: Array<TOptionValue>,
|
||||
}
|
||||
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption<TOptionValue> = { value: TOptionValue, label: string };
|
||||
|
||||
/**
|
||||
* This component is a wrapper around react-select to use with react-hook-form.
|
||||
* It is a multi-select component.
|
||||
*/
|
||||
export const FabMultiSelect = <TFieldValues extends FieldValues, TContext extends object, TOptionValue>({ id, label, className, control, placeholder, options, valuesDefault }: FabSelectProps<TFieldValues, TContext, TOptionValue>) => {
|
||||
return (
|
||||
<label className={`fab-multi-select ${className || ''}`}>
|
||||
{label && <div className="fab-multi-select-header">
|
||||
<p>{label}</p>
|
||||
</div>}
|
||||
<div className="fab-multi-select-field">
|
||||
<Controller name={id as FieldPath<TFieldValues>}
|
||||
control={control}
|
||||
defaultValue={valuesDefault as UnpackNestedValue<FieldPathValue<TFieldValues, Path<TFieldValues>>>}
|
||||
render={({ field: { onChange, value, ref } }) =>
|
||||
<Select inputRef={ref}
|
||||
value={options.filter(c => value?.includes(c.value))}
|
||||
onChange={val => onChange(val.map(c => c.value))}
|
||||
placeholder={placeholder}
|
||||
options={options}
|
||||
isMulti />
|
||||
} />
|
||||
</div>
|
||||
</label>
|
||||
);
|
||||
};
|
@ -1,72 +0,0 @@
|
||||
import React, { ReactNode } from 'react';
|
||||
import { FieldErrors, UseFormRegister, Validate } from 'react-hook-form';
|
||||
import { FieldValues } from 'react-hook-form/dist/types/fields';
|
||||
|
||||
type inputType = string|number|readonly string [];
|
||||
type ruleTypes = {
|
||||
required?: boolean | string,
|
||||
pattern?: RegExp | {value: RegExp, message: string},
|
||||
minLenght?: number,
|
||||
maxLenght?: number,
|
||||
min?: number,
|
||||
max?: number,
|
||||
validate?: Validate<FieldValues>;
|
||||
};
|
||||
|
||||
interface RHFInputProps {
|
||||
id: string,
|
||||
register: UseFormRegister<FieldValues>,
|
||||
label?: string,
|
||||
tooltip?: string,
|
||||
defaultValue?: inputType,
|
||||
icon?: ReactNode,
|
||||
addOn?: ReactNode,
|
||||
addOnClassName?: string,
|
||||
classes?: string,
|
||||
rules?: ruleTypes,
|
||||
readOnly?: boolean,
|
||||
disabled?: boolean,
|
||||
placeholder?: string,
|
||||
error?: FieldErrors,
|
||||
type?: 'text' | 'date' | 'password' | 'url' | 'time' | 'tel' | 'search' | 'number' | 'month' | 'email' | 'datetime-local' | 'week',
|
||||
step?: number | 'any'
|
||||
}
|
||||
|
||||
/**
|
||||
* This component is a template for an input component to use within React Hook Form
|
||||
*/
|
||||
export const RHFInput: React.FC<RHFInputProps> = ({ id, register, label, tooltip, defaultValue, icon, classes, rules, readOnly, disabled, type, addOn, addOnClassName, placeholder, error, step }) => {
|
||||
// Compose classnames from props
|
||||
const classNames = `
|
||||
rhf-input ${classes || ''}
|
||||
${error && error[id] ? 'is-incorrect' : ''}
|
||||
${rules && rules.required ? 'is-required' : ''}
|
||||
${readOnly ? 'is-readOnly' : ''}
|
||||
${disabled ? 'is-disabled' : ''}`;
|
||||
|
||||
return (
|
||||
<label className={classNames}>
|
||||
{label && <div className='rhf-input-header'>
|
||||
<p>{label}</p>
|
||||
{/* TODO: Create tooltip component */}
|
||||
{tooltip && <span>{tooltip}</span>}
|
||||
</div>}
|
||||
<div className='rhf-input-field'>
|
||||
{icon && <span className="icon">{icon}</span>}
|
||||
<input id={id}
|
||||
{...register(id, {
|
||||
...rules,
|
||||
valueAsNumber: type === 'number',
|
||||
value: defaultValue
|
||||
})}
|
||||
type={type}
|
||||
step={step}
|
||||
disabled={disabled}
|
||||
readOnly={readOnly}
|
||||
placeholder={placeholder} />
|
||||
{addOn && <span className={`addon ${addOnClassName || ''}`}>{addOn}</span>}
|
||||
</div>
|
||||
{(error && error[id]) && <div className="rhf-input-error">{error[id].message}</div> }
|
||||
</label>
|
||||
);
|
||||
};
|
@ -26,12 +26,12 @@
|
||||
@import "modules/base/fab-modal";
|
||||
@import "modules/base/fab-output-copy";
|
||||
@import "modules/base/fab-popover";
|
||||
@import "modules/base/fab-select";
|
||||
@import "modules/base/fab-text-editor";
|
||||
@import "modules/base/labelled-input";
|
||||
@import "modules/base/rhf-input";
|
||||
@import "modules/calendar/calendar";
|
||||
@import "modules/form/form-input";
|
||||
@import "modules/form/form-item";
|
||||
@import "modules/form/form-select";
|
||||
@import "modules/machines/machine-card";
|
||||
@import "modules/machines/machines-filters";
|
||||
@import "modules/machines/machines-list";
|
||||
|
@ -1,4 +1,4 @@
|
||||
.rhf-input {
|
||||
.form-input {
|
||||
width: 100%;
|
||||
margin-bottom: 1.6rem;
|
||||
|
@ -1,5 +1,5 @@
|
||||
.fab-select,
|
||||
.fab-multi-select {
|
||||
.form-select,
|
||||
.form-multi-select {
|
||||
width: 100%;
|
||||
margin-bottom: 1.6rem;
|
||||
|
Loading…
Reference in New Issue
Block a user