feat: add custom css for board and custom classes in advanced options for items (#512)
* feat: add custom css for board and custom classes in advanced options for items * chore: add mysql migration * fix: test not working * fix: format issues * fix: typecheck issue * fix: build issue * chore: add missing translations * fix: merge issues related to migrations * fix: format issues * fix: merge issue with migration * fix: format issue
This commit is contained in:
@@ -5,3 +5,4 @@ export { UserAvatar } from "./user-avatar";
|
||||
export { UserAvatarGroup } from "./user-avatar-group";
|
||||
export { TablePagination } from "./table-pagination";
|
||||
export { SearchInput } from "./search-input";
|
||||
export { TextMultiSelect } from "./text-multi-select";
|
||||
|
||||
98
packages/ui/src/components/text-multi-select.tsx
Normal file
98
packages/ui/src/components/text-multi-select.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
"use client";
|
||||
|
||||
import type { FocusEventHandler } from "react";
|
||||
import { useState } from "react";
|
||||
import { Combobox, Group, Pill, PillsInput, Text, useCombobox } from "@mantine/core";
|
||||
import { IconPlus } from "@tabler/icons-react";
|
||||
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
|
||||
interface TextMultiSelectProps {
|
||||
label: string;
|
||||
value?: string[];
|
||||
onChange: (value: string[]) => void;
|
||||
onFocus?: FocusEventHandler;
|
||||
onBlur?: FocusEventHandler;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export const TextMultiSelect = ({ label, value = [], onChange, onBlur, onFocus, error }: TextMultiSelectProps) => {
|
||||
const t = useI18n();
|
||||
const combobox = useCombobox({
|
||||
onDropdownClose: () => combobox.resetSelectedOption(),
|
||||
onDropdownOpen: () => combobox.updateSelectedOptionIndex("active"),
|
||||
});
|
||||
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
const exactOptionMatch = value.some((item) => item === search);
|
||||
|
||||
const handleValueSelect = (selectedValue: string) => {
|
||||
setSearch("");
|
||||
|
||||
if (selectedValue === "$create") {
|
||||
onChange([...value, search]);
|
||||
} else {
|
||||
onChange(value.filter((filterValue) => filterValue !== selectedValue));
|
||||
}
|
||||
};
|
||||
|
||||
const handleValueRemove = (removedValue: string) =>
|
||||
onChange(value.filter((filterValue) => filterValue !== removedValue));
|
||||
|
||||
const values = value.map((item) => (
|
||||
<Pill key={item} withRemoveButton onRemove={() => handleValueRemove(item)}>
|
||||
{item}
|
||||
</Pill>
|
||||
));
|
||||
|
||||
return (
|
||||
<Combobox store={combobox} onOptionSubmit={handleValueSelect} withinPortal={false}>
|
||||
<Combobox.DropdownTarget>
|
||||
<PillsInput label={label} error={error} onClick={() => combobox.openDropdown()}>
|
||||
<Pill.Group>
|
||||
{values}
|
||||
|
||||
<Combobox.EventsTarget>
|
||||
<PillsInput.Field
|
||||
onFocus={(event) => {
|
||||
onFocus?.(event);
|
||||
combobox.openDropdown();
|
||||
}}
|
||||
onBlur={(event) => {
|
||||
onBlur?.(event);
|
||||
combobox.closeDropdown();
|
||||
}}
|
||||
value={search}
|
||||
placeholder={t("common.multiText.placeholder")}
|
||||
onChange={(event) => {
|
||||
combobox.updateSelectedOptionIndex();
|
||||
setSearch(event.currentTarget.value);
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === "Backspace" && search.length === 0) {
|
||||
event.preventDefault();
|
||||
handleValueRemove(value.at(-1)!);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Combobox.EventsTarget>
|
||||
</Pill.Group>
|
||||
</PillsInput>
|
||||
</Combobox.DropdownTarget>
|
||||
|
||||
{!exactOptionMatch && search.trim().length > 0 && (
|
||||
<Combobox.Dropdown>
|
||||
<Combobox.Options>
|
||||
<Combobox.Option value="$create">
|
||||
<Group>
|
||||
<IconPlus size={12} />
|
||||
<Text size="sm">{t("common.multiText.addLabel", { value: search })}</Text>
|
||||
</Group>
|
||||
</Combobox.Option>
|
||||
</Combobox.Options>
|
||||
</Combobox.Dropdown>
|
||||
)}
|
||||
</Combobox>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user