diff --git a/demo/DemoApp.tsx b/demo/DemoApp.tsx index f340785..53842a5 100644 --- a/demo/DemoApp.tsx +++ b/demo/DemoApp.tsx @@ -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 + + + + + +

HTML

diff --git a/index.ts b/index.ts index 681f0ec..3ed05de 100644 --- a/index.ts +++ b/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"; diff --git a/package.json b/package.json index 0951e39..d935e29 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "1.4.2", + "version": "1.5.0", "name": "@kernelui/core", "description": "Kernel UI Core.", "scripts": { diff --git a/src/Components/Forms/CustomValidationRule.tsx b/src/Components/Forms/CustomValidationRule.tsx new file mode 100644 index 0000000..47b6b38 --- /dev/null +++ b/src/Components/Forms/CustomValidationRule.tsx @@ -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(); + + // 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 ( + {}} /> + ); +} diff --git a/src/Components/Select/Select.tsx b/src/Components/Select/Select.tsx index 20a2e66..b23b738 100644 --- a/src/Components/Select/Select.tsx +++ b/src/Components/Select/Select.tsx @@ -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 = 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( className, value, onChange, options, renderOption, match, + required, selectibleMinCount, selectibleMaxCount, multiple, blurOnSelect, blurWhenMaxCountSelected, // Properties to pass down. @@ -90,6 +98,10 @@ export function Select( // 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( + = selectibleMinCount} + errorMessage={`At least ${selectibleMinCount} option${selectibleMinCount > 1 ? "s are" : " is"} required.`} /> +
    { // Showing each selected value. selectedOptions.map(([optionKey, option]) => ( diff --git a/src/styles/_common.less b/src/styles/_common.less index df3448c..6db24ac 100644 --- a/src/styles/_common.less +++ b/src/styles/_common.less @@ -27,3 +27,9 @@ p margin: 0.75em auto; line-height: 1.6em; } + +.virtual +{ + position: absolute; + opacity: 0; +}