mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-18 07:52:23 +01:00
(ui) select authentication provier type
This commit is contained in:
parent
a60ae0534b
commit
a9bbae12a9
@ -0,0 +1,50 @@
|
||||
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>
|
||||
);
|
||||
};
|
@ -26,6 +26,7 @@
|
||||
@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";
|
||||
|
79
app/frontend/src/stylesheets/modules/base/fab-select.scss
Normal file
79
app/frontend/src/stylesheets/modules/base/fab-select.scss
Normal file
@ -0,0 +1,79 @@
|
||||
.fab-select,
|
||||
.fab-multi-select {
|
||||
width: 100%;
|
||||
margin-bottom: 1.6rem;
|
||||
|
||||
&-header {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 0.8rem;
|
||||
p {
|
||||
@include text-sm;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
&.is-required &-header p::after {
|
||||
content: "*";
|
||||
margin-left: 0.5ch;
|
||||
color: var(--error);
|
||||
}
|
||||
|
||||
&-field {
|
||||
height: 4rem;
|
||||
display: grid;
|
||||
grid-template-areas: "icon input addon";
|
||||
grid-template-columns: min-content 1fr min-content;
|
||||
border: 1px solid var(--gray-soft-dark);
|
||||
border-radius: var(--border-radius);
|
||||
overflow: hidden;
|
||||
transition: border-color ease-in-out 0.15s;
|
||||
|
||||
.icon,
|
||||
.addon {
|
||||
width: 4rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: var(--gray-hard-light);
|
||||
background-color: var(--gray-soft);
|
||||
}
|
||||
.icon {
|
||||
grid-area: icon;
|
||||
border-right: 1px solid var(--gray-soft-dark);
|
||||
}
|
||||
&-input {
|
||||
grid-area: input;
|
||||
border: none;
|
||||
border-radius: var(--border-radius);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .08);
|
||||
padding: 0 0.8rem;
|
||||
color: var(--gray-hard-darkest);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.addon {
|
||||
grid-area: addon;
|
||||
border-left: 1px solid var(--gray-soft-dark);
|
||||
}
|
||||
}
|
||||
&.is-incorrect &-field {
|
||||
border-color: var(--error);
|
||||
.icon {
|
||||
color: var(--error);
|
||||
border-color: var(--error);
|
||||
background-color: var(--error-lightest);
|
||||
}
|
||||
}
|
||||
&.is-disabled &-field input,
|
||||
&.is-readOnly &-field input {
|
||||
background-color: var(--gray-soft-light);
|
||||
}
|
||||
|
||||
&-error {
|
||||
margin-top: 0.4rem;
|
||||
color: var(--error);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user