Add selectibleMinCount property and fix required for Selects, add a custom validation rule component.
This commit is contained in:
parent
dd91d8dcfc
commit
a1b0cc816c
6 changed files with 60 additions and 1 deletions
|
@ -56,6 +56,7 @@ export function DemoApp()
|
|||
const [datetime, setDatetime] = useState(null);
|
||||
|
||||
const [selected, setSelected] = useState(null);
|
||||
const [anotherSelected, setAnotherSelected] = useState(null);
|
||||
|
||||
const [page, setPage] = useState(11);
|
||||
|
||||
|
@ -176,6 +177,18 @@ export function DemoApp()
|
|||
}} value={selected} onChange={setSelected} selectibleMaxCount={3} placeholder={"Simple test"}>
|
||||
Simple select test
|
||||
</Select>
|
||||
|
||||
<Select value={anotherSelected} onChange={setAnotherSelected} options={{
|
||||
"test": "test",
|
||||
"foo": "foo",
|
||||
"bar": "bar",
|
||||
}} required={true}>
|
||||
At least one selected element
|
||||
</Select>
|
||||
|
||||
<Buttons placement={"center"}>
|
||||
<button>Validation test</button>
|
||||
</Buttons>
|
||||
</form>
|
||||
|
||||
<h2>HTML</h2>
|
||||
|
|
1
index.ts
1
index.ts
|
@ -15,6 +15,7 @@ export * from "./src/Components/Dates/Datepicker";
|
|||
export * from "./src/Components/Floating/Float";
|
||||
export * from "./src/Components/Floating/Tooltip";
|
||||
export * from "./src/Components/Forms/Checkbox";
|
||||
export * from "./src/Components/Forms/CustomValidationRule";
|
||||
export * from "./src/Components/Forms/DatepickerInput";
|
||||
export * from "./src/Components/Forms/PasswordInput";
|
||||
export * from "./src/Components/Forms/Radio";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "1.4.2",
|
||||
"version": "1.5.0",
|
||||
"name": "@kernelui/core",
|
||||
"description": "Kernel UI Core.",
|
||||
"scripts": {
|
||||
|
|
24
src/Components/Forms/CustomValidationRule.tsx
Normal file
24
src/Components/Forms/CustomValidationRule.tsx
Normal file
|
@ -0,0 +1,24 @@
|
|||
import React, {useEffect, useRef} from "react";
|
||||
|
||||
/**
|
||||
* Custom validation rule in a form.
|
||||
*/
|
||||
export function CustomValidationRule({valid, errorMessage}: {
|
||||
valid: boolean;
|
||||
errorMessage: string;
|
||||
})
|
||||
{
|
||||
// HTML virtual input ref.
|
||||
const ref = useRef<HTMLInputElement>();
|
||||
|
||||
// When the validation is invalid, set a custom error message, set the custom error message.
|
||||
useEffect(() => {
|
||||
ref.current.setCustomValidity(valid ? "" : errorMessage);
|
||||
}, [ref, valid, errorMessage]);
|
||||
|
||||
return (
|
||||
<input ref={ref}
|
||||
className={"virtual"} type={"text"} required={true}
|
||||
value={valid ? "true" : ""} onChange={() => {}} />
|
||||
);
|
||||
}
|
|
@ -3,6 +3,7 @@ import {Suggestible} from "./Suggestible";
|
|||
import {OptionsSuggestions, useSuggestionsNavigation} from "./OptionsSuggestions";
|
||||
import {classes, Modify, normalizeString} from "../../Utils";
|
||||
import {CaretDown, Check, X} from "@phosphor-icons/react";
|
||||
import {CustomValidationRule} from "../Forms/CustomValidationRule";
|
||||
|
||||
/**
|
||||
* Generic select component properties.
|
||||
|
@ -37,6 +38,12 @@ export type SelectProperties<OptionKey extends keyof any, Option> = React.PropsW
|
|||
*/
|
||||
match?: (search: string, option: Option) => boolean;
|
||||
|
||||
/**
|
||||
* Min count of options to allow to select.
|
||||
* 0 by default, 1 when required is true.
|
||||
*/
|
||||
selectibleMinCount?: number;
|
||||
|
||||
/**
|
||||
* Max count of options to allow to select.
|
||||
* 1 by default when multiple is false, infinity when multiple is true.
|
||||
|
@ -74,6 +81,7 @@ export function Select<OptionKey extends keyof any, Option>(
|
|||
className,
|
||||
value, onChange,
|
||||
options, renderOption, match,
|
||||
required, selectibleMinCount,
|
||||
selectibleMaxCount, multiple,
|
||||
blurOnSelect, blurWhenMaxCountSelected,
|
||||
// Properties to pass down.
|
||||
|
@ -90,6 +98,10 @@ export function Select<OptionKey extends keyof any, Option>(
|
|||
// If `multiple` is set and `selectibleMaxCount` is not, allow an infinite count of options to select.
|
||||
selectibleMaxCount = selectibleMaxCount ?? ((multiple === undefined ? false : multiple) ? Infinity : 1);
|
||||
|
||||
// By default, allow to select no option.
|
||||
// If `required` is set, `selectibleMinCount` will be set as 1 by default.
|
||||
selectibleMinCount = selectibleMinCount ?? (required ? 1 : 0);
|
||||
|
||||
// true by default.
|
||||
blurOnSelect = blurOnSelect === undefined ? false : blurOnSelect;
|
||||
blurWhenMaxCountSelected = blurWhenMaxCountSelected === undefined ? true : blurWhenMaxCountSelected;
|
||||
|
@ -213,6 +225,9 @@ export function Select<OptionKey extends keyof any, Option>(
|
|||
<a className={"button"} tabIndex={-1}><CaretDown /></a>
|
||||
</div>
|
||||
|
||||
<CustomValidationRule valid={selectedOptions.length >= selectibleMinCount}
|
||||
errorMessage={`At least ${selectibleMinCount} option${selectibleMinCount > 1 ? "s are" : " is"} required.`} />
|
||||
|
||||
<ul className={"selected"}>
|
||||
{ // Showing each selected value.
|
||||
selectedOptions.map(([optionKey, option]) => (
|
||||
|
|
|
@ -27,3 +27,9 @@ p
|
|||
margin: 0.75em auto;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
|
||||
.virtual
|
||||
{
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue