Multi Select
A rich multi-select editor.
components/select-editor-demo.tsx
'use client';
import React from 'react';
import { useForm, useWatch } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { CheckIcon, PlusIcon } from 'lucide-react';
import * as z from 'zod';
import { Button } from '@/components/plate-ui/button';
import {
Form,
FormControl,
FormField,
FormItem,
FormMessage,
} from '@/components/plate-ui/form';
import {
type SelectItem,
SelectEditor,
SelectEditorCombobox,
SelectEditorContent,
SelectEditorInput,
} from '@/components/plate-ui/select-editor';
const LABELS = [
{ url: '/docs/components/editor', value: 'Editor' },
{ url: '/docs/components/select-editor', value: 'Select Editor' },
{ url: '/docs/components/block-selection', value: 'Block Selection' },
{ url: '/docs/components/button', value: 'Button' },
{ url: '/docs/components/command', value: 'Command' },
{ url: '/docs/components/dialog', value: 'Dialog' },
{ url: '/docs/components/form', value: 'Form' },
{ url: '/docs/components/input', value: 'Input' },
{ url: '/docs/components/label', value: 'Label' },
{ url: '/docs/components/plate-element', value: 'Plate Element' },
{ url: '/docs/components/popover', value: 'Popover' },
{ url: '/docs/components/tag-element', value: 'Tag Element' },
] satisfies (SelectItem & { url: string })[];
const formSchema = z.object({
labels: z
.array(
z.object({
value: z.string(),
})
)
.min(1, 'Select at least one label')
.max(10, 'Select up to 10 labels'),
});
type FormValues = z.infer<typeof formSchema>;
export default function EditorSelectForm() {
const [readOnly, setReadOnly] = React.useState(false);
const form = useForm<FormValues>({
defaultValues: {
labels: [LABELS[0]],
},
resolver: zodResolver(formSchema),
});
const labels = useWatch({ control: form.control, name: 'labels' });
return (
<div className="mx-auto w-full max-w-2xl space-y-8 p-11 pl-2 pt-24">
<Form {...form}>
<div className="space-y-6">
<FormField
name="labels"
control={form.control}
render={({ field }) => (
<FormItem>
<div className="flex items-start gap-2">
<Button
variant="ghost"
className="h-10"
onClick={() => setReadOnly(!readOnly)}
type="button"
>
{readOnly ? (
<PlusIcon className="size-4" />
) : (
<CheckIcon className="size-4" />
)}
</Button>
{readOnly && labels.length === 0 ? (
<Button
size="lg"
variant="ghost"
className="h-10"
onClick={() => {
setReadOnly(false);
}}
type="button"
>
Add labels
</Button>
) : (
<FormControl>
<SelectEditor
value={field.value}
onValueChange={readOnly ? undefined : field.onChange}
items={LABELS}
>
<SelectEditorContent>
<SelectEditorInput
readOnly={readOnly}
placeholder={
readOnly ? 'Empty' : 'Select labels...'
}
/>
{!readOnly && <SelectEditorCombobox />}
</SelectEditorContent>
</SelectEditor>
</FormControl>
)}
</div>
<FormMessage />
</FormItem>
)}
/>
</div>
</Form>
</div>
);
}
功能
与传统的基于输入框的多选组件不同,该组件基于 Plate 编辑器构建,提供以下功能:
- 完整的历史记录支持(撤销/重做)
- 标签之间和标签内的原生光标导航
- 支持选择一个或多个标签
- 复制/粘贴标签
- 拖放重新排序标签
- 只读模式
- 防止重复标签
- 创建新标签,不区分大小写
- 搜索文本清理
- 空格修剪
- 使用 cmdk 的模糊搜索
安装
npm install @udecode/plate-tag
用法
import { MultiSelectPlugin } from '@udecode/plate-tag/react';
import { TagElement } from '@/components/plate-ui/tag-element';
import {
SelectEditor,
SelectEditorContent,
SelectEditorInput,
SelectEditorCombobox,
type SelectItem,
} from '@/components/plate-ui/select-editor';
// Define your items
const ITEMS: SelectItem[] = [
{ value: 'React' },
{ value: 'TypeScript' },
{ value: 'JavaScript' },
];
export default function MySelectEditor() {
const [value, setValue] = React.useState<SelectItem[]>([ITEMS[0]]);
return (
<SelectEditor
value={value}
onValueChange={setValue}
items={ITEMS}
>
<SelectEditorContent>
<SelectEditorInput placeholder="Select items..." />
<SelectEditorCombobox />
</SelectEditorContent>
</SelectEditor>
);
}
插件
TagPlugin
内联空元素插件。
MultiSelectPlugin
继承 TagPlugin
API
editor.tf.insert.tag
在当前选择位置插入一个新的多选元素。
Parameters
Collapse all
多选元素的属性:
Hooks
useSelectedItems
获取编辑器中当前选中的标签项。
Returns
Collapse all
当前选中的标签项数组,每个标签项包含一个值和任何其他属性。
getSelectedItems
获取编辑器中所有标签项。
Parameters
Collapse all
编辑器实例。
Returns
Collapse all
编辑器中的标签项数组。
isEqualTags
比较两个标签集是否相等,忽略顺序。
Parameters
Collapse all
编辑器实例。
要与当前编辑器标签进行比较的新标签集。
Returns
Collapse all
true
如果两个集合包含相同的值,false
否则。
useSelectableItems
获取可以被选择的项目,通过搜索并排除已经选中的项目。
Parameters
Collapse all
Returns
Collapse all
过滤后的选择项目数组。
useSelectEditorCombobox
处理组合框行为,包括文本清理和项目选择。
Parameters
Collapse all
Types
TTagElement
type TTagElement = TElement & {
value: string;
[key: string]: unknown;
};
TagLike
type TagLike = {
value: string;
[key: string]: unknown;
};