Compare commits

...

2 commits

Author SHA1 Message Date
23d0ab147b
Export SelectProperties type.
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2024-09-24 19:54:18 +02:00
72a3b9b9d2
Fix max size of select suggestions. 2024-09-24 19:54:07 +02:00
4 changed files with 75 additions and 59 deletions

View file

@ -153,6 +153,14 @@ export function DemoApp()
"d": "DDDDDD", "d": "DDDDDD",
"e": "EEEEEE", "e": "EEEEEE",
"f": "FFFFFF", "f": "FFFFFF",
"g": "GGGGGG",
"h": "HHHHHH",
"i": "IIIIII",
"j": "JJJJJJ",
"k": "KKKKKK",
"l": "LLLLLL",
"m": "MMMMMM",
"n": "NNNNNN",
}} value={selected} onChange={setSelected} selectibleMaxCount={3} placeholder={"Simple test"}> }} value={selected} onChange={setSelected} selectibleMaxCount={3} placeholder={"Simple test"}>
Simple select test Simple select test
</Select> </Select>

View file

@ -1,5 +1,5 @@
{ {
"version": "1.3.2", "version": "1.3.3",
"name": "@kernelui/core", "name": "@kernelui/core",
"description": "Kernel UI Core.", "description": "Kernel UI Core.",
"scripts": { "scripts": {

View file

@ -4,6 +4,68 @@ import {OptionsSuggestions, useSuggestionsNavigation} from "./OptionsSuggestions
import {classes, Modify, normalizeString} from "../../Utils"; import {classes, Modify, normalizeString} from "../../Utils";
import {CaretDown, Check, X} from "@phosphor-icons/react"; import {CaretDown, Check, X} from "@phosphor-icons/react";
/**
* Generic select component properties.
*/
export type SelectProperties<OptionKey extends keyof any, Option> = React.PropsWithChildren<Modify<React.InputHTMLAttributes<HTMLInputElement>, {
/**
* The currently selected option(s).
*/
value: OptionKey|OptionKey[];
/**
* Called when new options are selected.
* @param newValue
*/
onChange: (newValue: OptionKey|OptionKey[]) => void;
/**
* Options list or a way to get it from a given search.
*/
options: Record<OptionKey, Option>;
/**
* Render an option.
* @param option The option to render.
*/
renderOption?: (option: Option) => React.ReactNode;
/**
* Option match function. Return true if the given option matches the given search query.
* @param search The search query.
* @param option The option that should match the search query.
*/
match?: (search: string, option: Option) => boolean;
/**
* Max count of options to allow to select.
* 1 by default when multiple is false, infinity when multiple is true.
*/
selectibleMaxCount?: number;
/**
* True to allow to select an infinite count of options.
* false by default.
*/
multiple?: boolean;
/**
* When true, the select loses focus when a new option is selected (by clicking or pressing Enter).
* false by default.
*/
blurOnSelect?: boolean;
/**
* When true, the select loses focus when the max count of selectible options have been reached (by clicking or pressing Enter).
* true by default.
*/
blurWhenMaxCountSelected?: boolean;
// Already set properties.
type?: never;
role?: never;
}>>;
/** /**
* Generic select component. * Generic select component.
*/ */
@ -20,64 +82,7 @@ export function Select<OptionKey extends keyof any, Option>(
type, role, type, role,
children, children,
...props ...props
}: React.PropsWithChildren<Modify<React.InputHTMLAttributes<HTMLInputElement>, { }: SelectProperties<OptionKey, Option>): React.ReactElement
/**
* The currently selected option(s).
*/
value: OptionKey|OptionKey[];
/**
* Called when new options are selected.
* @param newValue
*/
onChange: (newValue: OptionKey|OptionKey[]) => void;
/**
* Options list or a way to get it from a given search.
*/
options: Record<OptionKey, Option>;
/**
* Render an option.
* @param option The option to render.
*/
renderOption?: (option: Option) => React.ReactNode;
/**
* Option match function. Return true if the given option matches the given search query.
* @param search The search query.
* @param option The option that should match the search query.
*/
match?: (search: string, option: Option) => boolean;
/**
* Max count of options to allow to select.
* 1 by default when multiple is false, infinity when multiple is true.
*/
selectibleMaxCount?: number;
/**
* True to allow to select an infinite count of options.
* false by default.
*/
multiple?: boolean;
/**
* When true, the select loses focus when a new option is selected (by clicking or pressing Enter).
* false by default.
*/
blurOnSelect?: boolean;
/**
* When true, the select loses focus when the max count of selectible options have been reached (by clicking or pressing Enter).
* true by default.
*/
blurWhenMaxCountSelected?: boolean;
// Already set properties.
type?: never;
role?: never;
}>>): React.ReactElement
{ {
const [search, setSearch] = React.useState(""); const [search, setSearch] = React.useState("");

View file

@ -1,7 +1,10 @@
.floating.suggestions .floating.suggestions
{ {
max-height: ~"min(90vh, 18em)";
padding: 0.5em 0; padding: 0.5em 0;
overflow-y: auto;
.suggestion .suggestion
{ {
transition: background 0.2s ease; transition: background 0.2s ease;