A comprehensive cascading select component for React applications that enables hierarchical option selection through a dropdown interface
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Standalone cascader panel component for custom layouts without dropdown behavior. Provides the same hierarchical selection functionality as the main Cascader component but renders as an inline panel rather than a dropdown.
Creates a standalone cascader panel for embedding in custom layouts.
/**
* Standalone cascader panel without dropdown behavior
* @param props - Panel configuration props
* @returns JSX.Element
*/
function Panel<
OptionType extends DefaultOptionType = DefaultOptionType,
ValueField extends keyof OptionType = keyof OptionType,
Multiple extends boolean | React.ReactNode = false
>(props: PanelProps<OptionType, ValueField, Multiple>): JSX.Element;Configuration properties for the Panel component.
interface PanelProps<
OptionType extends DefaultOptionType = DefaultOptionType,
ValueField extends keyof OptionType = keyof OptionType,
Multiple extends boolean | React.ReactNode = false
> {
/** Controlled selected value */
value?: GetValueType<OptionType, ValueField, Multiple>;
/** Initial selected value for uncontrolled mode */
defaultValue?: GetValueType<OptionType, ValueField, Multiple>;
/** Trigger onChange on each level selection, not just leaf nodes */
changeOnSelect?: boolean;
/** Selection change callback */
onChange?: (
value: GetValueType<OptionType, ValueField, Multiple>,
selectOptions: GetOptionType<OptionType, Multiple>
) => void;
/** Hierarchical options data array */
options?: OptionType[];
/** CSS class prefix (default: 'rc-cascader') */
prefixCls?: string;
/** Enable multiple selection mode */
checkable?: Multiple;
/** Custom field name mapping */
fieldNames?: FieldNames<OptionType, ValueField>;
/** Strategy for displaying selected items in multiple mode */
showCheckedStrategy?: ShowCheckedStrategy;
/** Callback for loading child options dynamically */
loadData?: (selectOptions: OptionType[]) => void;
/** How to expand option menus: 'hover' or 'click' */
expandTrigger?: 'hover' | 'click';
/** Custom expand icon */
expandIcon?: React.ReactNode;
/** Custom loading icon */
loadingIcon?: React.ReactNode;
/** Additional CSS classes */
className?: string;
/** Inline styles */
style?: React.CSSProperties;
/** Text direction for RTL support */
direction?: 'ltr' | 'rtl';
/** Content to show when no options found */
notFoundContent?: React.ReactNode;
/** Disable the entire panel */
disabled?: boolean;
}import React, { useState } from 'react';
import { Panel } from 'rc-cascader';
const options = [
{
label: 'Zhejiang',
value: 'zhejiang',
children: [
{
label: 'Hangzhou',
value: 'hangzhou',
children: [
{ label: 'West Lake', value: 'xihu' },
{ label: 'Xiaoshan', value: 'xiaoshan' }
]
},
{
label: 'Ningbo',
value: 'ningbo'
}
]
},
{
label: 'Jiangsu',
value: 'jiangsu',
children: [
{
label: 'Nanjing',
value: 'nanjing'
}
]
}
];
const BasicPanelExample = () => {
const [value, setValue] = useState([]);
return (
<div style={{ border: '1px solid #d9d9d9', borderRadius: '6px' }}>
<Panel
options={options}
value={value}
onChange={(value, selectedOptions) => {
setValue(value);
console.log('Selected:', value, selectedOptions);
}}
/>
</div>
);
};const MultiplePanelExample = () => {
const [value, setValue] = useState([]);
return (
<Panel
checkable
options={options}
value={value}
onChange={(value, selectedOptions) => {
setValue(value);
console.log('Multiple selected:', value, selectedOptions);
}}
showCheckedStrategy="SHOW_CHILD"
/>
);
};const StyledPanelExample = () => {
return (
<Panel
options={options}
className="custom-panel"
style={{
width: '400px',
height: '300px',
border: '2px solid #1890ff',
borderRadius: '8px',
padding: '8px'
}}
expandTrigger="hover"
expandIcon={<span>→</span>}
/>
);
};const DynamicPanelExample = () => {
const [options, setOptions] = useState([
{
label: 'Dynamic Root',
value: 'root',
isLeaf: false
}
]);
const loadData = (selectedOptions) => {
const targetOption = selectedOptions[selectedOptions.length - 1];
targetOption.loading = true;
// Simulate async data loading
setTimeout(() => {
targetOption.loading = false;
targetOption.children = [
{
label: `Child of ${targetOption.label}`,
value: `${targetOption.value}_child`,
isLeaf: true
}
];
setOptions([...options]);
}, 1000);
};
return (
<Panel
options={options}
loadData={loadData}
changeOnSelect
loadingIcon={<span>Loading...</span>}
/>
);
};const customFieldOptions = [
{
name: 'Technology',
id: 'tech',
subcategories: [
{
name: 'Frontend',
id: 'frontend',
subcategories: [
{ name: 'React', id: 'react' },
{ name: 'Vue', id: 'vue' }
]
}
]
}
];
const CustomFieldPanelExample = () => {
return (
<Panel
options={customFieldOptions}
fieldNames={{
label: 'name',
value: 'id',
children: 'subcategories'
}}
expandTrigger="click"
/>
);
};const RTLPanelExample = () => {
return (
<Panel
options={options}
direction="rtl"
style={{ direction: 'rtl' }}
/>
);
};import React from 'react';
import { Panel } from 'rc-cascader';
const FormIntegrationExample = () => {
const [formData, setFormData] = useState({
location: [],
category: []
});
const handleLocationChange = (value, selectedOptions) => {
setFormData(prev => ({
...prev,
location: value
}));
};
return (
<form>
<div className="form-field">
<label>Location:</label>
<Panel
options={locationOptions}
value={formData.location}
onChange={handleLocationChange}
style={{ marginTop: '8px' }}
/>
</div>
<div className="form-field">
<label>Category:</label>
<Panel
options={categoryOptions}
value={formData.category}
onChange={(value) =>
setFormData(prev => ({ ...prev, category: value }))
}
style={{ marginTop: '8px' }}
/>
</div>
</form>
);
};Install with Tessl CLI
npx tessl i tessl/npm-rc-cascader