@lume98/cascader
v0.1.0
Published
A powerful cascading selector component built with React, Radix UI, and Tailwind CSS. Supports single/multiple selection, search, and custom rendering.
Maintainers
Readme
@lume98/cascader
一个功能强大的级联选择器组件,基于 React、Radix UI 和 Tailwind CSS 构建。支持单选/多选、搜索、自定义渲染等功能。
特性
- ✨ 支持单选和多选模式
- 🔍 内置搜索功能
- 🎯 支持父子节点独立选择(checkStrictly)
- 📦 支持多种选中策略(all、parent、child)
- 🎨 使用 Tailwind CSS 构建,支持亮色/暗色主题
- ♿️ 完全可访问,支持键盘导航
- 📏 可自定义标签数量限制
- 🔄 支持完整路径或仅返回最后节点值
- 🎭 可自定义占位符和渲染
- 📦 使用 TypeScript 编写,提供完整的类型支持
安装
pnpm add @lume98/cascader依赖
此组件依赖以下库:
{
"@radix-ui/react-checkbox": "^1.3.3",
"@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-scroll-area": "^1.2.10",
"@radix-ui/react-slot": "^1.2.4",
"clsx": "^2.1.1",
"lucide-react": "^0.468.0",
"tailwind-merge": "^2.6.0"
}使用
基础用法
import { Cascader } from '@lume98/cascader';
const options = [
{
label: '浙江',
value: 'zhejiang',
children: [
{
label: '杭州',
value: 'hangzhou',
children: [
{ label: '西湖区', value: 'xihu' },
{ label: '滨江区', value: 'binjiang' },
],
},
],
},
{
label: '江苏',
value: 'jiangsu',
children: [
{
label: '南京',
value: 'nanjing',
children: [
{ label: '玄武区', value: 'xuanwu' },
{ label: '秦淮区', value: 'qinhuai' },
],
},
],
},
];
export default function App() {
const [value, setValue] = React.useState([]);
return (
<Cascader
options={options}
value={value}
onChange={setValue}
placeholder="请选择地区"
/>
);
}多选模式
<Cascader
options={options}
value={selectedValues}
onChange={setSelectedValues}
multiple={true}
placeholder="请选择多个地区"
/>父子节点独立选择
<Cascader
options={options}
value={value}
onChange={setValue}
multiple={true}
checkStrictly={true}
placeholder="可独立选择父子节点"
/>自定义选中策略
控制多选模式下显示哪些节点:
// 显示所有选中节点
<Cascader
options={options}
multiple={true}
showCheckedStrategy="all"
/>
// 只显示父节点(当子节点全选时)
<Cascader
options={options}
multiple={true}
showCheckedStrategy="parent"
/>
// 只显示叶子节点
<Cascader
options={options}
multiple={true}
showCheckedStrategy="child"
/>限制标签数量
<Cascader
options={options}
multiple={true}
maxTagCount={2}
maxTagPlaceholder={omittedCount => `+${omittedCount}...`}
/>仅返回最后节点值
// 默认返回完整路径:['zhejiang', 'hangzhou', 'xihu']
<Cascader
options={options}
value={value}
onChange={setValue}
showFullPath={true}
/>
// 只返回最后一个节点:'xihu'
<Cascader
options={options}
value={value}
onChange={setValue}
showFullPath={false}
/>禁用选项
const optionsWithDisabled = [
{
label: '浙江',
value: 'zhejiang',
children: [
{
label: '杭州',
value: 'hangzhou',
disabled: true, // 禁用此选项
children: [{ label: '西湖区', value: 'xihu' }],
},
],
},
];
<Cascader options={optionsWithDisabled} value={value} onChange={setValue} />;禁用整个组件
<Cascader options={options} value={value} onChange={setValue} disabled={true} />API
CascaderProps
| 属性 | 类型 | 默认值 | 描述 |
| --------------------- | ------------------------------------- | ------------- | ---------------------------- |
| options | CascaderOption[] | - | 级联选择器的选项数据(必填) |
| value | string[] \| string[][] \| string | - | 当前选中的值 |
| onChange | (value, selectedOptions) => void | - | 值变化时的回调函数 |
| placeholder | string | '请选择...' | 占位符文本 |
| className | string | - | 自定义类名 |
| disabled | boolean | false | 是否禁用 |
| multiple | boolean | false | 是否支持多选 |
| checkStrictly | boolean | false | 是否严格的父子节点独立选择 |
| showCheckedStrategy | 'all' \| 'parent' \| 'child' | 'all' | 多选模式下的选中策略 |
| maxTagCount | number | - | 最多显示的标签数量 |
| maxTagPlaceholder | (omittedCount: number) => ReactNode | - | 超出标签数量时的占位内容 |
| showFullPath | boolean | true | 是否返回完整路径 |
CascaderOption
interface CascaderOption {
label: string; // 显示的标签
value: string; // 选项的值
children?: CascaderOption[]; // 子选项
disabled?: boolean; // 是否禁用
}值的格式
单选模式
showFullPath = true(默认):
value: string[] // 例如:['zhejiang', 'hangzhou', 'xihu']showFullPath = false:
value: string; // 例如:'xihu'多选模式
showFullPath = true(默认):
value: string[][] // 例如:[['zhejiang', 'hangzhou', 'xihu'], ['jiangsu', 'nanjing', 'xuanwu']]showFullPath = false:
value: string[] // 例如:['xihu', 'xuanwu']样式定制
使用自定义类名
<Cascader
className="w-full"
options={options}
value={value}
onChange={setValue}
/>主题变量
组件使用 CSS 变量来支持主题定制。你可以在你的 CSS 中覆盖这些变量:
:root {
--primary: /* 主色调 */ ;
--background: /* 背景色 */ ;
--border: /* 边框色 */ ;
--popover: /* 弹出层背景 */ ;
/* 更多变量... */
}示例
完整示例:地区选择器
import React from 'react';
import { Cascader } from '@lume98/cascader';
const regionOptions = [
{
label: '中国',
value: 'china',
children: [
{
label: '浙江',
value: 'zhejiang',
children: [
{
label: '杭州',
value: 'hangzhou',
children: [
{ label: '西湖区', value: 'xihu' },
{ label: '滨江区', value: 'binjiang' },
{ label: '余杭区', value: 'yuhang' },
],
},
{
label: '宁波',
value: 'ningbo',
children: [
{ label: '海曙区', value: 'haishu' },
{ label: '江北区', value: 'jiangbei' },
],
},
],
},
{
label: '江苏',
value: 'jiangsu',
children: [
{
label: '南京',
value: 'nanjing',
children: [
{ label: '玄武区', value: 'xuanwu' },
{ label: '秦淮区', value: 'qinhuai' },
],
},
],
},
],
},
];
export default function RegionSelector() {
const [value, setValue] = React.useState<string[]>([]);
return (
<div className="w-full max-w-md">
<Cascader
options={regionOptions}
value={value}
onChange={(newValue, selectedOptions) => {
setValue(newValue as string[]);
console.log('选中的值:', newValue);
console.log('选中的选项:', selectedOptions);
}}
placeholder="请选择地区"
/>
</div>
);
}注意事项
- value 类型:确保传入的
value类型与multiple和showFullPath设置相匹配 - 性能:对于大量数据,建议使用虚拟滚动或分页加载
- 样式导入:样式会自动导入,如需单独导入:
import '@lume98/cascader/styles.css'
许可证
MIT
贡献
欢迎提交 Issue 和 Pull Request!
