ui/multisearch: make controlled for now
This commit is contained in:
@@ -2,7 +2,15 @@ import Icon from "../Icon/Icon";
|
|||||||
import { Button } from "../Button/Button";
|
import { Button } from "../Button/Button";
|
||||||
import styles from "./Search.module.css";
|
import styles from "./Search.module.css";
|
||||||
import { Combobox } from "@kobalte/core/combobox";
|
import { Combobox } from "@kobalte/core/combobox";
|
||||||
import { createMemo, createSignal, For, JSX, Match, Switch } from "solid-js";
|
import {
|
||||||
|
createEffect,
|
||||||
|
createMemo,
|
||||||
|
createSignal,
|
||||||
|
For,
|
||||||
|
JSX,
|
||||||
|
Match,
|
||||||
|
Switch,
|
||||||
|
} from "solid-js";
|
||||||
import { createVirtualizer, VirtualizerOptions } from "@tanstack/solid-virtual";
|
import { createVirtualizer, VirtualizerOptions } from "@tanstack/solid-virtual";
|
||||||
import { CollectionNode } from "@kobalte/core/*";
|
import { CollectionNode } from "@kobalte/core/*";
|
||||||
import cx from "classnames";
|
import cx from "classnames";
|
||||||
@@ -11,13 +19,16 @@ import { Loader } from "../Loader/Loader";
|
|||||||
export interface Option {
|
export interface Option {
|
||||||
value: string;
|
value: string;
|
||||||
label: string;
|
label: string;
|
||||||
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ItemRenderOptions {
|
export interface ItemRenderOptions {
|
||||||
selected: boolean;
|
selected: boolean;
|
||||||
|
disabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SearchMultipleProps<T> {
|
export interface SearchMultipleProps<T> {
|
||||||
|
values: T[]; // controlled values
|
||||||
onChange: (values: T[]) => void;
|
onChange: (values: T[]) => void;
|
||||||
options: T[];
|
options: T[];
|
||||||
renderItem: (item: T, opts: ItemRenderOptions) => JSX.Element;
|
renderItem: (item: T, opts: ItemRenderOptions) => JSX.Element;
|
||||||
@@ -29,12 +40,13 @@ export interface SearchMultipleProps<T> {
|
|||||||
headerChildren?: JSX.Element;
|
headerChildren?: JSX.Element;
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
loadingComponent?: JSX.Element;
|
loadingComponent?: JSX.Element;
|
||||||
|
divider?: boolean;
|
||||||
}
|
}
|
||||||
export function SearchMultiple<T extends Option>(
|
export function SearchMultiple<T extends Option>(
|
||||||
props: SearchMultipleProps<T>,
|
props: SearchMultipleProps<T>,
|
||||||
) {
|
) {
|
||||||
// Controlled input value, to allow resetting the input itself
|
// Controlled input value, to allow resetting the input itself
|
||||||
const [values, setValues] = createSignal<T[]>(props.initialValues || []);
|
// const [values, setValues] = createSignal<T[]>(props.initialValues || []);
|
||||||
const [inputValue, setInputValue] = createSignal<string>("");
|
const [inputValue, setInputValue] = createSignal<string>("");
|
||||||
|
|
||||||
let inputEl: HTMLInputElement;
|
let inputEl: HTMLInputElement;
|
||||||
@@ -60,21 +72,23 @@ export function SearchMultiple<T extends Option>(
|
|||||||
return item?.rawValue?.value || `item-${index}`;
|
return item?.rawValue?.value || `item-${index}`;
|
||||||
},
|
},
|
||||||
estimateSize: () => 42,
|
estimateSize: () => 42,
|
||||||
gap: 6,
|
gap: 0,
|
||||||
overscan: 5,
|
overscan: 5,
|
||||||
...props.virtualizerOptions,
|
...props.virtualizerOptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
return newVirtualizer;
|
return newVirtualizer;
|
||||||
});
|
});
|
||||||
|
createEffect(() => {
|
||||||
|
console.log("multi values:", props.values);
|
||||||
|
});
|
||||||
return (
|
return (
|
||||||
<Combobox<T>
|
<Combobox<T>
|
||||||
multiple
|
multiple
|
||||||
value={values()}
|
value={props.values}
|
||||||
onChange={(values) => {
|
onChange={(values) => {
|
||||||
setValues(() => values);
|
// setValues(() => values);
|
||||||
// setInputValue(value ? value.label : "");
|
console.log("onChange", values);
|
||||||
props.onChange(values);
|
props.onChange(values);
|
||||||
}}
|
}}
|
||||||
class={styles.searchContainer}
|
class={styles.searchContainer}
|
||||||
@@ -83,6 +97,7 @@ export function SearchMultiple<T extends Option>(
|
|||||||
optionValue="value"
|
optionValue="value"
|
||||||
optionTextValue="label"
|
optionTextValue="label"
|
||||||
optionLabel="label"
|
optionLabel="label"
|
||||||
|
optionDisabled={"disabled"}
|
||||||
sameWidth={true}
|
sameWidth={true}
|
||||||
open={true}
|
open={true}
|
||||||
gutter={7}
|
gutter={7}
|
||||||
@@ -183,11 +198,16 @@ export function SearchMultiple<T extends Option>(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const isSelected = () =>
|
const isSelected = () =>
|
||||||
values().some((v) => v.value === item.rawValue.value);
|
props.values.some(
|
||||||
|
(v) => v.value === item.rawValue.value,
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<Combobox.Item
|
<Combobox.Item
|
||||||
item={item}
|
item={item}
|
||||||
class={styles.searchItem}
|
class={cx(
|
||||||
|
styles.searchItem,
|
||||||
|
props.divider && styles.hasDivider,
|
||||||
|
)}
|
||||||
style={{
|
style={{
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
top: 0,
|
top: 0,
|
||||||
@@ -199,6 +219,7 @@ export function SearchMultiple<T extends Option>(
|
|||||||
>
|
>
|
||||||
{props.renderItem(item.rawValue, {
|
{props.renderItem(item.rawValue, {
|
||||||
selected: isSelected(),
|
selected: isSelected(),
|
||||||
|
disabled: item.disabled,
|
||||||
})}
|
})}
|
||||||
</Combobox.Item>
|
</Combobox.Item>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user